deltatar: setting and checking mtime and ctime in dirs and files
authorEduardo Robles Elvira <edulix@wadobo.com>
Thu, 8 Aug 2013 08:55:10 +0000 (10:55 +0200)
committerEduardo Robles Elvira <edulix@wadobo.com>
Thu, 8 Aug 2013 08:55:10 +0000 (10:55 +0200)
deltatar/deltatar.py
testing/test_deltatar.py

index 2b37bd9..47b4a29 100644 (file)
@@ -21,7 +21,9 @@
 import logging
 import datetime
 import binascii
+import operator
 import os
+import copy
 import shutil
 import re
 import stat
@@ -351,8 +353,8 @@ class DeltaTar(object):
             u'type': ptype,
             u'path': unicode(path),
             u'mode': mode,
-            u'mtime': stinfo.st_mtime,
-            u'ctime': stinfo.st_ctime,
+            u'mtime': int(stinfo.st_mtime),
+            u'ctime': int(stinfo.st_ctime),
             u'uid': stinfo.st_uid,
             u'gid': stinfo.st_gid,
             u'inode': stinfo.st_ino,
@@ -363,9 +365,9 @@ class DeltaTar(object):
         '''
         Return if the dicts are equal in the stat keys
         '''
-        keys = [u'gid', u'type', u'mode',u'size', u'uid',
+        keys = [u'gid', u'type', u'mode',u'size', u'uid', u'mtime', u'ctime',
             # TODO: check how to restore this correctly if possible
-            #u'mtime', u'ctime', u'inode'
+            # u'inode'
         ]
 
         if (not d1 and d2 != None) or (d1 != None and not d2):
@@ -999,6 +1001,7 @@ class DeltaTar(object):
                 helper.delete(upath)
                 helper.restore(ipath, l_no)
 
+            helper.restore_directories_permissions()
             os.chdir(cwd)
             helper.cleanup()
 
@@ -1028,6 +1031,10 @@ class RestoreHelper(object):
 
     _cwd = None
 
+    # list of directories to be restored. This is done as a last step, see
+    # tarfile.extractall for details.
+    _directories = []
+
     def __init__(self, deltatar, cwd, index_list):
         '''
         Constructor opens the tars and init the data structures.
@@ -1035,6 +1042,7 @@ class RestoreHelper(object):
         Index list must be provided in reverse order (newer first)
         '''
         self._data = []
+        self._directories = []
         self._deltatar = deltatar
         self._cwd = cwd
 
@@ -1099,7 +1107,6 @@ class RestoreHelper(object):
         # we go from index to index, finding the path in the index, then finding
         # the index with the most recent snapshot of the file being restored
         cur_index = 1
-
         while cur_index < len(self._data):
             data = self._data[cur_index]
             it = data['iterator']
@@ -1146,6 +1153,24 @@ class RestoreHelper(object):
         self._deltatar.logger.warn(('Error restoring file %s from index, '
                                     'snapshot not found in any index') % path)
 
+    def restore_directories_permissions(self):
+        '''
+        Restore directory permissions when everything have been restored
+        '''
+        self._directories.sort(key=operator.attrgetter('name'))
+        self._directories.reverse()
+        tarobj = self._data[0]['tarobj']
+
+        # Set correct owner, mtime and filemode on directories.
+        for member in self._directories:
+            dirpath = member.name
+            try:
+                tarobj.chmod(member, dirpath)
+                tarobj.utime(member, dirpath)
+                tarobj.chown(member, dirpath)
+            except tarfile.ExtractError, e:
+                self._deltatar.logger.warn('tarfile: %s' % e)
+
     @classmethod
     def new_volume_handler(deltarobj, cwd, backup_path, tarobj, base_name, volume_number):
         '''
@@ -1209,5 +1234,11 @@ class RestoreHelper(object):
 
         member.path = unprefixed
         member.name = unprefixed
+
+        if op_type == 'directory':
+            self._directories.append(member)
+            member = copy.copy(member)
+            member.mode = 0700
+
         # finally, restore the file
-        index_data['tarobj'].extract(member)
\ No newline at end of file
+        index_data['tarobj'].extract(member)
index 8c45314..903e75e 100644 (file)
@@ -1053,7 +1053,6 @@ class DeltaTarTest(BaseTest):
             assert deltatar._equal_stat_dicts(sitem, titem)
 
 
-
 class DeltaTar2Test(DeltaTarTest):
     '''
     Same as DeltaTar but with specific ":" mode
@@ -1117,3 +1116,4 @@ class DeltaTarGzipAes256ConcatTest(DeltaTarTest):
     '''
     MODE = '#gz.aes256'
     PASSWORD = 'some magic key'
+1
\ No newline at end of file