From 452aa4a7e3909a3d96291afca08337d7a95d422b Mon Sep 17 00:00:00 2001 From: Ondřej Vašík Date: Jan 13 2016 11:30:46 +0000 Subject: mv: prevent dataloss when source dir is specified multiple times (#1297464, by P.Brady) --- diff --git a/coreutils-8.24-mv-duplicate-sources.patch b/coreutils-8.24-mv-duplicate-sources.patch new file mode 100644 index 0000000..f518cc6 --- /dev/null +++ b/coreutils-8.24-mv-duplicate-sources.patch @@ -0,0 +1,119 @@ +@@ -, +, @@ + destination + mv dir dir dir +--- + src/copy.c | 12 +++++++---- + tests/local.mk | 1 - + tests/mv/dup-source.sh | 46 +++++++++++++++++++++++++++++++++---------- + 3 files changed, 44 insertions(+), 15 deletions(-) +--- a/src/copy.c ++++ a/src/copy.c +@@ -2278,10 +2278,14 @@ copy_internal (char const *src_name, char const *dst_name, + error (0, 0, _("warning: source directory %s " + "specified more than once"), + quote (top_level_src_name)); +- /* We only do backups in move mode and for non dirs, +- and in move mode this won't be the issue as the source will +- be missing for subsequent attempts. +- There we just warn and return here. */ ++ /* In move mode, if a previous rename succeeded, then ++ we won't be in this path as the source is missing. If the ++ rename previously failed, then that has been handled. ++ Pretend this instance succeeded so the source isn't removed. */ ++ if (x->move_mode && rename_succeeded) ++ *rename_succeeded = true; ++ /* We only do backups in move mode, and for non directories. ++ So just ignore this repeated entry. */ + return true; + } + else if (x->dereference == DEREF_ALWAYS +--- a/tests/local.mk ++++ a/tests/local.mk +@@ -443,7 +443,6 @@ all_tests = \ + tests/cp/dir-rm-dest.sh \ + tests/cp/dir-slash.sh \ + tests/cp/dir-vs-file.sh \ +- tests/cp/duplicate-sources.sh \ + tests/cp/existing-perm-dir.sh \ + tests/cp/existing-perm-race.sh \ + tests/cp/fail-perm.sh \ +--- a/tests/mv/dup-source.sh ++++ a/tests/mv/dup-source.sh +@@ -24,25 +24,37 @@ print_ver_ cp mv + + skip_if_root_ + ++reset_files() { rm -fr a b d; touch a; mkdir b d; } ++ + for i in cp; do + + # cp may not fail in this case. +- +- rm -fr a d; touch a; mkdir d ++ reset_files + $i a a d/ 2> out || fail=1 +- rm -fr a d; touch a; mkdir d ++ reset_files + $i ./a a d/ 2>> out || fail=1 + ++ # Similarly for directories, but handle ++ # source == dest appropriately. ++ reset_files ++ $i -a ./b b d/ 2>> out || fail=1 ++ reset_files ++ returns_ 1 $i -a ./b b b/ 2>> out || fail=1 ++ + # cp succeeds with --backup=numbered. +- rm -fr a d; touch a; mkdir d ++ reset_files + $i --backup=numbered a a d/ 2>> out || fail=1 + + # But not with plain '--backup' +- rm -fr a d; touch a; mkdir d +- $i --backup a a d/ 2>> out && fail=1 ++ reset_files ++ returns_ 1 $i --backup a a d/ 2>> out || fail=1 ++ + cat < exp + $i: warning: source file 'a' specified more than once + $i: warning: source file 'a' specified more than once ++$i: warning: source directory 'b' specified more than once ++$i: cannot copy a directory, './b', into itself, 'b/b' ++$i: warning: source directory 'b' specified more than once + $i: will not overwrite just-created 'd/a' with 'a' + EOF + compare exp out || fail=1 +@@ -50,14 +62,28 @@ done + + for i in mv; do + # But mv *does* fail in this case (it has to). ++ reset_files ++ returns_ 1 $i a a d/ 2> out || fail=1 ++ returns_ 1 test -e a || fail=1 ++ reset_files ++ returns_ 1 $i ./a a d/ 2>> out || fail=1 ++ returns_ 1 test -e a || fail=1 ++ ++ # Similarly for directories, also handling ++ # source == dest appropriately. ++ reset_files ++ returns_ 1 $i ./b b d/ 2>> out || fail=1 ++ returns_ 1 test -e b || fail=1 ++ reset_files ++ returns_ 1 $i --verbose ./b b b/ 2>> out || fail=1 ++ test -d b || fail=1 + +- rm -fr a d; touch a; mkdir d +- $i a a d/ 2> out && fail=1 +- rm -fr a d; touch a; mkdir d +- $i ./a a d/ 2>> out && fail=1 + cat < exp + $i: cannot stat 'a': No such file or directory + $i: cannot stat 'a': No such file or directory ++$i: cannot stat 'b': No such file or directory ++$i: cannot move './b' to a subdirectory of itself, 'b/b' ++$i: warning: source directory 'b' specified more than once + EOF + compare exp out || fail=1 + done +-- diff --git a/coreutils.spec b/coreutils.spec index 3d28fb6..31cba83 100644 --- a/coreutils.spec +++ b/coreutils.spec @@ -1,7 +1,7 @@ Summary: A set of basic GNU tools commonly used in shell scripts Name: coreutils Version: 8.24 -Release: 105%{?dist} +Release: 106%{?dist} License: GPLv3+ Group: System Environment/Base Url: http://www.gnu.org/software/coreutils/ @@ -20,7 +20,10 @@ Source10: coreutils-find-requires.sh %global __find_provides %{_rpmconfigdir}/find-provides %global __find_requires %{SOURCE10} %{_rpmconfigdir}/find-requires -# From upstream +# From upstream +#mv: prevent dataloss when source directory is specified multiple t imes +Patch1: coreutils-8.24-mv-duplicate-sources.patch + # Our patches #general patch to workaround koji build system issues @@ -186,12 +189,13 @@ including documentation and translations. %patch908 -p1 -b .getgrouplist %patch912 -p1 -b .overflow %patch913 -p1 -b .testoff +%patch1 -p1 -b .dupl #SELinux %patch950 -p1 -b .selinux %patch951 -p1 -b .selinuxman -chmod a+x tests/misc/sort-mb-tests.sh tests/df/direct.sh || : +chmod a+x tests/misc/sort-mb-tests.sh tests/df/direct.sh tests/mv-dup-source.sh || : #fix typos/mistakes in localized documentation(#439410, #440056) find ./po/ -name "*.p*" | xargs \ @@ -352,6 +356,10 @@ fi %license COPYING %changelog +* Wed Jan 13 2016 Ondrej Vasik - 8.24-106 +- mv: prevent dataloss when source dir is specified multiple + times (#1297464, by P.Brady) + * Mon Dec 14 2015 Pádraig Brady - 8.24-105 - Give explicit priority to coreutils over coreutils-single