doc: use ASCII in .texi files where UTF-8 isn't needed
[gnulib.git] / lib / savewd.c
index bd3d118..88c5fef 100644 (file)
@@ -1,11 +1,11 @@
 /* Save and restore the working directory, possibly using a child process.
 
-   Copyright (C) 2006 Free Software Foundation, Inc.
+   Copyright (C) 2006-2007, 2009-2014 Free Software Foundation, Inc.
 
-   This program is free software; you can redistribute it and/or modify
+   This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 2, or (at your option)
-   any later version.
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
 
    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    GNU General Public License for more details.
 
    You should have received a copy of the GNU General Public License
-   along with this program; if not, write to the Free Software Foundation,
-   Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  */
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
 
 /* Written by Paul Eggert.  */
 
 #include <config.h>
 
+#define SAVEWD_INLINE _GL_EXTERN_INLINE
+
 #include "savewd.h"
 
 #include <assert.h>
 #include <fcntl.h>
 #include <signal.h>
 #include <stdbool.h>
+#include <stdlib.h>
 #include <sys/types.h>
 #include <sys/wait.h>
 #include <unistd.h>
 
-#include "exit.h"
-#include "dirname.h"
+#include "dosname.h"
 #include "fcntl-safer.h"
 
-
 /* Save the working directory into *WD, if it hasn't been saved
    already.  Return true if a child has been forked to do the real
    work.  */
@@ -47,38 +47,38 @@ 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);
-       if (0 <= fd)
-         {
-           wd->state = FD_STATE;
-           wd->val.fd = fd;
-           break;
-         }
-       if (errno != EACCES)
-         {
-           wd->state = ERROR_STATE;
-           wd->val.errnum = errno;
-           break;
-         }
+        int fd = open_safer (".", O_SEARCH);
+        if (0 <= fd)
+          {
+            wd->state = FD_STATE;
+            wd->val.fd = fd;
+            break;
+          }
+        if (errno != EACCES && errno != ESTALE)
+          {
+            wd->state = ERROR_STATE;
+            wd->val.errnum = errno;
+            break;
+          }
       }
       wd->state = FORKING_STATE;
       wd->val.child = -1;
       /* Fall through.  */
     case FORKING_STATE:
       if (wd->val.child < 0)
-       {
-         /* "Save" the initial working directory by forking a new
-            subprocess that will attempt all the work from the chdir
-            until until the next savewd_restore.  */
-         wd->val.child = fork ();
-         if (wd->val.child != 0)
-           {
-             if (0 < wd->val.child)
-               return true;
-             wd->state = ERROR_STATE;
-             wd->val.errnum = errno;
-           }
-       }
+        {
+          /* "Save" the initial working directory by forking a new
+             subprocess that will attempt all the work from the chdir
+             until until the next savewd_restore.  */
+          wd->val.child = fork ();
+          if (wd->val.child != 0)
+            {
+              if (0 < wd->val.child)
+                return true;
+              wd->state = ERROR_STATE;
+              wd->val.errnum = errno;
+            }
+        }
       break;
 
     case FD_STATE:
@@ -96,60 +96,61 @@ savewd_save (struct savewd *wd)
 
 int
 savewd_chdir (struct savewd *wd, char const *dir, int options,
-             int open_result[2])
+              int open_result[2])
 {
   int fd = -1;
   int result = 0;
 
   /* Open the directory if requested, or if avoiding a race condition
      is requested and possible.  */
-  if (open_result || (options & (O_NOFOLLOW ? SAVEWD_CHDIR_NOFOLLOW : 0)))
+  if (open_result
+      || (options & (HAVE_WORKING_O_NOFOLLOW ? SAVEWD_CHDIR_NOFOLLOW : 0)))
     {
       fd = open (dir,
-                (O_RDONLY | O_DIRECTORY | O_NOCTTY | O_NONBLOCK
-                 | (options & SAVEWD_CHDIR_NOFOLLOW ? O_NOFOLLOW : 0)));
+                 (O_SEARCH | O_DIRECTORY | O_NOCTTY | O_NONBLOCK
+                  | (options & SAVEWD_CHDIR_NOFOLLOW ? O_NOFOLLOW : 0)));
 
       if (open_result)
-       {
-         open_result[0] = fd;
-         open_result[1] = errno;
-       }
+        {
+          open_result[0] = fd;
+          open_result[1] = errno;
+        }
 
       if (fd < 0 && (errno != EACCES || (options & SAVEWD_CHDIR_READABLE)))
-       result = -1;
+        result = -1;
     }
 
   if (result == 0 && ! (0 <= fd && options & SAVEWD_CHDIR_SKIP_READABLE))
     {
       if (savewd_save (wd))
-       {
-         open_result = NULL;
-         result = -2;
-       }
+        {
+          open_result = NULL;
+          result = -2;
+        }
       else
-       {
-         result = (fd < 0 ? chdir (dir) : fchdir (fd));
-
-         if (result == 0)
-           switch (wd->state)
-             {
-             case FD_STATE:
-               wd->state = FD_POST_CHDIR_STATE;
-               break;
-
-             case ERROR_STATE:
-             case FD_POST_CHDIR_STATE:
-             case FINAL_STATE:
-               break;
-
-             case FORKING_STATE:
-               assert (wd->val.child == 0);
-               break;
-
-             default:
-               assert (false);
-             }
-       }
+        {
+          result = (fd < 0 ? chdir (dir) : fchdir (fd));
+
+          if (result == 0)
+            switch (wd->state)
+              {
+              case FD_STATE:
+                wd->state = FD_POST_CHDIR_STATE;
+                break;
+
+              case ERROR_STATE:
+              case FD_POST_CHDIR_STATE:
+              case FINAL_STATE:
+                break;
+
+              case FORKING_STATE:
+                assert (wd->val.child == 0);
+                break;
+
+              default:
+                assert (false);
+              }
+        }
     }
 
   if (0 <= fd && ! open_result)
@@ -170,23 +171,23 @@ savewd_restore (struct savewd *wd, int status)
     case INITIAL_STATE:
     case FD_STATE:
       /* The working directory is the desired directory, so there's no
-        work to do.  */
+         work to do.  */
       break;
 
     case FD_POST_CHDIR_STATE:
       /* Restore the working directory using fchdir.  */
       if (fchdir (wd->val.fd) == 0)
-       {
-         wd->state = FD_STATE;
-         break;
-       }
+        {
+          wd->state = FD_STATE;
+          break;
+        }
       else
-       {
-         int chdir_errno = errno;
-         close (wd->val.fd);
-         wd->state = ERROR_STATE;
-         wd->val.errnum = chdir_errno;
-       }
+        {
+          int chdir_errno = errno;
+          close (wd->val.fd);
+          wd->state = ERROR_STATE;
+          wd->val.errnum = chdir_errno;
+        }
       /* Fall through.  */
     case ERROR_STATE:
       /* Report an error if asked to restore the working directory.  */
@@ -195,21 +196,21 @@ savewd_restore (struct savewd *wd, int status)
 
     case FORKING_STATE:
       /* "Restore" the working directory by waiting for the subprocess
-        to finish.  */
+         to finish.  */
       {
-       pid_t child = wd->val.child;
-       if (child == 0)
-         _exit (status);
-       if (0 < child)
-         {
-           int child_status;
-           while (waitpid (child, &child_status, 0) < 0)
-             assert (errno == EINTR);
-           wd->val.child = -1;
-           if (! WIFEXITED (child_status))
-             raise (WTERMSIG (child_status));
-           return WEXITSTATUS (child_status);
-         }
+        pid_t child = wd->val.child;
+        if (child == 0)
+          _exit (status);
+        if (0 < child)
+          {
+            int child_status;
+            while (waitpid (child, &child_status, 0) < 0)
+              assert (errno == EINTR);
+            wd->val.child = -1;
+            if (! WIFEXITED (child_status))
+              raise (WTERMSIG (child_status));
+            return WEXITSTATUS (child_status);
+          }
       }
       break;
 
@@ -255,7 +256,7 @@ savewd_finish (struct savewd *wd)
    This is why savewd_chdir is broken out into another function;
    savewd_chdir's callers _can_ inspect the file system to decide
    whether to call savewd_chdir.  */
-static inline bool
+static bool
 savewd_delegating (struct savewd const *wd)
 {
   return wd->state == FORKING_STATE && 0 < wd->val.child;
@@ -263,8 +264,8 @@ savewd_delegating (struct savewd const *wd)
 
 int
 savewd_process_files (int n_files, char **file,
-                     int (*act) (char *, struct savewd *, void *),
-                     void *options)
+                      int (*act) (char *, struct savewd *, void *),
+                      void *options)
 {
   int i = 0;
   int last_relative;
@@ -279,18 +280,18 @@ savewd_process_files (int n_files, char **file,
   for (; i < last_relative; i++)
     {
       if (! savewd_delegating (&wd))
-       {
-         int s = act (file[i], &wd, options);
-         if (exit_status < s)
-           exit_status = s;
-       }
+        {
+          int s = act (file[i], &wd, options);
+          if (exit_status < s)
+            exit_status = s;
+        }
 
       if (! IS_ABSOLUTE_FILE_NAME (file[i + 1]))
-       {
-         int r = savewd_restore (&wd, exit_status);
-         if (exit_status < r)
-           exit_status = r;
-       }
+        {
+          int r = savewd_restore (&wd, exit_status);
+          if (exit_status < r)
+            exit_status = r;
+        }
     }
 
   savewd_finish (&wd);
@@ -299,7 +300,7 @@ savewd_process_files (int n_files, char **file,
     {
       int s = act (file[i], &wd, options);
       if (exit_status < s)
-       exit_status = s;
+        exit_status = s;
     }
 
   return exit_status;