diff options
| author | Bruce Evans <bde@FreeBSD.org> | 1995-04-21 15:23:27 +0000 |
|---|---|---|
| committer | Bruce Evans <bde@FreeBSD.org> | 1995-04-21 15:23:27 +0000 |
| commit | 55e2b2c608f8dff458deb2dc595df08b052bf3d1 (patch) | |
| tree | 6cc61941ffdb793694d99f0ff4adf4767816cac8 /lib/libc | |
| parent | 7332aa0b69e0a56b3c6fa00ae05b7f1f7601b0b3 (diff) | |
Notes
Diffstat (limited to 'lib/libc')
| -rw-r--r-- | lib/libc/gen/opendir.c | 32 |
1 files changed, 23 insertions, 9 deletions
diff --git a/lib/libc/gen/opendir.c b/lib/libc/gen/opendir.c index 83e041d2d9a9..b3c0e096d67e 100644 --- a/lib/libc/gen/opendir.c +++ b/lib/libc/gen/opendir.c @@ -36,8 +36,10 @@ static char sccsid[] = "@(#)opendir.c 8.2 (Berkeley) 2/12/94"; #endif /* LIBC_SCCS and not lint */ #include <sys/param.h> +#include <sys/stat.h> #include <dirent.h> +#include <errno.h> #include <fcntl.h> #include <stdlib.h> #include <unistd.h> @@ -51,14 +53,21 @@ opendir(name) { register DIR *dirp; register int fd; + int saved_errno; + struct stat sb; - if ((fd = open(name, 0)) == -1) - return NULL; - if (fcntl(fd, F_SETFD, FD_CLOEXEC) == -1 || - (dirp = (DIR *)malloc(sizeof(DIR))) == NULL) { - close (fd); + if ((fd = open(name, O_RDONLY | O_NONBLOCK)) == -1) return NULL; + dirp = NULL; + if (fstat(fd, &sb) != 0) + goto fail; + if (!S_ISDIR(sb.st_mode)) { + errno = ENOTDIR; + goto fail; } + if (fcntl(fd, F_SETFD, FD_CLOEXEC) == -1 || + (dirp = malloc(sizeof(DIR))) == NULL) + goto fail; /* * If CLBYTES is an exact multiple of DIRBLKSIZ, use a CLBYTES * buffer that it cluster boundary aligned. @@ -72,10 +81,8 @@ opendir(name) dirp->dd_buf = malloc(DIRBLKSIZ); dirp->dd_len = DIRBLKSIZ; } - if (dirp->dd_buf == NULL) { - close (fd); - return NULL; - } + if (dirp->dd_buf == NULL) + goto fail; dirp->dd_fd = fd; dirp->dd_loc = 0; dirp->dd_seek = 0; @@ -84,4 +91,11 @@ opendir(name) */ dirp->dd_rewind = telldir(dirp); return dirp; + +fail: + saved_errno = errno; + free(dirp); + close(fd); + errno = saved_errno; + return NULL; } |
