Finally removed the stat() and fstat() calls from the opendir() code.

They were made excessive in r205424 by opening with O_DIRECTORY.
Also eliminated the fcntl() call used to set FD_CLOEXEC by opening
with O_CLOEXEC.

(fdopendir() still checks that the passed descriptor is a directory,
and sets FD_CLOEXEC on it.)

Reviewed by:	ed
This commit is contained in:
ru 2012-03-02 10:03:38 +00:00
parent f90febf947
commit 50f29d6e48

View File

@ -66,7 +66,17 @@ opendir(const char *name)
DIR * DIR *
fdopendir(int fd) fdopendir(int fd)
{ {
struct stat statb;
/* Check that fd is associated with a directory. */
if (_fstat(fd, &statb) != 0)
return (NULL);
if (!S_ISDIR(statb.st_mode)) {
errno = ENOTDIR;
return (NULL);
}
if (_fcntl(fd, F_SETFD, FD_CLOEXEC) == -1)
return (NULL);
return (__opendir_common(fd, NULL, DTF_HIDEW|DTF_NODUP)); return (__opendir_common(fd, NULL, DTF_HIDEW|DTF_NODUP));
} }
@ -74,21 +84,11 @@ DIR *
__opendir2(const char *name, int flags) __opendir2(const char *name, int flags)
{ {
int fd; int fd;
struct stat statb;
DIR *dir; DIR *dir;
int saved_errno; int saved_errno;
/* if ((fd = _open(name,
* stat() before _open() because opening of special files may be O_RDONLY | O_NONBLOCK | O_DIRECTORY | O_CLOEXEC)) == -1)
* harmful.
*/
if (stat(name, &statb) != 0)
return (NULL);
if (!S_ISDIR(statb.st_mode)) {
errno = ENOTDIR;
return (NULL);
}
if ((fd = _open(name, O_RDONLY | O_NONBLOCK | O_DIRECTORY)) == -1)
return (NULL); return (NULL);
dir = __opendir_common(fd, name, flags); dir = __opendir_common(fd, name, flags);
@ -119,19 +119,9 @@ __opendir_common(int fd, const char *name, int flags)
int saved_errno; int saved_errno;
int unionstack; int unionstack;
int fd2; int fd2;
struct stat statb;
dirp = NULL; if ((dirp = malloc(sizeof(DIR) + sizeof(struct _telldir))) == NULL)
/* _fstat() the open handler because the file may have changed. */ return (NULL);
if (_fstat(fd, &statb) != 0)
goto fail;
if (!S_ISDIR(statb.st_mode)) {
errno = ENOTDIR;
goto fail;
}
if (_fcntl(fd, F_SETFD, FD_CLOEXEC) == -1 ||
(dirp = malloc(sizeof(DIR) + sizeof(struct _telldir))) == NULL)
goto fail;
dirp->dd_td = (struct _telldir *)((char *)dirp + sizeof(DIR)); dirp->dd_td = (struct _telldir *)((char *)dirp + sizeof(DIR));
LIST_INIT(&dirp->dd_td->td_locq); LIST_INIT(&dirp->dd_td->td_locq);