diff options
| author | tonnerre <tonnerre@NetBSD.org> | 2008-05-04 18:53:26 +0000 |
|---|---|---|
| committer | tonnerre <tonnerre@NetBSD.org> | 2008-05-04 18:53:26 +0000 |
| commit | 34f7daa87e5b8edd4df282ec49cd38df9b5a830e (patch) | |
| tree | 0bf98fad4f4086da9b486ef26c315f7b98b427a7 /lib | |
| parent | dd178c786ecdf5d8f7c6d3df38323ff3f58881cb (diff) | |
Fix a bug in the implementation of seekdir(). If the first entry in
a block has been unlinked, seekdir() may overshoot by one entry.
Thus, _readdir_unlinked() must not skip deleted entries when being
called from seekdir().
Christos agreed.
Diffstat (limited to 'lib')
| -rw-r--r-- | lib/libc/compat/gen/Makefile.inc | 10 | ||||
| -rw-r--r-- | lib/libc/compat/gen/compat__readdir_unlocked30.c | 20 | ||||
| -rw-r--r-- | lib/libc/compat/include/dirent.h | 5 | ||||
| -rw-r--r-- | lib/libc/gen/dirent_private.h | 6 | ||||
| -rw-r--r-- | lib/libc/gen/readdir.c | 16 | ||||
| -rw-r--r-- | lib/libc/gen/telldir.c | 6 |
6 files changed, 42 insertions, 21 deletions
diff --git a/lib/libc/compat/gen/Makefile.inc b/lib/libc/compat/gen/Makefile.inc index a4fb36895ed..a943a5b31e8 100644 --- a/lib/libc/compat/gen/Makefile.inc +++ b/lib/libc/compat/gen/Makefile.inc @@ -1,9 +1,9 @@ -# $NetBSD: Makefile.inc,v 1.5 2006/07/27 15:46:30 christos Exp $ +# $NetBSD: Makefile.inc,v 1.6 2008/05/04 18:53:26 tonnerre Exp $ .PATH: ${COMPATDIR}/gen SRCS+=compat_errlist.c compat_fts.c compat___fts13.c compat___fts30.c \ compat___fts31.c compat_getmntinfo.c compat_glob.c compat___glob13.c \ - compat_opendir.c compat_readdir.c compat_scandir.c compat_siglist.c \ - compat_signame.c compat_sigsetops.c compat_times.c compat_timezone.c \ - compat_unvis.c compat_utmpx.c compat__sys_errlist.c compat__sys_nerr.c \ - compat__sys_siglist.c + compat_opendir.c compat_readdir.c compat__readdir_unlocked30.c \ + compat_scandir.c compat_siglist.c compat_signame.c compat_sigsetops.c \ + compat_times.c compat_timezone.c compat_unvis.c compat_utmpx.c \ + compat__sys_errlist.c compat__sys_nerr.c compat__sys_siglist.c diff --git a/lib/libc/compat/gen/compat__readdir_unlocked30.c b/lib/libc/compat/gen/compat__readdir_unlocked30.c new file mode 100644 index 00000000000..df6fe22ee70 --- /dev/null +++ b/lib/libc/compat/gen/compat__readdir_unlocked30.c @@ -0,0 +1,20 @@ +/* $NetBSD: compat__readdir_unlocked30.c,v 1.1 2008/05/04 18:53:26 tonnerre Exp $ */ + +#define __LIBC12_SOURCE__ +#include "namespace.h" +#include <dirent.h> +#include <compat/include/dirent.h> + +#ifdef __warn_references +__warn_references(___readdir_unlocked30, + "warning: reference to compatibility _readdir_unlocked(); include <dirent.h> for correct reference") +#endif + +/** + * Compat version of _readdir_unlocked which always skips directories + */ +struct dirent * +___readdir_unlocked30(DIR *dirp) +{ + return ___readdir_unlocked50(dirp, 1); +} diff --git a/lib/libc/compat/include/dirent.h b/lib/libc/compat/include/dirent.h index 60f48d3648f..4a9112dc689 100644 --- a/lib/libc/compat/include/dirent.h +++ b/lib/libc/compat/include/dirent.h @@ -1,4 +1,4 @@ -/* $NetBSD: dirent.h,v 1.5 2006/03/26 18:22:40 christos Exp $ */ +/* $NetBSD: dirent.h,v 1.6 2008/05/04 18:53:26 tonnerre Exp $ */ /*- * Copyright (c) 1989, 1993 @@ -51,7 +51,8 @@ struct dirent *__readdir30(DIR *); #if defined(_NETBSD_SOURCE) -struct dirent12 *_readdir_unlocked(DIR *); +struct dirent12 *_readdir_unlocked(DIR *, int); +struct dirent *___readdir_unlocked50(DIR *, int); struct dirent *___readdir_unlocked30(DIR *); DIR *__opendir2(const char *, int); diff --git a/lib/libc/gen/dirent_private.h b/lib/libc/gen/dirent_private.h index bb76f31c043..613df3e2b91 100644 --- a/lib/libc/gen/dirent_private.h +++ b/lib/libc/gen/dirent_private.h @@ -1,4 +1,4 @@ -/* $NetBSD: dirent_private.h,v 1.1 2006/05/17 20:36:50 christos Exp $ */ +/* $NetBSD: dirent_private.h,v 1.2 2008/05/04 18:53:26 tonnerre Exp $ */ /* * One struct _dirpos is malloced to describe the current directory @@ -17,6 +17,6 @@ void _seekdir_unlocked(struct _dirdesc *, long); long _telldir_unlocked(struct _dirdesc *); #ifndef __LIBC12_SOURCE__ struct dirent; -struct dirent *_readdir_unlocked(struct _dirdesc *) - __RENAME(___readdir_unlocked30); +struct dirent *_readdir_unlocked(struct _dirdesc *, int) + __RENAME(___readdir_unlocked50); #endif diff --git a/lib/libc/gen/readdir.c b/lib/libc/gen/readdir.c index 2b94543a4a7..1992748d9c0 100644 --- a/lib/libc/gen/readdir.c +++ b/lib/libc/gen/readdir.c @@ -1,4 +1,4 @@ -/* $NetBSD: readdir.c,v 1.23 2006/05/17 20:36:50 christos Exp $ */ +/* $NetBSD: readdir.c,v 1.24 2008/05/04 18:53:26 tonnerre Exp $ */ /* * Copyright (c) 1983, 1993 @@ -34,7 +34,7 @@ #if 0 static char sccsid[] = "@(#)readdir.c 8.3 (Berkeley) 9/29/94"; #else -__RCSID("$NetBSD: readdir.c,v 1.23 2006/05/17 20:36:50 christos Exp $"); +__RCSID("$NetBSD: readdir.c,v 1.24 2008/05/04 18:53:26 tonnerre Exp $"); #endif #endif /* LIBC_SCCS and not lint */ @@ -54,7 +54,7 @@ __RCSID("$NetBSD: readdir.c,v 1.23 2006/05/17 20:36:50 christos Exp $"); * get next entry in a directory. */ struct dirent * -_readdir_unlocked(DIR *dirp) +_readdir_unlocked(DIR *dirp, int skipdeleted) { struct dirent *dp; @@ -80,7 +80,7 @@ _readdir_unlocked(DIR *dirp) if (dp->d_reclen > dirp->dd_len + 1 - dirp->dd_loc) return (NULL); dirp->dd_loc += dp->d_reclen; - if (dp->d_ino == 0) + if (dp->d_ino == 0 && skipdeleted) continue; if (dp->d_type == DT_WHT && (dirp->dd_flags & DTF_HIDEW)) continue; @@ -97,12 +97,12 @@ readdir(dirp) #ifdef _REENTRANT if (__isthreaded) { mutex_lock((mutex_t *)dirp->dd_lock); - dp = _readdir_unlocked(dirp); + dp = _readdir_unlocked(dirp, 1); mutex_unlock((mutex_t *)dirp->dd_lock); } else #endif - dp = _readdir_unlocked(dirp); + dp = _readdir_unlocked(dirp, 1); return (dp); } @@ -120,13 +120,13 @@ readdir_r(dirp, entry, result) #ifdef _REENTRANT if (__isthreaded) { mutex_lock((mutex_t *)dirp->dd_lock); - if ((dp = _readdir_unlocked(dirp)) != NULL) + if ((dp = _readdir_unlocked(dirp, 1)) != NULL) memcpy(entry, dp, (size_t)_DIRENT_SIZE(dp)); mutex_unlock((mutex_t *)dirp->dd_lock); } else #endif - if ((dp = _readdir_unlocked(dirp)) != NULL) + if ((dp = _readdir_unlocked(dirp, 1)) != NULL) memcpy(entry, dp, (size_t)_DIRENT_SIZE(dp)); if (errno != 0) { diff --git a/lib/libc/gen/telldir.c b/lib/libc/gen/telldir.c index a25083f88a2..f631642ac2c 100644 --- a/lib/libc/gen/telldir.c +++ b/lib/libc/gen/telldir.c @@ -1,4 +1,4 @@ -/* $NetBSD: telldir.c,v 1.18 2006/05/17 20:36:50 christos Exp $ */ +/* $NetBSD: telldir.c,v 1.19 2008/05/04 18:53:26 tonnerre Exp $ */ /* * Copyright (c) 1983, 1993 @@ -34,7 +34,7 @@ #if 0 static char sccsid[] = "@(#)telldir.c 8.1 (Berkeley) 6/4/93"; #else -__RCSID("$NetBSD: telldir.c,v 1.18 2006/05/17 20:36:50 christos Exp $"); +__RCSID("$NetBSD: telldir.c,v 1.19 2008/05/04 18:53:26 tonnerre Exp $"); #endif #endif /* LIBC_SCCS and not lint */ @@ -117,6 +117,6 @@ _seekdir_unlocked(DIR *dirp, long loc) dirp->dd_seek = lseek(dirp->dd_fd, lp->dp_seek, SEEK_SET); dirp->dd_loc = 0; while (dirp->dd_loc < lp->dp_loc) - if (_readdir_unlocked(dirp) == NULL) + if (_readdir_unlocked(dirp, 0) == NULL) break; } |
