Initial implemenation with quick test. Reviewed-by: Sam Ravnborg <sam at ravnborg.org> Signed-off-by: maximilian attems <max at stro.at> --- v3: return ENOMEM on malloc failure. v2: seperate file. usr/include/dirent.h | 1 + usr/klibc/Kbuild | 3 ++- usr/klibc/fdopendir.c | 41 +++++++++++++++++++++++++++++++++++++++++ usr/klibc/tests/Kbuild | 1 + usr/klibc/tests/fdopendir.c | 31 +++++++++++++++++++++++++++++++ 5 files changed, 76 insertions(+), 1 deletions(-) create mode 100644 usr/klibc/fdopendir.c 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/Kbuild b/usr/klibc/Kbuild index c4f9ae2..48575a5 100644 --- a/usr/klibc/Kbuild +++ b/usr/klibc/Kbuild @@ -42,7 +42,8 @@ klib-y := vsnprintf.o snprintf.o vsprintf.o sprintf.o \ seteuid.o setegid.o \ getenv.o setenv.o putenv.o __put_env.o unsetenv.o \ clearenv.o nullenv.o \ - getopt.o getopt_long.o readdir.o scandir.o alphasort.o remove.o \ + getopt.o getopt_long.o \ + readdir.o scandir.o fdopendir.o alphasort.o remove.o \ syslog.o closelog.o pty.o getpt.o posix_openpt.o isatty.o reboot.o \ time.o utime.o llseek.o nice.o getpriority.o \ qsort.o bsearch.o \ diff --git a/usr/klibc/fdopendir.c b/usr/klibc/fdopendir.c new file mode 100644 index 0000000..0eda33c --- /dev/null +++ b/usr/klibc/fdopendir.c @@ -0,0 +1,41 @@ +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <stdlib.h> +#include <errno.h> + +#define __KLIBC_DIRENT_INTERNALS +#include <dirent.h> + +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) { + errno = ENOMEM; + return NULL; + } + + dp->__fd = fd; + dp->next = NULL; + dp->bytes_left = 0; + return dp; +} 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