mirror of
https://github.com/coreutils/coreutils.git
synced 2024-11-24 02:17:22 +08:00
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.
This commit is contained in:
parent
0fc6edb714
commit
4767fc607e
15
ChangeLog
15
ChangeLog
@ -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.
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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) \
|
||||
|
56
tests/mkdir/p-v
Executable file
56
tests/mkdir/p-v
Executable file
@ -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
|
Loading…
Reference in New Issue
Block a user