diff options
author | Jeff Johnston <jjohnstn@redhat.com> | 2002-06-06 00:58:59 +0400 |
---|---|---|
committer | Jeff Johnston <jjohnstn@redhat.com> | 2002-06-06 00:58:59 +0400 |
commit | 39e65e0113e188e4177077407d337bb3a1ac1853 (patch) | |
tree | 7afb2759a870354f5267c72215acfcfc89bb12fa /newlib/libc/posix/telldir.c | |
parent | ea4e6ec8f9fe4a784d4ce2ef71037e05fb9a876d (diff) |
2002-06-05 Jeff Johnston <jjohnstn@redhat.com>
* libc/include/string.h[__linux__]: Add strsignal prototype.
* libc/include/sys/lock.h: New file with default locking support.
* libc/include/sys/reent.h: Add signal buffer support for strsignal
and psignal.
* libc/posix/Makefile.am: Add support for readdir_r.c.
* libc/posix/Makefile.in: Regenerated.
* libc/posix/closedir.c: Add locking support and hash table cleanup.
* libc/posix/opendir.c: Add lock support.
* libc/posix/readdir.c: Ditto.
* libc/posix/rewinddir.c: Ditto.
* libc/posix/scandir.c: Ditto.
* libc/posix/seekdir.c: Ditto.
* libc/posix/telldir.c: Ditto plus add _cleanupdir routine to
clean up leftover hash table entries.
* libc/posix/readdir_r.c: New file.
* libc/sys/linux/Makefile.am: Add psignal.c and strsignal.c support.
* libc/sys/linux/Makefile.in: Regenerated.
* libc/sys/linux/sys/dirent.h: Add dd_lock to DIR structure.
* libc/sys/linux/sys/signal.h: Add psignal prototype.
* libc/sys/linux/psignal.c: New file.
* libc/sys/linux/strsignal.c: Ditto.
Diffstat (limited to 'newlib/libc/posix/telldir.c')
-rw-r--r-- | newlib/libc/posix/telldir.c | 62 |
1 files changed, 61 insertions, 1 deletions
diff --git a/newlib/libc/posix/telldir.c b/newlib/libc/posix/telldir.c index 30c003760..6022bbe19 100644 --- a/newlib/libc/posix/telldir.c +++ b/newlib/libc/posix/telldir.c @@ -41,6 +41,7 @@ static char sccsid[] = "@(#)telldir.c 5.9 (Berkeley) 2/23/91"; #include <dirent.h> #include <stdlib.h> #include <unistd.h> +#include <sys/lock.h> /* * The option SINGLEUSE may be defined to say that a telldir @@ -60,6 +61,7 @@ struct ddloc { long loc_index; /* key associated with structure */ long loc_seek; /* magic cookie returned by getdirentries */ long loc_loc; /* offset of entry in buffer */ + DIR *loc_dirp; /* DIR pointer */ }; #define NDIRHASH 32 /* Num of hash lists, must be a power of 2 */ @@ -67,6 +69,7 @@ struct ddloc { static long dd_loccnt; /* Index of entry for sequential readdir's */ static struct ddloc *dd_hash[NDIRHASH]; /* Hash list heads for ddlocs */ +__LOCK_INIT(static, dd_hash_lock); /* * return a pointer into a directory @@ -80,12 +83,22 @@ telldir(dirp) if ((lp = (struct ddloc *)malloc(sizeof(struct ddloc))) == NULL) return (-1); + +#ifdef HAVE_DD_LOCK + __lock_acquire_recursive(dirp->dd_lock); + __lock_acquire(dd_hash_lock); +#endif index = dd_loccnt++; lp->loc_index = index; lp->loc_seek = dirp->dd_seek; lp->loc_loc = dirp->dd_loc; + lp->loc_dirp = dirp; lp->loc_next = dd_hash[LOCHASH(index)]; dd_hash[LOCHASH(index)] = lp; +#ifdef HAVE_DD_LOCK + __lock_release(dd_hash_lock); + __lock_release_recursive(dirp->dd_lock); +#endif return (index); } @@ -103,6 +116,9 @@ _seekdir(dirp, loc) struct dirent *dp; extern long lseek(); +#ifdef HAVE_DD_LOCK + __lock_acquire(dd_hash_lock); +#endif prevlp = &dd_hash[LOCHASH(loc)]; lp = *prevlp; while (lp != NULL) { @@ -111,8 +127,12 @@ _seekdir(dirp, loc) prevlp = &lp->loc_next; lp = lp->loc_next; } - if (lp == NULL) + if (lp == NULL) { +#ifdef HAVE_DD_LOCK + __lock_release(dd_hash_lock); +#endif return; + } if (lp->loc_loc == dirp->dd_loc && lp->loc_seek == dirp->dd_seek) goto found; (void) lseek(dirp->dd_fd, lp->loc_seek, 0); @@ -128,6 +148,46 @@ found: *prevlp = lp->loc_next; free((caddr_t)lp); #endif +#ifdef HAVE_DD_LOCK + __lock_release(dd_hash_lock); +#endif } +/* clean out any hash entries from a closed directory */ +void +_cleanupdir (dirp) + register DIR *dirp; +{ + int i; + +#ifdef HAVE_DD_LOCK + __lock_acquire(dd_hash_lock); +#endif + for (i = 0; i < NDIRHASH; ++i) { + register struct ddloc *lp; + register struct ddloc *prevlp; + lp = dd_hash[i]; + while (lp != NULL && lp->loc_dirp == dirp) { + dd_hash[i] = lp->loc_next; + prevlp = lp; + free((caddr_t)lp); + lp = prevlp->loc_next; + } + prevlp = lp; + while (lp != NULL) { + lp = lp->loc_next; + if (lp != NULL && lp->loc_dirp == dirp) { + prevlp->loc_next = lp->loc_next; + free((caddr_t)lp); + lp = prevlp; + } + else + prevlp = lp; + } + } +#ifdef HAVE_DD_LOCK + __lock_release(dd_hash_lock); +#endif + +} #endif /* ! HAVE_OPENDIR */ |