bug-gnulib
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[PATCH] fcntl-h, etc.: prefer O_SEARCH to O_RDONLY when applicable


From: Paul Eggert
Subject: [PATCH] fcntl-h, etc.: prefer O_SEARCH to O_RDONLY when applicable
Date: Wed, 01 Sep 2010 13:49:45 -0700
User-agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.1.11) Gecko/20100713 Thunderbird/3.0.6

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.
---
 ChangeLog         |   22 ++++++++++++++++++++++
 lib/chdir-long.c  |    2 +-
 lib/chdir-safer.c |   11 +++++++----
 lib/fcntl.in.h    |    4 ++++
 lib/fts.c         |    6 +++---
 lib/openat-proc.c |    2 +-
 lib/openat.c      |    2 +-
 lib/save-cwd.c    |    2 +-
 lib/savewd.c      |    4 ++--
 9 files changed, 42 insertions(+), 13 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index 35d2ce0..2d03ea7 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,25 @@
+2010-09-01  Paul Eggert  <address@hidden>
+
+       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  <address@hidden>
 
        New module 'host-cpu-c-abi'.
diff --git a/lib/chdir-long.c b/lib/chdir-long.c
index 28e2407..a88e27f 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 b3266b5..61c71c6 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 8fb7852..42fb81b 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 e4351f8..a308a8c 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 2538412..76fe42c 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 f2eac86..9970e46 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 cf43a35..8e636c2 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 e111207..9ec9877 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)
-- 
1.7.2




reply via email to

[Prev in Thread] Current Thread [Next in Thread]