/* Open a directory stream on NAME. */ DIR * __opendir (const char *name) { struct stat64 statbuf; if (__builtin_expect (name[0], '\1') == '\0') { /* POSIX.1-1990 says an empty name gets ENOENT; but `open' might like it fine. */ __set_errno (ENOENT); return NULL; } #ifdef O_DIRECTORY /* Test whether O_DIRECTORY works. */ if (o_directory_works == 0) tryopen_o_directory (); /* We can skip the expensive `stat' call if O_DIRECTORY works. */ if (o_directory_works < 0) #endif { /* We first have to check whether the name is for a directory. We cannot do this after the open() call since the open/close operation performed on, say, a tape device might have undesirable effects. */ if (__builtin_expect (__xstat64 (_STAT_VER, name, &statbuf), 0) < 0) return NULL; if (__builtin_expect (! S_ISDIR (statbuf.st_mode), 0)) { __set_errno (ENOTDIR); return NULL; } } int fd = open_not_cancel_2 (name, O_RDONLY|O_NDELAY|EXTRA_FLAGS|O_LARGEFILE); if (__builtin_expect (fd, 0) < 0) return NULL; /* Now make sure this really is a directory and nothing changed since the `stat' call. We do not have to perform the test for the descriptor being associated with a directory if we know the O_DIRECTORY flag is honored by the kernel. */ if (__builtin_expect (__fxstat64 (_STAT_VER, fd, &statbuf), 0) < 0) goto lose; #ifdef O_DIRECTORY if (o_directory_works <= 0) #endif { if (__builtin_expect (! S_ISDIR (statbuf.st_mode), 0)) { __set_errno (ENOTDIR); lose: close_not_cancel_no_status (fd); return NULL; } } return __alloc_dir (fd, true, &statbuf); }
static bool need_isdir_precheck (void) { #ifdef O_DIRECTORY /* Test whether O_DIRECTORY works. */ if (o_directory_works == 0) tryopen_o_directory (); /* We can skip the expensive `stat' call if O_DIRECTORY works. */ return o_directory_works < 0; #endif return true; }
internal_function __opendirat (int dfd, const char *name) { struct stat64 statbuf; struct stat64 *statp = NULL; if (__builtin_expect (name[0], '\1') == '\0') { /* POSIX.1-1990 says an empty name gets ENOENT; but `open' might like it fine. */ __set_errno (ENOENT); return NULL; } #ifdef O_DIRECTORY /* Test whether O_DIRECTORY works. */ if (o_directory_works == 0) tryopen_o_directory (); /* We can skip the expensive `stat' call if O_DIRECTORY works. */ if (o_directory_works < 0) #endif { /* We first have to check whether the name is for a directory. We cannot do this after the open() call since the open/close operation performed on, say, a tape device might have undesirable effects. */ if (__builtin_expect (__xstat64 (_STAT_VER, name, &statbuf), 0) < 0) return NULL; if (__builtin_expect (! S_ISDIR (statbuf.st_mode), 0)) { __set_errno (ENOTDIR); return NULL; } } int flags = O_RDONLY|O_NDELAY|EXTRA_FLAGS|O_LARGEFILE; #ifdef O_CLOEXEC flags |= O_CLOEXEC; #endif int fd; #ifdef IS_IN_rtld assert (dfd == AT_FDCWD); fd = open_not_cancel_2 (name, flags); #else fd = openat_not_cancel_3 (dfd, name, flags); #endif if (__builtin_expect (fd, 0) < 0) return NULL; #ifdef O_DIRECTORY if (o_directory_works <= 0) #endif { /* Now make sure this really is a directory and nothing changed since the `stat' call. */ if (__builtin_expect (__fxstat64 (_STAT_VER, fd, &statbuf), 0) < 0) goto lose; if (__builtin_expect (! S_ISDIR (statbuf.st_mode), 0)) { __set_errno (ENOTDIR); lose: close_not_cancel_no_status (fd); return NULL; } statp = &statbuf; } return __alloc_dir (fd, true, 0, statp); }
/* Open a directory stream on NAME. */ DIR * __opendir (const char *name) { DIR *dirp; struct stat64 statbuf; int fd; size_t allocation; int save_errno; if (__builtin_expect (name[0], '\1') == '\0') { /* POSIX.1-1990 says an empty name gets ENOENT; but `open' might like it fine. */ __set_errno (ENOENT); return NULL; } #ifdef O_DIRECTORY /* Test whether O_DIRECTORY works. */ if (o_directory_works == 0) tryopen_o_directory (); /* We can skip the expensive `stat' call if O_DIRECTORY works. */ if (o_directory_works < 0) #endif { /* We first have to check whether the name is for a directory. We cannot do this after the open() call since the open/close operation performed on, say, a tape device might have undesirable effects. */ if (__builtin_expect (__xstat64 (_STAT_VER, name, &statbuf), 0) < 0) return NULL; if (__builtin_expect (! S_ISDIR (statbuf.st_mode), 0)) { __set_errno (ENOTDIR); return NULL; } } fd = open_not_cancel_2 (name, O_RDONLY|O_NDELAY|EXTRA_FLAGS|O_LARGEFILE); if (__builtin_expect (fd, 0) < 0) return NULL; /* Now make sure this really is a directory and nothing changed since the `stat' call. We do not have to perform the test for the descriptor being associated with a directory if we know the O_DIRECTORY flag is honored by the kernel. */ if (__builtin_expect (__fxstat64 (_STAT_VER, fd, &statbuf), 0) < 0) goto lose; #ifdef O_DIRECTORY if (o_directory_works <= 0) #endif { if (__builtin_expect (! S_ISDIR (statbuf.st_mode), 0)) { save_errno = ENOTDIR; goto lose; } } if (__builtin_expect (__fcntl (fd, F_SETFD, FD_CLOEXEC), 0) < 0) goto lose; #ifdef _STATBUF_ST_BLKSIZE if (__builtin_expect ((size_t) statbuf.st_blksize >= sizeof (struct dirent64), 1)) allocation = statbuf.st_blksize; else #endif allocation = (BUFSIZ < sizeof (struct dirent64) ? sizeof (struct dirent64) : BUFSIZ); const int pad = -sizeof (DIR) % __alignof__ (struct dirent64); dirp = (DIR *) malloc (sizeof (DIR) + allocation + pad); if (dirp == NULL) lose: { save_errno = errno; close_not_cancel_no_status (fd); __set_errno (save_errno); return NULL; } memset (dirp, '\0', sizeof (DIR)); dirp->data = (char *) (dirp + 1) + pad; dirp->allocation = allocation; dirp->fd = fd; __libc_lock_init (dirp->lock); return dirp; }