* src/install.c (make_ancestor): New arg COMPONENT.
authorPaul Eggert <eggert@cs.ucla.edu>
Sat, 7 Oct 2006 07:08:29 +0000 (07:08 +0000)
committerPaul Eggert <eggert@cs.ucla.edu>
Sat, 7 Oct 2006 07:08:29 +0000 (07:08 +0000)
* src/mkdir.c (make_ancestor): Likewise.
* tests/install/basic-1: Check for install -Dv bug.

ChangeLog
src/install.c
src/mkdir.c
tests/install/basic-1

index 84c9d86..d296d44 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -2,14 +2,9 @@
 
        Fix bug reported today by Mike Frysinger: mkdir -pv is logging the
        wrong file name in some cases.
-       * src/install.c (struct install_options): New type.
-       (install_file_in_file_parents, main):
-       Use it instead of struct cp_options.
-       (process_dir): Remember the full name.
-       (announce_mkdir, make_ancestor): Use the full name in announcements.
-       * src/mkdir.c (struct mkdir_options): Add full_name member.
-       (make_ancestor): Use the full name in announcements.
-       (process_dir): Remember the full name.
+       * src/install.c (make_ancestor): New arg COMPONENT.
+       * src/mkdir.c (make_ancestor): Likewise.
+       * tests/install/basic-1: Check for install -Dv bug.
        * tests/mkdir/Makefile.am (TESTS): Add p-v.
        * tests/mkdir/p-v: New file, to test this bug.
 
index aabbafa..1ccc774 100644 (file)
 /* Number of bytes of a file to copy at a time. */
 #define READ_SIZE (32 * 1024)
 
-/* Options passed to subsidiary functions.  */
-struct install_options
-{
-  /* Full name of file being installed.  */
-  char const *full_name;
-
-  /* Options for cp-related code.  */
-  struct cp_options cp;
-};
-
 static bool change_timestamps (struct stat const *from_sb, char const *to);
 static bool change_attributes (char const *name);
 static bool copy_file (const char *from, const char *to,
                       const struct cp_options *x);
 static bool install_file_in_file_parents (char const *from, char *to,
-                                         struct install_options *x);
+                                         struct cp_options *x);
 static bool install_file_in_dir (const char *from, const char *to_dir,
                                 const struct cp_options *x);
 static bool install_file_in_file (const char *from, const char *to,
@@ -89,7 +79,8 @@ static bool install_file_in_file (const char *from, const char *to,
 static void get_ids (void);
 static void strip (char const *name);
 static void announce_mkdir (char const *dir, void *options);
-static int make_ancestor (char const *dir, void *options);
+static int make_ancestor (char const *dir, char const *component,
+                         void *options);
 void usage (int status);
 
 /* The name this program was run with, for error messages. */
@@ -208,8 +199,6 @@ target_directory_operand (char const *file)
 static int
 process_dir (char *dir, struct savewd *wd, void *options)
 {
-  struct install_options *o = options;
-  o->full_name = dir;
   return (make_dir_parents (dir, wd,
                            make_ancestor, options,
                            dir_mode, announce_mkdir,
@@ -228,7 +217,7 @@ main (int argc, char **argv)
   char *backup_suffix_string;
   char *version_control_string = NULL;
   bool mkdir_and_install = false;
-  struct install_options x;
+  struct cp_options x;
   char const *target_directory = NULL;
   bool no_target_directory = false;
   int n_files;
@@ -242,7 +231,7 @@ main (int argc, char **argv)
 
   atexit (close_stdout);
 
-  cp_option_init (&x.cp);
+  cp_option_init (&x);
 
   owner_name = NULL;
   group_name = NULL;
@@ -280,7 +269,7 @@ main (int argc, char **argv)
          mkdir_and_install = true;
          break;
        case 'v':
-         x.cp.verbose = true;
+         x.verbose = true;
          break;
        case 'g':
          group_name = optarg;
@@ -292,7 +281,7 @@ main (int argc, char **argv)
          owner_name = optarg;
          break;
        case 'p':
-         x.cp.preserve_timestamps = true;
+         x.preserve_timestamps = true;
          break;
        case 'S':
          make_backups = true;
@@ -334,10 +323,10 @@ main (int argc, char **argv)
   if (backup_suffix_string)
     simple_backup_suffix = xstrdup (backup_suffix_string);
 
-  x.cp.backup_type = (make_backups
-                     ? xget_version (_("backup type"),
-                                     version_control_string)
-                     : no_backups);
+  x.backup_type = (make_backups
+                  ? xget_version (_("backup type"),
+                                  version_control_string)
+                  : no_backups);
 
   n_files = argc - optind;
   file = argv + optind;
@@ -397,15 +386,15 @@ main (int argc, char **argv)
         {
           if (! (mkdir_and_install
                 ? install_file_in_file_parents (file[0], file[1], &x)
-                : install_file_in_file (file[0], file[1], &x.cp)))
+                : install_file_in_file (file[0], file[1], &x)))
            exit_status = EXIT_FAILURE;
        }
       else
        {
          int i;
-         dest_info_init (&x.cp);
+         dest_info_init (&x);
          for (i = 0; i < n_files; i++)
-           if (! install_file_in_dir (file[i], target_directory, &x.cp))
+           if (! install_file_in_dir (file[i], target_directory, &x))
              exit_status = EXIT_FAILURE;
        }
     }
@@ -418,7 +407,7 @@ main (int argc, char **argv)
 
 static bool
 install_file_in_file_parents (char const *from, char *to,
-                             struct install_options *x)
+                             struct cp_options *x)
 {
   bool save_working_directory =
     ! (IS_ABSOLUTE_FILE_NAME (from) && IS_ABSOLUTE_FILE_NAME (to));
@@ -449,7 +438,7 @@ install_file_in_file_parents (char const *from, char *to,
        }
     }
 
-  return (status == EXIT_SUCCESS && install_file_in_file (from, to, &x->cp));
+  return (status == EXIT_SUCCESS && install_file_in_file (from, to, x));
 }
 
 /* Copy file FROM onto file TO and give TO the appropriate
@@ -636,19 +625,20 @@ get_ids (void)
 static void
 announce_mkdir (char const *dir, void *options)
 {
-  struct install_options const *x = options;
-  if (x->cp.verbose)
+  struct cp_options const *x = options;
+  if (x->verbose)
     error (0, 0, _("creating directory %s"), quote (dir));
 }
 
-/* Make ancestor directory DIR, with options OPTIONS.  */
+/* Make ancestor directory DIR, whose last file name component is
+   COMPONENT, with options OPTIONS.  Assume the working directory is
+   COMPONENT's parent.  */
 static int
-make_ancestor (char const *dir, void *options)
+make_ancestor (char const *dir, char const *component, void *options)
 {
-  struct install_options const *x = options;
-  int r = mkdir (dir, DEFAULT_MODE);
+  int r = mkdir (component, DEFAULT_MODE);
   if (r == 0)
-    announce_mkdir (x->full_name, options);
+    announce_mkdir (dir, options);
   return r;
 }
 
index f8a0625..6fa0ac2 100644 (file)
@@ -79,12 +79,9 @@ Mandatory arguments to long options are mandatory for short options too.\n\
 /* Options passed to subsidiary functions.  */
 struct mkdir_options
 {
-  /* Full name of directory that we are making.  */
-  char const *full_name;
-
   /* Function to make an ancestor, or NULL if ancestors should not be
      made.  */
-  int (*make_ancestor_function) (char const *, void *);
+  int (*make_ancestor_function) (char const *, char const *, void *);
 
   /* Mode for ancestor directory.  */
   mode_t ancestor_mode;
@@ -108,19 +105,20 @@ announce_mkdir (char const *dir, void *options)
     error (0, 0, o->created_directory_format, quote (dir));
 }
 
-/* Make ancestor directory DIR, with options OPTIONS.  Return 0 if
-   successful and the resulting directory is readable, 1 if successful
-   but the resulting directory is not readable, -1 (setting errno)
-   otherwise.  */
+/* Make ancestor directory DIR, whose last component is COMPONENT,
+   with options OPTIONS.  Assume the working directory is COMPONENT's
+   parent.  Return 0 if successful and the resulting directory is
+   readable, 1 if successful but the resulting directory is not
+   readable, -1 (setting errno) otherwise.  */
 static int
-make_ancestor (char const *dir, void *options)
+make_ancestor (char const *dir, char const *component, void *options)
 {
   struct mkdir_options const *o = options;
-  int r = mkdir (dir, o->ancestor_mode);
+  int r = mkdir (component, o->ancestor_mode);
   if (r == 0)
     {
       r = ! (o->ancestor_mode & S_IRUSR);
-      announce_mkdir (o->full_name, options);
+      announce_mkdir (dir, options);
     }
   return r;
 }
@@ -129,8 +127,7 @@ make_ancestor (char const *dir, void *options)
 static int
 process_dir (char *dir, struct savewd *wd, void *options)
 {
-  struct mkdir_options *o = options;
-  o->full_name = dir;
+  struct mkdir_options const *o = options;
   return (make_dir_parents (dir, wd, o->make_ancestor_function, options,
                            o->mode, announce_mkdir,
                            o->mode_bits, (uid_t) -1, (gid_t) -1, true)
index 55f0b51..84a9434 100755 (executable)
@@ -24,6 +24,14 @@ if test "$VERBOSE" = yes; then
   ginstall --version
 fi
 
+# Make sure we get English translations.
+LANGUAGE=C
+export LANGUAGE
+LC_ALL=C
+export LC_ALL
+LANG=C
+export LANG
+
 . $srcdir/../envvar-check
 PRIV_CHECK_ARG=require-non-root . $srcdir/../priv-check
 
@@ -130,4 +138,14 @@ test -d xx/zz || fail=1
 test -d sub1/d/rel/a || fail=1
 test -d sub1/d/rel/b || fail=1
 
+touch file || fail=1
+ginstall -Dv file sub3/a/b/c/file >out 2>&1 || fail=1
+diff - out <<\EOF || fail=1
+ginstall: creating directory `sub3'
+ginstall: creating directory `sub3/a'
+ginstall: creating directory `sub3/a/b'
+ginstall: creating directory `sub3/a/b/c'
+`file' -> `sub3/a/b/c/file'
+EOF
+
 (exit $fail); exit $fail