FreeBSD Bugzilla – Attachment 85456 Details for
Bug 121656
[libc] [patch] telldir(3) issues
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Help
|
New Account
|
Log In
Remember
[x]
|
Forgot Password
Login:
[x]
file.shar
file.shar (text/plain), 12.81 KB, created by
Gary Stanley
on 2008-03-13 01:10:01 UTC
(
hide
)
Description:
file.shar
Filename:
MIME Type:
Creator:
Gary Stanley
Created:
2008-03-13 01:10:01 UTC
Size:
12.81 KB
patch
obsolete
># This is a shell archive. Save it in a file, remove anything before ># this line, and then unpack it by entering "sh file". Note, it may ># create directories; files and directories will be owned by you and ># have default permissions. ># ># This archive contains: ># ># . ># ./telldir-memuse.c ># ./libc.diff ># ./seekdir-twice.c ># >echo c - . >mkdir -p . > /dev/null 2>&1 >echo x - ./telldir-memuse.c >sed 's/^X//' >./telldir-memuse.c << 'END-of-./telldir-memuse.c' >X#include <stdlib.h> >X#include <unistd.h> >X#include <dirent.h> >X#include <err.h> >X >X >Xint main(void) { >X DIR *dp; >X long loc; >X void *memused; >X int i; >X int oktouse = 4096; >X >X dp = opendir("."); >X if (dp == NULL) >X err(EXIT_FAILURE, "Could not open current directory"); >X loc = telldir(dp); >X memused = sbrk(0); >X closedir(dp); >X >X for (i=0; i<1000; i++) { >X dp = opendir("."); >X if (dp == NULL) >X err(EXIT_FAILURE, "Could not open current directory"); >X loc = telldir(dp); >X closedir(dp); >X >X if (sbrk(0) - memused > oktouse) { >X warnx("Used %d extra bytes for %d telldir calls", >X (sbrk(0)-memused), i); >X oktouse = sbrk(0) - memused; >X } >X } >X if (oktouse > 4096) { >X errx(EXIT_FAILURE, "Failure: leaked %d bytes", oktouse); >X } else { >X printf("OK: used %d bytes\n", sbrk(0)-memused); >X } >X return 0; >X} >END-of-./telldir-memuse.c >echo x - ./libc.diff >sed 's/^X//' >./libc.diff << 'END-of-./libc.diff' >X--- include/dirent.h.old 2003-12-07 15:10:06.000000000 -0600 >X+++ include/dirent.h 2008-03-12 19:31:09.000000000 -0500 >X@@ -69,7 +69,7 @@ >X char *dd_buf; /* data buffer */ >X int dd_len; /* size of data buffer */ >X long dd_seek; /* magic cookie returned by getdirentries */ >X- long dd_rewind; /* magic cookie for rewinding */ >X+ void *dd_internal; /* state for seekdir/telldir */ >X int dd_flags; /* flags for readdir */ >X void *dd_lock; /* hack to avoid including <pthread.h> */ >X struct _telldir *dd_td; /* telldir position recording */ >Xdiff -u -r -N lib/libc.old/gen/closedir.c lib/libc/gen/closedir.c >X--- lib/libc.old/gen/closedir.c 2007-01-08 18:27:53.000000000 -0600 >X+++ lib/libc/gen/closedir.c 2008-03-12 19:22:10.000000000 -0500 >X@@ -43,24 +43,31 @@ >X >X #include "libc_private.h" >X #include "telldir.h" >X+#include "dirent_private.h" >X >X /* >X * close a directory. >X */ >X int >X-closedir(dirp) >X- DIR *dirp; >X+closedir(DIR *dirp) >X { >X int fd; >X+ struct dirpos *poslist; >X >X if (__isthreaded) >X _pthread_mutex_lock((pthread_mutex_t *)&dirp->dd_lock); >X- _seekdir(dirp, dirp->dd_rewind); /* free seekdir storage */ >X fd = dirp->dd_fd; >X dirp->dd_fd = -1; >X dirp->dd_loc = 0; >X- free((void *)dirp->dd_buf); >X- _reclaim_telldir(dirp); >X+ free(dirp->dd_buf); >X+ >X+ /* free seekdir/telldir storage */ >X+ for (poslist = dirp->dd_internal; poslist; ) { >X+ struct dirpos *nextpos = poslist->dp_next; >X+ free(poslist); >X+ poslist = nextpos; >X+ } >X+ >X if (__isthreaded) { >X _pthread_mutex_unlock((pthread_mutex_t *)&dirp->dd_lock); >X _pthread_mutex_destroy((pthread_mutex_t *)&dirp->dd_lock); >Xdiff -u -r -N lib/libc.old/gen/dirent_private.h lib/libc/gen/dirent_private.h >X--- lib/libc.old/gen/dirent_private.h 1969-12-31 18:00:00.000000000 -0600 >X+++ lib/libc/gen/dirent_private.h 2008-03-12 19:22:10.000000000 -0500 >X@@ -0,0 +1,17 @@ >X+/* $NetBSD: dirent_private.h,v 1.1 2006/05/17 20:36:50 christos Exp $ */ >X+ >X+/* >X+ * One struct _dirpos is malloced to describe the current directory >X+ * position each time telldir is called. It records the current magic >X+ * cookie returned by getdirentries and the offset within the buffer >X+ * associated with that return value. >X+ */ >X+struct dirpos { >X+ struct dirpos *dp_next; /* next structure in list */ >X+ off_t dp_seek; /* magic cookie returned by getdirentries */ >X+ long dp_loc; /* offset of entry in buffer */ >X+}; >X+ >X+struct _dirdesc; >X+void _seekdir_unlocked(struct _dirdesc *, long); >X+long _telldir_unlocked(struct _dirdesc *); >Xdiff -u -r -N lib/libc.old/gen/opendir.c lib/libc/gen/opendir.c >X--- lib/libc.old/gen/opendir.c 2007-01-08 18:27:54.000000000 -0600 >X+++ lib/libc/gen/opendir.c 2008-03-12 19:22:10.000000000 -0500 >X@@ -47,21 +47,20 @@ >X #include "un-namespace.h" >X >X #include "telldir.h" >X+#include "dirent_private.h" >X+ >X /* >X * Open a directory. >X */ >X DIR * >X-opendir(name) >X- const char *name; >X+opendir(const char *name) >X { >X >X return (__opendir2(name, DTF_HIDEW|DTF_NODUP)); >X } >X >X DIR * >X-__opendir2(name, flags) >X- const char *name; >X- int flags; >X+__opendir2(const char *name, int flags) >X { >X DIR *dirp; >X int fd; >X@@ -270,7 +269,8 @@ >X /* >X * Set up seek point for rewinddir. >X */ >X- dirp->dd_rewind = telldir(dirp); >X+ dirp->dd_internal = NULL; >X+ (void)telldir(dirp); >X >X return (dirp); >X >Xdiff -u -r -N lib/libc.old/gen/readdir.c lib/libc/gen/readdir.c >X--- lib/libc.old/gen/readdir.c 2007-01-08 18:27:55.000000000 -0600 >X+++ lib/libc/gen/readdir.c 2008-03-12 19:22:10.000000000 -0500 >X@@ -43,6 +43,7 @@ >X >X #include "libc_private.h" >X #include "telldir.h" >X+#include "dirent_private.h" >X >X /* >X * get next entry in a directory. >Xdiff -u -r -N lib/libc.old/gen/rewinddir.c lib/libc/gen/rewinddir.c >X--- lib/libc.old/gen/rewinddir.c 2007-01-08 18:27:55.000000000 -0600 >X+++ lib/libc/gen/rewinddir.c 2008-03-12 19:22:10.000000000 -0500 >X@@ -37,12 +37,16 @@ >X #include <dirent.h> >X >X #include "telldir.h" >X+#include "dirent_private.h" >X >X void >X-rewinddir(dirp) >X- DIR *dirp; >X+rewinddir(DIR *dirp) >X { >X >X- _seekdir(dirp, dirp->dd_rewind); >X- dirp->dd_rewind = telldir(dirp); >X+ struct dirpos *dp = dirp->dd_internal; >X+ >X+ while (dp->dp_next) >X+ dp = dp->dp_next; >X+ >X+ _seekdir(dirp, (long)(intptr_t)dp); >X } >Xdiff -u -r -N lib/libc.old/gen/seekdir.c lib/libc/gen/seekdir.c >X--- lib/libc.old/gen/seekdir.c 2007-01-08 18:27:55.000000000 -0600 >X+++ lib/libc/gen/seekdir.c 2008-03-12 19:22:10.000000000 -0500 >X@@ -41,15 +41,14 @@ >X >X #include "libc_private.h" >X #include "telldir.h" >X+#include "dirent_private.h" >X >X /* >X * Seek to an entry in a directory. >X * _seekdir is in telldir.c so that it can share opaque data structures. >X */ >X void >X-seekdir(dirp, loc) >X- DIR *dirp; >X- long loc; >X+seekdir(DIR *dirp, long loc) >X { >X if (__isthreaded) >X _pthread_mutex_lock((pthread_mutex_t *)&dirp->dd_lock); >Xdiff -u -r -N lib/libc.old/gen/telldir.c lib/libc/gen/telldir.c >X--- lib/libc.old/gen/telldir.c 2007-01-08 18:27:55.000000000 -0600 >X+++ lib/libc/gen/telldir.c 2008-03-12 19:22:56.000000000 -0500 >X@@ -45,33 +45,30 @@ >X #include "libc_private.h" >X #include "telldir.h" >X >X-/* >X- * The option SINGLEUSE may be defined to say that a telldir >X- * cookie may be used only once before it is freed. This option >X- * is used to avoid having memory usage grow without bound. >X- */ >X-#define SINGLEUSE >X+#include "dirent_private.h" >X >X /* >X * return a pointer into a directory >X */ >X long >X-telldir(dirp) >X- DIR *dirp; >X+telldir(DIR *dirp) >X { >X- struct ddloc *lp; >X+ struct dirpos *lp; >X >X- if ((lp = (struct ddloc *)malloc(sizeof(struct ddloc))) == NULL) >X+ for (lp = dirp->dd_internal; lp; lp = lp->dp_next) >X+ if (lp->dp_seek == dirp->dd_seek && >X+ lp->dp_loc == dirp->dd_loc) >X+ return (intptr_t)lp; >X+ if ((lp = malloc(sizeof(*lp))) == NULL) >X return (-1); >X- if (__isthreaded) >X- _pthread_mutex_lock((pthread_mutex_t *)&dirp->dd_lock); >X- lp->loc_index = dirp->dd_td->td_loccnt++; >X- lp->loc_seek = dirp->dd_seek; >X- lp->loc_loc = dirp->dd_loc; >X- LIST_INSERT_HEAD(&dirp->dd_td->td_locq, lp, loc_lqe); >X- if (__isthreaded) >X- _pthread_mutex_unlock((pthread_mutex_t *)&dirp->dd_lock); >X- return (lp->loc_index); >X+ >X+ lp->dp_seek = dirp->dd_seek; >X+ lp->dp_loc = dirp->dd_loc; >X+ lp->dp_next = dirp->dd_internal; >X+ dirp->dd_internal = lp; >X+ >X+ return (intptr_t)lp; >X+ >X } >X >X /* >X@@ -79,51 +76,23 @@ >X * Only values returned by "telldir" should be passed to seekdir. >X */ >X void >X-_seekdir(dirp, loc) >X- DIR *dirp; >X- long loc; >X+_seekdir(DIR *dirp, long loc) >X { >X- struct ddloc *lp; >X- struct dirent *dp; >X- >X- LIST_FOREACH(lp, &dirp->dd_td->td_locq, loc_lqe) { >X- if (lp->loc_index == loc) >X+ struct dirpos *lp; >X+ for (lp = dirp->dd_internal; lp; lp = lp->dp_next) >X+ if ((intptr_t)lp == loc) >X break; >X- } >X+ >X if (lp == NULL) >X return; >X- if (lp->loc_loc == dirp->dd_loc && lp->loc_seek == dirp->dd_seek) >X- goto found; >X- (void) lseek(dirp->dd_fd, (off_t)lp->loc_seek, SEEK_SET); >X- dirp->dd_seek = lp->loc_seek; >X- dirp->dd_loc = 0; >X- while (dirp->dd_loc < lp->loc_loc) { >X- dp = _readdir_unlocked(dirp); >X- if (dp == NULL) >X- break; >X- } >X-found: >X-#ifdef SINGLEUSE >X- LIST_REMOVE(lp, loc_lqe); >X- free((caddr_t)lp); >X-#endif >X-} >X >X-/* >X- * Reclaim memory for telldir cookies which weren't used. >X- */ >X-void >X-_reclaim_telldir(dirp) >X- DIR *dirp; >X-{ >X- struct ddloc *lp; >X- struct ddloc *templp; >X+ if (lp->dp_loc == dirp->dd_loc && lp->dp_seek == dirp->dd_seek) >X+ return; >X >X- lp = LIST_FIRST(&dirp->dd_td->td_locq); >X- while (lp != NULL) { >X- templp = lp; >X- lp = LIST_NEXT(lp, loc_lqe); >X- free(templp); >X- } >X- LIST_INIT(&dirp->dd_td->td_locq); >X+ dirp->dd_seek = lseek(dirp->dd_fd, lp->dp_seek, SEEK_SET); >X+ dirp->dd_loc = 0; >X+ while (dirp->dd_loc < lp->dp_loc) >X+ if (_readdir_unlocked(dirp) == NULL) >X+ break; >X+ >X } >Xdiff -u -r -N lib/libc.old/gen/telldir.h lib/libc/gen/telldir.h >X--- lib/libc.old/gen/telldir.h 2001-01-24 06:59:24.000000000 -0600 >X+++ lib/libc/gen/telldir.h 2008-03-12 19:22:10.000000000 -0500 >X@@ -38,19 +38,6 @@ >X #include <sys/queue.h> >X >X /* >X- * One of these structures is malloced to describe the current directory >X- * position each time telldir is called. It records the current magic >X- * cookie returned by getdirentries and the offset within the buffer >X- * associated with that return value. >X- */ >X-struct ddloc { >X- LIST_ENTRY(ddloc) loc_lqe; /* entry in list */ >X- long loc_index; /* key associated with structure */ >X- long loc_seek; /* magic cookie returned by getdirentries */ >X- long loc_loc; /* offset of entry in buffer */ >X-}; >X- >X-/* >X * One of these structures is malloced for each DIR to record telldir >X * positions. >X */ >END-of-./libc.diff >echo x - ./seekdir-twice.c >sed 's/^X//' >./seekdir-twice.c << 'END-of-./seekdir-twice.c' >X#include <stdio.h> >X#include <string.h> >X#include <dirent.h> >X#include <sys/stat.h> >X >Xint main(void) { >X DIR *dp; >X >X mkdir("t", 0755); >X creat("t/a", 0600); >X creat("t/b", 0600); >X creat("t/c", 0600); >X >X if (dp = opendir("t")) { >X char *wasname; >X struct dirent *entry; >X long here; >X >X /* skip two */ >X entry = readdir(dp); >X entry = readdir(dp); >X entry = readdir(dp); >X printf("first found: %s\n", entry->d_name); >X >X here = telldir(dp); >X printf("pos returned by telldir: %d\n", here); >X entry = readdir(dp); >X printf("second found: %s\n", entry->d_name); >X >X wasname = strdup(entry->d_name); >X entry = readdir(dp); >X printf("third found: %s\n", entry->d_name); >X >X seekdir(dp, here); >X entry = readdir(dp); >X printf("should be == second: %s\n", entry->d_name); >X >X printf("pos given to seekdir: %d\n", here); >X seekdir(dp, here); >X here = telldir(dp); >X printf("pos returned by telldir: %d\n", here); >X >X entry = readdir(dp); >X printf("should be == second: %s\n", entry->d_name); >X >X seekdir(dp, here); >X entry = readdir(dp); >X printf("should be == second: %s\n", entry->d_name); >X >X closedir(dp); >X } >X return 0; >X} >END-of-./seekdir-twice.c >exit
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Raw
Actions:
View
Attachments on
bug 121656
: 85456