summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPádraig Brady <P@draigBrady.com>2016-01-02 18:38:37 +0000
committerPádraig Brady <P@draigBrady.com>2016-01-03 12:58:39 +0000
commit6c65ce4c643b038c61bd332aab5ea87a75117273 (patch)
tree76190ad69cfe2f11a9c8b8c5e6a4ac2347887467
parent50a950ba69c2ba8f2300c9e77f67978979537ad5 (diff)
downloadcoreutils-6c65ce4c643b038c61bd332aab5ea87a75117273.tar.xz
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
-rw-r--r--NEWS4
-rw-r--r--src/install.c13
-rwxr-xr-xtests/install/create-leading.sh9
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