Initial implemenation with quick test. Signed-off-by: maximilian attems <max at stro.at> --- Should maybe go to a seperate file too.. usr/include/dirent.h | 1 + usr/klibc/readdir.c | 37 ++++++++++++++++++++++++++++++++++++- usr/klibc/tests/Kbuild | 1 + usr/klibc/tests/fdopendir.c | 31 +++++++++++++++++++++++++++++++ 4 files changed, 69 insertions(+), 1 deletions(-) create mode 100644 usr/klibc/tests/fdopendir.c diff --git a/usr/include/dirent.h b/usr/include/dirent.h index 725452e..bc08c5c 100644 --- a/usr/include/dirent.h +++ b/usr/include/dirent.h @@ -23,6 +23,7 @@ struct _IO_dir { typedef struct _IO_dir DIR; __extern DIR *opendir(const char *); +__extern DIR *fdopendir(int); __extern struct dirent *readdir(DIR *); __extern int closedir(DIR *); static __inline__ int dirfd(DIR * __d) diff --git a/usr/klibc/readdir.c b/usr/klibc/readdir.c index 453fc08..1ea8b99 100644 --- a/usr/klibc/readdir.c +++ b/usr/klibc/readdir.c @@ -1,10 +1,13 @@ /* - * readdir.c: opendir/readdir/closedir + * readdir.c: opendir/fdopendir/readdir/closedir */ +#include <sys/types.h> +#include <sys/stat.h> #include <unistd.h> #include <fcntl.h> #include <stdlib.h> +#include <errno.h> #define __KLIBC_DIRENT_INTERNALS #include <dirent.h> @@ -28,6 +31,38 @@ DIR *opendir(const char *name) return dp; } +DIR *fdopendir(int fd) +{ + DIR *dp; + int flags; + struct stat st; + + if (fstat(fd, &st)) + return NULL; + if (!S_ISDIR(st.st_mode)) { + errno = ENOTDIR; + return NULL; + } + + flags = fcntl(fd, F_GETFL); + if (flags == -1) + return NULL; + if ((flags & O_ACCMODE) == O_WRONLY) { + errno = EINVAL; + return NULL; + } + + dp = malloc(sizeof(DIR)); + + if(!dp) + return NULL; + + dp->__fd = fd; + dp->next = NULL; + dp->bytes_left = 0; + return dp; +} + struct dirent *readdir(DIR *dir) { struct dirent *dent; diff --git a/usr/klibc/tests/Kbuild b/usr/klibc/tests/Kbuild index a3e0254..5e6e073 100644 --- a/usr/klibc/tests/Kbuild +++ b/usr/klibc/tests/Kbuild @@ -14,6 +14,7 @@ static-y := $(test-files:.c=) shared-y := $(addsuffix .shared, $(static-y)) environ.shared-y := environ.o +fdopendir.shared-y := fdopendir.o fcntl.shared-y := fcntl.o fnmatch.shared-y := fnmatch.o getopttest.shared-y := getopttest.o diff --git a/usr/klibc/tests/fdopendir.c b/usr/klibc/tests/fdopendir.c new file mode 100644 index 0000000..14bd99b --- /dev/null +++ b/usr/klibc/tests/fdopendir.c @@ -0,0 +1,31 @@ +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <dirent.h> +#include <stdio.h> + +int main() +{ + DIR *dir; + struct dirent dirent; + int fd; + + /* XXX: use mktemps */ + fd = open("/tmp/", O_RDONLY); + if (fd < 0) { + perror("open"); + return 1; + } + + dir = fdopendir(fd); + if (!dir) { + perror("fdopendir"); + close(fd): + return 1; + } + while ((dirent = readdir(dir)) != NULL) + ; + + closedir(dir): + return 0; +} -- 1.7.5.4