From: Paul Eggert Date: Wed, 1 Sep 2010 20:45:53 +0000 (-0700) Subject: fcntl-h, etc.: prefer O_SEARCH to O_RDONLY when applicable X-Git-Tag: v0.1~3871 X-Git-Url: http://erislabs.org.uk/gitweb/?a=commitdiff_plain;h=24816be6c14cbc51938d036533ec5ccaa9a056e2;p=gnulib.git fcntl-h, etc.: prefer O_SEARCH to O_RDONLY when applicable POSIX 2008 specifies a new 'open' flag O_SEARCH, which can be used when one needs search access to a directory but not read access. On systems where it is available, it works in some cases where O_RDONLY does not, namely on directories that are searchable but not readable, and which need only to be searchable. If O_SEARCH is not available, fall back to the traditional method of using O_RDONLY. * lib/fcntl.in.h (O_SEARCH): #define to O_RDONLY if not defined. * lib/chdir-long.c (cdb_advance_fd): Use O_SEARCH, not O_RDONLY, when opening a directory that needs only to be searchable. * lib/chdir-safer.c (chdir_no_follow): Likewise. * lib/fts.c (diropen, fts_open, fd_ring_check): Likewise. * lib/openat-proc.c (openat_proc_name): Likewise. * lib/openat.c (openat_needs_fchdir): Likewise. * lib/save-cwd.c (save_cwd): Likewise. * lib/savewd.c (savewd_save, savewd_chdir): Likewise. --- diff --git a/ChangeLog b/ChangeLog index 35d2ce082..2d03ea739 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,25 @@ +2010-09-01 Paul Eggert + + fcntl-h, etc.: prefer O_SEARCH to O_RDONLY when applicable + + POSIX 2008 specifies a new 'open' flag O_SEARCH, which can be used + when one needs search access to a directory but not read access. + On systems where it is available, it works in some cases where + O_RDONLY does not, namely on directories that are searchable but + not readable, and which need only to be searchable. If O_SEARCH + is not available, fall back to the traditional method of using + O_RDONLY. + + * lib/fcntl.in.h (O_SEARCH): #define to O_RDONLY if not defined. + * lib/chdir-long.c (cdb_advance_fd): Use O_SEARCH, not O_RDONLY, + when opening a directory that needs only to be searchable. + * lib/chdir-safer.c (chdir_no_follow): Likewise. + * lib/fts.c (diropen, fts_open, fd_ring_check): Likewise. + * lib/openat-proc.c (openat_proc_name): Likewise. + * lib/openat.c (openat_needs_fchdir): Likewise. + * lib/save-cwd.c (save_cwd): Likewise. + * lib/savewd.c (savewd_save, savewd_chdir): Likewise. + 2010-08-28 Bruno Haible New module 'host-cpu-c-abi'. diff --git a/lib/chdir-long.c b/lib/chdir-long.c index 28e24070e..a88e27f34 100644 --- a/lib/chdir-long.c +++ b/lib/chdir-long.c @@ -72,7 +72,7 @@ static int cdb_advance_fd (struct cd_buf *cdb, char const *dir) { int new_fd = openat (cdb->fd, dir, - O_RDONLY | O_DIRECTORY | O_NOCTTY | O_NONBLOCK); + O_SEARCH | O_DIRECTORY | O_NOCTTY | O_NONBLOCK); if (new_fd < 0) return -1; diff --git a/lib/chdir-safer.c b/lib/chdir-safer.c index b3266b51b..61c71c612 100644 --- a/lib/chdir-safer.c +++ b/lib/chdir-safer.c @@ -34,16 +34,19 @@ #endif /* Like chdir, but fail if DIR is a symbolic link to a directory (or - similar funny business), or if DIR is not readable. This avoids a - minor race condition between when a directory is created or statted - and when the process chdirs into it. */ + similar funny business). This avoids a minor race condition + between when a directory is created or statted and when the process + chdirs into it. + + On older systems lacking full support for O_SEARCH, this function + can also fail if DIR is not readable. */ int chdir_no_follow (char const *dir) { int result = 0; int saved_errno; int fd = open (dir, - O_RDONLY | O_DIRECTORY | O_NOCTTY | O_NOFOLLOW | O_NONBLOCK); + O_SEARCH | O_DIRECTORY | O_NOCTTY | O_NOFOLLOW | O_NONBLOCK); if (fd < 0) return -1; diff --git a/lib/fcntl.in.h b/lib/fcntl.in.h index 8fb785220..42fb81bfb 100644 --- a/lib/fcntl.in.h +++ b/lib/fcntl.in.h @@ -210,6 +210,10 @@ _GL_WARN_ON_USE (openat, "openat is not portable - " # define O_RSYNC 0 #endif +#ifndef O_SEARCH +# define O_SEARCH O_RDONLY /* This is often close enough in older systems. */ +#endif + #ifndef O_SYNC # define O_SYNC 0 #endif diff --git a/lib/fts.c b/lib/fts.c index e4351f84b..a308a8c94 100644 --- a/lib/fts.c +++ b/lib/fts.c @@ -347,7 +347,7 @@ static inline int internal_function diropen (FTS const *sp, char const *dir) { - int open_flags = (O_RDONLY | O_DIRECTORY | O_NOCTTY | O_NONBLOCK + int open_flags = (O_SEARCH | O_DIRECTORY | O_NOCTTY | O_NONBLOCK | (ISSET (FTS_PHYSICAL) ? O_NOFOLLOW : 0)); int fd = (ISSET (FTS_CWDFD) @@ -405,7 +405,7 @@ fts_open (char * const *argv, early, doing it here saves us the trouble of ensuring later (where it'd be messier) that "." can in fact be opened. If not, revert to FTS_NOCHDIR mode. */ - int fd = open (".", O_RDONLY); + int fd = open (".", O_SEARCH); if (fd < 0) { /* Even if `.' is unreadable, don't revert to FTS_NOCHDIR mode @@ -1646,7 +1646,7 @@ fd_ring_check (FTS const *sp) int fd = i_ring_pop (&fd_w); if (0 <= fd) { - int parent_fd = openat (cwd_fd, "..", O_RDONLY); + int parent_fd = openat (cwd_fd, "..", O_SEARCH); if (parent_fd < 0) { // Warn? diff --git a/lib/openat-proc.c b/lib/openat-proc.c index 25384127e..76fe42ce6 100644 --- a/lib/openat-proc.c +++ b/lib/openat-proc.c @@ -75,7 +75,7 @@ openat_proc_name (char buf[OPENAT_BUFFER_SIZE], int fd, char const *file) problem is exhibited on code that built on Solaris 8 and running on Solaris 10. */ - int proc_self_fd = open ("/proc/self/fd", O_RDONLY); + int proc_self_fd = open ("/proc/self/fd", O_SEARCH); if (proc_self_fd < 0) proc_status = -1; else diff --git a/lib/openat.c b/lib/openat.c index f2eac868d..9970e460a 100644 --- a/lib/openat.c +++ b/lib/openat.c @@ -244,7 +244,7 @@ bool openat_needs_fchdir (void) { bool needs_fchdir = true; - int fd = open ("/", O_RDONLY); + int fd = open ("/", O_SEARCH); if (0 <= fd) { diff --git a/lib/save-cwd.c b/lib/save-cwd.c index cf43a3550..8e636c204 100644 --- a/lib/save-cwd.c +++ b/lib/save-cwd.c @@ -76,7 +76,7 @@ save_cwd (struct saved_cwd *cwd) { cwd->name = NULL; - cwd->desc = open (".", O_RDONLY); + cwd->desc = open (".", O_SEARCH); if (!GNULIB_FCNTL_SAFER) cwd->desc = fd_safer (cwd->desc); if (cwd->desc < 0) diff --git a/lib/savewd.c b/lib/savewd.c index e111207ba..9ec9877e1 100644 --- a/lib/savewd.c +++ b/lib/savewd.c @@ -45,7 +45,7 @@ savewd_save (struct savewd *wd) case INITIAL_STATE: /* Save the working directory, or prepare to fall back if possible. */ { - int fd = open_safer (".", O_RDONLY); + int fd = open_safer (".", O_SEARCH); if (0 <= fd) { wd->state = FD_STATE; @@ -105,7 +105,7 @@ savewd_chdir (struct savewd *wd, char const *dir, int options, || (options & (HAVE_WORKING_O_NOFOLLOW ? SAVEWD_CHDIR_NOFOLLOW : 0))) { fd = open (dir, - (O_RDONLY | O_DIRECTORY | O_NOCTTY | O_NONBLOCK + (O_SEARCH | O_DIRECTORY | O_NOCTTY | O_NONBLOCK | (options & SAVEWD_CHDIR_NOFOLLOW ? O_NOFOLLOW : 0))); if (open_result)