tweak diagnostic wording: Use `... return to working directory', rather
[platform/upstream/coreutils.git] / src / mkdir.c
index 419bda7..5fce2ce 100644 (file)
@@ -1,5 +1,5 @@
 /* mkdir -- make directories
-   Copyright (C) 90, 1995-2001 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"
 
 
 #define AUTHORS "David MacKenzie"
 
-void strip_trailing_slashes ();
-
 /* 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[] =
 {
@@ -55,22 +53,27 @@ 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
     {
       printf (_("Usage: %s [OPTION] DIRECTORY...\n"), program_name);
-      printf (_("\
+      fputs (_("\
 Create the DIRECTORY(ies), if they do not already exist.\n\
 \n\
+"), stdout);
+      fputs (_("\
+Mandatory arguments to long options are mandatory for short options too.\n\
+"), stdout);
+      fputs (_("\
   -m, --mode=MODE   set permission mode (as in chmod), not rwxrwxrwx - umask\n\
   -p, --parents     no error if existing, make parent directories as needed\n\
   -v, --verbose     print a message for each created directory\n\
-      --help        display this help and exit\n\
-      --version     output version information and exit\n\
-"));
-      puts (_("\nReport bugs to <bug-fileutils@gnu.org>."));
+"), stdout);
+      fputs (HELP_OPTION_DESCRIPTION, stdout);
+      fputs (VERSION_OPTION_DESCRIPTION, stdout);
+      printf (_("\nReport bugs to <%s>.\n"), PACKAGE_BUGREPORT);
     }
   exit (status);
 }
@@ -79,12 +82,14 @@ 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];
   setlocale (LC_ALL, "");
   bindtextdomain (PACKAGE, LOCALEDIR);
@@ -92,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;
@@ -112,58 +115,67 @@ main (int argc, char **argv)
        case_GETOPT_HELP_CHAR;
        case_GETOPT_VERSION_CHAR (PROGRAM_NAME, AUTHORS);
        default:
-         usage (1);
+         usage (EXIT_FAILURE);
        }
     }
 
   if (optind == argc)
     {
-      error (0, 0, _("too few arguments"));
-      usage (1);
+      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 (1, 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;
 
-      /* Remove any trailing slashes.  Not removing them would lead to calling
-        `mkdir ("dir/", mode)' for e.g., the commands `mkdir dir/' and
-        `mkdir -p dir/', and such a call fails on NetBSD systems when `dir'
-        doesn't already exist.  */
-      strip_trailing_slashes (argv[optind]);
+      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)
        {
-         char *parents = dir_name (argv[optind]);
-         fail = make_path (parents, parent_mode, parent_mode,
-                           -1, -1, 1, verbose_fmt_string);
-         free (parents);
+         bool different_cwd;
+         char *dir = argv[optind];
+         ok = make_dir_parents (dir, newmode, parent_mode,
+                                -1, -1, true, verbose_fmt_string,
+                                &different_cwd);
+         cwd_not_restored |= different_cwd;
        }
-
-      if (fail == 0)
+      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.  */
            }
@@ -174,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));
@@ -188,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);
 }