Răsfoiți Sursa

Implemented, mode, owner and ctime/mtime support

Jonas Borgström 14 ani în urmă
părinte
comite
0839e6bed3
2 a modificat fișierele cu 59 adăugiri și 4 ștergeri
  1. 17 2
      dedupestore/archiver.py
  2. 42 2
      dedupestore/helpers.py

+ 17 - 2
dedupestore/archiver.py

@@ -11,7 +11,8 @@ import msgpack
 from .chunkifier import chunkify
 from .cache import Cache, NS_ARCHIVES, NS_CHUNKS
 from .bandstore import BandStore
-from .helpers import location_validator, pretty_size, LevelFilter
+from .helpers import location_validator, pretty_size, LevelFilter, \
+    uid2user, user2uid, gid2group, group2gid
 
 CHUNK_SIZE = 55001
 
@@ -110,6 +111,14 @@ class Archive(object):
                             raise Exception('Invalid chunk checksum')
                         data = zlib.decompress(data)
                         fd.write(data)
+                os.chmod(path, item['mode'])
+                uid = user2uid(item['user']) or item['uid']
+                gid = group2gid(item['group']) or item['gid']
+                try:
+                    os.chown(path, uid, gid)
+                except OSError:
+                    pass
+                os.utime(path, (item['ctime'], item['mtime']))
 
     def verify(self):
         for item in self.items:
@@ -189,7 +198,13 @@ class Archive(object):
             for chunk in chunkify(fd, CHUNK_SIZE, 30):
                 size += len(chunk)
                 chunks.append(self.add_chunk(*self.cache.add_chunk(chunk)))
-        self.items.append({'type': 'FILE', 'path': path, 'chunks': chunks, 'size': size})
+        self.items.append({
+            'type': 'FILE', 'path': path, 'chunks': chunks, 'size': size,
+            'mode': st.st_mode,
+            'uid': st.st_uid, 'user': uid2user(st.st_uid),
+            'gid': st.st_gid, 'group': gid2group(st.st_gid),
+            'ctime': st.st_ctime, 'mtime': st.st_mtime,
+        })
 
 
 class Archiver(object):

+ 42 - 2
dedupestore/helpers.py

@@ -1,10 +1,51 @@
 import logging
 import argparse
 import re
+import grp
+import pwd
 
+def memoize(function):
+    cache = {}
+    def decorated_function(*args):
+        try:
+            return cache[args]
+        except KeyError:
+            val = function(*args)
+            cache[args] = val
+            return val
+    return decorated_function
+
+@memoize
+def uid2user(uid):
+    try:
+        return pwd.getpwuid(uid).pw_name
+    except KeyError:
+        return None
+
+@memoize
+def user2uid(user):
+    try:
+        return pwd.getpwnam(user).pw_uid
+    except KeyError:
+        return None
+
+@memoize
+def gid2group(gid):
+    try:
+        return grp.getgrgid(gid).gr_name
+    except KeyError:
+        return None
+
+@memoize
+def group2gid(group):
+    try:
+        return grp.getgrnam(group).gr_gid
+    except KeyError:
+        return None
 
 class LevelFilter(logging.Filter):
-
+    """Filter that counts record levels
+    """
     def __init__(self, *args, **kwargs):
         logging.Filter.__init__(self, *args, **kwargs)
         self.count = {}
@@ -15,7 +56,6 @@ class LevelFilter(logging.Filter):
         return record
 
 
-
 class Location(object):
 
     loc_re = re.compile(r'^((?:(?P<user>[^@]+)@)?(?P<host>[^:]+):)?'