If rewinddir(3) is called before the end of the directory was reached
with readdir(3), subsequent calls to readdir() will return entries
cached in the buffer, so any changes to the directory from before
rewinddir() was called will not be reflected.
Example:
DIR *dir = opendir("/tmp/empty");
struct dirent *dp;
FILE *fd;
int i;
for (i = 0; i < 2; i++) {
dp = readdir(dir);
printf("%s\n", dp->d_name);
}
fd = fopen("/tmp/empty/newfile", "w");
fclose(fd);
rewinddir(dir);
while ((dp = readdir(dir)))
printf("%s\n", dp->d_name);
Outputs (where /tmp/empty is an empty directory):
.
..
.
..
ie. "newfile" was created before the rewinddir() call but is not
returned by readdir().
My understanding of the spec is that it should be:
IEEE Std 1003.1-2008 rewinddir
"The rewinddir() function shall reset the position of the
directory stream to which dirp refers to the beginning of the
directory. It shall also cause the directory stream to refer to
the current state of the corresponding directory, as a call to
opendir() would have done. [...]"
Possible fix:
Index: lib/libc/gen/rewinddir.c
===================================================================
RCS file: /cvs/src/lib/libc/gen/rewinddir.c,v
retrieving revision 1.11
diff -u -p -u -r1.11 rewinddir.c
--- lib/libc/gen/rewinddir.c 5 Nov 2013 20:36:51 -0000 1.11
+++ lib/libc/gen/rewinddir.c 4 Jul 2016 22:22:22 -0000
@@ -35,5 +35,8 @@
void
rewinddir(DIR *dirp)
{
- seekdir(dirp, 0);
+ _MUTEX_LOCK(&dirp->dd_lock);
+ dirp->dd_loc = dirp->dd_size;
+ dirp->dd_bufpos = dirp->dd_curpos = lseek(dirp->dd_fd, 0, SEEK_SET);
+ _MUTEX_UNLOCK(&dirp->dd_lock);
}