opendir.c.patch   [plain text]


--- opendir.c.orig	2009-11-08 17:01:43.000000000 -0800
+++ opendir.c	2009-11-08 17:01:51.000000000 -0800
@@ -44,6 +44,7 @@ __FBSDID("$FreeBSD: src/lib/libc/gen/ope
 #include <stdlib.h>
 #include <string.h>
 #include <unistd.h>
+#include <pthread.h>
 #include "un-namespace.h"
 
 #include "telldir.h"
@@ -65,27 +66,15 @@ __opendir2(const char *name, int flags)
 	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.
+	 * Use O_DIRECTORY to only open directories (because opening of
+	 * special files may be harmful).  errno is set to ENOTDIR if
+	 * not a directory.
 	 */
-	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)) == -1)
+	if ((fd = _open(name, O_RDONLY | O_NONBLOCK | O_DIRECTORY)) == -1)
 		return (NULL);
 	dirp = 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;
@@ -147,7 +136,11 @@ __opendir2(const char *name, int flags)
 				ddptr = buf + (len - space);
 			}
 
+#if __DARWIN_64_BIT_INO_T
+			n = __getdirentries64(fd, ddptr, space, &dirp->dd_td->seekoff);
+#else /* !__DARWIN_64_BIT_INO_T */
 			n = _getdirentries(fd, ddptr, space, &dirp->dd_seek);
+#endif /* __DARWIN_64_BIT_INO_T */
 			if (n > 0) {
 				ddptr += n;
 				space -= n;
@@ -255,14 +248,18 @@ __opendir2(const char *name, int flags)
 		dirp->dd_buf = malloc(dirp->dd_len);
 		if (dirp->dd_buf == NULL)
 			goto fail;
+#if __DARWIN_64_BIT_INO_T
+		dirp->dd_td->seekoff = 0;
+#else /* !__DARWIN_64_BIT_INO_T */
 		dirp->dd_seek = 0;
+#endif /* __DARWIN_64_BIT_INO_T */
 		flags &= ~DTF_REWIND;
 	}
 
 	dirp->dd_loc = 0;
 	dirp->dd_fd = fd;
 	dirp->dd_flags = flags;
-	dirp->dd_lock = NULL;
+	dirp->dd_lock = (pthread_mutex_t)PTHREAD_MUTEX_INITIALIZER;
 
 	/*
 	 * Set up seek point for rewinddir.