399 lines
9.3 KiB
Bash
399 lines
9.3 KiB
Bash
#! /bin/sh
|
|
|
|
# Copyright (C) 2001 by Martin Pool <mbp@samba.org>
|
|
|
|
# General-purpose test functions for rsync.
|
|
|
|
# This program is free software; you can redistribute it and/or modify
|
|
# it under the terms of the GNU General Public License version
|
|
# 2 as published by the Free Software Foundation.
|
|
#
|
|
# 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
|
|
# Lesser General Public License for more details.
|
|
#
|
|
# You should have received a copy of the GNU Lesser General Public
|
|
# License along with this program; if not, write to the Free Software
|
|
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
|
|
|
tmpdir="$scratchdir"
|
|
fromdir="$tmpdir/from"
|
|
todir="$tmpdir/to"
|
|
chkdir="$tmpdir/chk"
|
|
|
|
# For itemized output:
|
|
all_plus='+++++++++'
|
|
allspace=' '
|
|
dots='.....' # trailing dots after changes
|
|
tab_ch=' ' # a single tab character
|
|
|
|
# Berkley's nice.
|
|
PATH="$PATH:/usr/ucb"
|
|
|
|
if diff -u "$suitedir/rsync.fns" "$suitedir/rsync.fns" >/dev/null 2>&1; then
|
|
diffopt="-u"
|
|
else
|
|
diffopt="-c"
|
|
fi
|
|
|
|
HOME="$scratchdir"
|
|
export HOME
|
|
|
|
runtest() {
|
|
echo $ECHO_N "Test $1: $ECHO_C"
|
|
if eval "$2"
|
|
then
|
|
echo "$ECHO_T done."
|
|
return 0
|
|
else
|
|
echo "$ECHO_T failed!"
|
|
return 1
|
|
fi
|
|
}
|
|
|
|
set_cp_destdir() {
|
|
while test $# -gt 1; do
|
|
shift
|
|
done
|
|
destdir="$1"
|
|
}
|
|
|
|
# Perform a "cp -p", making sure that timestamps are really the same,
|
|
# even if the copy rounded microsecond times on the destination file.
|
|
cp_touch() {
|
|
cp -p "${@}" || test_fail "cp -p failed"
|
|
if test $# -gt 2 -o -d "$2"; then
|
|
set_cp_destdir "${@}" # sets destdir var
|
|
while test $# -gt 1; do
|
|
destname="$destdir/`basename $1`"
|
|
touch -r "$destname" "$1" "$destname"
|
|
shift
|
|
done
|
|
else
|
|
touch -r "$2" "$1" "$2"
|
|
fi
|
|
}
|
|
|
|
# Call this if you want to filter out verbose messages (-v or -vv) from
|
|
# the output of an rsync run (whittling the output down to just the file
|
|
# messages). This isn't needed if you use -i without -v.
|
|
filter_outfile() {
|
|
sed -e '/^building file list /d' \
|
|
-e '/^sending incremental file list/d' \
|
|
-e '/^created directory /d' \
|
|
-e '/^done$/d' \
|
|
-e '/ --whole-file$/d' \
|
|
-e '/^total: /d' \
|
|
-e '/^client charset: /d' \
|
|
-e '/^server charset: /d' \
|
|
-e '/^$/,$d' \
|
|
<"$outfile" >"$outfile.new"
|
|
mv "$outfile.new" "$outfile"
|
|
}
|
|
|
|
printmsg() {
|
|
echo "$1"
|
|
}
|
|
|
|
rsync_ls_lR() {
|
|
find "$@" -print | sort | sed 's/ /\\ /g' | xargs "$TOOLDIR/tls" $TLS_ARGS
|
|
}
|
|
|
|
get_testuid() {
|
|
id 2>/dev/null | sed 's/^[^0-9]*\([0-9][0-9]*\).*/\1/'
|
|
}
|
|
|
|
check_perms() {
|
|
perms=`"$TOOLDIR/tls" "$1" | sed 's/^[-d]\(.........\).*/\1/'`
|
|
if test $perms = $2; then
|
|
return 0
|
|
fi
|
|
echo "permissions: $perms on $1"
|
|
echo "should be: $2"
|
|
test_fail "failed test $3"
|
|
}
|
|
|
|
rsync_getgroups() {
|
|
"$TOOLDIR/getgroups"
|
|
}
|
|
|
|
|
|
####################
|
|
# Build test directories $todir and $fromdir, with $fromdir full of files.
|
|
|
|
hands_setup() {
|
|
# Clean before creation
|
|
rm -rf "$fromdir"
|
|
rm -rf "$todir"
|
|
|
|
[ -d "$tmpdir" ] || mkdir "$tmpdir"
|
|
[ -d "$fromdir" ] || mkdir "$fromdir"
|
|
[ -d "$todir" ] || mkdir "$todir"
|
|
|
|
# On some BSD systems, the umask affects the mode of created
|
|
# symlinks, even though the mode apparently has no effect on how
|
|
# the links behave in the future, and it cannot be changed using
|
|
# chmod! rsync always sets its umask to 000 so that it can
|
|
# accurately recreate permissions, but this script is probably run
|
|
# with a different umask.
|
|
|
|
# This causes a little problem that "ls -l" of the two will not be
|
|
# the same. So, we need to set our umask before doing any creations.
|
|
|
|
# set up test data
|
|
touch "$fromdir/empty"
|
|
mkdir "$fromdir/emptydir"
|
|
|
|
# a hundred lines of text or so
|
|
rsync_ls_lR "$srcdir" > "$fromdir/filelist"
|
|
|
|
echo $ECHO_N "This file has no trailing lf$ECHO_C" > "$fromdir/nolf"
|
|
umask 0
|
|
ln -s nolf "$fromdir/nolf-symlink"
|
|
umask 022
|
|
|
|
cat "$srcdir"/*.c > "$fromdir/text"
|
|
mkdir "$fromdir/dir"
|
|
cp "$fromdir/text" "$fromdir/dir"
|
|
mkdir "$fromdir/dir/subdir"
|
|
echo some data > "$fromdir/dir/subdir/foobar.baz"
|
|
mkdir "$fromdir/dir/subdir/subsubdir"
|
|
if [ -r /etc ]; then
|
|
ls -ltr /etc > "$fromdir/dir/subdir/subsubdir/etc-ltr-list"
|
|
else
|
|
ls -ltr / > "$fromdir/dir/subdir/subsubdir/etc-ltr-list"
|
|
fi
|
|
mkdir "$fromdir/dir/subdir/subsubdir2"
|
|
if [ -r /bin ]; then
|
|
ls -lt /bin > "$fromdir/dir/subdir/subsubdir2/bin-lt-list"
|
|
else
|
|
ls -lt / > "$fromdir/dir/subdir/subsubdir2/bin-lt-list"
|
|
fi
|
|
|
|
# echo testing head:
|
|
# ls -lR "$srcdir" | head -10 || echo failed
|
|
}
|
|
|
|
|
|
####################
|
|
# Many machines do not have "mkdir -p", so we have to build up long paths.
|
|
# How boring.
|
|
makepath() {
|
|
for p in "${@}"; do
|
|
(echo " makepath $p"
|
|
|
|
# Absolut Unix.
|
|
if echo $p | grep '^/' >/dev/null
|
|
then
|
|
cd /
|
|
fi
|
|
|
|
# This will break if $p contains a space.
|
|
for c in `echo $p | tr '/' ' '`
|
|
do
|
|
if [ -d "$c" ] || mkdir "$c"
|
|
then
|
|
cd "$c" || return $?
|
|
else
|
|
echo "failed to create $c" >&2; return $?
|
|
fi
|
|
done)
|
|
done
|
|
}
|
|
|
|
|
|
|
|
###########################
|
|
# Run a test (in '$1') then compare directories $2 and $3 to see if
|
|
# there are any difference. If there are, explain them.
|
|
|
|
# So normally basically $1 should be an rsync command, and $2 and $3
|
|
# the source and destination directories. This is only good when you
|
|
# expect to transfer the whole directory exactly as is. If some files
|
|
# should be excluded, you might need to use something else.
|
|
|
|
checkit() {
|
|
failed=
|
|
|
|
# We can just write everything to stdout/stderr, because the
|
|
# wrapper hides it unless there is a problem.
|
|
|
|
echo "Running: \"$1\""
|
|
eval "$1"
|
|
status=$?
|
|
if [ $status != 0 ]; then
|
|
failed="$failed status=$status"
|
|
fi
|
|
|
|
echo "-------------"
|
|
echo "check how the directory listings compare with diff:"
|
|
echo ""
|
|
( cd "$2" && rsync_ls_lR . ) > "$tmpdir/ls-from"
|
|
( cd "$3" && rsync_ls_lR . ) > "$tmpdir/ls-to"
|
|
diff $diffopt "$tmpdir/ls-from" "$tmpdir/ls-to" || failed="$failed dir-diff"
|
|
|
|
echo "-------------"
|
|
echo "check how the files compare with diff:"
|
|
echo ""
|
|
if [ "x$4" != x ]; then
|
|
echo " === Skipping (as directed) ==="
|
|
else
|
|
diff -r $diffopt "$2" "$3" || failed="$failed file-diff"
|
|
fi
|
|
|
|
echo "-------------"
|
|
if [ -z "$failed" ] ; then
|
|
return 0
|
|
fi
|
|
|
|
echo "Failed: $failed"
|
|
return 1
|
|
}
|
|
|
|
|
|
build_rsyncd_conf() {
|
|
# Build an appropriate configuration file
|
|
conf="$scratchdir/test-rsyncd.conf"
|
|
echo "building configuration $conf"
|
|
|
|
port=2612
|
|
pidfile="$scratchdir/rsyncd.pid"
|
|
logfile="$scratchdir/rsyncd.log"
|
|
hostname=`uname -n`
|
|
|
|
uid_setting='uid = 0'
|
|
gid_setting='gid = 0'
|
|
case `get_testuid` in
|
|
0) ;;
|
|
*)
|
|
# Non-root cannot specify uid & gid settings
|
|
uid_setting="#$uid_setting"
|
|
gid_setting="#$gid_setting"
|
|
;;
|
|
esac
|
|
|
|
cat >"$conf" <<EOF
|
|
# rsyncd configuration file autogenerated by $0
|
|
|
|
pid file = $pidfile
|
|
use chroot = no
|
|
munge symlinks = no
|
|
hosts allow = localhost 127.0.0.0/24 192.168.0.0/16 10.0.0.0/8 $hostname
|
|
log file = $logfile
|
|
log format = %i %h [%a] %m (%u) %l %f%L
|
|
transfer logging = yes
|
|
exclude = ? foobar.baz
|
|
max verbosity = 4
|
|
$uid_setting
|
|
$gid_setting
|
|
|
|
[test-from]
|
|
path = $fromdir
|
|
read only = yes
|
|
comment = r/o
|
|
|
|
[test-to]
|
|
path = $todir
|
|
read only = no
|
|
comment = r/w
|
|
|
|
[test-scratch]
|
|
path = $scratchdir
|
|
read only = no
|
|
|
|
[test-hidden]
|
|
path = $fromdir
|
|
list = no
|
|
EOF
|
|
|
|
# Build a helper script to ignore exit code 23
|
|
ignore23="$scratchdir/ignore23"
|
|
echo "building help script $ignore23"
|
|
|
|
cat >"$ignore23" <<'EOT'
|
|
if "${@}"; then
|
|
exit
|
|
fi
|
|
|
|
ret=$?
|
|
|
|
if test $ret = 23; then
|
|
exit
|
|
fi
|
|
|
|
exit $ret
|
|
EOT
|
|
chmod +x "$ignore23"
|
|
}
|
|
|
|
|
|
build_symlinks() {
|
|
mkdir "$fromdir"
|
|
date >"$fromdir/referent"
|
|
ln -s referent "$fromdir/relative"
|
|
ln -s "$fromdir/referent" "$fromdir/absolute"
|
|
ln -s nonexistent "$fromdir/dangling"
|
|
ln -s "$srcdir/rsync.c" "$fromdir/unsafe"
|
|
}
|
|
|
|
test_fail() {
|
|
echo "$@" >&2
|
|
exit 1
|
|
}
|
|
|
|
test_skipped() {
|
|
echo "$@" >&2
|
|
echo "$@" > "$tmpdir/whyskipped"
|
|
exit 77
|
|
}
|
|
|
|
# It failed, but we expected that. don't dump out error logs,
|
|
# because most users won't want to see them. But do leave
|
|
# the working directory around.
|
|
test_xfail() {
|
|
echo "$@" >&2
|
|
exit 78
|
|
}
|
|
|
|
# Determine what shell command will appropriately test for links.
|
|
ln -s foo "$scratchdir/testlink"
|
|
for cmd in test /bin/test /usr/bin/test /usr/ucb/bin/test /usr/ucb/test
|
|
do
|
|
for switch in -h -L
|
|
do
|
|
if $cmd $switch "$scratchdir/testlink" 2>/dev/null
|
|
then
|
|
# how nice
|
|
TEST_SYMLINK_CMD="$cmd $switch"
|
|
# i wonder if break 2 is portable?
|
|
break 2
|
|
fi
|
|
done
|
|
done
|
|
# ok, now get rid of it
|
|
rm "$scratchdir/testlink"
|
|
|
|
|
|
if [ "x$TEST_SYMLINK_CMD" = 'x' ]
|
|
then
|
|
test_fail "Couldn't determine how to test for symlinks"
|
|
else
|
|
echo "Testing for symlinks using '$TEST_SYMLINK_CMD'"
|
|
fi
|
|
|
|
|
|
# Test whether something is a link, allowing for shell peculiarities
|
|
is_a_link() {
|
|
# note the variable contains the first option and therefore is not quoted
|
|
$TEST_SYMLINK_CMD "$1"
|
|
}
|
|
|
|
|
|
# We need to set the umask to be reproducible. Note also that when we
|
|
# do some daemon tests as root, we will setuid() and therefore the
|
|
# directory has to be writable by the nobody user in some cases. The
|
|
# best thing is probably to explicitly chmod those directories after
|
|
# creation.
|
|
|
|
umask 022
|