diff options
Diffstat (limited to 'sysdeps/unix/opendir.c')
-rw-r--r-- | sysdeps/unix/opendir.c | 45 |
1 files changed, 35 insertions, 10 deletions
diff --git a/sysdeps/unix/opendir.c b/sysdeps/unix/opendir.c index 59772cda75..0a116247d2 100644 --- a/sysdeps/unix/opendir.c +++ b/sysdeps/unix/opendir.c @@ -31,6 +31,7 @@ #include <dirstream.h> #include <not-cancel.h> +#include <kernel-features.h> /* opendir() must not accidentally open something other than a directory. @@ -110,7 +111,11 @@ __opendir (const char *name) } } - int fd = open_not_cancel_2 (name, O_RDONLY|O_NDELAY|EXTRA_FLAGS|O_LARGEFILE); + int flags = O_RDONLY|O_NDELAY|EXTRA_FLAGS|O_LARGEFILE; +#ifdef O_CLOEXEC + flags |= O_CLOEXEC; +#endif + int fd = open_not_cancel_2 (name, flags); if (__builtin_expect (fd, 0) < 0) return NULL; @@ -138,12 +143,33 @@ __opendir (const char *name) weak_alias (__opendir, opendir) +#ifdef __ASSUME_O_CLOEXEC +# define check_have_o_cloexec(fd) 1 +#else +static int +check_have_o_cloexec (int fd) +{ + if (__have_o_cloexec == 0) + __have_o_cloexec = (__fcntl (fd, F_GETFD, 0) & FD_CLOEXEC) == 0 ? -1 : 1; + return __have_o_cloexec > 0; +} +#endif + + DIR * internal_function __alloc_dir (int fd, bool close_fd, const struct stat64 *statp) { - if (__builtin_expect (__fcntl (fd, F_SETFD, FD_CLOEXEC), 0) < 0) - goto lose; + /* We always have to set the close-on-exit flag if the user provided + the file descriptor. Otherwise only if we have no working + O_CLOEXEC support. */ +#ifdef O_CLOEXEC + if (! close_fd || ! check_have_o_cloexec (fd)) +#endif + { + if (__builtin_expect (__fcntl (fd, F_SETFD, FD_CLOEXEC), 0) < 0) + goto lose; + } size_t allocation; #ifdef _STATBUF_ST_BLKSIZE @@ -155,9 +181,7 @@ __alloc_dir (int fd, bool close_fd, const struct stat64 *statp) allocation = (BUFSIZ < sizeof (struct dirent64) ? sizeof (struct dirent64) : BUFSIZ); - const int pad = -sizeof (DIR) % __alignof__ (struct dirent64); - - DIR *dirp = (DIR *) malloc (sizeof (DIR) + allocation + pad); + DIR *dirp = (DIR *) malloc (sizeof (DIR) + allocation); if (dirp == NULL) lose: { @@ -169,14 +193,15 @@ __alloc_dir (int fd, bool close_fd, const struct stat64 *statp) } return NULL; } - memset (dirp, '\0', sizeof (DIR)); - dirp->data = (char *) (dirp + 1) + pad; - dirp->allocation = allocation; - dirp->fd = fd; + dirp->fd = fd; #ifndef NOT_IN_libc __libc_lock_init (dirp->lock); #endif + dirp->allocation = allocation; + dirp->size = 0; + dirp->offset = 0; + dirp->filepos = 0; return dirp; } |