imaxdiv: Avoid link error on OSF/1 with DTK cc.
[gnulib.git] / lib / mkdir-p.c
index f38dbc7..566aadb 100644 (file)
@@ -1,7 +1,7 @@
 /* mkdir-p.c -- Ensure that a directory and its parents exist.
 
-   Copyright (C) 1990, 1997, 1998, 1999, 2000, 2002, 2003, 2004, 2005,
-   2006, 2007 Free Software Foundation, Inc.
+   Copyright (C) 1990, 1997-2000, 2002-2007, 2009-2011 Free Software
+   Foundation, Inc.
 
    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
 
 bool
 make_dir_parents (char *dir,
-                 struct savewd *wd,
-                 int (*make_ancestor) (char const *, char const *, void *),
-                 void *options,
-                 mode_t mode,
-                 void (*announce) (char const *, void *),
-                 mode_t mode_bits,
-                 uid_t owner,
-                 gid_t group,
-                 bool preserve_existing)
+                  struct savewd *wd,
+                  int (*make_ancestor) (char const *, char const *, void *),
+                  void *options,
+                  mode_t mode,
+                  void (*announce) (char const *, void *),
+                  mode_t mode_bits,
+                  uid_t owner,
+                  gid_t group,
+                  bool preserve_existing)
 {
   int mkdir_errno = (IS_ABSOLUTE_FILE_NAME (dir) ? 0 : savewd_errno (wd));
 
@@ -102,105 +102,105 @@ make_dir_parents (char *dir,
       int savewd_chdir_options = (HAVE_FCHMOD ? SAVEWD_CHDIR_SKIP_READABLE : 0);
 
       if (make_ancestor)
-       {
-         prefix_len = mkancesdirs (dir, wd, make_ancestor, options);
-         if (prefix_len < 0)
-           {
-             if (prefix_len < -1)
-               return true;
-             mkdir_errno = errno;
-           }
-       }
+        {
+          prefix_len = mkancesdirs (dir, wd, make_ancestor, options);
+          if (prefix_len < 0)
+            {
+              if (prefix_len < -1)
+                return true;
+              mkdir_errno = errno;
+            }
+        }
 
       if (0 <= prefix_len)
-       {
-         /* If the ownership might change, or if the directory will be
-            writeable to other users and its special mode bits may
-            change after the directory is created, create it with
-            more restrictive permissions at first, so unauthorized
-            users cannot nip in before the directory is ready.  */
-         bool keep_owner = owner == (uid_t) -1 && group == (gid_t) -1;
-         bool keep_special_mode_bits =
-           ((mode_bits & (S_ISUID | S_ISGID)) | (mode & S_ISVTX)) == 0;
-         mode_t mkdir_mode = mode;
-         if (! keep_owner)
-           mkdir_mode &= ~ (S_IRWXG | S_IRWXO);
-         else if (! keep_special_mode_bits)
-           mkdir_mode &= ~ (S_IWGRP | S_IWOTH);
-
-         if (mkdir (dir + prefix_len, mkdir_mode) == 0)
-           {
-             announce (dir, options);
-             preserve_existing = keep_owner & keep_special_mode_bits;
-             savewd_chdir_options |=
-               (SAVEWD_CHDIR_NOFOLLOW
-                | (mode & S_IRUSR ? SAVEWD_CHDIR_READABLE : 0));
-           }
-         else
-           {
-             mkdir_errno = errno;
-             mkdir_mode = -1;
-           }
-
-         if (preserve_existing)
-           {
-             struct stat st;
-             if (mkdir_errno == 0
-                 || (mkdir_errno != ENOENT && make_ancestor
-                     && stat (dir + prefix_len, &st) == 0
-                     && S_ISDIR (st.st_mode)))
-               return true;
-           }
-         else
-           {
-             int open_result[2];
-             int chdir_result =
-               savewd_chdir (wd, dir + prefix_len,
-                             savewd_chdir_options, open_result);
-             if (chdir_result < -1)
-               return true;
-             else
-               {
-                 bool chdir_ok = (chdir_result == 0);
-                 int chdir_errno = errno;
-                 int fd = open_result[0];
-                 bool chdir_failed_unexpectedly =
-                   (mkdir_errno == 0
-                    && ((! chdir_ok && (mode & S_IXUSR))
-                        || (fd < 0 && (mode & S_IRUSR))));
-
-                 if (chdir_failed_unexpectedly)
-                   {
-                     /* No need to save errno here; it's irrelevant.  */
-                     if (0 <= fd)
-                       close (fd);
-                   }
-                 else
-                   {
-                     char const *subdir = (chdir_ok ? "." : dir + prefix_len);
-                     if (dirchownmod (fd, subdir, mkdir_mode, owner, group,
-                                      mode, mode_bits)
-                         == 0)
-                       return true;
-                   }
-
-                 if (mkdir_errno == 0
-                     || (mkdir_errno != ENOENT && make_ancestor
-                         && errno != ENOTDIR))
-                   {
-                     error (0,
-                            (! chdir_failed_unexpectedly ? errno
-                             : ! chdir_ok && (mode & S_IXUSR) ? chdir_errno
-                             : open_result[1]),
-                            _(keep_owner
-                              ? "cannot change permissions of %s"
-                              : "cannot change owner and permissions of %s"),
-                            quote (dir));
-                     return false;
-                   }
-               }
-           }
-       }
+        {
+          /* If the ownership might change, or if the directory will be
+             writeable to other users and its special mode bits may
+             change after the directory is created, create it with
+             more restrictive permissions at first, so unauthorized
+             users cannot nip in before the directory is ready.  */
+          bool keep_owner = owner == (uid_t) -1 && group == (gid_t) -1;
+          bool keep_special_mode_bits =
+            ((mode_bits & (S_ISUID | S_ISGID)) | (mode & S_ISVTX)) == 0;
+          mode_t mkdir_mode = mode;
+          if (! keep_owner)
+            mkdir_mode &= ~ (S_IRWXG | S_IRWXO);
+          else if (! keep_special_mode_bits)
+            mkdir_mode &= ~ (S_IWGRP | S_IWOTH);
+
+          if (mkdir (dir + prefix_len, mkdir_mode) == 0)
+            {
+              announce (dir, options);
+              preserve_existing = keep_owner & keep_special_mode_bits;
+              savewd_chdir_options |=
+                (SAVEWD_CHDIR_NOFOLLOW
+                 | (mode & S_IRUSR ? SAVEWD_CHDIR_READABLE : 0));
+            }
+          else
+            {
+              mkdir_errno = errno;
+              mkdir_mode = -1;
+            }
+
+          if (preserve_existing)
+            {
+              struct stat st;
+              if (mkdir_errno == 0
+                  || (mkdir_errno != ENOENT && make_ancestor
+                      && stat (dir + prefix_len, &st) == 0
+                      && S_ISDIR (st.st_mode)))
+                return true;
+            }
+          else
+            {
+              int open_result[2];
+              int chdir_result =
+                savewd_chdir (wd, dir + prefix_len,
+                              savewd_chdir_options, open_result);
+              if (chdir_result < -1)
+                return true;
+              else
+                {
+                  bool chdir_ok = (chdir_result == 0);
+                  int chdir_errno = errno;
+                  int fd = open_result[0];
+                  bool chdir_failed_unexpectedly =
+                    (mkdir_errno == 0
+                     && ((! chdir_ok && (mode & S_IXUSR))
+                         || (fd < 0 && (mode & S_IRUSR))));
+
+                  if (chdir_failed_unexpectedly)
+                    {
+                      /* No need to save errno here; it's irrelevant.  */
+                      if (0 <= fd)
+                        close (fd);
+                    }
+                  else
+                    {
+                      char const *subdir = (chdir_ok ? "." : dir + prefix_len);
+                      if (dirchownmod (fd, subdir, mkdir_mode, owner, group,
+                                       mode, mode_bits)
+                          == 0)
+                        return true;
+                    }
+
+                  if (mkdir_errno == 0
+                      || (mkdir_errno != ENOENT && make_ancestor
+                          && errno != ENOTDIR))
+                    {
+                      error (0,
+                             (! chdir_failed_unexpectedly ? errno
+                              : ! chdir_ok && (mode & S_IXUSR) ? chdir_errno
+                              : open_result[1]),
+                             _(keep_owner
+                               ? "cannot change permissions of %s"
+                               : "cannot change owner and permissions of %s"),
+                             quote (dir));
+                      return false;
+                    }
+                }
+            }
+        }
     }
 
   error (0, mkdir_errno, _("cannot create directory %s"), quote (dir));