From 6c65ce4c643b038c61bd332aab5ea87a75117273 Mon Sep 17 00:00:00 2001 From: Pádraig Brady Date: Sat, 2 Jan 2016 18:38:37 +0000 Subject: install: fix relative copies to absolute directory with -D * src/install.c (mkancesdirs_safe_wd): Unconditionally restore the current working directory when possibly called multiple times (from install_file_in_dir()). * tests/install/create-leading.sh: Add a test case. * NEWS: Mention the fix. Fixes http://bugs.gnu.org/21497 --- NEWS | 4 ++++ src/install.c | 13 ++++++++----- tests/install/create-leading.sh | 9 ++++++++- 3 files changed, 20 insertions(+), 6 deletions(-) diff --git a/NEWS b/NEWS index 863be187e..72d69b8b5 100644 --- a/NEWS +++ b/NEWS @@ -12,6 +12,10 @@ GNU coreutils NEWS -*- outline -*- cut --fields no longer outputs extraneous characters on some uClibc configs. [bug introduced in coreutils-6.11] + install -D again copies relative file names when absolute file names + are also specified along with an absolute destination directory name. + [bug introduced in coreutils-6.2] + ls no longer prematurely wraps lines when printing short file names. [bug introduced in coreutils-5.1.0] diff --git a/src/install.c b/src/install.c index 1bdb757a1..6efb29e66 100644 --- a/src/install.c +++ b/src/install.c @@ -704,14 +704,17 @@ install_file_in_file (const char *from, const char *to, return change_attributes (to); } -/* Copy file FROM onto file TO, creating any missing parent directories of TO. +/* Create any missing parent directories of TO, + while maintaining the current Working Directory. Return true if successful. */ static bool -mkancesdirs_safe_wd (char const *from, char *to, struct cp_options *x) +mkancesdirs_safe_wd (char const *from, char *to, struct cp_options *x, + bool save_always) { bool save_working_directory = - ! (IS_ABSOLUTE_FILE_NAME (from) && IS_ABSOLUTE_FILE_NAME (to)); + save_always + || ! (IS_ABSOLUTE_FILE_NAME (from) && IS_ABSOLUTE_FILE_NAME (to)); int status = EXIT_SUCCESS; struct savewd wd; @@ -749,7 +752,7 @@ static bool install_file_in_file_parents (char const *from, char *to, const struct cp_options *x) { - return (mkancesdirs_safe_wd (from, to, (struct cp_options *)x) + return (mkancesdirs_safe_wd (from, to, (struct cp_options *)x, false) && install_file_in_file (from, to, x)); } @@ -766,7 +769,7 @@ install_file_in_dir (const char *from, const char *to_dir, bool ret = true; if (mkdir_and_install) - ret = mkancesdirs_safe_wd (from, to, (struct cp_options *)x); + ret = mkancesdirs_safe_wd (from, to, (struct cp_options *)x, true); ret = ret && install_file_in_file (from, to, x); free (to); diff --git a/tests/install/create-leading.sh b/tests/install/create-leading.sh index 8971d5fde..62f74f53f 100755 --- a/tests/install/create-leading.sh +++ b/tests/install/create-leading.sh @@ -24,7 +24,7 @@ print_ver_ ginstall file=file -echo foo > $file +echo foo > $file || framework_failure_ # Before 4.0q, this would mistakenly create $file, not 'dest' # in no-dir1/no-dir2/. @@ -32,4 +32,11 @@ ginstall -D $file no-dir1/no-dir2/dest || fail=1 test -d no-dir1/no-dir2 || fail=1 test -r no-dir1/no-dir2/dest || fail=1 +# Between 6.1 and 8.24, this would not copy $file +# due to incorrectly modified working directory +mkdir dir1 || framework_failure_ +touch dir1/file1 || framework_failure_ +ginstall -D $PWD/dir1/file1 $file -t $PWD/no-dir2/ || fail=1 +test -r no-dir2/$file && test -r no-dir2/file1 || fail=1 + Exit $fail -- cgit v1.2.3-54-g00ecf