diff options
author | Otto Moerbeek <otto@cvs.openbsd.org> | 2008-05-01 19:49:19 +0000 |
---|---|---|
committer | Otto Moerbeek <otto@cvs.openbsd.org> | 2008-05-01 19:49:19 +0000 |
commit | a889b94e4da0d0640d5168711d6a48c3ce71085e (patch) | |
tree | 0bccdaeaee6eb855d6d969970a2ff0bf03456d94 /lib/libc/gen | |
parent | 6cc9e5d5f4b3fce118d0b0c004269fe7c9a9d12d (diff) |
Be carefull not to read away the target entry when encountering
deleted files after a seekdir(); testcase produced by mbalmer@; fix
with and ok mbalmer; ok millert@
Diffstat (limited to 'lib/libc/gen')
-rw-r--r-- | lib/libc/gen/readdir.c | 16 | ||||
-rw-r--r-- | lib/libc/gen/telldir.c | 6 |
2 files changed, 14 insertions, 8 deletions
diff --git a/lib/libc/gen/readdir.c b/lib/libc/gen/readdir.c index 577a51a0995..cd6c046549c 100644 --- a/lib/libc/gen/readdir.c +++ b/lib/libc/gen/readdir.c @@ -1,4 +1,4 @@ -/* $OpenBSD: readdir.c,v 1.13 2008/04/04 21:26:07 okan Exp $ */ +/* $OpenBSD: readdir.c,v 1.14 2008/05/01 19:49:18 otto Exp $ */ /* * Copyright (c) 1983, 1993 * The Regents of the University of California. All rights reserved. @@ -38,7 +38,7 @@ * get next entry in a directory. */ int -_readdir_unlocked(DIR *dirp, struct dirent **result) +_readdir_unlocked(DIR *dirp, struct dirent **result, int skipdeleted) { struct dirent *dp; @@ -61,7 +61,13 @@ _readdir_unlocked(DIR *dirp, struct dirent **result) dp->d_reclen > dirp->dd_len + 1 - dirp->dd_loc) return (-1); dirp->dd_loc += dp->d_reclen; - if (dp->d_ino == 0) + /* + * When called from seekdir(), we let it decide on + * the end condition to avoid overshooting: the next + * readdir call should produce the next non-deleted entry, + * and we already advanced dd_loc. + */ + if (dp->d_ino == 0 && skipdeleted) continue; *result = dp; return (0); @@ -74,7 +80,7 @@ readdir(DIR *dirp) struct dirent *dp; _MUTEX_LOCK(&dirp->dd_lock); - _readdir_unlocked(dirp, &dp); + _readdir_unlocked(dirp, &dp, 1); _MUTEX_UNLOCK(&dirp->dd_lock); return (dp); @@ -86,7 +92,7 @@ readdir_r(DIR *dirp, struct dirent *entry, struct dirent **result) struct dirent *dp; _MUTEX_LOCK(&dirp->dd_lock); - if (_readdir_unlocked(dirp, &dp) != 0) { + if (_readdir_unlocked(dirp, &dp, 1) != 0) { _MUTEX_UNLOCK(&dirp->dd_lock); return errno; } diff --git a/lib/libc/gen/telldir.c b/lib/libc/gen/telldir.c index 57829a2af43..5ffdfc1a6a9 100644 --- a/lib/libc/gen/telldir.c +++ b/lib/libc/gen/telldir.c @@ -1,4 +1,4 @@ -/* $OpenBSD: telldir.c,v 1.12 2008/04/04 21:26:07 okan Exp $ */ +/* $OpenBSD: telldir.c,v 1.13 2008/05/01 19:49:18 otto Exp $ */ /* * Copyright (c) 1983, 1993 * The Regents of the University of California. All rights reserved. @@ -37,7 +37,7 @@ #include "thread_private.h" #include "telldir.h" -int _readdir_unlocked(DIR *, struct dirent **); +int _readdir_unlocked(DIR *, struct dirent **, int); /* * return a pointer into a directory @@ -109,7 +109,7 @@ __seekdir(DIR *dirp, long loc) dirp->dd_seek = lp->loc_seek; dirp->dd_loc = 0; while (dirp->dd_loc < lp->loc_loc) { - _readdir_unlocked(dirp, &dp); + _readdir_unlocked(dirp, &dp, 0); if (dp == NULL) break; } |