From bec34b42e1779d219c43f451c17621f86b75071f Mon Sep 17 00:00:00 2001 From: Philipp Gesang Date: Fri, 21 Apr 2017 18:03:17 +0200 Subject: [PATCH] =?utf8?q?explicitly=20disable=20gz=20initalization=20for=20=5FStream=E2=80=99s=20used=20in=20aux=20files?= MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit The process of writing an auxiliary (index, info) file differs drastically from that of tar archives: Since files are not added individually, the encryption must be initialized externally and the compression layer cannot rely on being enable in the ctor because, obviously, the latter is executed before the manual encryption setup can be performed. Extend the API of the _Stream ctor with a parameter to “noinit” to request that all initialization be postponed until the encryption has been set up. This seems to do the trick but is quite ugly. --- deltatar/deltatar.py | 3 +-- deltatar/tarfile.py | 17 ++++++++--------- testing/test_deltatar.py | 1 - 3 files changed, 9 insertions(+), 12 deletions(-) diff --git a/deltatar/deltatar.py b/deltatar/deltatar.py index 345e33f..26375e8 100644 --- a/deltatar/deltatar.py +++ b/deltatar/deltatar.py @@ -533,9 +533,8 @@ class DeltaTar(object): comptype = 'tar' sink = tarfile._Stream(name=path, mode=mode, comptype=comptype, - concat_stream=True, # no global zlib header bufsize=tarfile.RECORDSIZE, fileobj=None, - encryption=self.crypto_ctx) + encryption=self.crypto_ctx, noinit=True) if self.crypto_ctx is not None and mode == "w": counter = None if kind == AUXILIARY_FILE_INFO: diff --git a/deltatar/tarfile.py b/deltatar/tarfile.py index 84a3c12..13e092c 100644 --- a/deltatar/tarfile.py +++ b/deltatar/tarfile.py @@ -418,7 +418,8 @@ class _Stream: remainder = -1 # track size in encrypted entries def __init__(self, name, mode, comptype, fileobj, bufsize, - concat_stream=False, encryption=None, compresslevel=9): + concat_stream=False, encryption=None, compresslevel=9, + noinit=False): """Construct a _Stream object. """ self._extfileobj = True @@ -461,14 +462,14 @@ class _Stream: except ImportError: raise CompressionError("zlib module is not available") self.zlib = zlib - if concat_stream is False: - if mode == "r": + if mode == "r": + self.exception = zlib.error + if concat_stream is True: self._init_read_gz() - elif mode == "w": + elif mode == "w": + if noinit is False: self._new_gz_block() self.crc = zlib.crc32(b"") & 0xFFFFffff - if mode == "r": - self.exception = zlib.error elif comptype == "bz2": if self.encryption is not None: @@ -1975,7 +1976,6 @@ class TarFile(object): 'r#gz' open a stream of gzip compressed tar blocks for reading 'w#gz' open a stream of gzip compressed tar blocks for writing """ - if not name and not fileobj: raise ValueError("nothing to open") @@ -2041,11 +2041,10 @@ class TarFile(object): if filemode not in "rw": raise ValueError("mode must be 'r' or 'w'") - kwargs['concat_compression'] = True - stream = _Stream(name, filemode, comptype, fileobj, bufsize, concat_stream=True, encryption=encryption, compresslevel=compresslevel) + kwargs ["concat_compression"] = True try: t = cls(name, filemode, stream, **kwargs) except: # XXX except what? diff --git a/testing/test_deltatar.py b/testing/test_deltatar.py index e1646be..b776d5b 100644 --- a/testing/test_deltatar.py +++ b/testing/test_deltatar.py @@ -209,7 +209,6 @@ class DeltaTarTest(BaseTest): with big files bigger than the max volume size and restore it. ''' - if self.MODE.startswith(':') or self.MODE.startswith('|'): raise SkipTest('this test only works for uncompressed ' 'or concat compressed modes') -- 1.7.1