diff options
author | Okan Demirmen <okan@cvs.openbsd.org> | 2008-04-04 21:26:08 +0000 |
---|---|---|
committer | Okan Demirmen <okan@cvs.openbsd.org> | 2008-04-04 21:26:08 +0000 |
commit | 77b01758cdd4f3d22af1ad0d6b43c6d9f86ef5c5 (patch) | |
tree | a94b57f618bc11d613fb35404fcedf9e86975320 /lib/libc/gen/readdir.c | |
parent | 2419060533a4e33e9985400be7adb6ab4ce3263b (diff) |
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/gen/readdir.c')
-rw-r--r-- | lib/libc/gen/readdir.c | 33 |
1 files changed, 18 insertions, 15 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; |