Changeset View
Changeset View
Standalone View
Standalone View
head/lib/libc/gen/readdir.c
Show First 20 Lines • Show All 43 Lines • ▼ Show 20 Lines | |||||
#include "libc_private.h" | #include "libc_private.h" | ||||
#include "gen-private.h" | #include "gen-private.h" | ||||
#include "telldir.h" | #include "telldir.h" | ||||
/* | /* | ||||
* get next entry in a directory. | * get next entry in a directory. | ||||
*/ | */ | ||||
struct dirent * | struct dirent * | ||||
_readdir_unlocked(DIR *dirp, int skip) | _readdir_unlocked(DIR *dirp, int flags) | ||||
{ | { | ||||
struct dirent *dp; | struct dirent *dp; | ||||
long initial_seek; | long initial_seek; | ||||
long initial_loc = 0; | long initial_loc = 0; | ||||
for (;;) { | for (;;) { | ||||
if (dirp->dd_loc >= dirp->dd_size) { | if (dirp->dd_loc >= dirp->dd_size) { | ||||
if (dirp->dd_flags & __DTF_READALL) | if (dirp->dd_flags & __DTF_READALL) | ||||
Show All 14 Lines | for (;;) { | ||||
dirp->dd_flags &= ~__DTF_SKIPREAD; | dirp->dd_flags &= ~__DTF_SKIPREAD; | ||||
dp = (struct dirent *)(dirp->dd_buf + dirp->dd_loc); | dp = (struct dirent *)(dirp->dd_buf + dirp->dd_loc); | ||||
if ((long)dp & 03L) /* bogus pointer check */ | if ((long)dp & 03L) /* bogus pointer check */ | ||||
return (NULL); | return (NULL); | ||||
if (dp->d_reclen <= 0 || | if (dp->d_reclen <= 0 || | ||||
dp->d_reclen > dirp->dd_len + 1 - dirp->dd_loc) | dp->d_reclen > dirp->dd_len + 1 - dirp->dd_loc) | ||||
return (NULL); | return (NULL); | ||||
dirp->dd_loc += dp->d_reclen; | dirp->dd_loc += dp->d_reclen; | ||||
if (dp->d_ino == 0 && skip) | if (dp->d_ino == 0 && (flags & RDU_SKIP) != 0) | ||||
continue; | continue; | ||||
if (dp->d_type == DT_WHT && (dirp->dd_flags & DTF_HIDEW)) | if (dp->d_type == DT_WHT && (dirp->dd_flags & DTF_HIDEW)) | ||||
continue; | continue; | ||||
if (dp->d_namlen >= sizeof(dp->d_name) && | |||||
(flags & RDU_SHORT) != 0) | |||||
continue; | |||||
return (dp); | return (dp); | ||||
} | } | ||||
} | } | ||||
struct dirent * | struct dirent * | ||||
readdir(DIR *dirp) | readdir(DIR *dirp) | ||||
{ | { | ||||
struct dirent *dp; | struct dirent *dp; | ||||
if (__isthreaded) { | if (__isthreaded) | ||||
_pthread_mutex_lock(&dirp->dd_lock); | _pthread_mutex_lock(&dirp->dd_lock); | ||||
dp = _readdir_unlocked(dirp, 1); | dp = _readdir_unlocked(dirp, RDU_SKIP); | ||||
if (__isthreaded) | |||||
_pthread_mutex_unlock(&dirp->dd_lock); | _pthread_mutex_unlock(&dirp->dd_lock); | ||||
} | |||||
else | |||||
dp = _readdir_unlocked(dirp, 1); | |||||
return (dp); | return (dp); | ||||
} | } | ||||
int | int | ||||
readdir_r(DIR *dirp, struct dirent *entry, struct dirent **result) | __readdir_r(DIR *dirp, struct dirent *entry, struct dirent **result) | ||||
{ | { | ||||
struct dirent *dp; | struct dirent *dp; | ||||
int saved_errno; | int saved_errno; | ||||
saved_errno = errno; | saved_errno = errno; | ||||
errno = 0; | errno = 0; | ||||
if (__isthreaded) { | if (__isthreaded) | ||||
_pthread_mutex_lock(&dirp->dd_lock); | _pthread_mutex_lock(&dirp->dd_lock); | ||||
if ((dp = _readdir_unlocked(dirp, 1)) != NULL) | dp = _readdir_unlocked(dirp, RDU_SKIP | RDU_SHORT); | ||||
if (dp != NULL) | |||||
memcpy(entry, dp, _GENERIC_DIRSIZ(dp)); | memcpy(entry, dp, _GENERIC_DIRSIZ(dp)); | ||||
if (__isthreaded) | |||||
_pthread_mutex_unlock(&dirp->dd_lock); | _pthread_mutex_unlock(&dirp->dd_lock); | ||||
} | |||||
else if ((dp = _readdir_unlocked(dirp, 1)) != NULL) | |||||
memcpy(entry, dp, _GENERIC_DIRSIZ(dp)); | |||||
if (errno != 0) { | if (errno != 0) { | ||||
if (dp == NULL) | if (dp == NULL) | ||||
return (errno); | return (errno); | ||||
} else | } else | ||||
errno = saved_errno; | errno = saved_errno; | ||||
if (dp != NULL) | if (dp != NULL) | ||||
*result = entry; | *result = entry; | ||||
else | else | ||||
*result = NULL; | *result = NULL; | ||||
return (0); | return (0); | ||||
} | } | ||||
__strong_reference(__readdir_r, readdir_r); |