diff options
-rw-r--r-- | ChangeLog | 15 | ||||
-rw-r--r-- | src/install.c | 47 | ||||
-rw-r--r-- | src/mkdir.c | 8 | ||||
-rw-r--r-- | tests/mkdir/Makefile.am | 2 | ||||
-rwxr-xr-x | tests/mkdir/p-v | 56 |
5 files changed, 108 insertions, 20 deletions
@@ -1,3 +1,18 @@ +2006-10-06 Paul Eggert <eggert@cs.ucla.edu> + + 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. + * tests/mkdir/Makefile.am (TESTS): Add p-v. + * tests/mkdir/p-v: New file, to test this bug. + 2006-10-05 Paul Eggert <eggert@cs.ucla.edu> * src/chgrp.c: Don't include lchown.h; no longer needed. diff --git a/src/install.c b/src/install.c index 9c5150fbc..aabbafaf0 100644 --- a/src/install.c +++ b/src/install.c @@ -66,12 +66,22 @@ /* 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 cp_options *x); + struct install_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, @@ -198,6 +208,8 @@ 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, @@ -216,7 +228,7 @@ main (int argc, char **argv) char *backup_suffix_string; char *version_control_string = NULL; bool mkdir_and_install = false; - struct cp_options x; + struct install_options x; char const *target_directory = NULL; bool no_target_directory = false; int n_files; @@ -230,7 +242,7 @@ main (int argc, char **argv) atexit (close_stdout); - cp_option_init (&x); + cp_option_init (&x.cp); owner_name = NULL; group_name = NULL; @@ -268,7 +280,7 @@ main (int argc, char **argv) mkdir_and_install = true; break; case 'v': - x.verbose = true; + x.cp.verbose = true; break; case 'g': group_name = optarg; @@ -280,7 +292,7 @@ main (int argc, char **argv) owner_name = optarg; break; case 'p': - x.preserve_timestamps = true; + x.cp.preserve_timestamps = true; break; case 'S': make_backups = true; @@ -322,10 +334,10 @@ main (int argc, char **argv) if (backup_suffix_string) simple_backup_suffix = xstrdup (backup_suffix_string); - x.backup_type = (make_backups - ? xget_version (_("backup type"), - version_control_string) - : no_backups); + x.cp.backup_type = (make_backups + ? xget_version (_("backup type"), + version_control_string) + : no_backups); n_files = argc - optind; file = argv + optind; @@ -385,15 +397,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))) + : install_file_in_file (file[0], file[1], &x.cp))) exit_status = EXIT_FAILURE; } else { int i; - dest_info_init (&x); + dest_info_init (&x.cp); for (i = 0; i < n_files; i++) - if (! install_file_in_dir (file[i], target_directory, &x)) + if (! install_file_in_dir (file[i], target_directory, &x.cp)) exit_status = EXIT_FAILURE; } } @@ -406,7 +418,7 @@ main (int argc, char **argv) static bool install_file_in_file_parents (char const *from, char *to, - struct cp_options *x) + struct install_options *x) { bool save_working_directory = ! (IS_ABSOLUTE_FILE_NAME (from) && IS_ABSOLUTE_FILE_NAME (to)); @@ -437,7 +449,7 @@ install_file_in_file_parents (char const *from, char *to, } } - return (status == EXIT_SUCCESS && install_file_in_file (from, to, x)); + return (status == EXIT_SUCCESS && install_file_in_file (from, to, &x->cp)); } /* Copy file FROM onto file TO and give TO the appropriate @@ -624,8 +636,8 @@ get_ids (void) static void announce_mkdir (char const *dir, void *options) { - struct cp_options const *x = options; - if (x->verbose) + struct install_options const *x = options; + if (x->cp.verbose) error (0, 0, _("creating directory %s"), quote (dir)); } @@ -633,9 +645,10 @@ announce_mkdir (char const *dir, void *options) static int make_ancestor (char const *dir, void *options) { + struct install_options const *x = options; int r = mkdir (dir, DEFAULT_MODE); if (r == 0) - announce_mkdir (dir, options); + announce_mkdir (x->full_name, options); return r; } diff --git a/src/mkdir.c b/src/mkdir.c index b28a02ac0..f8a0625a2 100644 --- a/src/mkdir.c +++ b/src/mkdir.c @@ -79,6 +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 *); @@ -117,7 +120,7 @@ make_ancestor (char const *dir, void *options) if (r == 0) { r = ! (o->ancestor_mode & S_IRUSR); - announce_mkdir (dir, options); + announce_mkdir (o->full_name, options); } return r; } @@ -126,7 +129,8 @@ make_ancestor (char const *dir, void *options) static int process_dir (char *dir, struct savewd *wd, void *options) { - struct mkdir_options const *o = options; + struct mkdir_options *o = options; + o->full_name = dir; 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) diff --git a/tests/mkdir/Makefile.am b/tests/mkdir/Makefile.am index 7512f7b4b..7f4351655 100644 --- a/tests/mkdir/Makefile.am +++ b/tests/mkdir/Makefile.am @@ -3,7 +3,7 @@ AUTOMAKE_OPTIONS = 1.1 gnits TESTS = \ p-thru-slink \ - p-3 p-1 p-2 special-1 perm parents t-slash p-slashdot + p-3 p-1 p-2 p-v special-1 perm parents t-slash p-slashdot EXTRA_DIST = $(TESTS) TESTS_ENVIRONMENT = \ srcdir=$(srcdir) \ diff --git a/tests/mkdir/p-v b/tests/mkdir/p-v new file mode 100755 index 000000000..c80e0acda --- /dev/null +++ b/tests/mkdir/p-v @@ -0,0 +1,56 @@ +#!/bin/sh +# Test mkdir -pv. + +# Copyright (C) 2006 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 +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. + +# 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., 51 Franklin Street, Fifth Floor, Boston, MA +# 02110-1301, USA. + +if test "$VERBOSE" = yes; then + set -x + mkdir --version +fi + +# Make sure we get English translations. +LANGUAGE=C +export LANGUAGE +LC_ALL=C +export LC_ALL +LANG=C +export LANG + +pwd=`pwd` +t0=`echo "$0"|sed 's,.*/,,'`.tmp; tmp=$t0/$$ +trap 'status=$?; cd $pwd; rm -rf $t0 && exit $status' 0 +trap '(exit $?); exit $?' 1 2 13 15 + +framework_failure=0 +mkdir -p $tmp || framework_failure=1 +cd $tmp || framework_failure=1 + +if test $framework_failure = 1; then + echo "$0: failure in testing framework" 1>&2 + (exit 1); exit 1 +fi + +mkdir -pv foo/a/b/c/d 2>out || exit + +diff - out <<\EOF +mkdir: created directory `foo' +mkdir: created directory `foo/a' +mkdir: created directory `foo/a/b' +mkdir: created directory `foo/a/b/c' +mkdir: created directory `foo/a/b/c/d' +EOF |