From 458e92da32ddd3c18fc1c3e52a76e9f0b48b832f Mon Sep 17 00:00:00 2001 From: Rob Browning Date: Sun, 3 Jun 2012 16:49:39 -0500 Subject: [PATCH] Defer errors when the restore target doesn't support relevant metadata. When the restore target doesn't support POSIX1e ACLs, extended attributes, or Linux attributes, handle the failures via add_error() (i.e. defer them). Test these cases by creating a loopback VFAT filesystem (testfs-limited) and using it as a restore target. Signed-off-by: Rob Browning Reviewed-by: Zoran Zaric --- Makefile | 2 ++ lib/bup/metadata.py | 28 ++++++++++++++----- t/test-meta.sh | 66 ++++++++++++++++++++++++++++++++++++++------- 3 files changed, 80 insertions(+), 16 deletions(-) diff --git a/Makefile b/Makefile index 99248cb..c382466 100644 --- a/Makefile +++ b/Makefile @@ -160,4 +160,6 @@ clean: Documentation/clean then umount bupmeta.tmp/testfs || true; fi if test -e lib/bup/t/testfs; \ then umount lib/bup/t/testfs || true; fi + if test -e bupmeta.tmp/testfs-limited; \ + then umount bupmeta.tmp/testfs-limited || true; fi rm -rf *.tmp t/*.tmp lib/*/*/*.tmp build lib/bup/build lib/bup/t/testfs diff --git a/lib/bup/metadata.py b/lib/bup/metadata.py index 87fd10b..6feef21 100644 --- a/lib/bup/metadata.py +++ b/lib/bup/metadata.py @@ -459,6 +459,15 @@ class Metadata: self.posix1e_acl = [posix1e.ACL(text=x) for x in acl_reps] def _apply_posix1e_acl_rec(self, path, restore_numeric_ids=False): + def apply_acl(acl, kind): + try: + acl.applyto(path, kind) + except IOError, e: + if e.errno == errno.EPERM or e.errno == errno.EOPNOTSUPP: + raise ApplyError('POSIX1e ACL applyto: %s' % e) + else: + raise + if not posix1e: if self.posix1e_acl: add_error("%s: can't restore ACLs; posix1e support missing.\n" @@ -468,13 +477,13 @@ class Metadata: acls = self.posix1e_acl if len(acls) > 2: if restore_numeric_ids: - acls[3].applyto(path, posix1e.ACL_TYPE_DEFAULT) + apply_acl(acls[3], posix1e.ACL_TYPE_DEFAULT) else: - acls[2].applyto(path, posix1e.ACL_TYPE_DEFAULT) + apply_acl(acls[2], posix1e.ACL_TYPE_DEFAULT) if restore_numeric_ids: - acls[1].applyto(path, posix1e.ACL_TYPE_ACCESS) + apply_acl(acls[1], posix1e.ACL_TYPE_ACCESS) else: - acls[0].applyto(path, posix1e.ACL_TYPE_ACCESS) + apply_acl(acls[0], posix1e.ACL_TYPE_ACCESS) ## Linux attributes (lsattr(1), chattr(1)) @@ -513,7 +522,13 @@ class Metadata: add_error("%s: can't restore linuxattrs: " "linuxattr support missing.\n" % path) return - set_linux_file_attr(path, self.linux_attr) + try: + set_linux_file_attr(path, self.linux_attr) + except OSError, e: + if e.errno == errno.ENOTTY: + raise ApplyError('Linux chattr: %s' % e) + else: + raise ## Linux extended attributes (getfattr(1), setfattr(1)) @@ -559,7 +574,8 @@ class Metadata: try: xattr.set(path, k, v, nofollow=True) except IOError, e: - if e.errno == errno.EPERM: + if e.errno == errno.EPERM \ + or e.errno == errno.EOPNOTSUPP: raise ApplyError('xattr.set: %s' % e) else: raise diff --git a/t/test-meta.sh b/t/test-meta.sh index 06e06ac..aea9b77 100755 --- a/t/test-meta.sh +++ b/t/test-meta.sh @@ -110,9 +110,16 @@ test-src-save-restore() ) } -if actually-root; then +universal-cleanup() +{ + if ! actually-root; then return 0; fi + cd "$TOP" umount "$TOP/bupmeta.tmp/testfs" || true -fi + umount "$TOP/bupmeta.tmp/testfs-limited" || true +} + +universal-cleanup +trap universal-cleanup EXIT setup-test-tree() ( @@ -355,18 +362,12 @@ WVSTART 'meta --edit' # Linux attr, Linux xattr, etc. if actually-root; then ( + set -e + # Some cleanup handled in universal-cleanup() above. # These tests are only likely to work under Linux for now # (patches welcome). [[ $(uname) =~ Linux ]] || exit 0 - cleanup_at_exit() - { - cd "$TOP" - umount "$TOP/bupmeta.tmp/testfs" || true - } - - trap cleanup_at_exit EXIT - WVSTART 'meta - general (as root)' setup-test-tree cd "$TOP/bupmeta.tmp" @@ -380,6 +381,13 @@ if actually-root; then chown root:root testfs chmod 0700 testfs + umount testfs-limited || true + dd if=/dev/zero of=testfs-limited.img bs=1M count=32 + mkfs -t vfat testfs-limited.img + mkdir testfs-limited + mount -o loop,uid=root,gid=root,umask=0077 \ + testfs-limited.img testfs-limited + #cp -a src testfs/src cp -pPR src testfs/src (cd testfs && test-src-create-extract) @@ -423,6 +431,18 @@ if actually-root; then chattr +acdeijstuADST testfs/src/foo chattr +acdeijstuADST testfs/src/bar (cd testfs && test-src-create-extract) + # Test restoration to a limited filesystem (vfat). + ( + WVPASS bup meta --create --recurse --file testfs/src.meta \ + testfs/src + force-delete testfs-limited/src-restore + mkdir testfs-limited/src-restore + cd testfs-limited/src-restore + WVFAIL bup meta --extract --file ../../testfs/src.meta 2>&1 \ + | WVPASS grep -e '^Linux chattr:' \ + | WVPASS python -c \ + 'import sys; exit(not len(sys.stdin.readlines()) == 2)' + ) ) WVSTART 'meta - Linux xattr (as root)' @@ -434,6 +454,19 @@ if actually-root; then attr -s foo -V bar testfs/src/foo attr -s foo -V bar testfs/src/bar (cd testfs && test-src-create-extract) + + # Test restoration to a limited filesystem (vfat). + ( + WVPASS bup meta --create --recurse --file testfs/src.meta \ + testfs/src + force-delete testfs-limited/src-restore + mkdir testfs-limited/src-restore + cd testfs-limited/src-restore + WVFAIL bup meta --extract --file ../../testfs/src.meta 2>&1 \ + | WVPASS grep -e '^xattr\.set:' \ + | WVPASS python -c \ + 'import sys; exit(not len(sys.stdin.readlines()) == 2)' + ) ) WVSTART 'meta - POSIX.1e ACLs (as root)' @@ -445,6 +478,19 @@ if actually-root; then setfacl -m u:root:r testfs/src/foo setfacl -m u:root:r testfs/src/bar (cd testfs && test-src-create-extract) + + # Test restoration to a limited filesystem (vfat). + ( + WVPASS bup meta --create --recurse --file testfs/src.meta \ + testfs/src + force-delete testfs-limited/src-restore + mkdir testfs-limited/src-restore + cd testfs-limited/src-restore + WVFAIL bup meta --extract --file ../../testfs/src.meta 2>&1 \ + | WVPASS grep -e '^POSIX1e ACL applyto:' \ + | WVPASS python -c \ + 'import sys; exit(not len(sys.stdin.readlines()) == 2)' + ) ) ) fi -- 2.39.2