diff options
Diffstat (limited to 'libc/misc/dirent/readdir.c')
-rw-r--r-- | libc/misc/dirent/readdir.c | 54 |
1 files changed, 24 insertions, 30 deletions
diff --git a/libc/misc/dirent/readdir.c b/libc/misc/dirent/readdir.c index 81575283d..b9f5f55bd 100644 --- a/libc/misc/dirent/readdir.c +++ b/libc/misc/dirent/readdir.c @@ -10,7 +10,7 @@ extern int getdents __P ((unsigned int fd, struct dirent *dirp, unsigned int cou struct dirent *readdir(DIR * dir) { - int result; + ssize_t bytes; struct dirent *de; if (!dir) { @@ -18,42 +18,36 @@ struct dirent *readdir(DIR * 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; } |