summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authortonnerre <tonnerre@NetBSD.org>2008-05-04 18:53:26 +0000
committertonnerre <tonnerre@NetBSD.org>2008-05-04 18:53:26 +0000
commit34f7daa87e5b8edd4df282ec49cd38df9b5a830e (patch)
tree0bf98fad4f4086da9b486ef26c315f7b98b427a7 /lib
parentdd178c786ecdf5d8f7c6d3df38323ff3f58881cb (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.inc10
-rw-r--r--lib/libc/compat/gen/compat__readdir_unlocked30.c20
-rw-r--r--lib/libc/compat/include/dirent.h5
-rw-r--r--lib/libc/gen/dirent_private.h6
-rw-r--r--lib/libc/gen/readdir.c16
-rw-r--r--lib/libc/gen/telldir.c6
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;
}