Module Name:    src
Committed By:   christos
Date:           Wed Nov 26 16:48:43 UTC 2014

Modified Files:
        src/lib/libc/gen: opendir.c

Log Message:
- Use O_DIRECTORY to open the file, so that we don't need to stat() after
  that.
- Move the stat() call to fdopendir() and change it's error handling so that
  it does not hide errors.
- According to POSIX, fdopendir() transfers ownership of the fd only on
  success, so don't close it on failure. XXX: We still make it non-blocking
  on failure, but that's nitpicking.

XXX: pullup-7?


To generate a diff of this commit:
cvs rdiff -u -r1.38 -r1.39 src/lib/libc/gen/opendir.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/lib/libc/gen/opendir.c
diff -u src/lib/libc/gen/opendir.c:1.38 src/lib/libc/gen/opendir.c:1.39
--- src/lib/libc/gen/opendir.c:1.38	Sat Oct 15 19:00:01 2011
+++ src/lib/libc/gen/opendir.c	Wed Nov 26 11:48:43 2014
@@ -1,4 +1,4 @@
-/*	$NetBSD: opendir.c,v 1.38 2011/10/15 23:00:01 christos Exp $	*/
+/*	$NetBSD: opendir.c,v 1.39 2014/11/26 16:48:43 christos Exp $	*/
 
 /*
  * Copyright (c) 1983, 1993
@@ -34,7 +34,7 @@
 #if 0
 static char sccsid[] = "@(#)opendir.c	8.7 (Berkeley) 12/10/94";
 #else
-__RCSID("$NetBSD: opendir.c,v 1.38 2011/10/15 23:00:01 christos Exp $");
+__RCSID("$NetBSD: opendir.c,v 1.39 2014/11/26 16:48:43 christos Exp $");
 #endif
 #endif /* LIBC_SCCS and not lint */
 
@@ -75,17 +75,36 @@ opendir(const char *name)
 DIR *
 __opendir2(const char *name, int flags)
 {
+	DIR *dirp;
 	int fd;
 
-	if ((fd = open(name, O_RDONLY | O_NONBLOCK | O_CLOEXEC)) == -1)
+	if ((fd = open(name, O_RDONLY|O_DIRECTORY|O_NONBLOCK|O_CLOEXEC)) == -1)
 		return NULL;
-	return __opendir_common(fd, name, flags);
+
+	dirp = __opendir_common(fd, name, flags);
+	if (dirp == NULL) {
+		int serrno = errno;
+		(void)close(fd);
+		errno = serrno;
+	}
+	return dirp;
 }
 
 #ifndef __LIBC12_SOURCE__
 DIR *
 _fdopendir(int fd)
 {
+	struct stat sb;
+
+	if (fstat(fd, &sb) == -1)
+		return NULL;
+
+	if (!S_ISDIR(sb.st_mode)) {
+		errno = ENOTDIR;
+		return NULL;
+	}
+
+	/* This is optional according to POSIX, but a good measure */
 	if (fcntl(fd, F_SETFD, FD_CLOEXEC) == -1)
 		return NULL;
 
@@ -96,16 +115,11 @@ _fdopendir(int fd)
 static DIR *
 __opendir_common(int fd, const char *name, int flags)
 {
-	DIR *dirp = NULL;
+	DIR *dirp;
 	int serrno;
-	struct stat sb;
 	struct statvfs sfb;
 	int error;
 
-	if (fstat(fd, &sb) || !S_ISDIR(sb.st_mode)) {
-		errno = ENOTDIR;
-		goto error;
-	}
 	if ((dirp = malloc(sizeof(*dirp))) == NULL)
 		goto error;
 	dirp->dd_buf = NULL;
@@ -157,8 +171,6 @@ error:
 		free(dirp->dd_buf);
 	}
 	free(dirp);
-	if (fd != -1)
-		(void)close(fd);
 	errno = serrno;
 	return NULL;
 }

Reply via email to