summaryrefslogtreecommitdiffstats
path: root/tests/mv
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 16:11:47 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 16:11:47 +0000
commit758f820bcc0f68aeebac1717e537ca13a320b909 (patch)
tree48111ece75cf4f98316848b37a7e26356e00669e /tests/mv
parentInitial commit. (diff)
downloadcoreutils-upstream.tar.xz
coreutils-upstream.zip
Adding upstream version 9.1.upstream/9.1upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to '')
-rwxr-xr-xtests/mv/acl.sh67
-rwxr-xr-xtests/mv/atomic.sh46
-rwxr-xr-xtests/mv/atomic2.sh45
-rwxr-xr-xtests/mv/backup-dir.sh39
-rwxr-xr-xtests/mv/backup-is-src.sh46
-rwxr-xr-xtests/mv/childproof.sh83
-rwxr-xr-xtests/mv/diag.sh48
-rwxr-xr-xtests/mv/dir-file.sh30
-rwxr-xr-xtests/mv/dir2dir.sh42
-rwxr-xr-xtests/mv/dup-source.sh91
-rwxr-xr-xtests/mv/force.sh43
-rwxr-xr-xtests/mv/hard-2.sh77
-rwxr-xr-xtests/mv/hard-3.sh69
-rwxr-xr-xtests/mv/hard-4.sh41
-rwxr-xr-xtests/mv/hard-link-1.sh41
-rwxr-xr-xtests/mv/hardlink-case.sh37
-rwxr-xr-xtests/mv/i-1.pl44
-rwxr-xr-xtests/mv/i-2.sh52
-rwxr-xr-xtests/mv/i-3.sh72
-rwxr-xr-xtests/mv/i-4.sh47
-rwxr-xr-xtests/mv/i-5.sh29
-rwxr-xr-xtests/mv/i-link-no.sh43
-rwxr-xr-xtests/mv/into-self-2.sh52
-rwxr-xr-xtests/mv/into-self-3.sh41
-rwxr-xr-xtests/mv/into-self-4.sh34
-rwxr-xr-xtests/mv/into-self.sh53
-rwxr-xr-xtests/mv/leak-fd.sh55
-rwxr-xr-xtests/mv/mv-n.sh57
-rwxr-xr-xtests/mv/mv-special-1.sh75
-rwxr-xr-xtests/mv/no-target-dir.sh51
-rwxr-xr-xtests/mv/part-fail.sh55
-rwxr-xr-xtests/mv/part-hardlink.sh43
-rwxr-xr-xtests/mv/part-rename.sh57
-rwxr-xr-xtests/mv/part-symlink.sh262
-rwxr-xr-xtests/mv/partition-perm.sh37
-rwxr-xr-xtests/mv/perm-1.sh35
-rwxr-xr-xtests/mv/sticky-to-xpart.sh68
-rwxr-xr-xtests/mv/symlink-onto-hardlink-to-self.sh63
-rwxr-xr-xtests/mv/symlink-onto-hardlink.sh41
-rwxr-xr-xtests/mv/to-symlink.sh43
-rwxr-xr-xtests/mv/trailing-slash.sh65
-rwxr-xr-xtests/mv/update.sh54
42 files changed, 2373 insertions, 0 deletions
diff --git a/tests/mv/acl.sh b/tests/mv/acl.sh
new file mode 100755
index 0000000..bc8341a
--- /dev/null
+++ b/tests/mv/acl.sh
@@ -0,0 +1,67 @@
+#!/bin/sh
+# move files/directories across file system boundaries
+# and make sure acls are preserved
+
+# Copyright (C) 2005-2022 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 3 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, see <https://www.gnu.org/licenses/>.
+
+. "${srcdir=.}/tests/init.sh"; path_prepend_ ./src
+print_ver_ mv
+
+require_acl_
+
+# Skip this test if cp was built without ACL support:
+grep '^#define USE_ACL 1' $CONFIG_HEADER > /dev/null ||
+ skip_ "insufficient ACL support"
+
+cleanup_() { rm -rf "$other_partition_tmpdir"; }
+. "$abs_srcdir/tests/other-fs-tmpdir"
+
+touch file || framework_failure_
+t1=$other_partition_tmpdir/t1
+touch $t1 || framework_failure_
+
+skip_partition=none
+# Ensure that setfacl and getfacl work on this file system.
+setfacl -m user:bin:rw- file 2> /dev/null || skip_partition=.
+# And on the destination file system.
+setfacl -m user:bin:rw- $t1 || skip_partition=$other_partition_tmpdir
+acl1=$(getfacl file) || skip_partition=.
+
+test $skip_partition != none &&
+ skip_ "'$skip_partition' is not on a suitable file system for this test"
+
+# move the access acl of a file
+mv file "$other_partition_tmpdir" || fail=1
+acl2=$(cd "$other_partition_tmpdir" && getfacl file) || framework_failure_
+test "$acl1" = "$acl2" || fail=1
+
+# move the access acl of a directory
+mkdir dir || framework_failure_
+setfacl -m user:bin:rw- dir || framework_failure_
+acl1=$(getfacl dir) || framework_failure_
+mv dir "$other_partition_tmpdir" || fail=1
+acl2=$(cd "$other_partition_tmpdir" && getfacl dir) || framework_failure_
+test "$acl1" = "$acl2" || fail=1
+
+# move the default acl of a directory
+mkdir dir2 || framework_failure_
+setfacl -d -m user:bin:rw- dir2 || framework_failure_
+acl1=$(getfacl dir2) || framework_failure_
+mv dir2 "$other_partition_tmpdir" || fail=1
+acl2=$(cd "$other_partition_tmpdir" && getfacl dir2) || framework_failure_
+test "$acl1" = "$acl2" || fail=1
+
+Exit $fail
diff --git a/tests/mv/atomic.sh b/tests/mv/atomic.sh
new file mode 100755
index 0000000..1b1d357
--- /dev/null
+++ b/tests/mv/atomic.sh
@@ -0,0 +1,46 @@
+#!/bin/sh
+# ensure that mv doesn't first unlink its destination in one particular case
+
+# Copyright (C) 2006-2022 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 3 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, see <https://www.gnu.org/licenses/>.
+
+. "${srcdir=.}/tests/init.sh"; path_prepend_ ./src
+print_ver_ mv
+require_strace_ unlink
+
+# Before the fix, mv would unnecessarily unlink the destination symlink:
+# $ rm -rf s[12]; ln -s / s1; ln -s /tmp s2
+# $ strace -qe unlink /bin/mv -T s1 s2
+# unlink("s2") = 0
+#
+# With the fix, it doesn't call unlink:
+# $ rm -rf s[12]; ln -s / s1; ln -s /tmp s2
+# $ strace -qe unlink ./mv -T s1 s2
+# $
+
+ln -s t1 s1 || framework_failure_
+ln -s t2 s2 || framework_failure_
+
+
+strace -qe unlink mv -T s1 s2 > out 2>&1 || fail=1
+$EGREP 'unlink.*"s1"' out && fail=1
+
+# Ensure that the source, s1, is gone.
+ls -dl s1 > /dev/null 2>&1 && fail=1
+
+# Ensure that the destination, s2, contains the link from s1.
+test "$(readlink s2)" = t1 || fail=1
+
+Exit $fail
diff --git a/tests/mv/atomic2.sh b/tests/mv/atomic2.sh
new file mode 100755
index 0000000..cad9276
--- /dev/null
+++ b/tests/mv/atomic2.sh
@@ -0,0 +1,45 @@
+#!/bin/sh
+# ensure that mv doesn't first unlink a multi-hard-linked destination
+
+# Copyright (C) 2008-2022 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 3 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, see <https://www.gnu.org/licenses/>.
+
+. "${srcdir=.}/tests/init.sh"; path_prepend_ ./src
+print_ver_ mv
+require_strace_ unlink
+
+# Before the fix, mv would unnecessarily unlink the destination symlink:
+# $ rm -f a b b2; touch a b; ln b b2; strace -e unlink /p/bin/mv a b
+# unlink("b") = 0
+#
+# With the fix, it doesn't call unlink:
+# $ rm -f a b b2; touch a b; ln b b2; strace -e unlink ./mv a b
+# $
+
+touch a b || framework_failure_
+ln b b2 || framework_failure_
+
+
+strace -qe unlink mv a b > out 2>&1 || fail=1
+$EGREP 'unlink.*"b"' out && fail=1
+
+# Ensure that the source, "a", is gone.
+ls -dl a > /dev/null 2>&1 && fail=1
+
+# Ensure that the destination, "b", has link count 1.
+n_links=$(stat --printf=%h b) || fail=1
+test "$n_links" = 1 || fail=1
+
+Exit $fail
diff --git a/tests/mv/backup-dir.sh b/tests/mv/backup-dir.sh
new file mode 100755
index 0000000..84c51af
--- /dev/null
+++ b/tests/mv/backup-dir.sh
@@ -0,0 +1,39 @@
+#!/bin/sh
+# Ensure "mv --verbose --backup" works the same for dirs and non-dirs.
+
+# Copyright (C) 2006-2022 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 3 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, see <https://www.gnu.org/licenses/>.
+
+. "${srcdir=.}/tests/init.sh"; path_prepend_ ./src
+print_ver_ mv
+
+mkdir A B || framework_failure_
+touch X Y || framework_failure_
+
+
+# Before coreutils-6.2, the " (backup: 'B.~1~')" suffix was not printed.
+mv --verbose --backup=numbered -T A B > out || fail=1
+cat <<\EOF > exp || framework_failure_
+renamed 'A' -> 'B' (backup: 'B.~1~')
+EOF
+
+compare exp out || fail=1
+
+# Bug#52410
+mkdir C D E || framework_failure_
+mv -T --backup=numbered C E/ || fail=1
+mv -T --backup=numbered D E/ || fail=1
+
+Exit $fail
diff --git a/tests/mv/backup-is-src.sh b/tests/mv/backup-is-src.sh
new file mode 100755
index 0000000..67ab05a
--- /dev/null
+++ b/tests/mv/backup-is-src.sh
@@ -0,0 +1,46 @@
+#!/bin/sh
+# Force mv to use the copying code.
+
+# Copyright (C) 1998-2022 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 3 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, see <https://www.gnu.org/licenses/>.
+
+. "${srcdir=.}/tests/init.sh"; path_prepend_ ./src
+print_ver_ mv
+cleanup_() { rm -rf "$other_partition_tmpdir"; }
+. "$abs_srcdir/tests/other-fs-tmpdir"
+
+a="$other_partition_tmpdir/a"
+a2="$other_partition_tmpdir/a~"
+
+rm -f "$a" "$a2" || framework_failure_
+echo a > "$a" || framework_failure_
+echo a2 > "$a2" || framework_failure_
+
+# This mv command should exit nonzero.
+mv --b=simple "$a2" "$a" > out 2>&1 && fail=1
+
+sed \
+ -e "s,mv:,XXX:," \
+ -e "s,$a,YYY," \
+ -e "s,$a2,ZZZ," \
+ out > out2
+
+cat > exp <<\EOF
+XXX: backing up 'YYY' might destroy source; 'ZZZ' not moved
+EOF
+
+compare exp out2 || fail=1
+
+Exit $fail
diff --git a/tests/mv/childproof.sh b/tests/mv/childproof.sh
new file mode 100755
index 0000000..f9c2f6d
--- /dev/null
+++ b/tests/mv/childproof.sh
@@ -0,0 +1,83 @@
+#!/bin/sh
+# Ensure that cp/mv/ln don't clobber a just-copied/moved/linked file.
+# With fileutils-4.1 and earlier, this test would fail for cp and mv.
+# With coreutils-6.9 and earlier, this test would fail for ln.
+
+# Copyright (C) 2001-2022 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 3 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, see <https://www.gnu.org/licenses/>.
+
+. "${srcdir=.}/tests/init.sh"; path_prepend_ ./src
+print_ver_ cp mv ln
+
+skip_if_root_
+
+mkdir a b c || framework_failure_
+echo a > a/f || framework_failure_
+echo b > b/f || framework_failure_
+
+
+returns_ 1 cp a/f b/f c 2> /dev/null || fail=1
+test -f a/f || fail=1
+test -f b/f || fail=1
+test -f c/f || fail=1
+test "$(cat c/f)" = a || fail=1
+rm -f c/f
+
+# With --backup=numbered, it should succeed
+cp --backup=numbered a/f b/f c || fail=1
+test -f a/f || fail=1
+test -f b/f || fail=1
+test -f c/f || fail=1
+test -f c/f.~1~ || fail=1
+rm -f c/f*
+
+returns_ 1 mv a/f b/f c 2> /dev/null || fail=1
+test -f a/f && fail=1
+test -f b/f || fail=1
+test -f c/f || fail=1
+test "$(cat c/f)" = a || fail=1
+
+# Make sure mv still works when moving hard links.
+# This is where the same_file test is necessary, and why
+# we save file names in addition to dev/ino.
+rm -f c/f* b/f
+touch a/f
+ln a/f b/g
+mv a/f b/g c || fail=1
+test -f a/f && fail=1
+test -f b/g && fail=1
+test -f c/f || fail=1
+test -f c/g || fail=1
+
+touch a/f b/f b/g
+returns_ 1 mv a/f b/f b/g c 2> /dev/null || fail=1
+test -f a/f && fail=1 # a/f should have been moved
+test -f b/f || fail=1 # b/f should remain
+test -f b/g && fail=1 # b/g should have been moved
+test -f c/f || fail=1
+test -f c/g || fail=1
+
+# Test ln -f.
+
+rm -f a/f b/f c/f
+echo a > a/f || framework_failure_
+echo b > b/f || framework_failure_
+returns_ 1 ln -f a/f b/f c 2> /dev/null || fail=1
+# a/f and c/f must be linked
+test $(stat --format %i a/f) = $(stat --format %i c/f) || fail=1
+# b/f and c/f must not be linked
+test $(stat --format %i b/f) = $(stat --format %i c/f) && fail=1
+
+Exit $fail
diff --git a/tests/mv/diag.sh b/tests/mv/diag.sh
new file mode 100755
index 0000000..c0a5585
--- /dev/null
+++ b/tests/mv/diag.sh
@@ -0,0 +1,48 @@
+#!/bin/sh
+# make sure we get proper diagnostics: e.g., with --target-dir=d but no args
+
+# Copyright (C) 2000-2022 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 3 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, see <https://www.gnu.org/licenses/>.
+
+. "${srcdir=.}/tests/init.sh"; path_prepend_ ./src
+print_ver_ mv
+
+touch f1 || framework_failure_
+touch f2 || framework_failure_
+touch d || framework_failure_
+
+# These mv commands should all exit nonzero.
+
+# Too few args. This first one did fail, but with an incorrect diagnostic
+# until fileutils-4.0u.
+mv --target=. >> out 2>&1 && fail=1
+mv no-file >> out 2>&1 && fail=1
+
+# Target is not a directory.
+mv f1 f2 f1 >> out 2>&1 && fail=1
+mv --target=f2 f1 >> out 2>&1 && fail=1
+
+cat > exp <<\EOF
+mv: missing file operand
+Try 'mv --help' for more information.
+mv: missing destination file operand after 'no-file'
+Try 'mv --help' for more information.
+mv: target 'f1': Not a directory
+mv: target directory 'f2': Not a directory
+EOF
+
+compare exp out || fail=1
+
+Exit $fail
diff --git a/tests/mv/dir-file.sh b/tests/mv/dir-file.sh
new file mode 100755
index 0000000..8a54412
--- /dev/null
+++ b/tests/mv/dir-file.sh
@@ -0,0 +1,30 @@
+#!/bin/sh
+# mv must fail when src and dest are mismatched directory/non-directory.
+
+# Copyright (C) 2000-2022 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 3 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, see <https://www.gnu.org/licenses/>.
+
+. "${srcdir=.}/tests/init.sh"; path_prepend_ ./src
+print_ver_ mv
+
+mkdir -p dir/file || framework_failure_
+> file || framework_failure_
+
+
+# These should both fail, but until fileutils-4.0q only the second one did.
+returns_ 1 mv dir file > /dev/null 2>&1 || fail=1
+returns_ 1 mv file dir > /dev/null 2>&1 || fail=1
+
+Exit $fail
diff --git a/tests/mv/dir2dir.sh b/tests/mv/dir2dir.sh
new file mode 100755
index 0000000..b5b3562
--- /dev/null
+++ b/tests/mv/dir2dir.sh
@@ -0,0 +1,42 @@
+#!/bin/sh
+# Ensure that mv prints the right diagnostic for a dir->dir move
+# where the destination directory is not empty.
+
+# Copyright (C) 2006-2022 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 3 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, see <https://www.gnu.org/licenses/>.
+
+. "${srcdir=.}/tests/init.sh"; path_prepend_ ./src
+print_ver_ mv
+
+mkdir -p a/t b/t || framework_failure_
+touch a/t/f || framework_failure_
+
+
+# Expect this to fail with the expected diagnostic.
+# For an interim (pre-6.0) release, it would give an erroneous
+# diagnostic about moving one directory to a subdirectory of itself.
+mv b/t a 2> out && fail=1
+
+# Accept any of these: EEXIST, ENOTEMPTY, EBUSY.
+sed 's/: File exists/: Directory not empty/'<out>o1;mv o1 out
+sed 's/: Device or resource busy/: Directory not empty/'<out>o1;mv o1 out
+
+cat <<\EOF > exp || framework_failure_
+mv: cannot move 'b/t' to 'a/t': Directory not empty
+EOF
+
+compare exp out || fail=1
+
+Exit $fail
diff --git a/tests/mv/dup-source.sh b/tests/mv/dup-source.sh
new file mode 100755
index 0000000..4fa666a
--- /dev/null
+++ b/tests/mv/dup-source.sh
@@ -0,0 +1,91 @@
+#!/bin/sh
+# Ensure that cp merely warns when a non-directory source file is
+# listed on the command line more than once. fileutils-4.1.1
+# made this fail: cp a a d/
+# Ensure that mv fails with a similar command.
+
+# Copyright (C) 2001-2022 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 3 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, see <https://www.gnu.org/licenses/>.
+
+. "${srcdir=.}/tests/init.sh"; path_prepend_ ./src
+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.
+ reset_files
+ $i a a d/ 2> out || fail=1
+ 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.
+ reset_files
+ $i --backup=numbered a a d/ 2>> out || fail=1
+
+ # But not with plain '--backup'
+ reset_files
+ returns_ 1 $i --backup a a d/ 2>> out || fail=1
+
+ cat <<EOF > 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
+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
+
+ cat <<EOF > 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
+
+Exit $fail
diff --git a/tests/mv/force.sh b/tests/mv/force.sh
new file mode 100755
index 0000000..41968ef
--- /dev/null
+++ b/tests/mv/force.sh
@@ -0,0 +1,43 @@
+#!/bin/sh
+# move a file onto itself
+
+# Copyright (C) 1999-2022 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 3 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, see <https://www.gnu.org/licenses/>.
+
+. "${srcdir=.}/tests/init.sh"; path_prepend_ ./src
+print_ver_ mv
+
+ff=mvforce
+ff2=mvforce2
+
+echo force-contents > $ff || framework_failure_
+ln $ff $ff2 || framework_failure_
+
+# mv should fail for the same name, or separate hardlinks as in
+# both cases rename() will do nothing and return success.
+# One could unlink(src) in the hardlink case, but that would
+# introduce races with overlapping mv instances removing both hardlinks.
+
+for dest in $ff $ff2; do
+ # This mv command should exit nonzero.
+ mv $ff $dest > out 2>&1 && fail=1
+
+ printf "mv: '$ff' and '$dest' are the same file\n" > exp
+ compare exp out || fail=1
+
+ test $(cat $ff) = force-contents || fail=1
+done
+
+Exit $fail
diff --git a/tests/mv/hard-2.sh b/tests/mv/hard-2.sh
new file mode 100755
index 0000000..ceb41a5
--- /dev/null
+++ b/tests/mv/hard-2.sh
@@ -0,0 +1,77 @@
+#!/bin/sh
+# Ensure that moving hard-linked arguments onto existing destinations works.
+# Likewise when using cp --preserve=link.
+
+# Copyright (C) 2003-2022 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 3 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, see <https://www.gnu.org/licenses/>.
+
+. "${srcdir=.}/tests/init.sh"; path_prepend_ ./src
+print_ver_ cp mv
+
+skip_if_root_
+
+mkdir dst || framework_failure_
+(cd dst && touch a b c) || framework_failure_
+touch a || framework_failure_
+ln a b || framework_failure_
+ln a c || framework_failure_
+
+
+# ======================================
+cp --preserve=link a b c dst || fail=1
+# The source files must remain.
+test -f a || fail=1
+test -f b || fail=1
+test -f c || fail=1
+cd dst
+
+# Three destination files must exist.
+test -f a || fail=1
+test -f b || fail=1
+test -f c || fail=1
+
+# The three i-node numbers must be the same.
+ia=$(ls -i a|sed 's/ a//')
+ib=$(ls -i b|sed 's/ b//')
+ic=$(ls -i c|sed 's/ c//')
+test $ia = $ib || fail=1
+test $ia = $ic || fail=1
+
+cd ..
+rm -f dst/[abc]
+(cd dst && touch a b c)
+
+# ======================================
+mv a b c dst || fail=1
+
+# The source files must be gone.
+test -f a && fail=1
+test -f b && fail=1
+test -f c && fail=1
+cd dst
+
+# Three destination files must exist.
+test -f a || fail=1
+test -f b || fail=1
+test -f c || fail=1
+
+# The three i-node numbers must be the same.
+ia=$(ls -i a|sed 's/ a//')
+ib=$(ls -i b|sed 's/ b//')
+ic=$(ls -i c|sed 's/ c//')
+test $ia = $ib || fail=1
+test $ia = $ic || fail=1
+
+Exit $fail
diff --git a/tests/mv/hard-3.sh b/tests/mv/hard-3.sh
new file mode 100755
index 0000000..970ff05
--- /dev/null
+++ b/tests/mv/hard-3.sh
@@ -0,0 +1,69 @@
+#!/bin/sh
+# Ensure that using 'cp --preserve=link' to copy hard-linked arguments
+# onto existing destinations works, even when one of the link operations fails.
+
+# Copyright (C) 2003-2022 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 3 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, see <https://www.gnu.org/licenses/>.
+
+
+# This bug was fixed in coreutils-4.5.9.
+# To exercise this bug is non-trivial:
+# Set-up requires at least three hard-linked files. In copying them,
+# while preserving links, the initial copy must succeed, the attempt
+# to create the second file via 'link' must fail, and the final 'link'
+# (to create the third) must succeed. Before the corresponding fix,
+# the first and third destination files would not be linked.
+#
+# Note that this is nominally a test of 'cp', yet it is in the tests/mv
+# directory, because it requires use of the --preserve=link option that
+# mv enables by default.
+
+. "${srcdir=.}/tests/init.sh"; path_prepend_ ./src
+print_ver_ cp
+skip_if_root_
+
+mkdir -p x dst/x || framework_failure_
+touch dst/x/b || framework_failure_
+chmod a-w dst/x
+touch a || framework_failure_
+ln a x/b || framework_failure_
+ln a c || framework_failure_
+
+
+# ======================================
+# This must fail -- because x/b cannot be unlinked.
+cp --preserve=link --parents a x/b c dst 2> /dev/null && fail=1
+
+# Source files must remain.
+test -f a || fail=1
+test -f x/b || fail=1
+test -f c || fail=1
+cd dst
+
+# Three destination files must exist.
+test -f a || fail=1
+test -f x/b || fail=1
+test -f c || fail=1
+
+# The i-node numbers of a and c must be the same.
+ia=$(ls -i a) || fail=1; set x $ia; ia=$2
+ic=$(ls -i c) || fail=1; set x $ic; ic=$2
+test "$ia" = "$ic" || fail=1
+
+# The i-node number of x/b must be different.
+ib=$(ls -i x/b) || fail=1; set x $ib; ib=$2
+test "$ia" = "$ib" && fail=1
+
+Exit $fail
diff --git a/tests/mv/hard-4.sh b/tests/mv/hard-4.sh
new file mode 100755
index 0000000..f725b87
--- /dev/null
+++ b/tests/mv/hard-4.sh
@@ -0,0 +1,41 @@
+#!/bin/sh
+# ensure that mv maintains a in this case: touch a; ln a b; mv a b
+
+# Copyright (C) 2003-2022 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 3 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, see <https://www.gnu.org/licenses/>.
+
+. "${srcdir=.}/tests/init.sh"; path_prepend_ ./src
+print_ver_ mv
+touch a || framework_failure_
+ln a b || framework_failure_
+
+# Between coreutils-5.0 and coreutils-8.24, 'a' would be removed.
+# Before coreutils-5.0.1 the issue would not have been diagnosed.
+# We don't emulate the rename(a,b) with unlink(a) as that would
+# introduce races with overlapping mv instances removing both links.
+mv a b 2>err && fail=1
+printf "mv: 'a' and 'b' are the same file\n" > exp
+compare exp err || fail=1
+
+test -r a || fail=1
+test -r b || fail=1
+
+# Make sure it works with --backup.
+mv --backup=simple a b || fail=1
+test -r a && fail=1
+test -r b || fail=1
+test -r b~ || fail=1
+
+Exit $fail
diff --git a/tests/mv/hard-link-1.sh b/tests/mv/hard-link-1.sh
new file mode 100755
index 0000000..524fc13
--- /dev/null
+++ b/tests/mv/hard-link-1.sh
@@ -0,0 +1,41 @@
+#!/bin/sh
+# move a directory containing hard-linked files and
+# make sure the links are preserved
+
+# Copyright (C) 1998-2022 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 3 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, see <https://www.gnu.org/licenses/>.
+
+. "${srcdir=.}/tests/init.sh"; path_prepend_ ./src
+print_ver_ mv
+cleanup_() { rm -rf "$other_partition_tmpdir"; }
+. "$abs_srcdir/tests/other-fs-tmpdir"
+
+dir=hlink
+
+mkdir $dir || framework_failure_
+> $dir/a || framework_failure_
+ln $dir/a $dir/b || framework_failure_
+
+mv $dir "$other_partition_tmpdir" || fail=1
+
+# Display inode numbers, one per line.
+ls -1i "$other_partition_tmpdir/$dir" > out || fail=1
+
+# Make sure the inode numbers are the same.
+a=$(sed -n 's/ a$//p' out)
+b=$(sed -n 's/ b$//p' out)
+test "$a" = "$b" || fail=1
+
+Exit $fail
diff --git a/tests/mv/hardlink-case.sh b/tests/mv/hardlink-case.sh
new file mode 100755
index 0000000..35728b9
--- /dev/null
+++ b/tests/mv/hardlink-case.sh
@@ -0,0 +1,37 @@
+#!/bin/sh
+# Ensure multi-hardlinked files are not lost on case insensitive file systems
+
+# Copyright (C) 2014-2022 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 3 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, see <https://www.gnu.org/licenses/>.
+
+. "${srcdir=.}/tests/init.sh"; path_prepend_ ./src
+print_ver_ mv
+require_root_
+
+cwd=$(pwd)
+cleanup_() { cd /; umount "$cwd/mnt"; }
+
+truncate -s100M hfs.img || framework_failure_
+mkfs -t hfsplus hfs.img || skip_ 'failed to create hfs file system'
+mkdir mnt || framework_failure_
+mount hfs.img mnt || skip_ 'failed to mount hfs file system'
+
+cd mnt
+touch foo
+ln foo whatever
+returns_ 1 mv foo Foo || fail=1
+test -r foo || fail=1
+
+Exit $fail
diff --git a/tests/mv/i-1.pl b/tests/mv/i-1.pl
new file mode 100755
index 0000000..2d852d6
--- /dev/null
+++ b/tests/mv/i-1.pl
@@ -0,0 +1,44 @@
+#!/usr/bin/perl
+# Make sure a 'n' reply to 'mv -i...' aborts the move operation.
+
+# Copyright (C) 2001-2022 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 3 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, see <https://www.gnu.org/licenses/>.
+
+use strict;
+
+(my $program_name = $0) =~ s|.*/||;
+
+# Turn off localization of executable's output.
+@ENV{qw(LANGUAGE LANG LC_ALL)} = ('C') x 3;
+
+my $test_a = 'a';
+
+my @Tests =
+ (
+ # Make sure a 'n' reply to 'mv -i...' aborts the move operation.
+ [$test_a, '-i',
+ {IN => {src => "a\n"}}, {IN => {dst => "b\n"}}, '<', {IN => "n\n"},
+ {ERR => "mv: overwrite 'dst'? "},
+ {POST => sub { -r 'src' or die "test $test_a failed\n"}},
+ {EXIT => 0},
+ ],
+ );
+
+my $save_temps = $ENV{DEBUG};
+my $verbose = $ENV{VERBOSE};
+
+my $prog = 'mv';
+my $fail = run_tests ($program_name, $prog, \@Tests, $save_temps, $verbose);
+exit $fail;
diff --git a/tests/mv/i-2.sh b/tests/mv/i-2.sh
new file mode 100755
index 0000000..a7b7939
--- /dev/null
+++ b/tests/mv/i-2.sh
@@ -0,0 +1,52 @@
+#!/bin/sh
+# Test both cp and mv for their behavior with -if and -fi
+# The standards (POSIX and SuS) dictate annoyingly inconsistent behavior.
+
+# Copyright (C) 2000-2022 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 3 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, see <https://www.gnu.org/licenses/>.
+
+. "${srcdir=.}/tests/init.sh"; path_prepend_ ./src
+print_ver_ cp mv
+
+skip_if_root_
+
+for i in a b c d e f g h; do
+ echo $i > $i || framework_failure_
+done
+chmod 0 b d f h || framework_failure_
+echo y > y || framework_failure_
+
+mv -if a b || fail=1
+mv -fi c d < y >/dev/null 2>&1 || fail=1
+
+# Before 4.0s, this would not prompt.
+cp -if e f < y > out 2>&1 || fail=1
+
+# Make sure out contains the prompt.
+case "$(cat out)" in
+ "cp: replace 'f', overriding mode 0000 (---------)?"*) ;;
+ *) fail=1 ;;
+esac
+
+test -f e || fail=1
+test -f f || fail=1
+compare e f || fail=1
+
+cp -fi g h < y > out 2>&1 || fail=1
+test -f g || fail=1
+test -f h || fail=1
+compare g h || fail=1
+
+Exit $fail
diff --git a/tests/mv/i-3.sh b/tests/mv/i-3.sh
new file mode 100755
index 0000000..c631f4e
--- /dev/null
+++ b/tests/mv/i-3.sh
@@ -0,0 +1,72 @@
+#!/bin/sh
+# Make sure that 'mv file unwritable-file' prompts the user
+# and that 'mv -f file unwritable-file' doesn't.
+
+# Copyright (C) 2001-2022 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 3 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, see <https://www.gnu.org/licenses/>.
+
+. "${srcdir=.}/tests/init.sh"; path_prepend_ ./src
+print_ver_ mv
+require_controlling_input_terminal_
+skip_if_root_
+trap '' TTIN # Ignore SIGTTIN
+
+uname -s | grep 'BSD$' && skip_ 'known spurious failure on *BSD'
+
+touch f g h i || framework_failure_
+chmod 0 g i || framework_failure_
+
+
+ls /dev/stdin >/dev/null 2>&1 \
+ || skip_ 'there is no /dev/stdin file'
+
+# work around a dash bug when redirecting
+# from symlinked ttys in the background
+tty=$(readlink -f /dev/stdin)
+
+test -r "$tty" 2>&1 \
+ || skip_ '/dev/stdin is not readable'
+
+# Terminate any background processes
+cleanup_() { kill $pid 2>/dev/null && wait $pid; }
+
+mv f g < $tty > out 2>&1 & pid=$!
+
+# Test for the expected prompt; sleep upon non-match.
+check_overwrite_prompt()
+{
+ local delay="$1"
+ case "$(cat out)" in
+ "mv: replace 'g', overriding mode 0000"*) ;;
+ *) sleep $delay; return 1;;
+ esac
+}
+
+# Wait for up to 12.7 seconds for the expected prompt.
+retry_delay_ check_overwrite_prompt .1 7 || { fail=1; cat out; }
+
+cleanup_
+
+mv -f h i > out 2>&1 || fail=1
+test -f i || fail=1
+test -f h && fail=1
+
+# Make sure there was no prompt.
+case "$(cat out)" in
+ '') ;;
+ *) fail=1 ;;
+esac
+
+Exit $fail
diff --git a/tests/mv/i-4.sh b/tests/mv/i-4.sh
new file mode 100755
index 0000000..8648be7
--- /dev/null
+++ b/tests/mv/i-4.sh
@@ -0,0 +1,47 @@
+#!/bin/sh
+# make sure 'mv -i a b' does its job with a positive response
+
+# Copyright (C) 2001-2022 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 3 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, see <https://www.gnu.org/licenses/>.
+
+. "${srcdir=.}/tests/init.sh"; path_prepend_ ./src
+print_ver_ mv
+
+for i in a b; do
+ echo $i > $i || framework_failure_
+done
+echo y > y || framework_failure_
+echo n > n || framework_failure_
+
+mv -i a b < y >/dev/null 2>&1 || fail=1
+
+# Make sure out contains the prompt.
+case "$(cat b)" in
+ a) ;;
+ *) fail=1 ;;
+esac
+
+# Ensure that mv -i a b works properly with 'n' and 'y' responses,
+# when a and b are hard links to the same file.
+rm -f a b
+echo a > a
+ln a b
+mv -i a b < y 2>err && fail=1
+test -r a || fail=1
+test -r b || fail=1
+printf "mv: 'a' and 'b' are the same file\n" > exp
+compare exp err || fail=1
+
+Exit $fail
diff --git a/tests/mv/i-5.sh b/tests/mv/i-5.sh
new file mode 100755
index 0000000..c7e2696
--- /dev/null
+++ b/tests/mv/i-5.sh
@@ -0,0 +1,29 @@
+#!/bin/sh
+# Make sure 'mv -i dir file' prompts before failing.
+
+# Copyright (C) 2006-2022 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 3 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, see <https://www.gnu.org/licenses/>.
+
+. "${srcdir=.}/tests/init.sh"; path_prepend_ ./src
+print_ver_ mv
+
+mkdir a || framework_failure_
+touch b || framework_failure_
+
+
+# coreutils 6.2 mv would neglect to prompt in this case.
+echo n | mv -i a b 2>/dev/null || fail=1
+
+Exit $fail
diff --git a/tests/mv/i-link-no.sh b/tests/mv/i-link-no.sh
new file mode 100755
index 0000000..e135243
--- /dev/null
+++ b/tests/mv/i-link-no.sh
@@ -0,0 +1,43 @@
+#!/bin/sh
+# Show that mv doesn't preserve links to files the user has declined to move.
+
+# Copyright (C) 2002-2022 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 3 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, see <https://www.gnu.org/licenses/>.
+
+. "${srcdir=.}/tests/init.sh"; path_prepend_ ./src
+print_ver_ mv
+
+mkdir a b || framework_failure_
+echo foo > a/foo || framework_failure_
+ln a/foo a/bar || framework_failure_
+echo FUBAR > b/FUBAR || framework_failure_
+ln b/FUBAR b/bar || framework_failure_
+chmod a-w b/bar || framework_failure_
+echo n > no || framework_failure_
+
+
+mv a/bar a/foo b < no > out 2> err || fail=1
+touch exp
+touch exp_err
+
+compare exp out || fail=1
+compare exp_err err || fail=1
+
+case "$(cat b/foo)" in
+ foo) ;;
+ *) fail=1;;
+esac
+
+Exit $fail
diff --git a/tests/mv/into-self-2.sh b/tests/mv/into-self-2.sh
new file mode 100755
index 0000000..83a7268
--- /dev/null
+++ b/tests/mv/into-self-2.sh
@@ -0,0 +1,52 @@
+#!/bin/sh
+# Force mv to use the copying code.
+# Consider the case where SRC and DEST are on different
+# partitions and DEST is a symlink to SRC.
+
+# Copyright (C) 1998-2022 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 3 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, see <https://www.gnu.org/licenses/>.
+
+. "${srcdir=.}/tests/init.sh"; path_prepend_ ./src
+print_ver_ mv
+cleanup_() { rm -rf "$other_partition_tmpdir"; }
+. "$abs_srcdir/tests/other-fs-tmpdir"
+
+file="$other_partition_tmpdir/file"
+symlink=symlink
+
+
+echo whatever > $file || framework_failure_
+ln -s $file $symlink || framework_failure_
+
+# This mv command should exit nonzero.
+mv $symlink $file > out 2>&1 && fail=1
+
+# This should succeed.
+mv $file $symlink || fail=1
+
+sed \
+ -e "s,mv:,XXX:," \
+ -e "s,$file,YYY," \
+ -e "s,$symlink,ZZZ," \
+ out > out2
+
+cat > exp <<\EOF
+XXX: 'ZZZ' and 'YYY' are the same file
+EOF
+#'
+
+compare exp out2 || fail=1
+
+Exit $fail
diff --git a/tests/mv/into-self-3.sh b/tests/mv/into-self-3.sh
new file mode 100755
index 0000000..cd3bcf0
--- /dev/null
+++ b/tests/mv/into-self-3.sh
@@ -0,0 +1,41 @@
+#!/bin/sh
+# move a directory into itself, with a twist
+
+# Copyright (C) 1998-2022 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 3 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, see <https://www.gnu.org/licenses/>.
+
+. "${srcdir=.}/tests/init.sh"; path_prepend_ ./src
+print_ver_ mv
+
+dir1=is3-dir1
+dir2=is3-dir2
+
+mkdir $dir1 $dir2 || framework_failure_
+
+# This mv command should exit nonzero.
+mv $dir1 $dir2 $dir2 > out 2>&1 && fail=1
+
+sed \
+ -e "s,mv:,XXX:,g" \
+ -e "s,$dir2,ZZZ,g" \
+ out > out2
+
+cat > exp <<\EOF
+XXX: cannot move 'ZZZ' to a subdirectory of itself, 'ZZZ/ZZZ'
+EOF
+
+compare exp out2 || fail=1
+
+Exit $fail
diff --git a/tests/mv/into-self-4.sh b/tests/mv/into-self-4.sh
new file mode 100755
index 0000000..39446a5
--- /dev/null
+++ b/tests/mv/into-self-4.sh
@@ -0,0 +1,34 @@
+#!/bin/sh
+# confirm that 'mv symlink symlink' doesn't remove symlink
+# Based on an example from David Luyer.
+
+# Copyright (C) 2001-2022 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 3 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, see <https://www.gnu.org/licenses/>.
+
+. "${srcdir=.}/tests/init.sh"; path_prepend_ ./src
+print_ver_ mv
+
+touch file || framework_failure_
+ln -s file s || framework_failure_
+
+
+# This must fail.
+returns_ 1 mv s s 2> /dev/null || fail=1
+
+# But the symlink, s, must not be removed.
+# Before 4.0.36, 's' would have been removed.
+test -f s || fail=1
+
+Exit $fail
diff --git a/tests/mv/into-self.sh b/tests/mv/into-self.sh
new file mode 100755
index 0000000..3834640
--- /dev/null
+++ b/tests/mv/into-self.sh
@@ -0,0 +1,53 @@
+#!/bin/sh
+# Demonstrate how mv fails when it tries to move a directory into itself.
+
+# Copyright (C) 1998-2022 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 3 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, see <https://www.gnu.org/licenses/>.
+
+. "${srcdir=.}/tests/init.sh"; path_prepend_ ./src
+print_ver_ mv
+
+dir=toself-dir
+file=toself-file
+
+rm -rf $dir $file || framework_failure_
+mkdir -p $dir/a/b || framework_failure_
+touch $file || framework_failure_
+
+
+# This mv command should fail.
+mv $dir $file $dir > out 2>&1 && fail=1
+
+sed \
+ -e "s,mv:,XXX:," \
+ -e "s,$dir,SRC," \
+ -e "s,$dir/$dir,DEST," \
+ out > out2
+
+cat > exp <<\EOF
+XXX: cannot move 'SRC' to a subdirectory of itself, 'DEST'
+EOF
+
+compare exp out2 || fail=1
+
+# Make sure the file is gone.
+test -f $file && fail=1
+# Make sure the directory is *not* moved.
+test -d $dir || fail=1
+test -d $dir/$dir && fail=1
+# Make sure the file has been moved to the right place.
+test -f $dir/$file || fail=1
+
+Exit $fail
diff --git a/tests/mv/leak-fd.sh b/tests/mv/leak-fd.sh
new file mode 100755
index 0000000..8d2940e
--- /dev/null
+++ b/tests/mv/leak-fd.sh
@@ -0,0 +1,55 @@
+#!/bin/sh
+# Exercise mv's file-descriptor-leak bug, reported against coreutils-5.2.1
+# and fixed (properly) on 2004-10-21.
+
+# Copyright (C) 2004-2022 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 3 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, see <https://www.gnu.org/licenses/>.
+# limit so don't run it by default.
+
+. "${srcdir=.}/tests/init.sh"; path_prepend_ ./src
+print_ver_ mv
+skip_if_root_
+cleanup_() { rm -rf "$other_partition_tmpdir"; }
+. "$abs_srcdir/tests/other-fs-tmpdir"
+
+# This test is relatively expensive, and might well evoke a
+# framework-failure on systems with a smaller command-line length
+expensive_
+
+b="0 1 2 3 4 5 6 7 8 9
+a b c d e f g h i j k l m n o p q r s t u v w x y z
+_A _B _C _D _E _F _G _H _I _J _K _L _M _N _O _P _Q _R _S _T _U _V _W _X _Y _Z"
+
+for i in $(echo $b); do
+ echo $i
+ for j in $b; do
+ echo $i$j
+ done
+done > .dirs
+mkdir $(cat .dirs) || framework_failure_
+sed 's,$,/f,' .dirs | xargs touch
+
+last_file=$(tail -n1 .dirs)/f
+test -f $last_file || framework_failure_
+
+
+mv * "$other_partition_tmpdir" || fail=1
+test -f $last_file/f && fail=1
+rm .dirs
+
+out=$(ls -A) || fail=1
+test -z "$out" || fail=1
+
+Exit $fail
diff --git a/tests/mv/mv-n.sh b/tests/mv/mv-n.sh
new file mode 100755
index 0000000..3733d65
--- /dev/null
+++ b/tests/mv/mv-n.sh
@@ -0,0 +1,57 @@
+#!/bin/sh
+# Test whether mv -n works as documented (not overwrite target).
+
+# Copyright (C) 2006-2022 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 3 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, see <https://www.gnu.org/licenses/>.
+
+. "${srcdir=.}/tests/init.sh"; path_prepend_ ./src
+print_ver_ mv
+
+
+# test miscellaneous combinations of -f -i -n parameters
+touch a b || framework_failure_
+echo "renamed 'a' -> 'b'" > out_move
+> out_empty
+
+# ask for overwrite, answer no
+touch a b || framework_failure_
+echo n | mv -vi a b 2>/dev/null > out1 || fail=1
+compare out1 out_empty || fail=1
+
+# ask for overwrite, answer yes
+touch a b || framework_failure_
+echo y | mv -vi a b 2>/dev/null > out2 || fail=1
+compare out2 out_move || fail=1
+
+# -n wins (as the last option)
+touch a b || framework_failure_
+echo y | mv -vin a b 2>/dev/null > out3 || fail=1
+compare out3 out_empty || fail=1
+
+# -n wins (as the last option)
+touch a b || framework_failure_
+echo y | mv -vfn a b 2>/dev/null > out4 || fail=1
+compare out4 out_empty || fail=1
+
+# -n wins (as the last option)
+touch a b || framework_failure_
+echo y | mv -vifn a b 2>/dev/null > out5 || fail=1
+compare out5 out_empty || fail=1
+
+# options --backup and --no-clobber are mutually exclusive
+touch a || framework_failure_
+returns_ 1 mv -bn a b 2>/dev/null || fail=1
+
+Exit $fail
diff --git a/tests/mv/mv-special-1.sh b/tests/mv/mv-special-1.sh
new file mode 100755
index 0000000..6abc916
--- /dev/null
+++ b/tests/mv/mv-special-1.sh
@@ -0,0 +1,75 @@
+#!/bin/sh
+# Test "mv" with special files.
+
+# Copyright (C) 1998-2022 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 3 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, see <https://www.gnu.org/licenses/>.
+
+. "${srcdir=.}/tests/init.sh"; path_prepend_ ./src
+print_ver_ mv
+cleanup_() { rm -rf "$other_partition_tmpdir"; }
+. "$abs_srcdir/tests/other-fs-tmpdir"
+
+null=mv-null
+dir=mv-dir
+
+rm -f $null || framework_failure_
+mknod $null p || framework_failure_
+test -p $null || framework_failure_
+mkdir -p $dir/a/b/c $dir/d/e/f || framework_failure_
+touch $dir/a/b/c/file1 $dir/d/e/f/file2 || framework_failure_
+
+# We used to...
+# exit 77 here to indicate that we couldn't run the test.
+# At least running on SunOS 4.1.4, using a directory NFS mounted
+# from an OpenBSD system, the above mknod fails.
+# It's not worth making an exception any more.
+
+mv --verbose $null $dir "$other_partition_tmpdir" > out || fail=1
+# Make sure the files are gone.
+test -p $null && fail=1
+test -d $dir && fail=1
+# Make sure they were moved.
+test -p "$other_partition_tmpdir/$null" || fail=1
+test -d "$other_partition_tmpdir/$dir/a/b/c" || fail=1
+
+# POSIX says rename (A, B) can succeed if A and B are on different file systems,
+# so ignore chatter about when files are removed and copied rather than renamed.
+sed "
+ /^removed /d
+ s,renamed ,,
+ s,copied ,,
+ s,$other_partition_tmpdir,XXX,
+ s,created directory 'XXX/\(.*\)','\1' -> 'XXX/\1',
+" out | sort > out2
+
+cat <<EOF | sort > exp
+'$null' -> 'XXX/$null'
+'$dir' -> 'XXX/$dir'
+'$dir/a' -> 'XXX/$dir/a'
+'$dir/a/b' -> 'XXX/$dir/a/b'
+'$dir/a/b/c' -> 'XXX/$dir/a/b/c'
+'$dir/a/b/c/file1' -> 'XXX/$dir/a/b/c/file1'
+'$dir/d' -> 'XXX/$dir/d'
+'$dir/d/e' -> 'XXX/$dir/d/e'
+'$dir/d/e/f' -> 'XXX/$dir/d/e/f'
+'$dir/d/e/f/file2' -> 'XXX/$dir/d/e/f/file2'
+EOF
+
+compare exp out2 || fail=1
+
+# cd "$other_partition_tmpdir"
+# ls -l -A -R "$other_partition_tmpdir"
+
+Exit $fail
diff --git a/tests/mv/no-target-dir.sh b/tests/mv/no-target-dir.sh
new file mode 100755
index 0000000..bfadcb0
--- /dev/null
+++ b/tests/mv/no-target-dir.sh
@@ -0,0 +1,51 @@
+#!/bin/sh
+# ensure that --no-target-directory (-T) works when the destination is
+# an empty directory.
+
+# Copyright (C) 2006-2022 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 3 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, see <https://www.gnu.org/licenses/>.
+
+. "${srcdir=.}/tests/init.sh"; path_prepend_ ./src
+print_ver_ mv
+
+LS_FAILURE=2
+
+mkdir -p d/sub empty src d2/sub e2 || framework_failure_
+touch f || framework_failure_
+
+# Skip this test if there's an underlying kernel bug.
+mkdir a b b/a || framework_failure_
+
+mv a b ||
+ skip_ "your kernel's rename syscall is buggy"
+
+
+# This should succeed, since both src and dest are directories,
+# and the dest dir is empty.
+mv -fT d empty || fail=1
+
+# Ensure that the source, d, is gone.
+returns_ $LS_FAILURE ls -d d > /dev/null 2>&1 || fail=1
+
+# Ensure that the dest dir now has a subdirectory.
+test -d empty/sub || fail=1
+
+# rename must fail, since the dest is non-empty.
+returns_ 1 mv -fT src d2 2> /dev/null || fail=1
+
+# rename must fail, since the src is not a directory.
+returns_ 1 mv -fT f e2 2> /dev/null || fail=1
+
+Exit $fail
diff --git a/tests/mv/part-fail.sh b/tests/mv/part-fail.sh
new file mode 100755
index 0000000..e617025
--- /dev/null
+++ b/tests/mv/part-fail.sh
@@ -0,0 +1,55 @@
+#!/bin/sh
+# Make sure we give a sensible diagnostic when a cross-device 'mv'
+# fails, e.g., because the destination cannot be unlinked.
+# This is a bit fragile since it relies on the string used
+# for EPERM: 'permission denied'.
+
+# Copyright (C) 2002-2022 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 3 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, see <https://www.gnu.org/licenses/>.
+
+. "${srcdir=.}/tests/init.sh"; path_prepend_ ./src
+print_ver_ mv
+skip_if_root_
+cleanup_() { t=$other_partition_tmpdir; chmod -R 700 "$t"; rm -rf "$t"; }
+. "$abs_srcdir/tests/other-fs-tmpdir"
+
+touch k "$other_partition_tmpdir/k" || framework_failure_
+chmod u-w "$other_partition_tmpdir" || framework_failure_
+
+
+mv -f k "$other_partition_tmpdir" 2> out && fail=1
+printf \
+"mv: inter-device move failed: '%s' to '%s';"\
+' unable to remove target: Permission denied\n' \
+ k "$other_partition_tmpdir/k" >exp
+
+# On some (less-compliant) systems, we get EPERM in this case.
+# Accept either diagnostic.
+cat <<EOF > exp2
+mv: cannot move 'k' to '$other_partition_tmpdir/k': Permission denied
+EOF
+
+if cmp out exp >/dev/null 2>&1; then
+ :
+else
+ if cmp out exp2; then
+ :
+ else
+ fail=1
+ fi
+fi
+test $fail = 1 && compare exp out
+
+Exit $fail
diff --git a/tests/mv/part-hardlink.sh b/tests/mv/part-hardlink.sh
new file mode 100755
index 0000000..b292584
--- /dev/null
+++ b/tests/mv/part-hardlink.sh
@@ -0,0 +1,43 @@
+#!/bin/sh
+# Ensure that hard links are preserved when moving between partitions
+# and when the links are in separate command line arguments.
+# For additional constraints, see the comment in copy.c.
+# Before coreutils-5.2.1, this test would fail.
+
+# Copyright (C) 2004-2022 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 3 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, see <https://www.gnu.org/licenses/>.
+
+. "${srcdir=.}/tests/init.sh"; path_prepend_ ./src
+print_ver_ mv
+cleanup_() { rm -rf "$other_partition_tmpdir"; }
+. "$abs_srcdir/tests/other-fs-tmpdir"
+
+touch f || framework_failure_
+ln f g || framework_failure_
+mkdir a b || framework_failure_
+touch a/1 || framework_failure_
+ln a/1 b/1 || framework_failure_
+
+
+mv f g "$other_partition_tmpdir" || fail=1
+mv a b "$other_partition_tmpdir" || fail=1
+
+cd "$other_partition_tmpdir"
+set $(ls -Ci f g)
+test $1 = $3 || fail=1
+set $(ls -Ci a/1 b/1)
+test $1 = $3 || fail=1
+
+Exit $fail
diff --git a/tests/mv/part-rename.sh b/tests/mv/part-rename.sh
new file mode 100755
index 0000000..c9fb9b6
--- /dev/null
+++ b/tests/mv/part-rename.sh
@@ -0,0 +1,57 @@
+#!/bin/sh
+# Test various cases for moving directories across file systems
+
+# Copyright (C) 2000-2022 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 3 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, see <https://www.gnu.org/licenses/>.
+
+. "${srcdir=.}/tests/init.sh"; path_prepend_ ./src
+print_ver_ mv
+cleanup_() { rm -rf "$other_partition_tmpdir"; }
+. "$abs_srcdir/tests/other-fs-tmpdir"
+
+
+# Moving a directory specified with a trailing slash from one partition to
+# another, and giving it a different name at the destination would cause mv
+# to get a failed assertion.
+mkdir foo || framework_failure_
+mv foo/ "$other_partition_tmpdir/bar" || fail=1
+
+
+# Moving a non directory from source shouldn't replace empty dir in dest
+touch bar || framework_failure_
+returns_ 1 mv bar "$other_partition_tmpdir/" || fail=1
+
+
+# Moving a directory from source shouldn't replace non directory in dest
+mkdir bar2
+touch "$other_partition_tmpdir/bar2"
+returns_ 1 mv bar2 "$other_partition_tmpdir/" || fail=1
+
+
+# As per POSIX moving directory from source should replace empty dir in dest
+mkdir bar3
+touch bar3/file
+mkdir "$other_partition_tmpdir/bar3"
+mv bar3 "$other_partition_tmpdir/" || fail=1
+test -e "$other_partition_tmpdir/bar3/file" || fail=1
+
+
+# As per POSIX moving directory from source shouldn't update dir in dest
+mkdir bar3
+touch bar3/file2
+returns_ 1 mv bar3 "$other_partition_tmpdir/" || fail=1
+test -e "$other_partition_tmpdir/bar3/file2" && fail=1
+
+Exit $fail
diff --git a/tests/mv/part-symlink.sh b/tests/mv/part-symlink.sh
new file mode 100755
index 0000000..563757a
--- /dev/null
+++ b/tests/mv/part-symlink.sh
@@ -0,0 +1,262 @@
+#!/bin/sh
+# make sure cp and mv can handle many combinations of local and
+# other-partition regular/symlink'd files.
+
+# Copyright (C) 2000-2022 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 3 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, see <https://www.gnu.org/licenses/>.
+
+. "${srcdir=.}/tests/init.sh"; path_prepend_ ./src
+print_ver_ cp mv
+
+cleanup_() { rm -rf "$other_partition_tmpdir"; }
+. "$abs_srcdir/tests/other-fs-tmpdir"
+
+# On NFS on Linux 2.6.9 at least we get:
+# mv: preserving permissions for 'rem_sl': Operation not supported
+require_local_dir_
+
+pwd_tmp=$(pwd)
+
+# Unset CDPATH. Otherwise, output from the 'cd dir' command
+# can make this test fail.
+(unset CDPATH) >/dev/null 2>&1 && unset CDPATH
+
+
+# Four cases:
+# local regular file w/symlink on another partition
+# (loc_reg, rem_sl)
+# (rem_sl, loc_reg)
+# local symlink to regular file on another partition
+# (loc_sl, rem_reg)
+# (rem_reg, loc_sl)
+
+# Exercise those four cases for each of
+# cp and mv, with lots of combinations of options.
+
+exec 1> actual
+
+# FIXME: This should be bigger: like more than 8k
+contents=XYZ
+
+loc_reg=loc_reg
+loc_sl=loc_sl
+rem_reg=$other_partition_tmpdir/rem_reg
+rem_sl=$other_partition_tmpdir/rem_sl
+
+for copy in cp mv; do
+ for args in \
+ 'loc_reg rem_sl' \
+ 'rem_sl loc_reg' \
+ 'loc_sl rem_reg' \
+ 'rem_reg loc_sl' \
+ ; do
+ for options in '' --rem '--rem -d' '--rem -b' -b -bd -d; do
+ case "$options" in *d*|*--rem*) test $copy = mv && continue;; esac
+ rm -rf dir || fail=1
+ rm -f "$other_partition_tmpdir"/* || fail=1
+ mkdir dir || fail=1
+ cd dir || fail=1
+ case "$args" in *loc_reg*) reg_abs="$(pwd)/$loc_reg" ;; esac
+ case "$args" in *rem_reg*) reg_abs=$rem_reg ;; esac
+ case "$args" in *loc_sl*) slink=$loc_sl ;; esac
+ case "$args" in *rem_sl*) slink=$rem_sl ;; esac
+
+ echo $contents > "$reg_abs" || framework_failure_
+ ln -nsf "$reg_abs" $slink || fail=1
+ actual_args=$(echo $args|sed 's,^,$,;s/ / $/')
+ actual_args=$(eval echo $actual_args)
+
+ (
+ (
+ # echo 1>&2 cp $options $args
+ $copy $options $actual_args 2>.err
+ copy_status=$?
+ echo $copy_status $copy $options $args
+
+ # Normalize the program name in the error output,
+ # remove any site-dependent part of other-partition file name,
+ # and put brackets around the output.
+ test -s .err \
+ && {
+ echo ' [' | tr -d '\n'
+ sed 's/^[^:][^:]*\(..\):/\1:/;s,'"$other_partition_tmpdir/,," .err |
+ tr -d '\n'
+ echo ']'
+ }
+ # Strip off all but the file names.
+ # Remove any site-dependent part of each file name.
+ ls=$(ls -gG --ignore=.err . \
+ | sed \
+ -e '/^total /d' \
+ -e "s,$other_partition_tmpdir/,," \
+ -e "s,$pwd_tmp/,," \
+ -e 's/^[^ ]* *[^ ]* *[^ ]* *[^ ]* *[^ ]* *[^ ]* *//')
+ ls2=$(cd "$other_partition_tmpdir" && ls -gG --ignore=.err . \
+ | sed \
+ -e '/^total /d' \
+ -e "s,$other_partition_tmpdir/,," \
+ -e "s,$pwd_tmp/,," \
+ -e 's/^[^ ]* *[^ ]* *[^ ]* *[^ ]* *[^ ]* *[^ ]* *//')
+ echo " ("$ls") ("$ls2")"
+
+ # If the command failed, then it must not have changed the files.
+ if test $copy_status != 0; then
+ for f in $actual_args; do
+ test -f $f ||
+ { echo " $copy FAILED but removed $f"; continue; }
+ case "$(cat $f)" in
+ "$contents") ;;
+ *) echo " $copy FAILED but modified $f";;
+ esac
+ done
+ fi
+
+ if test $copy = cp; then
+ # Make sure the original is unchanged and that
+ # the destination is a copy.
+ for f in $actual_args; do
+ if test -f $f; then
+ if test $copy_status != 0; then
+ test
+ fi
+ case "$(cat $f)" in
+ "$contents") ;;
+ *) echo " $copy FAILED";;
+ esac
+ else
+ echo " symlink-loop"
+ fi
+ done
+ fi
+ )
+ ) | sed 's/ *$//'
+ cd ..
+ done
+ echo
+ done
+done
+
+test $fail = 1 &&
+ { (exit 1); exit; }
+
+cat <<\EOF > expected || framework_failure_
+1 cp loc_reg rem_sl
+ [cp: 'loc_reg' and 'rem_sl' are the same file]
+ (loc_reg) (rem_sl -> dir/loc_reg)
+0 cp --rem loc_reg rem_sl
+ (loc_reg) (rem_sl)
+0 cp --rem -d loc_reg rem_sl
+ (loc_reg) (rem_sl)
+0 cp --rem -b loc_reg rem_sl
+ (loc_reg) (rem_sl rem_sl~ -> dir/loc_reg)
+0 cp -b loc_reg rem_sl
+ (loc_reg) (rem_sl rem_sl~ -> dir/loc_reg)
+0 cp -bd loc_reg rem_sl
+ (loc_reg) (rem_sl rem_sl~ -> dir/loc_reg)
+1 cp -d loc_reg rem_sl
+ [cp: 'loc_reg' and 'rem_sl' are the same file]
+ (loc_reg) (rem_sl -> dir/loc_reg)
+
+1 cp rem_sl loc_reg
+ [cp: 'rem_sl' and 'loc_reg' are the same file]
+ (loc_reg) (rem_sl -> dir/loc_reg)
+1 cp --rem rem_sl loc_reg
+ [cp: 'rem_sl' and 'loc_reg' are the same file]
+ (loc_reg) (rem_sl -> dir/loc_reg)
+1 cp --rem -d rem_sl loc_reg
+ [cp: 'rem_sl' and 'loc_reg' are the same file]
+ (loc_reg) (rem_sl -> dir/loc_reg)
+1 cp --rem -b rem_sl loc_reg
+ [cp: 'rem_sl' and 'loc_reg' are the same file]
+ (loc_reg) (rem_sl -> dir/loc_reg)
+1 cp -b rem_sl loc_reg
+ [cp: 'rem_sl' and 'loc_reg' are the same file]
+ (loc_reg) (rem_sl -> dir/loc_reg)
+0 cp -bd rem_sl loc_reg
+ (loc_reg -> dir/loc_reg loc_reg~) (rem_sl -> dir/loc_reg)
+ symlink-loop
+ symlink-loop
+1 cp -d rem_sl loc_reg
+ [cp: 'rem_sl' and 'loc_reg' are the same file]
+ (loc_reg) (rem_sl -> dir/loc_reg)
+
+1 cp loc_sl rem_reg
+ [cp: 'loc_sl' and 'rem_reg' are the same file]
+ (loc_sl -> rem_reg) (rem_reg)
+1 cp --rem loc_sl rem_reg
+ [cp: 'loc_sl' and 'rem_reg' are the same file]
+ (loc_sl -> rem_reg) (rem_reg)
+1 cp --rem -d loc_sl rem_reg
+ [cp: 'loc_sl' and 'rem_reg' are the same file]
+ (loc_sl -> rem_reg) (rem_reg)
+1 cp --rem -b loc_sl rem_reg
+ [cp: 'loc_sl' and 'rem_reg' are the same file]
+ (loc_sl -> rem_reg) (rem_reg)
+1 cp -b loc_sl rem_reg
+ [cp: 'loc_sl' and 'rem_reg' are the same file]
+ (loc_sl -> rem_reg) (rem_reg)
+0 cp -bd loc_sl rem_reg
+ (loc_sl -> rem_reg) (rem_reg -> rem_reg rem_reg~)
+ symlink-loop
+ symlink-loop
+1 cp -d loc_sl rem_reg
+ [cp: 'loc_sl' and 'rem_reg' are the same file]
+ (loc_sl -> rem_reg) (rem_reg)
+
+1 cp rem_reg loc_sl
+ [cp: 'rem_reg' and 'loc_sl' are the same file]
+ (loc_sl -> rem_reg) (rem_reg)
+0 cp --rem rem_reg loc_sl
+ (loc_sl) (rem_reg)
+0 cp --rem -d rem_reg loc_sl
+ (loc_sl) (rem_reg)
+0 cp --rem -b rem_reg loc_sl
+ (loc_sl loc_sl~ -> rem_reg) (rem_reg)
+0 cp -b rem_reg loc_sl
+ (loc_sl loc_sl~ -> rem_reg) (rem_reg)
+0 cp -bd rem_reg loc_sl
+ (loc_sl loc_sl~ -> rem_reg) (rem_reg)
+1 cp -d rem_reg loc_sl
+ [cp: 'rem_reg' and 'loc_sl' are the same file]
+ (loc_sl -> rem_reg) (rem_reg)
+
+0 mv loc_reg rem_sl
+ () (rem_sl)
+0 mv -b loc_reg rem_sl
+ () (rem_sl rem_sl~ -> dir/loc_reg)
+
+1 mv rem_sl loc_reg
+ [mv: 'rem_sl' and 'loc_reg' are the same file]
+ (loc_reg) (rem_sl -> dir/loc_reg)
+0 mv -b rem_sl loc_reg
+ (loc_reg -> dir/loc_reg loc_reg~) ()
+
+1 mv loc_sl rem_reg
+ [mv: 'loc_sl' and 'rem_reg' are the same file]
+ (loc_sl -> rem_reg) (rem_reg)
+0 mv -b loc_sl rem_reg
+ () (rem_reg -> rem_reg rem_reg~)
+
+0 mv rem_reg loc_sl
+ (loc_sl) ()
+0 mv -b rem_reg loc_sl
+ (loc_sl loc_sl~ -> rem_reg) ()
+
+EOF
+
+# Redirect to stderr, since stdout is already taken.
+compare expected actual 1>&2 || fail=1
+
+Exit $fail
diff --git a/tests/mv/partition-perm.sh b/tests/mv/partition-perm.sh
new file mode 100755
index 0000000..c813ec8
--- /dev/null
+++ b/tests/mv/partition-perm.sh
@@ -0,0 +1,37 @@
+#!/bin/sh
+# Make sure permissions are preserved when moving from one partition to another.
+
+# Copyright (C) 1999-2022 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 3 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, see <https://www.gnu.org/licenses/>.
+
+. "${srcdir=.}/tests/init.sh"; path_prepend_ ./src
+print_ver_ mv
+cleanup_() { rm -rf "$other_partition_tmpdir"; }
+. "$abs_srcdir/tests/other-fs-tmpdir"
+
+> file || framework_failure_
+chmod a=rwx file || framework_failure_
+
+umask 077
+mv file "$other_partition_tmpdir" || framework_failure_
+
+test -f file && fail=1
+test -f "$other_partition_tmpdir/file" || fail=1
+
+# This would have failed with the mv from fileutils-4.0i.
+mode=$(ls -l "$other_partition_tmpdir/file" | cut -b-10)
+test "$mode" = "-rwxrwxrwx" || fail=1
+
+Exit $fail
diff --git a/tests/mv/perm-1.sh b/tests/mv/perm-1.sh
new file mode 100755
index 0000000..079201a
--- /dev/null
+++ b/tests/mv/perm-1.sh
@@ -0,0 +1,35 @@
+#!/bin/sh
+# ensure that mv gives one diagnostic, not two, when failing
+# due to lack of permissions
+
+# Copyright (C) 2002-2022 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 3 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, see <https://www.gnu.org/licenses/>.
+
+. "${srcdir=.}/tests/init.sh"; path_prepend_ ./src
+print_ver_ mv
+skip_if_root_
+
+mkdir -p no-write/dir || framework_failure_
+chmod ug-w no-write || framework_failure_
+
+
+mv no-write/dir . > out 2>&1 && fail=1
+cat <<\EOF > exp
+mv: cannot move 'no-write/dir' to './dir': Permission denied
+EOF
+
+compare exp out || fail=1
+
+Exit $fail
diff --git a/tests/mv/sticky-to-xpart.sh b/tests/mv/sticky-to-xpart.sh
new file mode 100755
index 0000000..e9d87a3
--- /dev/null
+++ b/tests/mv/sticky-to-xpart.sh
@@ -0,0 +1,68 @@
+#!/bin/sh
+# A cross-partition move of a file in a sticky tmpdir and owned by
+# someone else would evoke an invalid diagnostic:
+# mv: cannot remove 'x': Operation not permitted
+# Affects coreutils-6.0-6.9.
+
+# Copyright (C) 2007-2022 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 3 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, see <https://www.gnu.org/licenses/>.
+
+. "${srcdir=.}/tests/init.sh"; path_prepend_ ./src
+print_ver_ mv
+require_root_
+
+cleanup_() { rm -rf "$other_partition_tmpdir"; }
+. "$abs_srcdir/tests/other-fs-tmpdir"
+
+# Set up to run a test where non-root user tries to move a root-owned
+# file from a sticky tmpdir to a directory owned by that user on
+# a different partition.
+
+mkdir t || framework_failure_
+chmod a=rwx,o+t t || framework_failure_
+echo > t/root-owned || framework_failure_
+chmod a+r t/root-owned || framework_failure_
+chown "$NON_ROOT_USERNAME" "$other_partition_tmpdir" || framework_failure_
+
+# We have to allow $NON_ROOT_USERNAME access to ".".
+chmod go+x . || framework_failure_
+
+
+# Ensure that $NON_ROOT_USERNAME can access the required version of mv.
+version=$(
+ chroot --skip-chdir --user=$NON_ROOT_USERNAME / env PATH="$PATH" \
+ mv --version |
+ sed -n '1s/.* //p'
+)
+case $version in
+ $PACKAGE_VERSION) ;;
+ *) skip_ "cannot access just-built mv as user $NON_ROOT_USERNAME";;
+esac
+
+chroot --skip-chdir --user=$NON_ROOT_USERNAME / env PATH="$PATH" \
+ mv t/root-owned "$other_partition_tmpdir" 2> out-t && fail=1
+
+# On some systems, we get 'Not owner'. Convert it.
+# On other systems (HPUX), we get 'Permission denied'. Convert it, too.
+onp='Operation not permitted'
+sed "s/Not owner/$onp/;s/Permission denied/$onp/" out-t > out
+
+cat <<\EOF > exp
+mv: cannot remove 't/root-owned': Operation not permitted
+EOF
+
+compare exp out || fail=1
+
+Exit $fail
diff --git a/tests/mv/symlink-onto-hardlink-to-self.sh b/tests/mv/symlink-onto-hardlink-to-self.sh
new file mode 100755
index 0000000..686cfbb
--- /dev/null
+++ b/tests/mv/symlink-onto-hardlink-to-self.sh
@@ -0,0 +1,63 @@
+#!/bin/sh
+# Demonstrate that when moving a symlink onto a hardlink-to-that-symlink,
+# an error is presented. Depending on your kernel (e.g., Linux, Solaris,
+# but not NetBSD), prior to coreutils-8.16, the mv would successfully perform
+# a no-op. I.e., surprisingly, mv s1 s2 would succeed, yet fail to remove s1.
+
+# Copyright (C) 2012-2022 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 3 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, see <https://www.gnu.org/licenses/>.
+
+. "${srcdir=.}/tests/init.sh"; path_prepend_ ./src
+print_ver_ mv
+
+# Create a file f, and a symlink s1 to that file.
+touch f || framework_failure_
+ln -s f s2 || framework_failure_
+
+# Attempt to create a hard link to that symlink.
+# On some systems, it's not possible: they create a hard link to the referent.
+ln s2 s1 || framework_failure_
+
+# If s1 is not a symlink, skip this test.
+test -h s1 \
+ || skip_ your kernel or file system cannot create a hard link to a symlink
+
+for opt in '' --backup; do
+
+ if test "$opt" = --backup; then
+ mv $opt s1 s2 > out 2>&1 || fail=1
+ compare /dev/null out || fail=1
+
+ # Ensure that s1 is gone.
+ test -e s1 && fail=1
+
+ # With --backup, ensure that the backup file was created.
+ ref=$(readlink s2~) || fail=1
+ test "$ref" = f || fail=1
+ else
+ echo "mv: 's1' and 's2' are the same file" > exp
+ mv $opt s1 s2 2>err && fail=1
+ compare exp err || fail=1
+
+ # Ensure that s1 is still present.
+ test -e s1 || fail=1
+
+ # Without --backup, ensure there is no backup file.
+ test -e s2~ && fail=1
+ fi
+
+done
+
+Exit $fail
diff --git a/tests/mv/symlink-onto-hardlink.sh b/tests/mv/symlink-onto-hardlink.sh
new file mode 100755
index 0000000..c24e3fc
--- /dev/null
+++ b/tests/mv/symlink-onto-hardlink.sh
@@ -0,0 +1,41 @@
+#!/bin/sh
+# Ensure that mv works with a few symlink-onto-hard-link cases.
+
+# Copyright (C) 2012-2022 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 3 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, see <https://www.gnu.org/licenses/>.
+
+. "${srcdir=.}/tests/init.sh"; path_prepend_ ./src
+print_ver_ mv
+
+touch f || framework_failure_
+ln f h || framework_failure_
+ln -s f s || framework_failure_
+
+# Given two links f and h to some important content, and a symlink s to f,
+# "mv s f" must fail because it might then be hard to find the link, h.
+# "mv s l" may succeed because then, s (now "l") still points to f.
+# Of course, if the symlink were being moved into a different destination
+# directory, things would be very different, and, I suspect, implausible.
+
+echo "mv: 's' and 'f' are the same file" > exp || framework_failure_
+mv s f > out 2> err && fail=1
+compare /dev/null out || fail=1
+compare exp err || fail=1
+
+mv s l > out 2> err || fail=1
+compare /dev/null out || fail=1
+compare /dev/null err || fail=1
+
+Exit $fail
diff --git a/tests/mv/to-symlink.sh b/tests/mv/to-symlink.sh
new file mode 100755
index 0000000..f249498
--- /dev/null
+++ b/tests/mv/to-symlink.sh
@@ -0,0 +1,43 @@
+#!/bin/sh
+# Make sure that the copying code used in an inter-partition
+# move unlinks a destination symlink before opening it.
+
+# Copyright (C) 1999-2022 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 3 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, see <https://www.gnu.org/licenses/>.
+
+. "${srcdir=.}/tests/init.sh"; path_prepend_ ./src
+print_ver_ mv
+cleanup_() { rm -rf "$other_partition_tmpdir"; }
+. "$abs_srcdir/tests/other-fs-tmpdir"
+
+rem_file="$other_partition_tmpdir/file"
+rem_symlink="$other_partition_tmpdir/symlink"
+file=to-sym
+
+echo local > $file || framework_failure_
+echo remote > $rem_file || framework_failure_
+ln -s $rem_file $rem_symlink || framework_failure_
+
+# This mv command should succeed, unlinking the symlink
+# before copying.
+mv $file $rem_symlink || fail=1
+
+# Make sure $file is gone.
+test -f $file && fail=1
+
+# Make sure $rem_file is unmodified.
+test $(cat $rem_file) = remote || fail=1
+
+Exit $fail
diff --git a/tests/mv/trailing-slash.sh b/tests/mv/trailing-slash.sh
new file mode 100755
index 0000000..9675d20
--- /dev/null
+++ b/tests/mv/trailing-slash.sh
@@ -0,0 +1,65 @@
+#!/bin/sh
+# On some operating systems, e.g. SunOS-4.1.1_U1 on sun3x,
+# rename() doesn't accept trailing slashes.
+# Also, ensure that "mv dir non-exist-dir/" works.
+# Also, ensure that "cp dir non-exist-dir/" works.
+
+# Copyright (C) 2004-2022 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 3 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, see <https://www.gnu.org/licenses/>.
+
+. "${srcdir=.}/tests/init.sh"; path_prepend_ ./src
+print_ver_ mv
+
+mkdir foo || framework_failure_
+
+
+mv foo/ bar || fail=1
+
+# mv and cp would misbehave for coreutils versions [5.3.0..5.97], 6.0 and 6.1
+for cmd in mv 'cp -r'; do
+ for opt in '' -T -u; do
+ rm -rf d e || framework_failure_
+ mkdir d || framework_failure_
+
+ $cmd $opt d e/ || fail=1
+ if test "$cmd" = mv; then
+ test -d d && fail=1
+ else
+ test -d d || fail=1
+ fi
+ test -d e || fail=1
+ done
+done
+
+# We would like the erroneous-looking "mv any non-dir/" to fail,
+# but with the current implementation, it depends on how the
+# underlying rename syscall handles the trailing slash.
+# It does fail, as desired, on recent Linux and Solaris systems.
+#touch a a2
+#returns_ 1 mv a a2/ || fail=1
+
+# Test for a cp-specific diagnostic introduced after coreutils-8.7:
+printf '%s\n' \
+ "cp: cannot create regular file 'no-such/': Not a directory" \
+> expected-err
+touch b
+cp b no-such/ 2> err
+
+# Map "No such file..." diagnostic to the expected "Not a directory"
+sed 's/No such file or directory/Not a directory/' err > k && mv k err
+
+compare expected-err err || fail=1
+
+Exit $fail
diff --git a/tests/mv/update.sh b/tests/mv/update.sh
new file mode 100755
index 0000000..4637448
--- /dev/null
+++ b/tests/mv/update.sh
@@ -0,0 +1,54 @@
+#!/bin/sh
+# make sure --update works as advertised
+
+# Copyright (C) 2001-2022 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 3 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, see <https://www.gnu.org/licenses/>.
+
+. "${srcdir=.}/tests/init.sh"; path_prepend_ ./src
+print_ver_ cp mv
+
+echo old > old || framework_failure_
+touch -d yesterday old || framework_failure_
+echo new > new || framework_failure_
+
+
+for interactive in '' -i; do
+ for cp_or_mv in cp mv; do
+ # This is a no-op, with no prompt.
+ # With coreutils-6.9 and earlier, using --update with -i would
+ # mistakenly elicit a prompt.
+ $cp_or_mv $interactive --update old new < /dev/null > out 2>&1 || fail=1
+ compare /dev/null out || fail=1
+ case "$(cat new)" in new) ;; *) fail=1 ;; esac
+ case "$(cat old)" in old) ;; *) fail=1 ;; esac
+ done
+done
+
+# This will actually perform the rename.
+mv --update new old || fail=1
+test -f new && fail=1
+case "$(cat old)" in new) ;; *) fail=1 ;; esac
+
+# Restore initial conditions.
+echo old > old || framework_failure_
+touch -d yesterday old || fail=1
+echo new > new || framework_failure_
+
+# This will actually perform the copy.
+cp --update new old || fail=1
+case "$(cat old)" in new) ;; *) fail=1 ;; esac
+case "$(cat new)" in new) ;; *) fail=1 ;; esac
+
+Exit $fail