From 6de9444af0aa5060465910e39954a74a4b22d3aa Mon Sep 17 00:00:00 2001 From: Philipp Gesang Date: Fri, 28 Apr 2017 14:04:42 +0200 Subject: [PATCH] cleanly perform block transition in non-concat mode --- deltatar/deltatar.py | 11 ++++----- deltatar/tarfile.py | 58 +++++++++++++++++++++++++++++-------------------- 2 files changed, 39 insertions(+), 30 deletions(-) diff --git a/deltatar/deltatar.py b/deltatar/deltatar.py index d28617a..180745c 100644 --- a/deltatar/deltatar.py +++ b/deltatar/deltatar.py @@ -559,21 +559,20 @@ class DeltaTar(object): comptype = 'tar' crypto_ctx = None + enccounter = None if mode == "w": self.initialize_encryption (CRYPTO_MODE_ENCRYPT) crypto_ctx = self.encryptor + if crypto_ctx is not None and \ + kind == AUXILIARY_FILE_INFO: + enccounter = crypto.AES_GCM_IV_CNT_INFOFILE elif mode == "r": self.initialize_encryption (CRYPTO_MODE_DECRYPT) crypto_ctx = self.decryptor sink = tarfile._Stream(name=path, mode=mode, comptype=comptype, bufsize=tarfile.RECORDSIZE, fileobj=None, - encryption=crypto_ctx) - if self.encryptor is not None and mode == "w": - counter = None - if kind == AUXILIARY_FILE_INFO: - counter = crypto.AES_GCM_IV_CNT_INFOFILE - sink._init_write_encrypt (path, counter) + encryption=crypto_ctx, enccounter=enccounter) return sink diff --git a/deltatar/tarfile.py b/deltatar/tarfile.py index 6bd3a42..59f9c9e 100644 --- a/deltatar/tarfile.py +++ b/deltatar/tarfile.py @@ -420,7 +420,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, enccounter=None, + compresslevel=9): """Construct a _Stream object. """ self._extfileobj = True @@ -466,7 +467,9 @@ class _Stream: self.exception = zlib.error self._init_read_gz() elif mode == "w": - if concat_stream is False and self.encryption is None: + if concat_stream is False: + if self.encryption is not None: + self._init_write_encrypt (name, enccounter) self._init_write_gz () self.crc = zlib.crc32(b"") & 0xFFFFffff @@ -500,7 +503,13 @@ class _Stream: else: self.cmp = lzma.LZMACompressor() - elif comptype != "tar": + elif comptype == "tar": + if concat_stream is False \ + and mode == "w" \ + and self.encryption is not None: + self._init_write_encrypt (name, enccounter) + + else: if self.encryption is not None: raise InvalidEncryptionError("encryption not available for " "compression %s" % comptype) @@ -517,7 +526,8 @@ class _Stream: self.close() - def _init_write_encrypt (self, entry=None, counter=None): + def _init_write_encrypt (self, entry=None, counter=None, + set_last_block_offset=False): """Save position for delayed write of header; fill the header location with dummy bytes.""" if self.encryption is not None: @@ -531,6 +541,8 @@ class _Stream: self.lasthdr = self.fileobj.tell() self.__write_to_file(dummyhdr) + if set_last_block_offset is True: + self.last_block_offset = self.lasthdr def _finalize_write_encrypt (self): @@ -580,9 +592,7 @@ class _Stream: ''' self.concat_pos = 0 self.crc = self.zlib.crc32(b"") & 0xFFFFffff - first = False - if self.cmp is None: - first = True + first = self.cmp is None self.cmp = self.zlib.compressobj(self.compresslevel, self.zlib.DEFLATED, -self.zlib.MAX_WBITS, @@ -590,7 +600,7 @@ class _Stream: 0) # if aes, we encrypt after compression - if self.encryption is None and set_last_block_offset: + if set_last_block_offset is True: self.last_block_offset = self.fileobj.tell() self.__write(gz_header (self.name if first is True else None)) @@ -2431,16 +2441,15 @@ class TarFile(object): tarinfo = copy.copy(tarinfo) - if self.concat_compression is True and \ - getattr (self.fileobj, "cmp", None) is not None: - self.fileobj._finalize_write_gz () - - if getattr (self.fileobj, "encryption", None) is not None: - self.fileobj._finalize_write_encrypt () - self.fileobj._init_write_encrypt (tarinfo.name) - - if self.concat_compression: - self.fileobj._init_write_gz (True) + if self.concat_compression is True: + if getattr (self.fileobj, "cmp", None) is not None: + self.fileobj._finalize_write_gz () + encrypt = getattr (self.fileobj, "encryption", None) is not None + if encrypt is True: + self.fileobj._finalize_write_encrypt () + self.fileobj._init_write_encrypt (tarinfo.name, + set_last_block_offset=True) + self.fileobj._init_write_gz (set_last_block_offset=not encrypt) self.last_block_offset = self.fileobj.last_block_offset else: self.last_block_offset = self.fileobj.tell() @@ -2516,16 +2525,17 @@ class TarFile(object): # the “new_volume_handler” is supposed to call .close() on the # “fileobj” _Stream self.new_volume_handler(self, self.base_name, self.volume_number) - if self.concat_compression and \ - getattr (self.fileobj, "cmp", None) is not None: - # e. g. compressed PAX header written - self.fileobj._finalize_write_gz () self.volume_tarinfo = None - if getattr (self.fileobj, "encryption", None) is not None: - self.fileobj._init_write_encrypt (tarinfo.name) if self.concat_compression is True: + # with non-concat modes, this is taken care by the _Stream + # ctor as invoked by the newvol handler + if getattr (self.fileobj, "cmp", None) is not None: + # e. g. compressed PAX header written + self.fileobj._finalize_write_gz () + if getattr (self.fileobj, "encryption", None) is not None: + self.fileobj._init_write_encrypt (tarinfo.name) self.fileobj._init_write_gz () # write new volume header -- 1.7.1