From b7408b92f85e2892c202fa256787b5d75d45e991 Mon Sep 17 00:00:00 2001 From: Rob Browning Date: Mon, 23 Dec 2013 20:10:49 -0600 Subject: [PATCH 1/1] Change -x/--xdev/--one-filesystem to include the mount point itself. Match rsync, tar, etc., and add and use t/cleanup-mounts-under to clean up all temporary mounts under t/mnt and t/tmp. Thanks to Karl Kiniger for the report. Signed-off-by: Rob Browning Tested-by: Karl Kiniger --- Documentation/bup-drecurse.md | 3 +- Documentation/bup-index.md | 7 ++-- Documentation/bup-meta.md | 4 ++ Makefile | 4 +- lib/bup/drecurse.py | 30 +++++++-------- t/cleanup-mounts-under | 32 ++++++++++++++++ t/test-xdev.sh | 71 +++++++++++++++++++++++++++++++++++ 7 files changed, 131 insertions(+), 20 deletions(-) create mode 100755 t/cleanup-mounts-under create mode 100755 t/test-xdev.sh diff --git a/Documentation/bup-drecurse.md b/Documentation/bup-drecurse.md index 4692025..2a36362 100644 --- a/Documentation/bup-drecurse.md +++ b/Documentation/bup-drecurse.md @@ -30,7 +30,8 @@ come after its children, making this easy. # OPTIONS -x, \--xdev, \--one-file-system -: don't cross filesystem boundaries. +: don't cross filesystem boundaries -- though as with tar and rsync, + the mount points themselves will still be reported. -q, \--quiet : don't print filenames as they are encountered. Useful diff --git a/Documentation/bup-index.md b/Documentation/bup-index.md index a540444..003548f 100644 --- a/Documentation/bup-index.md +++ b/Documentation/bup-index.md @@ -121,9 +121,10 @@ does, due to the accommodations described above. format to the `-l` option to `ls`(1). -x, \--xdev, \--one-file-system -: don't cross filesystem boundaries when recursing - through the filesystem. Only applicable if you're - using `-u`. +: don't cross filesystem boundaries when recursing through the + filesystem -- though as with tar and rsync, the mount points + themselves will still be indexed. Only applicable if you're using + `-u`. \--fake-valid : mark specified filenames as up-to-date even if they diff --git a/Documentation/bup-meta.md b/Documentation/bup-meta.md index 00096dd..c8d1d37 100644 --- a/Documentation/bup-meta.md +++ b/Documentation/bup-meta.md @@ -80,6 +80,10 @@ is restored. -R, \--recurse : Recursively descend into subdirectories during `--create`. +\--xdev, \--one-file-system +: don't cross filesystem boundaries -- though as with tar and rsync, + the mount points themselves will still be handled. + \--numeric-ids : Apply numeric IDs (user, group, etc.) rather than names during `--extract` or `--finish-extract`. diff --git a/Makefile b/Makefile index 2835005..34f227a 100644 --- a/Makefile +++ b/Makefile @@ -102,6 +102,7 @@ runtests-cmdline: all TMPDIR="$(test_tmp)" t/test-save-restore-excludes.sh TMPDIR="$(test_tmp)" t/test-save-strip-graft.sh TMPDIR="$(test_tmp)" t/test-import-rdiff-backup.sh + TMPDIR="$(test_tmp)" t/test-xdev.sh TMPDIR="$(test_tmp)" t/test.sh stupid: @@ -172,8 +173,9 @@ clean: Documentation/clean config/clean bup bup-* cmd/bup-* lib/bup/_version.py randomgen memtest \ out[12] out2[tc] tags[12] tags2[tc] \ testfs.img lib/bup/t/testfs.img - umount t/mnt/* || true + if test -e t/mnt; then t/cleanup-mounts-under t/mnt; fi if test -e t/mnt; then rm -r t/mnt; fi + if test -e t/tmp; then t/cleanup-mounts-under t/tmp; fi # FIXME: migrate these to t/mnt/ if test -e bupmeta.tmp/testfs; \ then umount bupmeta.tmp/testfs || true; fi diff --git a/lib/bup/drecurse.py b/lib/bup/drecurse.py index 694c403..6be7fa2 100644 --- a/lib/bup/drecurse.py +++ b/lib/bup/drecurse.py @@ -61,25 +61,25 @@ def _recursive_dirlist(prepend, xdev, bup_dir=None, if exclude_rxs and should_rx_exclude_path(path, exclude_rxs): continue if name.endswith('/'): - if xdev != None and pst.st_dev != xdev: - debug1('Skipping %r: different filesystem.\n' % (prepend+name)) - continue if bup_dir != None: - if os.path.normpath(prepend+name) == bup_dir: + if os.path.normpath(path) == bup_dir: debug1('Skipping BUP_DIR.\n') continue - try: - OsFile(name).fchdir() - except OSError, e: - add_error('%s: %s' % (prepend, e)) + if xdev != None and pst.st_dev != xdev: + debug1('Skipping contents of %r: different filesystem.\n' % path) else: - for i in _recursive_dirlist(prepend=prepend+name, xdev=xdev, - bup_dir=bup_dir, - excluded_paths=excluded_paths, - exclude_rxs=exclude_rxs): - yield i - os.chdir('..') - yield (prepend + name, pst) + try: + OsFile(name).fchdir() + except OSError, e: + add_error('%s: %s' % (prepend, e)) + else: + for i in _recursive_dirlist(prepend=prepend+name, xdev=xdev, + bup_dir=bup_dir, + excluded_paths=excluded_paths, + exclude_rxs=exclude_rxs): + yield i + os.chdir('..') + yield (path, pst) def recursive_dirlist(paths, xdev, bup_dir=None, excluded_paths=None, diff --git a/t/cleanup-mounts-under b/t/cleanup-mounts-under new file mode 100755 index 0000000..6d5cb87 --- /dev/null +++ b/t/cleanup-mounts-under @@ -0,0 +1,32 @@ +#!/usr/bin/env python + +import os.path, re, subprocess, sys + +def mntent_unescape(x): + def replacement(m): + unescapes = { + "\\\\" : "\\", + "\\011" : "\t", + "\\012" : "\n", + "\\040" : " " + } + return unescapes.get(m.group(0)) + return re.sub(r'(\\\\|\\011|\\012|\\040)', replacement, x) + +targets = sys.argv[1:] +exit_status = 0 +for target in targets: + if not os.path.isdir(target): + print >> sys.stderr, target, 'is not a directory' + exit_status = 1 + continue + top = os.path.realpath(target) + proc_mounts = open('/proc/mounts', 'r') + for line in proc_mounts: + _, point, _ = line.split(' ', 2) + point = mntent_unescape(point) + if top == point or os.path.commonprefix((top + '/', point)) == top + '/': + if subprocess.call(['umount', point]) != 0: + exit_status = 1 + +sys.exit(exit_status) diff --git a/t/test-xdev.sh b/t/test-xdev.sh new file mode 100755 index 0000000..18530f6 --- /dev/null +++ b/t/test-xdev.sh @@ -0,0 +1,71 @@ +#!/usr/bin/env bash +. ./wvtest-bup.sh + +set -o pipefail + +if [ $(t/root-status) != root ]; then + echo 'Not root: skipping xdev tests.' + exit 0 # FIXME: add WVSKIP. +fi + +# These tests are only likely to work under Linux for now +# (patches welcome). +if ! [[ $(uname) =~ Linux ]]; then + echo 'Not Linux: skipping xdev tests.' + exit 0 # FIXME: add WVSKIP. +fi + +top="$(WVPASS pwd)" || exit $? +tmpdir="$(WVPASS wvmktempdir)" || exit $? + +export BUP_DIR="$tmpdir/bup" +export GIT_DIR="$tmpdir/bup" + +bup() { "$top/bup" "$@"; } + +WVPASS bup init +WVPASS pushd "$tmpdir" + +WVSTART 'drecurse' + +WVPASS dd if=/dev/zero of=testfs.img bs=1M count=32 +WVPASS mkfs -F testfs.img # Don't care what type. +WVPASS mkdir -p src/mnt/{a,b,c} +WVPASS mount -o loop testfs.img src/mnt +WVPASS mkdir -p src/mnt/x +WVPASS touch src/1 src/mnt/2 src/mnt/x/3 + +WVPASSEQ "$(bup drecurse src | grep -vF lost+found)" "src/mnt/x/3 +src/mnt/x/ +src/mnt/2 +src/mnt/ +src/1 +src/" + +WVPASSEQ "$(bup drecurse -x src)" "src/mnt/ +src/1 +src/" + +WVSTART 'index/save/restore' + +WVPASS bup index src +WVPASS bup save -n src src +WVPASS mkdir src-restore +WVPASS bup restore -C src-restore "/src/latest$(pwd)/" +WVPASS test -d src-restore/src +WVPASS "$top/t/compare-trees" -c src/ src-restore/src/ + +WVPASS rm -r "$BUP_DIR" src-restore +WVPASS bup init +WVPASS bup index -x src +WVPASS bup save -n src src +WVPASS mkdir src-restore +WVPASS bup restore -C src-restore "/src/latest$(pwd)/" +WVPASS test -d src-restore/src +WVPASSEQ "$(cd src-restore/src && find . -not -name lost+found | sort)" ". +./1 +./mnt" + +WVPASS popd +WVPASS umount "$tmpdir/src/mnt" +WVPASS rm -r "$tmpdir" -- 2.39.2