diff --git a/include/dirent.h b/include/dirent.h index 3c2f0715f8cb..63626b59bc72 100644 --- a/include/dirent.h +++ b/include/dirent.h @@ -100,6 +100,7 @@ int getdents(int, char *, int); int getdirentries(int, char *, int, long *); #endif DIR *opendir(const char *); +DIR *fdopendir(int); struct dirent * readdir(DIR *); #if __POSIX_VISIBLE >= 199506 || __XSI_VISIBLE >= 500 diff --git a/lib/libc/gen/Makefile.inc b/lib/libc/gen/Makefile.inc index 6aa45a434162..c39fdb3c8679 100644 --- a/lib/libc/gen/Makefile.inc +++ b/lib/libc/gen/Makefile.inc @@ -72,6 +72,7 @@ MLINKS+=arc4random.3 arc4random_addrandom.3 arc4random.3 arc4random_stir.3 MLINKS+=ctermid.3 ctermid_r.3 MLINKS+=devname.3 devname_r.3 MLINKS+=directory.3 closedir.3 directory.3 dirfd.3 directory.3 opendir.3 \ + directory.3 fdopendir.3 \ directory.3 readdir.3 directory.3 readdir_r.3 directory.3 rewinddir.3 \ directory.3 seekdir.3 directory.3 telldir.3 MLINKS+=dlopen.3 dlclose.3 dlopen.3 dlerror.3 dlopen.3 dlfunc.3 \ diff --git a/lib/libc/gen/Symbol.map b/lib/libc/gen/Symbol.map index 5ec8144842f6..22c43953db7f 100644 --- a/lib/libc/gen/Symbol.map +++ b/lib/libc/gen/Symbol.map @@ -329,6 +329,7 @@ FBSD_1.0 { }; FBSD_1.1 { + fdopendir; fts_open; fts_close; fts_read; diff --git a/lib/libc/gen/directory.3 b/lib/libc/gen/directory.3 index 353def2651ed..3be3fa894fc3 100644 --- a/lib/libc/gen/directory.3 +++ b/lib/libc/gen/directory.3 @@ -28,11 +28,12 @@ .\" @(#)directory.3 8.1 (Berkeley) 6/4/93 .\" $FreeBSD$ .\" -.Dd June 4, 1993 +.Dd April 16, 2008 .Dt DIRECTORY 3 .Os .Sh NAME .Nm opendir , +.Nm fdopendir , .Nm readdir , .Nm readdir_r , .Nm telldir , @@ -48,6 +49,8 @@ .In dirent.h .Ft DIR * .Fn opendir "const char *filename" +.Ft DIR * +.Fn fdopendir "int fd" .Ft struct dirent * .Fn readdir "DIR *dirp" .Ft int @@ -84,6 +87,36 @@ cannot be accessed, or if it cannot enough memory to hold the whole thing. .Pp The +.Fn fdopendir +function is equivalent to the +.Fn opendir +function except that the directory is specified by a file descriptor +.Fa fd +rather than by a name. +The file offset associated with the file descriptor at the time of the call +determines which entries are returned. +.Pp +Upon successful return from +.Fn fdopendir , +the file descriptor is under the control of the system, +and if any attempt is made to close the file descriptor, +or to modify the state of the associated description other than by means +of +.Fn closedir , +.Fn readdir , +.Fn readdir_r , +or +.Fn rewinddir , +the behavior is undefined. +Upon calling +.Fn closedir +the file descriptor is closed. +The +.Dv FD_CLOEXEC +flag is set on the file descriptor by a successful call to +.Fn fdopendir . +.Pp +The .Fn readdir function returns a pointer to the next directory entry. @@ -202,3 +235,7 @@ and .Fn dirfd functions appeared in .Bx 4.2 . +The +.Fn fdopendir +function appeared in +.Fx 8.0 . diff --git a/lib/libc/gen/opendir.c b/lib/libc/gen/opendir.c index 5725ca3bc1a6..9625ec690941 100644 --- a/lib/libc/gen/opendir.c +++ b/lib/libc/gen/opendir.c @@ -47,6 +47,9 @@ __FBSDID("$FreeBSD$"); #include "un-namespace.h" #include "telldir.h" + +static DIR * __opendir_common(int, const char *, int); + /* * Open a directory. */ @@ -57,19 +60,25 @@ opendir(const char *name) return (__opendir2(name, DTF_HIDEW|DTF_NODUP)); } +/* + * Open a directory with existing file descriptor. + */ +DIR * +fdopendir(int fd) +{ + + return (__opendir_common(fd, NULL, DTF_HIDEW|DTF_NODUP)); +} + DIR * __opendir2(const char *name, int flags) { - DIR *dirp; int fd; - int incr; - int saved_errno; - int unionstack; struct stat statb; /* * 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); @@ -79,7 +88,24 @@ __opendir2(const char *name, int flags) } if ((fd = _open(name, O_RDONLY | O_NONBLOCK)) == -1) return (NULL); + + return __opendir_common(fd, name, flags); +} + +/* + * Common routine for opendir(3), __opendir2(3) and fdopendir(3). + */ +static DIR * +__opendir_common(int fd, const char *name, int flags) +{ + DIR *dirp; + int incr; + int saved_errno; + int unionstack; + struct stat statb; + dirp = NULL; + /* _fstat() the open handler because the file may have changed. */ if (_fstat(fd, &statb) != 0) goto fail; if (!S_ISDIR(statb.st_mode)) { diff --git a/sys/sys/param.h b/sys/sys/param.h index d9d51255cf66..ffeb7c7f0d30 100644 --- a/sys/sys/param.h +++ b/sys/sys/param.h @@ -57,7 +57,7 @@ * is created, otherwise 1. */ #undef __FreeBSD_version -#define __FreeBSD_version 800034 /* Master, propagated to newvers */ +#define __FreeBSD_version 800035 /* Master, propagated to newvers */ #ifndef LOCORE #include