diff options
Diffstat (limited to 'libc/misc')
-rw-r--r-- | libc/misc/dirent/Makefile | 3 | ||||
-rw-r--r-- | libc/misc/dirent/readdir64_r.c | 79 |
2 files changed, 81 insertions, 1 deletions
diff --git a/libc/misc/dirent/Makefile b/libc/misc/dirent/Makefile index d50cdb520..c3dc95a8f 100644 --- a/libc/misc/dirent/Makefile +++ b/libc/misc/dirent/Makefile @@ -25,7 +25,8 @@ TOPDIR=../../../ include $(TOPDIR)Rules.mak CSRC=alphasort.c closedir.c dirfd.c opendir.c readdir.c rewinddir.c scandir.c \ - seekdir.c telldir.c readdir64.c alphasort64.c scandir64.c readdir_r.c + seekdir.c telldir.c readdir64.c alphasort64.c scandir64.c readdir_r.c \ + readdir64_r.c COBJS=$(patsubst %.c,%.o, $(CSRC)) OBJS=$(COBJS) diff --git a/libc/misc/dirent/readdir64_r.c b/libc/misc/dirent/readdir64_r.c new file mode 100644 index 000000000..6735db8d8 --- /dev/null +++ b/libc/misc/dirent/readdir64_r.c @@ -0,0 +1,79 @@ +#include <features.h> +#ifdef __UCLIBC_HAVE_LFS__ +#if defined _FILE_OFFSET_BITS && _FILE_OFFSET_BITS != 64 +#undef _FILE_OFFSET_BITS +#define _FILE_OFFSET_BITS 64 +#endif +#ifndef __USE_LARGEFILE64 +# define __USE_LARGEFILE64 1 +#endif +/* We absolutely do _NOT_ want interfaces silently + * renamed under us or very bad things will happen... */ +#ifdef __USE_FILE_OFFSET64 +# undef __USE_FILE_OFFSET64 +#endif +#include <errno.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <dirent.h> +#include "dirstream.h" + +extern int getdents64 __P ((unsigned int fd, struct dirent64 *dirp, unsigned int count)); + + +int readdir64_r(DIR *dir, struct dirent64 *entry, struct dirent64 **result) +{ + int ret; + ssize_t bytes; + struct dirent64 *de; + + if (!dir) { + __set_errno(EBADF); + return(EBADF); + } + de = NULL; + +#ifdef __UCLIBC_HAS_THREADS__ + pthread_mutex_lock(&(dir->dd_lock)); +#endif + + do { + if (dir->dd_size <= dir->dd_nextloc) { + /* read dir->dd_max bytes of directory entries. */ + bytes = getdents64(dir->dd_fd, dir->dd_buf, dir->dd_max); + if (bytes <= 0) { + *result = NULL; + ret = errno; + goto all_done; + } + dir->dd_size = bytes; + dir->dd_nextloc = 0; + } + + de = (struct dirent64 *) (((char *) dir->dd_buf) + dir->dd_nextloc); + + /* Am I right? H.J. */ + dir->dd_nextloc += de->d_reclen; + + /* We have to save the next offset here. */ + dir->dd_nextoff = de->d_off; + /* Skip deleted files. */ + } while (de->d_ino == 0); + + if (de == NULL) { + *result = NULL; + } else { + *result = memcpy (entry, de, de->d_reclen); + } + ret = 0; + +all_done: + +#ifdef __UCLIBC_HAS_THREADS__ + pthread_mutex_unlock(&(dir->dd_lock)); +#endif + return((de != NULL)? 0 : ret); +} +#endif /* __UCLIBC_HAVE_LFS__ */ + |