diff options
Diffstat (limited to 'sysdeps/unix/sysv/linux/readdir.c')
-rw-r--r-- | sysdeps/unix/sysv/linux/readdir.c | 65 |
1 files changed, 64 insertions, 1 deletions
diff --git a/sysdeps/unix/sysv/linux/readdir.c b/sysdeps/unix/sysv/linux/readdir.c index df7a92aa78..2e03e66e69 100644 --- a/sysdeps/unix/sysv/linux/readdir.c +++ b/sysdeps/unix/sysv/linux/readdir.c @@ -19,5 +19,68 @@ #include <dirent.h> #if !_DIRENT_MATCHES_DIRENT64 -# include <sysdeps/posix/readdir.c> +#include <dirstream.h> + +/* Read a directory entry from DIRP. */ +struct dirent * +__readdir (DIR *dirp) +{ + struct dirent *dp; + int saved_errno = errno; + +#if IS_IN (libc) + __libc_lock_lock (dirp->lock); +#endif + + do + { + size_t reclen; + + if (dirp->offset >= dirp->size) + { + /* We've emptied out our buffer. Refill it. */ + + size_t maxread = dirp->allocation; + ssize_t bytes; + + bytes = __getdents (dirp->fd, dirp->data, maxread); + if (bytes <= 0) + { + /* On some systems getdents fails with ENOENT when the + open directory has been rmdir'd already. POSIX.1 + requires that we treat this condition like normal EOF. */ + if (bytes < 0 && errno == ENOENT) + bytes = 0; + + /* Don't modifiy errno when reaching EOF. */ + if (bytes == 0) + __set_errno (saved_errno); + dp = NULL; + break; + } + dirp->size = (size_t) bytes; + + /* Reset the offset into the buffer. */ + dirp->offset = 0; + } + + dp = (struct dirent *) &dirp->data[dirp->offset]; + + reclen = dp->d_reclen; + + dirp->offset += reclen; + + dirp->filepos = dp->d_off; + + /* Skip deleted files. */ + } while (dp->d_ino == 0); + +#if IS_IN (libc) + __libc_lock_unlock (dirp->lock); +#endif + + return dp; +} +weak_alias (__readdir, readdir) + #endif |