summaryrefslogtreecommitdiffstats
path: root/lib/libc
diff options
context:
space:
mode:
authorokan <okan@openbsd.org>2008-04-04 21:26:07 +0000
committerokan <okan@openbsd.org>2008-04-04 21:26:07 +0000
commitb1daa819cf516d73d3d1cb84b75ec79adc9e39ef (patch)
treec01df79e22d109db38761d65856e0689bc11239a /lib/libc
parent- do not call pthread_atfork(3) handlers when a multithreaded program (diff)
downloadwireguard-openbsd-b1daa819cf516d73d3d1cb84b75ec79adc9e39ef.tar.xz
wireguard-openbsd-b1daa819cf516d73d3d1cb84b75ec79adc9e39ef.zip
alter internal _readdir_unlocked() api to be less confusing, so that
callers may respond accordingly and correctly. this fixes an issue where readdir_r() could not decipher the difference between an error or no more entires. feedback and ok kurt@, ok millert@
Diffstat (limited to 'lib/libc')
-rw-r--r--lib/libc/gen/readdir.c33
-rw-r--r--lib/libc/gen/telldir.c6
2 files changed, 21 insertions, 18 deletions
diff --git a/lib/libc/gen/readdir.c b/lib/libc/gen/readdir.c
index 5f4c447e576..577a51a0995 100644
--- a/lib/libc/gen/readdir.c
+++ b/lib/libc/gen/readdir.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: readdir.c,v 1.12 2007/06/05 18:11:48 kurt Exp $ */
+/* $OpenBSD: readdir.c,v 1.13 2008/04/04 21:26:07 okan Exp $ */
/*
* Copyright (c) 1983, 1993
* The Regents of the University of California. All rights reserved.
@@ -37,31 +37,34 @@
/*
* get next entry in a directory.
*/
-struct dirent *
-_readdir_unlocked(DIR *dirp)
+int
+_readdir_unlocked(DIR *dirp, struct dirent **result)
{
struct dirent *dp;
+ *result = NULL;
for (;;) {
- if (dirp->dd_loc >= dirp->dd_size) {
+ if (dirp->dd_loc >= dirp->dd_size)
dirp->dd_loc = 0;
- }
if (dirp->dd_loc == 0) {
dirp->dd_size = getdirentries(dirp->dd_fd,
dirp->dd_buf, dirp->dd_len, &dirp->dd_seek);
- if (dirp->dd_size <= 0)
- return (NULL);
+ if (dirp->dd_size == 0)
+ return (0);
+ if (dirp->dd_size < 0)
+ return (-1);
}
dp = (struct dirent *)(dirp->dd_buf + dirp->dd_loc);
if ((long)dp & 03) /* bogus pointer check */
- return (NULL);
+ return (-1);
if (dp->d_reclen <= 0 ||
dp->d_reclen > dirp->dd_len + 1 - dirp->dd_loc)
- return (NULL);
+ return (-1);
dirp->dd_loc += dp->d_reclen;
if (dp->d_ino == 0)
continue;
- return (dp);
+ *result = dp;
+ return (0);
}
}
@@ -71,7 +74,7 @@ readdir(DIR *dirp)
struct dirent *dp;
_MUTEX_LOCK(&dirp->dd_lock);
- dp = _readdir_unlocked(dirp);
+ _readdir_unlocked(dirp, &dp);
_MUTEX_UNLOCK(&dirp->dd_lock);
return (dp);
@@ -83,13 +86,13 @@ readdir_r(DIR *dirp, struct dirent *entry, struct dirent **result)
struct dirent *dp;
_MUTEX_LOCK(&dirp->dd_lock);
- dp = _readdir_unlocked(dirp);
- if (dp == NULL && errno != 0) {
+ if (_readdir_unlocked(dirp, &dp) != 0) {
_MUTEX_UNLOCK(&dirp->dd_lock);
return errno;
}
- if (dp != NULL)
- memcpy(entry, dp, sizeof (struct dirent) - MAXNAMLEN + dp->d_namlen);
+ if (dp != NULL)
+ memcpy(entry, dp,
+ sizeof (struct dirent) - MAXNAMLEN + dp->d_namlen);
_MUTEX_UNLOCK(&dirp->dd_lock);
if (dp != NULL)
*result = entry;
diff --git a/lib/libc/gen/telldir.c b/lib/libc/gen/telldir.c
index cc9761c92f8..57829a2af43 100644
--- a/lib/libc/gen/telldir.c
+++ b/lib/libc/gen/telldir.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: telldir.c,v 1.11 2007/10/02 16:14:58 kurt Exp $ */
+/* $OpenBSD: telldir.c,v 1.12 2008/04/04 21:26:07 okan 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"
-struct dirent *_readdir_unlocked(DIR *);
+int _readdir_unlocked(DIR *, struct dirent **);
/*
* 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) {
- dp = _readdir_unlocked(dirp);
+ _readdir_unlocked(dirp, &dp);
if (dp == NULL)
break;
}