bug-gnulib
[Top][All Lists]
Advanced

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

openat: don't exit program if save_cwd fails


From: Paul Eggert
Subject: openat: don't exit program if save_cwd fails
Date: Thu, 24 Jan 2013 09:47:51 -0800
User-agent: Mozilla/5.0 (X11; Linux x86_64; rv:17.0) Gecko/20130110 Thunderbird/17.0.2

I found this problem while looking into Bug#13516
<http://bugs.gnu.org/13515>.  Currently, the openat
emulator exits the program if savedir fails, but it's
nicer if it merely causes openat to fail.  If savedir
fails, no harm has been done yet -- the program's
working directory has not changed, so there's no need
to do something as drastic as exit the program.

Here's a proposed patch.  It also fixes some more-obscure
issues in functions like linkat.  I suppose I could pull
them out as a separate patch but I'm not sure it's worth
the trouble.

openat: don't exit program if save_cwd fails
* lib/at-func.c (AT_FUNC_NAME):
* lib/at-func2.c (at_func2):
* lib/openat.c (openat_permissive):
If save_cwd fails, simply return a failure rather than exiting the
program.  No harm has been done yet, since we haven't used chdir.
* lib/at-func2.c (at_func2): Simplify, and fix bugs whereby the
code would leave the application in the wrong directory (!) in
some tricky failure cases.
diff --git a/lib/at-func.c b/lib/at-func.c
index 03c5678..aa94561 100644
--- a/lib/at-func.c
+++ b/lib/at-func.c
@@ -108,7 +108,7 @@ AT_FUNC_NAME (int fd, char const *file 
AT_FUNC_POST_FILE_PARAM_DECLS)
   }

   if (save_cwd (&saved_cwd) != 0)
-    openat_save_fail (errno);
+    return FUNC_FAIL;
   if (0 <= fd && fd == saved_cwd.desc)
     {
       /* If saving the working directory collides with the user's
diff --git a/lib/at-func2.c b/lib/at-func2.c
index bbbddc0..169d886 100644
--- a/lib/at-func2.c
+++ b/lib/at-func2.c
@@ -180,7 +180,7 @@ at_func2 (int fd1, char const *file1,
      place, it is time to start changing directories.  */

   if (save_cwd (&saved_cwd) != 0)
-    openat_save_fail (errno);
+    return -1;

   if (fd1 != AT_FDCWD && fd2 != AT_FDCWD && fd1 != fd2) /* Case 15b.  */
     {
@@ -199,6 +199,7 @@ at_func2 (int fd1, char const *file1,

   file1_alt = (char *) file1;
   file2_alt = (char *) file2;
+  saved_errno = 0;

   if (fd1 == AT_FDCWD && !IS_ABSOLUTE_FILE_NAME (file1)) /* Case 7.  */
     {
@@ -207,63 +208,41 @@ at_func2 (int fd1, char const *file1,
          but libraries should not call xalloc_die.  */
       char *cwd = getcwd (NULL, 0);
       if (!cwd)
+        saved_errno = errno;
+      else
         {
-          saved_errno = errno;
-          free_cwd (&saved_cwd);
-          errno = saved_errno;
-          return -1;
-        }
-      file1_alt = mfile_name_concat (cwd, file1, NULL);
-      if (!file1_alt)
-        {
-          saved_errno = errno;
+          file1_alt = mfile_name_concat (cwd, file1, NULL);
+          if (!file1_alt)
+            saved_errno = errno;
           free (cwd);
-          free_cwd (&saved_cwd);
-          errno = saved_errno;
-          return -1;
         }
-      free (cwd); /* Reduced to case 3.  */
+      /* Reduced to case 3.  */
     }
   else if (fd2 == AT_FDCWD && !IS_ABSOLUTE_FILE_NAME (file2)) /* Case 13.  */
     {
       char *cwd = getcwd (NULL, 0);
       if (!cwd)
+        saved_errno = errno;
+      else
         {
-          saved_errno = errno;
-          free_cwd (&saved_cwd);
-          errno = saved_errno;
-          return -1;
-        }
-      file2_alt = mfile_name_concat (cwd, file2, NULL);
-      if (!file2_alt)
-        {
-          saved_errno = errno;
+          file2_alt = mfile_name_concat (cwd, file2, NULL);
+          if (!file2_alt)
+            saved_errno = errno;
           free (cwd);
-          free_cwd (&saved_cwd);
-          errno = saved_errno;
-          return -1;
         }
-      free (cwd); /* Reduced to case 12.  */
+      /* Reduced to case 12.  */
     }

-  /* Cases 3, 12, 15a remain.  Change to the correct directory.  */
-  if (fchdir (fd1 == AT_FDCWD ? fd2 : fd1) != 0)
+  err = -1;
+  if (! saved_errno)
     {
+      /* Cases 3, 12, 15a remain.  Change to the correct directory
+         and perform the user's function.  */
+      if (fchdir (fd1 == AT_FDCWD ? fd2 : fd1) == 0)
+        err = func (file1_alt, file2_alt);
       saved_errno = errno;
-      free_cwd (&saved_cwd);
-      if (file1 != file1_alt)
-        free (file1_alt);
-      else if (file2 != file2_alt)
-        free (file2_alt);
-      errno = saved_errno;
-      return -1;
     }

-  /* Finally safe to perform the user's function, then clean up.  */
-
-  err = func (file1_alt, file2_alt);
-  saved_errno = (err < 0 ? errno : 0);
-
   if (file1 != file1_alt)
     free (file1_alt);
   else if (file2 != file2_alt)
@@ -274,8 +253,7 @@ at_func2 (int fd1, char const *file1,

   free_cwd (&saved_cwd);

-  if (saved_errno)
-    errno = saved_errno;
+  errno = saved_errno;
   return err;
 }
 #undef CALL_FUNC
diff --git a/lib/openat.c b/lib/openat.c
index fd1ff91..7ea0e58 100644
--- a/lib/openat.c
+++ b/lib/openat.c
@@ -220,7 +220,7 @@ openat_permissive (int fd, char const *file, int flags, 
mode_t mode,
   if (! save_ok)
     {
       if (! cwd_errno)
-        openat_save_fail (errno);
+        return -1;
       *cwd_errno = errno;
     }
   if (0 <= fd && fd == saved_cwd.desc)



reply via email to

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