# HG changeset patch # User Paul Eggert # Date 1283373953 25200 # Node ID acc972b5da60c83880d7b1bc21505232fcba9e13 # Parent 48942856d1d08065fae280c48ed7c773bb9e197e 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 --- 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 --- a/lib/chdir-long.c +++ b/lib/chdir-long.c @@ -72,7 +72,7 @@ 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 --- 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 --- a/lib/fcntl.in.h +++ b/lib/fcntl.in.h @@ -210,6 +210,10 @@ # 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 --- a/lib/fts.c +++ b/lib/fts.c @@ -347,7 +347,7 @@ 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 @@ 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 @@ 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 --- a/lib/openat-proc.c +++ b/lib/openat-proc.c @@ -75,7 +75,7 @@ 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 --- a/lib/openat.c +++ b/lib/openat.c @@ -244,7 +244,7 @@ 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 --- a/lib/save-cwd.c +++ b/lib/save-cwd.c @@ -76,7 +76,7 @@ { 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 --- a/lib/savewd.c +++ b/lib/savewd.c @@ -45,7 +45,7 @@ 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 @@ || (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)