def _detect_eas(self, rp, write): """ Set extended attributes from rp. Tests writing if write is true. """ assert rp.conn is Globals.local_connection, ( "Action only foreseen locally and not over {conn}.".format( conn=rp.conn)) assert rp.lstat(), "Path '{rp}' must exist to test EAs.".format(rp=rp) if not Globals.eas_active: log.Log( "Extended attributes test skipped as rdiff-backup was " "started with --no-eas option", log.INFO) self.eas = None return try: import xattr.pyxattr_compat as xattr except ImportError: try: import xattr except ImportError: log.Log( "Unable to import module (py)xattr. Extended attributes " "not supported on filesystem at path {pa}".format(pa=rp), log.INFO) self.eas = False return test_ea = b"test val" try: xattr.list(rp.path) if write: xattr.set(rp.path, b"user.test", test_ea) read_ea = xattr.get(rp.path, b"user.test") except OSError as exc: log.Log( "Extended attributes not supported by filesystem at " "path {pa} due to exception '{ex}'".format(pa=rp, ex=exc), log.NOTE) self.eas = False else: if write and read_ea != test_ea: log.Log( "Extended attributes support is broken on filesystem at " "path {pa}. Please upgrade the filesystem driver, contact " "the developers, or use the --no-eas option to disable " "extended attributes support and suppress this " "message".format(pa=rp), log.WARNING) self.eas = False else: self.eas = True
def read_from_rp(self, rp): """Set the extended attributes from an rpath""" try: attr_list = xattr.list(rp.path, rp.issym()) except OSError as exc: if exc.errno in (errno.EOPNOTSUPP, errno.EPERM, errno.ETXTBSY): return # if not supported, consider empty if exc.errno in (errno.EACCES, errno.ENOENT, errno.ELOOP): log.Log( "Listing extended attributes of path {pa} produced " "exception '{ex}', ignored".format(pa=rp, ex=exc), log.INFO) return raise for attr in attr_list: if attr.startswith(b'system.'): # Do not preserve system extended attributes continue if not rp.isdir() and attr == b'com.apple.ResourceFork': # Resource Fork handled elsewhere, except for directories continue try: self.attr_dict[attr] = xattr.get(rp.path, attr, rp.issym()) except OSError as exc: # File probably modified while reading, just continue if exc.errno == errno.ENODATA: continue elif exc.errno == errno.ENOENT: break # Handle bug in pyxattr < 0.2.2 elif exc.errno == errno.ERANGE: continue else: raise
def _clear_rp(self, rp): """Delete all the extended attributes in rpath""" try: for name in xattr.list(rp.path, rp.issym()): try: xattr.remove(rp.path, name, rp.issym()) except PermissionError: # errno.EACCES # SELinux attributes cannot be removed, and we don't want # to bail out or be too noisy at low log levels. log.Log( "Not allowed to remove extended attribute " "{ea} from path {pa}".format(ea=name, pa=rp), log.DEBUG) continue except OSError as exc: # can happen because trusted.SGI_ACL_FILE is deleted # together with system.posix_acl_access on XFS file systems. if exc.errno == errno.ENODATA: continue else: # can be anything, just fail raise except io.UnsupportedOperation: # errno.EOPNOTSUPP or errno.EPERM return # if not supported, consider empty except FileNotFoundError as exc: log.Log( "Unable to clear extended attributes on path {pa} due to " "exception '{ex}', ignoring".format(pa=rp, ex=exc), log.NOTE) return
def _detect_eas(self, rp, write): """Set extended attributes from rp. Tests writing if write is true.""" assert rp.conn is Globals.local_connection, ( "Action only foreseen locally and not over {conn}.".format( conn=rp.conn)) assert rp.lstat(), "Path '{rp!s}' must exist to test EAs.".format( rp=rp) if Globals.eas_active == 0: log.Log( "Extended attributes test skipped. rdiff-backup run " "with --no-eas option.", 4) self.eas = 0 return try: import xattr.pyxattr_compat as xattr except ImportError: try: import xattr except ImportError: log.Log( "Unable to import module (py)xattr.\nExtended attributes not " "supported on filesystem at %s" % (rp.get_safepath(), ), 4) self.eas = 0 return test_ea = b"test val" try: xattr.list(rp.path) if write: xattr.set(rp.path, b"user.test", test_ea) read_ea = xattr.get(rp.path, b"user.test") except IOError: log.Log( "Extended attributes not supported by " "filesystem at %s" % (rp.get_safepath(), ), 4) self.eas = 0 else: if write and read_ea != test_ea: log.Log( "Extended attributes support is broken on filesystem at " "%s.\nPlease upgrade the filesystem driver, contact the " "developers,\nor use the --no-eas option to disable " "extended attributes\nsupport and suppress this message." % (rp.get_safepath(), ), 1) self.eas = 0 else: self.eas = 1
def set_eas(self, rp, write): """Set extended attributes from rp. Tests writing if write is true.""" assert Globals.local_connection is rp.conn assert rp.lstat() if Globals.eas_active == 0: log.Log( "Extended attributes test skipped. rdiff-backup run " "with --no-eas option.", 4) self.eas = 0 return try: import xattr.pyxattr_compat as xattr except ImportError: try: import xattr except ImportError: log.Log( "Unable to import module (py)xattr.\nExtended attributes not " "supported on filesystem at %s" % (rp.get_safepath(), ), 4) self.eas = 0 return try: xattr.list(rp.path) if write: xattr.set(rp.path, b"user.test", b"test val") assert xattr.get(rp.path, b"user.test") == b"test val" except IOError: log.Log( "Extended attributes not supported by " "filesystem at %s" % (rp.get_safepath(), ), 4) self.eas = 0 except AssertionError: log.Log( "Extended attributes support is broken on filesystem at " "%s.\nPlease upgrade the filesystem driver, contact the " "developers,\nor use the --no-eas option to disable " "extended attributes\nsupport and suppress this message." % (rp.get_safepath(), ), 1) self.eas = 0 else: self.eas = 1