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
Example #2
0
 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
Example #3
0
 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
Example #5
0
    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