mirror of
https://github.com/RsyncProject/rsync.git
synced 2026-03-10 10:27:13 -04:00
If a symlink, device, special-file, or hard-linked file is replacing an existing non-directory, the new file is created using a temporary filename and then renamed into place. Also changed the handling of a cluster of hard-linked symlinks/devices/special-files to always ensure the first item in the cluster is correct, since it doesn't really save any significant work to try to find an existing correct item later in the cluster to link with.
151 lines
3.9 KiB
Bash
151 lines
3.9 KiB
Bash
#! /bin/sh
|
|
|
|
# Copyright (C) 2002 by Martin Pool <mbp@samba.org>
|
|
|
|
# This program is distributable under the terms of the GNU GPL (see
|
|
# COPYING).
|
|
|
|
# Test rsync handling of devices. This can only run if you're root.
|
|
|
|
. "$suitedir/rsync.fns"
|
|
|
|
chkfile="$scratchdir/rsync.chk"
|
|
outfile="$scratchdir/rsync.out"
|
|
|
|
# Build some hardlinks
|
|
|
|
case $0 in
|
|
*fake*)
|
|
$RSYNC --version | grep ", xattrs" >/dev/null || test_skipped "Rsync needs xattrs for fake device tests"
|
|
RSYNC="$RSYNC --fake-super"
|
|
TLS_ARGS="$TLS_ARGS --fake-super"
|
|
case "`xattr 2>&1`" in
|
|
*--list:*)
|
|
mknod() {
|
|
fn="$1"
|
|
case "$2" in
|
|
p) mode=10644 ;;
|
|
c) mode=20644 ;;
|
|
b) mode=60644 ;;
|
|
esac
|
|
maj="${3:-0}"
|
|
min="${4:-0}"
|
|
touch "$fn"
|
|
xattr -s 'rsync.%stat' "$mode $maj,$min 0:0" "$fn"
|
|
}
|
|
;;
|
|
*)
|
|
mknod() {
|
|
fn="$1"
|
|
case "$2" in
|
|
p) mode=10644 ;;
|
|
c) mode=20644 ;;
|
|
b) mode=60644 ;;
|
|
esac
|
|
maj="${3:-0}"
|
|
min="${4:-0}"
|
|
touch "$fn"
|
|
setfattr -n 'user.rsync.%stat' -v "$mode $maj,$min 0:0" "$fn"
|
|
}
|
|
;;
|
|
esac
|
|
;;
|
|
*)
|
|
case `id -u` in
|
|
'') ;; # If "id" failed, try to continue...
|
|
0) ;;
|
|
*) if [ -f /usr/bin/fakeroot ]; then
|
|
echo "Let's try re-running the script under fakeroot..."
|
|
exec /usr/bin/fakeroot /bin/sh $RUNSHFLAGS "$0"
|
|
fi
|
|
test_skipped "Rsync needs root/fakeroot for device tests"
|
|
;;
|
|
esac
|
|
;;
|
|
esac
|
|
|
|
# TODO: Need to test whether hardlinks are possible on this OS/filesystem
|
|
|
|
mkdir "$fromdir"
|
|
mkdir "$todir"
|
|
mknod "$fromdir/char" c 41 67 || test_skipped "Can't create char device node"
|
|
mknod "$fromdir/char2" c 42 68 || test_skipped "Can't create char device node"
|
|
mknod "$fromdir/char3" c 42 69 || test_skipped "Can't create char device node"
|
|
mknod "$fromdir/block" b 42 69 || test_skipped "Can't create block device node"
|
|
mknod "$fromdir/block2" b 42 73 || test_skipped "Can't create block device node"
|
|
mknod "$fromdir/block3" b 105 73 || test_skipped "Can't create block device node"
|
|
ln "$fromdir/block3" "$fromdir/block2.5" || echo "Skipping hard-linked device test..."
|
|
mkfifo "$fromdir/fifo" || mknod "$fromdir/fifo" p || test_skipped "Can't run mkfifo"
|
|
# Work around time rounding/truncating issue by touching both files.
|
|
touch -r "$fromdir/block" "$fromdir/block" "$fromdir/block2"
|
|
|
|
$RSYNC -ai "$fromdir/block" "$todir/block2" \
|
|
| tee "$outfile"
|
|
cat <<EOT >"$chkfile"
|
|
cD$all_plus block
|
|
EOT
|
|
diff $diffopt "$chkfile" "$outfile" || test_fail "test 1 failed"
|
|
|
|
$RSYNC -ai "$fromdir/block2" "$todir/block" \
|
|
| tee "$outfile"
|
|
cat <<EOT >"$chkfile"
|
|
cD$all_plus block2
|
|
EOT
|
|
diff $diffopt "$chkfile" "$outfile" || test_fail "test 2 failed"
|
|
|
|
sleep 1
|
|
|
|
$RSYNC -Di "$fromdir/block3" "$todir/block" \
|
|
| tee "$outfile"
|
|
cat <<EOT >"$chkfile"
|
|
cDc.T.$dots block3
|
|
EOT
|
|
diff $diffopt "$chkfile" "$outfile" || test_fail "test 3 failed"
|
|
|
|
$RSYNC -aiHvv "$fromdir/" "$todir/" \
|
|
| tee "$outfile"
|
|
filter_outfile
|
|
cat <<EOT >"$chkfile"
|
|
.d..t.$dots ./
|
|
cDc.t.$dots block
|
|
cDc...$dots block2
|
|
cD$all_plus block2.5
|
|
hD$all_plus block3 => block2.5
|
|
cD$all_plus char
|
|
cD$all_plus char2
|
|
cD$all_plus char3
|
|
cS$all_plus fifo
|
|
EOT
|
|
if test ! -r "$fromdir/block2.5"; then
|
|
sed -e '/block2\.5/d' <"$chkfile" >"$chkfile.new"
|
|
mv "$chkfile.new" "$chkfile"
|
|
fi
|
|
diff $diffopt "$chkfile" "$outfile" || test_fail "test 4 failed"
|
|
|
|
echo "check how the directory listings compare with diff:"
|
|
echo ""
|
|
( cd "$fromdir" && rsync_ls_lR . ) > "$tmpdir/ls-from"
|
|
( cd "$todir" && rsync_ls_lR . ) > "$tmpdir/ls-to"
|
|
diff $diffopt "$tmpdir/ls-from" "$tmpdir/ls-to"
|
|
|
|
if test -b "$fromdir/block2.5"; then
|
|
set -x
|
|
$RSYNC -aii --link-dest="$todir" "$fromdir/" "$chkdir/" \
|
|
| tee "$outfile"
|
|
cat <<EOT >"$chkfile"
|
|
cd$allspace ./
|
|
hD$allspace block
|
|
hD$allspace block2
|
|
hD$allspace block2.5
|
|
hD$allspace block3
|
|
hD$allspace char
|
|
hD$allspace char2
|
|
hD$allspace char3
|
|
hS$allspace fifo
|
|
EOT
|
|
diff $diffopt "$chkfile" "$outfile" || test_fail "test 4 failed"
|
|
fi
|
|
|
|
# The script would have aborted on error, so getting here means we've won.
|
|
exit 0
|