diff options
-rw-r--r-- | ChangeLog | 9 | ||||
-rw-r--r-- | NEWS | 3 | ||||
-rw-r--r-- | src/cp.c | 12 | ||||
-rwxr-xr-x | tests/cp/cp-parents | 9 |
4 files changed, 29 insertions, 4 deletions
@@ -1,3 +1,12 @@ +2007-02-02 Paul Eggert <eggert@cs.ucla.edu> + + * NEWS: Document fix for cp --parents. + * src/cp.c (make_dir_parents_private): Report the error sooner with + "cp --parents DIR/FILE DEST" when DIR is a non-directory, thus not + creating the directory, DEST/DIR. + * tests/cp/cp-parents: Test for the non-race-condition bug fixed + by the above change. + 2007-02-02 Jim Meyering <jim@meyering.net> * src/nl.c (proc_text): Use "NULL", not "(struct re_registers *) 0". @@ -10,6 +10,9 @@ GNU coreutils NEWS -*- outline -*- chmod no longer fails in an environment (e.g., a chroot) with openat support but with insufficient /proc support. + "cp --parents F/G D" no longer creates a directory D/F when F is not + a directory (and F/G is therefore invalid). + cut no longer dumps core for usage like "cut -f2- f1 f2" with two or more file arguments. This was due to a double-free bug, introduced in coreutils-5.3.0. @@ -1,5 +1,5 @@ /* cp.c -- file copying (main routines) - Copyright (C) 89, 90, 91, 1995-2006 Free Software Foundation. + Copyright (C) 89, 90, 91, 1995-2007 Free Software Foundation. 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 @@ -415,6 +415,7 @@ make_dir_parents_private (char const *const_dir, size_t src_offset, mode_t src_mode; mode_t omitted_permissions; mode_t mkdir_mode; + int src_errno; /* This component does not exist. We must set *new_dst and new->mode inside this loop because, @@ -422,9 +423,14 @@ make_dir_parents_private (char const *const_dir, size_t src_offset, make_dir_parents_private creates only e_dir/../a if ./b already exists. */ *new_dst = true; - if (XSTAT (x, src, &stats)) + src_errno = (XSTAT (x, src, &stats) != 0 + ? errno + : S_ISDIR (stats.st_mode) + ? 0 + : ENOTDIR); + if (src_errno) { - error (0, errno, _("failed to get attributes of %s"), + error (0, src_errno, _("failed to get attributes of %s"), quote (src)); return false; } diff --git a/tests/cp/cp-parents b/tests/cp/cp-parents index 373e60776..6c123d225 100755 --- a/tests/cp/cp-parents +++ b/tests/cp/cp-parents @@ -2,7 +2,8 @@ # cp -R --parents dir-specified-with-trailing-slash/ other-dir # would get a failed assertion. -# Copyright (C) 2000, 2002, 2004, 2005, 2006 Free Software Foundation, Inc. +# Copyright (C) 2000, 2002, 2004, 2005, 2006, 2007 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 @@ -48,6 +49,7 @@ cd $tmp || framework_failure=1 mkdir foo bar || framework_failure=1 mkdir -p a/b/c d e || framework_failure=1 +touch f || framework_failure=1 if test $framework_failure = 1; then echo 'failure in testing framework' @@ -65,6 +67,11 @@ cp -R --parents foo/ bar || fail=1 cp --verbose -a --parents a/b/c d > /dev/null 2>&1 || fail=1 test -d d/a/b/c || fail=1 +# With 6.7 and earlier, cp --parents f/g d would mistakenly create a +# directory d/f, even though f is a regular file. +cp --parents f/g d 2>/dev/null && fail=1 +test -d d/f && fail=1 + # Check that re_protect works. chmod go=w d/a cp -a --parents d/a/b/c e || fail=1 |