add restore helper handling for reconstructed indices
authorPhilipp Gesang <philipp.gesang@intra2net.com>
Fri, 25 Aug 2017 09:12:39 +0000 (11:12 +0200)
committerThomas Jarosch <thomas.jarosch@intra2net.com>
Mon, 2 Apr 2018 11:34:09 +0000 (13:34 +0200)
deltatar/deltatar.py
deltatar/tarfile.py

index 2983ac2..f51cee7 100644 (file)
@@ -1176,7 +1176,7 @@ class DeltaTar(object):
         """
 
         class RawIndexIterator(object):
-            def __init__(self, delta_tar, tar_path, index):
+            def __init__(self, delta_tar, index):
                 self.delta_tar = delta_tar
                 self.index = index
                 self.__enter__()
@@ -1185,8 +1185,7 @@ class DeltaTar(object):
                 return self
 
             def release(self):
-                if self.tar_obj:
-                    self.tar_obj.close()
+                pass
 
             def __enter__(self):
                 '''
@@ -1202,7 +1201,7 @@ class DeltaTar(object):
 
             def __next__(self):
                 idxent = self.iter.__next__ ()
-                return idxent
+                return idxent, 0
 
         return RawIndexIterator(self, index)
 
@@ -1443,7 +1442,9 @@ class DeltaTar(object):
                 return [(index1, exn)]
         elif mode == "disaster":
             index_it = self.iterate_disaster_index (backup_index)
-            helper = RestoreHelper (self, cwd, disaster=disaster)
+            helper = RestoreHelper (self, cwd, backup_path=backup_tar_path,
+                                    backup_index=backup_index,
+                                    disaster=disaster)
 
 
         dir_it = self._recursive_walk_dir('.')
@@ -1547,6 +1548,7 @@ class DeltaTar(object):
 
         return self.restore_backup(target_path,
                                    backup_index=backup_index,
+                                   backup_tar_path=backup_tar_path,
                                    disaster=tarfile.TOLERANCE_RESCUE)
 
 
@@ -1593,7 +1595,8 @@ class RestoreHelper(object):
     _disaster = tarfile.TOLERANCE_STRICT
 
     def __init__(self, deltatar, cwd, index_list=None, backup_path=False,
-                 tarobj=None, disaster=tarfile.TOLERANCE_STRICT):
+                 backup_index=None, tarobj=None,
+                 disaster=tarfile.TOLERANCE_STRICT):
         '''
         Constructor opens the tars and init the data structures.
 
@@ -1629,7 +1632,23 @@ class RestoreHelper(object):
         else:
             self.canchown = False
 
-        if index_list is not None:
+        if isinstance (backup_index, list) is True:
+            def dummy_volume_handler (*_a, **_kwa):
+                pass
+            self._data = \
+                [{ "curr_vol_no" : None
+                 , "vol_fd" : None
+                 , "offset" : -1
+                 , "tarobj" : None
+                 , "path" : backup_path
+                 , "is_full" : True
+                 , "iterator" : None
+                 , "last_itelement" : None
+                 , "last_lno" : 0
+                 , "new_volume_handler" : dummy_volume_handler
+                 , "decryptor" : self._deltatar.decryptor
+                 }]
+        elif index_list is not None:
             for index in index_list:
                 is_full = index == index_list[-1]
 
@@ -1748,10 +1767,7 @@ class RestoreHelper(object):
         # if path is found in the newest index as to be snapshotted, deal with it
         # and finish
         if path.startswith('snapshot://'):
-            try:
-                self.restore_file(itpath, data, path, l_no, upath)
-            except Exception:
-                raise
+            self.restore_file(itpath, data, path, l_no, upath)
 
             # now we restore parent_directory mtime
             os.utime(parent_dir, (parent_dir_mtime, parent_dir_mtime))
index c052fa5..5477c04 100644 (file)
@@ -381,6 +381,7 @@ class EncryptionError(TarError):
     pass
 class EndOfFile(Exception):
     """Signal end of file condition when they’re not an error."""
+    pass
 
 #---------------------------
 # internal stream interface
@@ -3315,6 +3316,14 @@ class TarIter:
 # support functionality for rescue mode
 #---------------------------------------------------------
 
+def locate_tar_hdr_candidates (fd):
+    raise NotImplementedError ("too soon")
+
+
+def readable_tar_objects_offsets (ifd, cands):
+    raise NotImplementedError ("too soon")
+
+
 def locate_gz_hdr_candidates (fd):
     """
     Walk over instances of the GZ magic in the payload, collecting their
@@ -3523,6 +3532,21 @@ def reconstruct_offsets_gz (fname):
         os.close (ifd)
 
 
+def reconstruct_offsets_tar (fname):
+    """
+    From the given file, retrieve all tar header-like offsets (“candidates”).
+    Then check each of those locations whether they can be processed as tar
+    data.
+    """
+    ifd = os.open (fname, os.O_RDONLY)
+
+    try:
+        cands = locate_tar_hdr_candidates (ifd)
+        return readable_tar_objects_offsets (ifd, cands)
+    finally:
+        os.close (ifd)
+
+
 def read_tarobj_at_offset (fileobj, offset, mode, secret=None):
     decr = None
 
@@ -3596,6 +3620,10 @@ def gen_rescue_index (backup_tar_path, mode, password=None, key=None):
         offsets = crypto.reconstruct_offsets (backup_tar_path, secret)
     elif mode == "#gz":
         offsets = reconstruct_offsets_gz (backup_tar_path)
+    elif mode == "#":
+        offsets = reconstruct_offsets_tar (backup_tar_path)
+    else:
+        raise TarError ("no rescue handling for mode “%s”" % mode)
 
     fileobj = bltn_open (backup_tar_path, "rb")
     infos   = [ (off, read_tarobj_at_offset (fileobj, off, mode, secret=secret))