]> arthur.barton.de Git - bup.git/commitdiff
Defer errors when the restore target doesn't support relevant metadata.
authorRob Browning <rlb@defaultvalue.org>
Sun, 3 Jun 2012 21:49:39 +0000 (16:49 -0500)
committerRob Browning <rlb@defaultvalue.org>
Tue, 25 Dec 2012 00:50:04 +0000 (18:50 -0600)
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 <rlb@defaultvalue.org>
Reviewed-by: Zoran Zaric <zz@zoranzaric.de>
Makefile
lib/bup/metadata.py
t/test-meta.sh

index 99248cbfdd2f3cc90d837748474ad2472e57b499..c382466c34c2e87485a1048ca34ef5627bb5177d 100644 (file)
--- 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
index 87fd10b84a84383b63c075f0467767bba33ac0c5..6feef21ca01267db43b03ad261b43fb0a1873b49 100644 (file)
@@ -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
index 06e06ace4d668c7a5d1b7e73ea20f8d967b14107..aea9b77146330a8ebfd7efdb1bfae57ddb510a70 100755 (executable)
@@ -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