浏览代码

xattr: use some string processing functions, dedup, simplify

Thomas Waldmann 9 年之前
父节点
当前提交
b6ead3dce2
共有 1 个文件被更改,包括 22 次插入26 次删除
  1. 22 26
      borg/xattr.py

+ 22 - 26
borg/xattr.py

@@ -109,6 +109,22 @@ except OSError as e:
     raise Exception(msg)
     raise Exception(msg)
 
 
 
 
+def split_string0(buf):
+    """split a list of zero-terminated strings into python not-zero-terminated bytes"""
+    return buf.split(b'\0')[:-1]
+
+
+def split_lstring(buf):
+    """split a list of length-prefixed strings into python not-length-prefixed bytes"""
+    result = []
+    mv = memoryview(buf)
+    while mv:
+        length = mv[0]
+        result.append(bytes(mv[1:1 + length]))
+        mv = mv[1 + length:]
+    return result
+
+
 class BufferTooSmallError(Exception):
 class BufferTooSmallError(Exception):
     """the buffer given to an xattr function was too small for the result"""
     """the buffer given to an xattr function was too small for the result"""
 
 
@@ -200,10 +216,7 @@ if sys.platform.startswith('linux'):  # pragma: linux only
                     return libc.llistxattr(path, buf, size)
                     return libc.llistxattr(path, buf, size)
 
 
         n, buf = _listxattr_inner(func, path)
         n, buf = _listxattr_inner(func, path)
-        if n == 0:
-            return []
-        names = buf[:n].split(b'\0')[:-1]
-        return [os.fsdecode(name) for name in names
+        return [os.fsdecode(name) for name in split_string0(buf[:n])
                 if not name.startswith(b'system.posix_acl_')]
                 if not name.startswith(b'system.posix_acl_')]
 
 
     def getxattr(path, name, *, follow_symlinks=True):
     def getxattr(path, name, *, follow_symlinks=True):
@@ -217,9 +230,7 @@ if sys.platform.startswith('linux'):  # pragma: linux only
                     return libc.lgetxattr(path, name, buf, size)
                     return libc.lgetxattr(path, name, buf, size)
 
 
         n, buf = _getxattr_inner(func, path, name)
         n, buf = _getxattr_inner(func, path, name)
-        if n == 0:
-            return
-        return buf[:n]
+        return buf[:n] or None
 
 
     def setxattr(path, name, value, *, follow_symlinks=True):
     def setxattr(path, name, value, *, follow_symlinks=True):
         def func(path, name, value, size):
         def func(path, name, value, size):
@@ -262,10 +273,7 @@ elif sys.platform == 'darwin':  # pragma: darwin only
                     return libc.listxattr(path, buf, size, XATTR_NOFOLLOW)
                     return libc.listxattr(path, buf, size, XATTR_NOFOLLOW)
 
 
         n, buf = _listxattr_inner(func, path)
         n, buf = _listxattr_inner(func, path)
-        if n == 0:
-            return []
-        names = buf[:n].split(b'\0')[:-1]
-        return [os.fsdecode(name) for name in names]
+        return [os.fsdecode(name) for name in split_string0(buf[:n])]
 
 
     def getxattr(path, name, *, follow_symlinks=True):
     def getxattr(path, name, *, follow_symlinks=True):
         def func(path, name, buf, size):
         def func(path, name, buf, size):
@@ -278,9 +286,7 @@ elif sys.platform == 'darwin':  # pragma: darwin only
                     return libc.getxattr(path, name, buf, size, 0, XATTR_NOFOLLOW)
                     return libc.getxattr(path, name, buf, size, 0, XATTR_NOFOLLOW)
 
 
         n, buf = _getxattr_inner(func, path, name)
         n, buf = _getxattr_inner(func, path, name)
-        if n == 0:
-            return
-        return buf[:n]
+        return buf[:n] or None
 
 
     def setxattr(path, name, value, *, follow_symlinks=True):
     def setxattr(path, name, value, *, follow_symlinks=True):
         def func(path, name, value, size):
         def func(path, name, value, size):
@@ -326,15 +332,7 @@ elif sys.platform.startswith('freebsd'):  # pragma: freebsd only
                     return libc.extattr_list_link(path, ns, buf, size)
                     return libc.extattr_list_link(path, ns, buf, size)
 
 
         n, buf = _listxattr_inner(func, path)
         n, buf = _listxattr_inner(func, path)
-        if n == 0:
-            return []
-        names = []
-        mv = memoryview(buf)[:n]
-        while mv:
-            length = mv[0]
-            names.append(os.fsdecode(bytes(mv[1:1 + length])))
-            mv = mv[1 + length:]
-        return names
+        return [os.fsdecode(name) for name in split_lstring(buf[:n])]
 
 
     def getxattr(path, name, *, follow_symlinks=True):
     def getxattr(path, name, *, follow_symlinks=True):
         def func(path, name, buf, size):
         def func(path, name, buf, size):
@@ -347,9 +345,7 @@ elif sys.platform.startswith('freebsd'):  # pragma: freebsd only
                     return libc.extattr_get_link(path, ns, name, buf, size)
                     return libc.extattr_get_link(path, ns, name, buf, size)
 
 
         n, buf = _getxattr_inner(func, path, name)
         n, buf = _getxattr_inner(func, path, name)
-        if n == 0:
-            return
-        return buf[:n]
+        return buf[:n] or None
 
 
     def setxattr(path, name, value, *, follow_symlinks=True):
     def setxattr(path, name, value, *, follow_symlinks=True):
         def func(path, name, value, size):
         def func(path, name, value, size):