]> arthur.barton.de Git - bup.git/commitdiff
metadata: recover politely if xattr/acl support is missing.
authorAvery Pennarun <apenwarr@gmail.com>
Sun, 20 Mar 2011 08:25:13 +0000 (01:25 -0700)
committerAvery Pennarun <apenwarr@gmail.com>
Sun, 20 Mar 2011 09:41:44 +0000 (02:41 -0700)
...previously we'd just crash, which is definitely not polite.

metadata.py now prints warning on import if these features are missing.
That's probably overly obnoxious, especially on systems that don't support
those types of metadata at all.  Is there a way to determine whether a
kernel *should* support that type of metadata, so we can warn only if so?

(Obviously if the kernel doesn't support, say, xattrs, there's no point
warning that bup doesn't support them, because no files will be using them
anyway.  Hmm...)

Signed-off-by: Avery Pennarun <apenwarr@gmail.com>
cmd/xstat-cmd.py
lib/bup/metadata.py
lib/bup/t/tmetadata.py

index c3a672cc5827b4bb58db21df3356b2bbd012b4a5..888dc0986240ac19a976ff9c644eb584f2307be2 100755 (executable)
@@ -107,8 +107,8 @@ for path in remainder:
     if 'linux-xattr' in active_fields and m.linux_xattr:
         for name, value in m.linux_xattr:
             print 'linux-xattr: %s -> %s' % (name, repr(value))
-    if 'posix1e-acl' in active_fields and m.posix1e_acl:
-        flags = posix1e.TEXT_ABBREVIATE
+    if 'posix1e-acl' in active_fields and m.posix1e_acl and metadata.posix1e:
+        flags = metadata.posix1e.TEXT_ABBREVIATE
         if stat.S_ISDIR(m.mode):
             acl = m.posix1e_acl[0]
             default_acl = m.posix1e_acl[2]
index 38eb76b163c842d7e39198a01b675b3cb5d866aa..e2ace93636d0195a5dee9a7b5c9b8fc96f482cb7 100644 (file)
@@ -4,9 +4,7 @@
 #
 # This code is covered under the terms of the GNU Library General
 # Public License as described in the bup LICENSE file.
-
-import errno, os, sys, stat, pwd, grp, struct, xattr, posix1e, re
-
+import errno, os, sys, stat, pwd, grp, struct, re
 from cStringIO import StringIO
 from bup import vint
 from bup.drecurse import recursive_dirlist
@@ -14,6 +12,16 @@ from bup.helpers import add_error, mkdirp, log
 from bup.xstat import utime, lutime, lstat, FSTime
 import bup._helpers as _helpers
 
+try:
+    import xattr
+except ImportError:
+    log('Warning: Linux xattr support missing; install python-pyxattr.\n')
+    xattr = None
+try:
+    import posix1e
+except ImportError:
+    log('Warning: POSIX ACL support missing; install python-pylibacl.\n')
+    posix1e = None
 if _helpers.get_linux_file_attr:
     from bup._helpers import get_linux_file_attr, set_linux_file_attr
 
@@ -354,6 +362,7 @@ class Metadata:
     # The numeric/text distinction only matters when reading/restoring
     # a stored record.
     def _add_posix1e_acl(self, path, st):
+        if not posix1e: return
         if not stat.S_ISLNK(st.st_mode):
             try:
                 if posix1e.has_extended(path):
@@ -392,6 +401,11 @@ 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):
+        if not posix1e:
+            if self.posix1e_acl:
+                add_error("%s: can't restore ACLs; posix1e support missing.\n"
+                          % path)
+            return
         if self.posix1e_acl:
             acls = self.posix1e_acl
             if len(acls) > 2:
@@ -439,6 +453,7 @@ class Metadata:
     ## Linux extended attributes (getfattr(1), setfattr(1))
 
     def _add_linux_xattr(self, path, st):
+        if not xattr: return
         try:
             self.linux_xattr = xattr.get_all(path, nofollow=True)
         except EnvironmentError, e:
@@ -465,6 +480,11 @@ class Metadata:
         self.linux_xattr = result
 
     def _apply_linux_xattr_rec(self, path, restore_numeric_ids=False):
+        if not xattr:
+            if self.linux_xattr:
+                add_error("%s: can't restore xattr; xattr support missing.\n"
+                          % path)
+            return
         existing_xattrs = set(xattr.list(path, nofollow=True))
         if self.linux_xattr:
             for k, v in self.linux_xattr:
index 8852a38942f8f38e474c4747a1a4c3fb1098c887..a5f7a4f2eac364061c311989ab7b94aeb5b8e7dc 100644 (file)
@@ -1,4 +1,4 @@
-import glob, grp, pwd, stat, tempfile, subprocess, xattr
+import glob, grp, pwd, stat, tempfile, subprocess
 import bup.helpers as helpers
 from bup import metadata
 from bup.helpers import clear_errors, detect_fakeroot
@@ -229,27 +229,40 @@ def test_restore_over_existing_target():
         subprocess.call(['rm', '-rf', tmpdir])
 
 
-@wvtest
-def test_handling_of_incorrect_existing_linux_xattrs():
-    if os.geteuid() != 0 or detect_fakeroot():
-        return
-    setup_testfs()
-    subprocess.check_call('rm -rf testfs/*', shell=True)
-    path = 'testfs/foo'
-    open(path, 'w').close()
-    xattr.set(path, 'foo', 'bar', namespace=xattr.NS_USER)
-    m = metadata.from_path(path, archive_path=path, save_symlinks=True)
-    xattr.set(path, 'baz', 'bax', namespace=xattr.NS_USER)
-    m.apply_to_path(path, restore_numeric_ids=False)
-    WVPASSEQ(xattr.list(path), ['user.foo'])
-    WVPASSEQ(xattr.get(path, 'user.foo'), 'bar')
-    xattr.set(path, 'foo', 'baz', namespace=xattr.NS_USER)
-    m.apply_to_path(path, restore_numeric_ids=False)
-    WVPASSEQ(xattr.list(path), ['user.foo'])
-    WVPASSEQ(xattr.get(path, 'user.foo'), 'bar')
-    xattr.remove(path, 'foo', namespace=xattr.NS_USER)
-    m.apply_to_path(path, restore_numeric_ids=False)
-    WVPASSEQ(xattr.list(path), ['user.foo'])
-    WVPASSEQ(xattr.get(path, 'user.foo'), 'bar')
-    os.chdir(top_dir)
-    cleanup_testfs()
+from bup.metadata import posix1e
+if not posix1e:
+    @wvtest
+    def POSIX1E_ACL_SUPPORT_IS_MISSING():
+        pass
+
+
+from bup.metadata import xattr
+if not xattr:
+    @wvtest
+    def LINUX_XATTR_SUPPORT_IS_MISSING():
+        pass
+else:
+    @wvtest
+    def test_handling_of_incorrect_existing_linux_xattrs():
+        if os.geteuid() != 0 or detect_fakeroot():
+            return
+        setup_testfs()
+        subprocess.check_call('rm -rf testfs/*', shell=True)
+        path = 'testfs/foo'
+        open(path, 'w').close()
+        xattr.set(path, 'foo', 'bar', namespace=xattr.NS_USER)
+        m = metadata.from_path(path, archive_path=path, save_symlinks=True)
+        xattr.set(path, 'baz', 'bax', namespace=xattr.NS_USER)
+        m.apply_to_path(path, restore_numeric_ids=False)
+        WVPASSEQ(xattr.list(path), ['user.foo'])
+        WVPASSEQ(xattr.get(path, 'user.foo'), 'bar')
+        xattr.set(path, 'foo', 'baz', namespace=xattr.NS_USER)
+        m.apply_to_path(path, restore_numeric_ids=False)
+        WVPASSEQ(xattr.list(path), ['user.foo'])
+        WVPASSEQ(xattr.get(path, 'user.foo'), 'bar')
+        xattr.remove(path, 'foo', namespace=xattr.NS_USER)
+        m.apply_to_path(path, restore_numeric_ids=False)
+        WVPASSEQ(xattr.list(path), ['user.foo'])
+        WVPASSEQ(xattr.get(path, 'user.foo'), 'bar')
+        os.chdir(top_dir)
+        cleanup_testfs()