From 7385abbc8717da729dccdfd2852be88ce75579e7 Mon Sep 17 00:00:00 2001 From: Nicolas Thery Date: Sun, 26 Jul 2009 07:45:47 +0200 Subject: [PATCH] add fdopendir(3) implementation (1/?) POSIX states that the file offset of the passed descriptor determines the directory entry read but this commit supports only descriptors with null offsets. Also add __fdopendir2() for symmetry with opendir/__opendir2(). --- include/dirent.h | 2 ++ lib/libc/gen/opendir.c | 55 ++++++++++++++++++++++++++++++++++++------ 2 files changed, 50 insertions(+), 7 deletions(-) diff --git a/include/dirent.h b/include/dirent.h index 4d4b6420f1..070baa56a4 100644 --- a/include/dirent.h +++ b/include/dirent.h @@ -84,11 +84,13 @@ typedef struct _dirdesc { __BEGIN_DECLS DIR *opendir (const char *); +DIR *fdopendir (int); struct dirent *readdir (DIR *); void rewinddir (DIR *); int closedir (DIR *); #ifndef _POSIX_SOURCE DIR *__opendir2 (const char *, int); +DIR *__fdopendir2 (int, int); long telldir (const DIR *); struct dirent *_readdir_unlocked(DIR *, int); void seekdir(DIR *, long); diff --git a/lib/libc/gen/opendir.c b/lib/libc/gen/opendir.c index f45eb2d25a..49eae64e53 100644 --- a/lib/libc/gen/opendir.c +++ b/lib/libc/gen/opendir.c @@ -48,27 +48,38 @@ #include #include "un-namespace.h" + +#define DEFAULT_FLAGS (DTF_HIDEW | DTF_NODUP) + /* - * Open a directory. + * Open a directory given its path. */ DIR * opendir(const char *name) { - return (__opendir2(name, DTF_HIDEW|DTF_NODUP)); + return (__opendir2(name, DEFAULT_FLAGS)); +} + +/* + * Open a directory given a descriptor representing it. + */ +DIR * +fdopendir(int fd) +{ + return (__fdopendir2(fd, DEFAULT_FLAGS)); } DIR * __opendir2(const char *name, int flags) { - DIR *dirp; int fd; - int incr; - int saved_errno; struct stat statb; + DIR *dirp; + int saved_errno; /* * stat() before _open() because opening of special files may be - * harmful. _fstat() after open because the file may have changed. + * harmful. */ if (stat(name, &statb) != 0) return (NULL); @@ -76,9 +87,30 @@ __opendir2(const char *name, int flags) errno = ENOTDIR; return (NULL); } + if ((fd = _open(name, O_RDONLY | O_NONBLOCK)) == -1) return (NULL); + dirp = __fdopendir2(fd, flags); + if (dirp == NULL) { + saved_errno = errno; + _close(fd); + errno = saved_errno; + } + + return (dirp); +} + +DIR * +__fdopendir2(int fd, int flags) +{ + DIR *dirp; + int incr; + int saved_errno; + struct stat statb; + off_t off; + dirp = NULL; + if (_fstat(fd, &statb) != 0) goto fail; if (!S_ISDIR(statb.st_mode)) { @@ -89,6 +121,16 @@ __opendir2(const char *name, int flags) (dirp = malloc(sizeof(DIR))) == NULL) goto fail; + /* + * XXX We don't support yet the POSIX requirement that states that the + * file offset associated with the fd passed to fdopendir() determines + * which directory entry is returned. + */ + if ((off = lseek(fd, 0, SEEK_CUR)) != 0) { + errno = (off != -1) ? ENOTSUP : errno; + goto fail; + } + /* * Use the system page size if that is a multiple of DIRBLKSIZ. * Hopefully this can be a big win someday by allowing page @@ -120,7 +162,6 @@ __opendir2(const char *name, int flags) fail: saved_errno = errno; free(dirp); - _close(fd); errno = saved_errno; return (NULL); } -- 2.41.0