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
+ seekdir.c telldir.c readdir64.c alphasort64.c scandir64.c readdir_r.c
COBJS=$(patsubst %.c,%.o, $(CSRC))
OBJS=$(COBJS)
__set_errno(EBADF);
return -1;
}
+#ifdef _POSIX_THREADS
+ pthread_mutex_lock(dir->dd_lock);
+#endif
fd = dir->dd_fd;
dir->dd_fd = -1;
+#ifdef _POSIX_THREADS
+ pthread_mutex_unlock(dir->dd_lock);
+#endif
free(dir->dd_buf);
free(dir);
return close(fd);
#include <pthread.h>
#endif
-
-#ifdef __UCLIBC_HAVE_LFS__
-#ifndef __USE_LARGEFILE64
-# define __USE_LARGEFILE64
-#endif
-# define stuff_t __off64_t
-#else
-# define stuff_t __off_t
-#endif
-
-
/* For now, syscall readdir () only supports one entry at a time. It
* will be changed in the future.
#define NUMENT 3
int dd_fd;
/* offset of the next dir entry in buffer */
- stuff_t dd_nextloc;
+ size_t dd_nextloc;
/* bytes of valid entries in buffer */
- stuff_t dd_size;
+ size_t dd_size;
/* -> directory buffer */
void *dd_buf;
/* offset of the next dir entry in directory. */
- stuff_t dd_nextoff;
+ off_t dd_nextoff;
/* total size of buffer */
- stuff_t dd_max;
+ size_t dd_max;
- enum {unknown, have_getdents, no_getdents} dd_getdents;
-
/* lock */
#ifdef _POSIX_THREADS
pthread_mutex_t *dd_lock;
ptr->dd_fd = fd;
ptr->dd_nextloc = ptr->dd_size = ptr->dd_nextoff = 0;
- ptr->dd_getdents = unknown;
ptr->dd_max = statbuf.st_blksize;
if (ptr->dd_max < 512)
return NULL;
}
ptr->dd_buf = buf;
+#ifdef _POSIX_THREADS
+ pthread_mutex_init(ptr->dd_lock, NULL);
+#endif
return ptr;
}
struct dirent *readdir(DIR * dir)
{
- int result;
+ ssize_t bytes;
struct dirent *de;
if (!dir) {
return NULL;
}
- /* Are we running an old kernel? */
- if (dir->dd_getdents == no_getdents) {
- abort();
- }
+#ifdef _POSIX_THREADS
+ pthread_mutex_lock(dir->dd_lock);
+#endif
- if (dir->dd_size <= dir->dd_nextloc) {
+ do {
+ if (dir->dd_size <= dir->dd_nextloc) {
/* read dir->dd_max bytes of directory entries. */
- result = getdents(dir->dd_fd, dir->dd_buf, dir->dd_max);
-
- /* We assume we have getdents (). */
- dir->dd_getdents = have_getdents;
- if (result <= 0) {
- result = -result;
- if (result > 0) {
- /* Are we right? */
- if (result == ENOSYS) {
- dir->dd_getdents = no_getdents;
- abort();
- }
- __set_errno(result);
- }
-
- return NULL;
+ bytes = getdents(dir->dd_fd, dir->dd_buf, dir->dd_max);
+ if (bytes <= 0) {
+ de = NULL;
+ goto all_done;
}
-
- dir->dd_size = result;
+ dir->dd_size = bytes;
dir->dd_nextloc = 0;
- }
+ }
+
+ de = (struct dirent *) (((char *) dir->dd_buf) + dir->dd_nextloc);
- de = (struct dirent *) (((char *) dir->dd_buf) + dir->dd_nextloc);
+ /* Am I right? H.J. */
+ dir->dd_nextloc += de->d_reclen;
- /* 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;
- /* We have to save the next offset here. */
- dir->dd_nextoff = de->d_off;
+ /* Skip deleted files. */
+ } while (de->d_ino == 0);
+all_done:
+#ifdef _POSIX_THREADS
+ pthread_mutex_unlock(dir->dd_lock);
+#endif
return de;
}
struct dirent64 *readdir64(DIR * dir)
{
- int result;
+ ssize_t bytes;
struct dirent64 *de;
if (!dir) {
return NULL;
}
- /* Are we running an old kernel? */
- if (dir->dd_getdents == no_getdents) {
- abort();
- }
+#ifdef _POSIX_THREADS
+ pthread_mutex_lock(dir->dd_lock);
+#endif
- if (dir->dd_size <= dir->dd_nextloc) {
+ do {
+ if (dir->dd_size <= dir->dd_nextloc) {
/* read dir->dd_max bytes of directory entries. */
- result = getdents64(dir->dd_fd, dir->dd_buf, dir->dd_max);
-
- /* We assume we have getdents64 (). */
- dir->dd_getdents = have_getdents;
- if (result <= 0) {
- result = -result;
- if (result > 0) {
- /* Are we right? */
- if (result == ENOSYS) {
- dir->dd_getdents = no_getdents;
- abort();
- }
- __set_errno(result);
- }
-
- return NULL;
+ bytes = getdents64(dir->dd_fd, dir->dd_buf, dir->dd_max);
+ if (bytes <= 0) {
+ de = NULL;
+ goto all_done;
}
-
- dir->dd_size = result;
+ dir->dd_size = bytes;
dir->dd_nextloc = 0;
- }
+ }
+
+ de = (struct dirent64 *) (((char *) dir->dd_buf) + dir->dd_nextloc);
- de = (struct dirent64 *) (((char *) dir->dd_buf) + dir->dd_nextloc);
+ /* Am I right? H.J. */
+ dir->dd_nextloc += de->d_reclen;
- /* 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;
- /* We have to save the next offset here. */
- dir->dd_nextoff = de->d_off;
+ /* Skip deleted files. */
+ } while (dir->d_ino == 0);
+
+all_done:
+#ifdef _POSIX_THREADS
+ pthread_mutex_unlock(dir->dd_lock);
+#endif
return de;
}
--- /dev/null
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <dirent.h>
+#include "dirstream.h"
+
+extern int getdents __P ((unsigned int fd, struct dirent *dirp, unsigned int count));
+
+
+int readdir_r(DIR *dir, struct dirent *entry, struct dirent **result)
+{
+ int ret;
+ ssize_t bytes;
+ struct dirent *de;
+
+ if (!dir) {
+ __set_errno(EBADF);
+ return(EBADF);
+ }
+ de = NULL;
+
+#ifdef _POSIX_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 = getdents(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 dirent *) (((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 _POSIX_THREADS
+ pthread_mutex_unlock(dir->dd_lock);
+#endif
+ return((de != NULL)? 0 : ret);
+}
__set_errno(EBADF);
return;
}
+#ifdef _POSIX_THREADS
+ pthread_mutex_lock(dir->dd_lock);
+#endif
lseek(dir->dd_fd, 0, SEEK_SET);
dir->dd_nextoff = dir->dd_nextloc = dir->dd_size = 0;
+#ifdef _POSIX_THREADS
+ pthread_mutex_unlock(dir->dd_lock);
+#endif
}
__set_errno(EBADF);
return;
}
+#ifdef _POSIX_THREADS
+ pthread_mutex_lock(dir->dd_lock);
+#endif
dir->dd_nextoff = lseek(dir->dd_fd, offset, SEEK_SET);
dir->dd_size = dir->dd_nextloc = 0;
+#ifdef _POSIX_THREADS
+ pthread_mutex_unlock(dir->dd_lock);
+#endif
}
long int telldir(DIR * dir)
{
- off_t offset;
-
if (!dir) {
__set_errno(EBADF);
return -1;
}
- switch (dir->dd_getdents) {
- case no_getdents:
- /* We are running the old kernel. This is the starting offset
- of the next readdir(). */
- offset = lseek(dir->dd_fd, 0, SEEK_CUR);
- break;
-
- case unknown:
- /* readdir () is not called yet. but seekdir () may be called. */
- case have_getdents:
- /* The next entry. */
- offset = dir->dd_nextoff;
- break;
-
- default:
- __set_errno(EBADF);
- offset = -1;
- }
-
- return offset;
+ /* The next entry. */
+ return dir->dd_nextoff;
}