From d39d4cbf70412567b3cf6b5be4968651f8c8871f Mon Sep 17 00:00:00 2001 From: Philipp Gesang Date: Thu, 24 Aug 2017 11:57:53 +0200 Subject: [PATCH] read tar objects at predetermined offsets for rescue index Leverage the tarobj to read the object headers at the determined offsets. Currently only implemented for encrypted archives whose offsets are located with *crypto.py*. --- deltatar/tarfile.py | 44 +++++++++++++++++++++++++++++++++++++++++++- 1 files changed, 43 insertions(+), 1 deletions(-) diff --git a/deltatar/tarfile.py b/deltatar/tarfile.py index ef4fca0..4f9e033 100644 --- a/deltatar/tarfile.py +++ b/deltatar/tarfile.py @@ -2218,6 +2218,19 @@ class TarFile(object): raise ValueError("undiscernible mode %r" % mode) + + @classmethod + def open_at_offset(cls, offset, *a, **kwa): + """ + Same as ``.open()``, but start reading at the given offset. Assumes a + seekable file object. + """ + fileobj = kwa.get ("fileobj") + if fileobj is not None: + fileobj.seek (offset) + return cls.open (*a, **kwa) + + @classmethod def taropen(cls, name, mode="r", fileobj=None, **kwargs): """Open uncompressed tar archive name for reading or writing. @@ -3295,10 +3308,36 @@ class TarIter: # support functionality for rescue mode #--------------------------------------------------------- -def gen_rescue_index (backup_tar_path, password=None, key=None): +def read_tarobj_at_offset (fileobj, offset, mode, secret=None): + decr = None + ks = secret [0] + + if ks == crypto.PDTCRYPT_SECRET_PW: + decr = crypto.Decrypt (password=secret [1]) + elif ks == crypto.PDTCRYPT_SECRET_KEY: + key = binascii.unhexlify (secret [1]) + decr = crypto.Decrypt (key=key) + else: + raise RuntimeError + + tarobj = \ + TarFile.open_at_offset (offset, + mode=mode, + fileobj=fileobj, + format=GNU_FORMAT, + concat='#' in mode, + encryption=decr, + save_to_members=False, + tolerance=TOLERANCE_RESCUE) + + return tarobj.next () + + +def gen_rescue_index (backup_tar_path, mode, password=None, key=None): psidx = [] # pseudo index, return value offsets = None secret = None + mode = "r" + mode if password is not None: secret = (crypto.PDTCRYPT_SECRET_PW, password) @@ -3307,6 +3346,9 @@ def gen_rescue_index (backup_tar_path, password=None, key=None): if secret is not None: offsets = crypto.reconstruct_offsets (backup_tar_path, secret) + fileobj = bltn_open (backup_tar_path, "rb") + psinfos = [ read_tarobj_at_offset (fileobj, off, mode, secret=secret) + for off in offsets ] return psidx -- 1.7.1