tweak diagnostic wording: Use `... return to working directory', rather
[platform/upstream/coreutils.git] / src / mkdir.c
index 3527e10..5fce2ce 100644 (file)
@@ -1,5 +1,5 @@
 /* mkdir -- make directories
-   Copyright (C) 90, 1995-2002 Free Software Foundation, Inc.
+   Copyright (C) 90, 1995-2002, 2004, 2005 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
@@ -13,7 +13,7 @@
 
    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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
+   Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  */
 
 /* David MacKenzie <djm@ai.mit.edu>  */
 
@@ -25,7 +25,7 @@
 #include "system.h"
 #include "dirname.h"
 #include "error.h"
-#include "makepath.h"
+#include "mkdir-p.h"
 #include "modechange.h"
 #include "quote.h"
 
@@ -37,8 +37,8 @@
 /* The name this program was run with. */
 char *program_name;
 
-/* If nonzero, ensure that all parents of the specified directory exist.  */
-static int create_parents;
+/* If true, ensure that all parents of the specified directory exist.  */
+static bool create_parents;
 
 static struct option const longopts[] =
 {
@@ -53,7 +53,7 @@ static struct option const longopts[] =
 void
 usage (int status)
 {
-  if (status != 0)
+  if (status != EXIT_SUCCESS)
     fprintf (stderr, _("Try `%s --help' for more information.\n"),
             program_name);
   else
@@ -82,11 +82,12 @@ int
 main (int argc, char **argv)
 {
   mode_t newmode;
-  mode_t parent_mode;
+  mode_t parent_mode IF_LINT (= 0);
   const char *specified_mode = NULL;
   const char *verbose_fmt_string = NULL;
-  int errors = 0;
+  int exit_status = EXIT_SUCCESS;
   int optc;
+  bool cwd_not_restored;
 
   initialize_main (&argc, &argv);
   program_name = argv[0];
@@ -96,16 +97,14 @@ main (int argc, char **argv)
 
   atexit (close_stdout);
 
-  create_parents = 0;
+  create_parents = false;
 
   while ((optc = getopt_long (argc, argv, "pm:v", longopts, NULL)) != -1)
     {
       switch (optc)
        {
-       case 0:                 /* Long option. */
-         break;
        case 'p':
-         create_parents = 1;
+         create_parents = true;
          break;
        case 'm':
          specified_mode = optarg;
@@ -122,44 +121,61 @@ main (int argc, char **argv)
 
   if (optind == argc)
     {
-      error (0, 0, _("too few arguments"));
+      error (0, 0, _("missing operand"));
       usage (EXIT_FAILURE);
     }
 
   newmode = S_IRWXUGO;
-  {
-    mode_t umask_value = umask (0);
-    umask (umask_value);               /* Restore the old value. */
-    parent_mode = (newmode & (~ umask_value)) | S_IWUSR | S_IXUSR;
-  }
 
-  if (specified_mode)
+  if (specified_mode || create_parents)
     {
-      struct mode_change *change = mode_compile (specified_mode, 0);
-      newmode &= ~ umask (0);
-      if (change == MODE_INVALID)
-       error (EXIT_FAILURE, 0, _("invalid mode %s"), quote (specified_mode));
-      else if (change == MODE_MEMORY_EXHAUSTED)
-       xalloc_die ();
-      newmode = mode_adjust (newmode, change);
+      mode_t umask_value = umask (0);
+
+      parent_mode = (S_IRWXUGO & ~umask_value) | (S_IWUSR | S_IXUSR);
+
+      if (specified_mode)
+       {
+         struct mode_change *change = mode_compile (specified_mode);
+         if (!change)
+           error (EXIT_FAILURE, 0, _("invalid mode %s"),
+                  quote (specified_mode));
+         newmode = mode_adjust (S_IRWXUGO, change, umask_value);
+         free (change);
+       }
+      else
+       umask (umask_value);
     }
 
+  /* FIXME: when we assume C99, declare this here.  */
+  cwd_not_restored = false;
   for (; optind < argc; ++optind)
     {
-      int fail = 0;
+      bool ok;
+
+      if (cwd_not_restored && IS_RELATIVE_FILE_NAME (argv[optind]))
+       {
+         error (0, 0, _("unable to create relative-named directory, %s,"
+                        " due to prior failure to return to working directory"),
+                quote (argv[optind]));
+         exit_status = EXIT_FAILURE;
+         continue;
+       }
 
       if (create_parents)
        {
+         bool different_cwd;
          char *dir = argv[optind];
-         fail = make_path (dir, newmode, parent_mode,
-                           -1, -1, 1, verbose_fmt_string);
+         ok = make_dir_parents (dir, newmode, parent_mode,
+                                -1, -1, true, verbose_fmt_string,
+                                &different_cwd);
+         cwd_not_restored |= different_cwd;
        }
       else
        {
          const char *dir = argv[optind];
-         int dir_created;
-         fail = make_dir (dir, dir, newmode, &dir_created);
-         if (fail)
+         bool dir_created;
+         ok = make_dir (dir, dir, newmode, &dir_created);
+         if (! ok)
            {
              /* make_dir already gave a diagnostic.  */
            }
@@ -170,7 +186,7 @@ main (int argc, char **argv)
                 was specified.  */
              error (0, EEXIST, _("cannot create directory %s"),
                     quote (dir));
-             fail = 1;
+             ok = false;
            }
          else if (verbose_fmt_string)
            error (0, 0, verbose_fmt_string, quote (dir));
@@ -184,18 +200,18 @@ main (int argc, char **argv)
          /* Set the permissions only if this directory has just
             been created.  */
 
-         if (fail == 0 && specified_mode && dir_created)
+         if (ok && specified_mode && dir_created
+             && chmod (dir, newmode) != 0)
            {
-             fail = chmod (dir, newmode);
-             if (fail)
-               error (0, errno, _("cannot set permissions of directory %s"),
-                      quote (dir));
+             error (0, errno, _("cannot set permissions of directory %s"),
+                    quote (dir));
+             ok = false;
            }
        }
 
-      if (fail)
-       errors = 1;
+      if (! ok)
+       exit_status = EXIT_FAILURE;
     }
 
-  exit (errors);
+  exit (exit_status);
 }