write auxiliary files whilst processing the backup
authorPhilipp Gesang <philipp.gesang@intra2net.com>
Thu, 4 May 2017 13:12:50 +0000 (15:12 +0200)
committerThomas Jarosch <thomas.jarosch@intra2net.com>
Mon, 2 Apr 2018 11:34:08 +0000 (13:34 +0200)
Introduce a fixed value for the index file counter to allow
encryption on the fly.

deltatar/deltatar.py

index 2dcb6ee..62ad560 100644 (file)
@@ -523,16 +523,11 @@ class DeltaTar(object):
         if password is None:
             return
         if mode == CRYPTO_MODE_ENCRYPT:
-            if self.encryptor is None:
-                self.encryptor = \
-                        crypto.Encrypt (password,
-                                        version=DELTATAR_HEADER_VERSION,
-                                        paramversion=self.crypto_paramversion)
-            return
+            return crypto.Encrypt (password,
+                                   version=DELTATAR_HEADER_VERSION,
+                                   paramversion=self.crypto_paramversion)
         if mode == CRYPTO_MODE_DECRYPT:
-            if self.decryptor is None:
-                self.decryptor = crypto.Decrypt (password)
-            return
+            return crypto.Decrypt (password)
 
         raise Exception ("invalid encryption mode [%r]" % mode)
 
@@ -546,9 +541,9 @@ class DeltaTar(object):
         :param mode:        IO mode (read or write, ``"r"`` and ``"w"``,
                             respectively).
         :type  mode:        str
-        :param kind:        Role of the file, see AUXILIARY_FILE_* constants. The
-                            only special value is AUXILIARY_FILE_INFO which
-                            sets the appropriate counter in the crypto layer.
+        :param kind:        Role of the file, see AUXILIARY_FILE_* constants.
+                            Both the info and the auxiliary file have a globally
+                            unique, constant counter value.
         :type  kind:        str
         '''
         if self.index_mode.startswith('gz'):
@@ -561,14 +556,16 @@ class DeltaTar(object):
         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
+            crypto_ctx = self.initialize_encryption (CRYPTO_MODE_ENCRYPT)
+            if crypto_ctx is not None:
+                if kind == AUXILIARY_FILE_INFO:
+                    enccounter = crypto.AES_GCM_IV_CNT_INFOFILE
+                elif kind == AUXILIARY_FILE_INDEX:
+                    enccounter = crypto.AES_GCM_IV_CNT_INDEX
+                else:
+                    raise Exception ("invalid kind of aux file %r" % kind)
         elif mode == "r":
-            self.initialize_encryption (CRYPTO_MODE_DECRYPT)
-            crypto_ctx = self.decryptor
+            crypto_ctx = self.initialize_encryption (CRYPTO_MODE_DECRYPT)
 
         sink = tarfile._Stream(name=path, mode=mode, comptype=comptype,
                                bufsize=tarfile.RECORDSIZE, fileobj=None,
@@ -639,7 +636,8 @@ class DeltaTar(object):
             raise Exception('Unrecognized extension')
 
         # setup for encrypting payload
-        self.initialize_encryption (CRYPTO_MODE_ENCRYPT)
+        if self.encryptor is None:
+            self.encryptor = self.initialize_encryption (CRYPTO_MODE_ENCRYPT)
 
         # some initialization
         self.vol_no = 0
@@ -648,7 +646,10 @@ class DeltaTar(object):
         vol_name = self.volume_name_func(backup_path, True, 0)
         tarfile_path = os.path.join(backup_path, vol_name)
 
-        index_accu = io.BytesIO ()
+        # init index
+        index_name = self.index_name_func(True)
+        index_path = os.path.join(backup_path, index_name)
+        index_sink = self.open_auxiliary_file(index_path, 'w')
 
         cwd = os.getcwd()
 
@@ -674,12 +675,12 @@ class DeltaTar(object):
         # wraps some args from context into the handler
         new_volume_handler = partial(new_volume_handler, self, cwd, backup_path, self.encryptor)
 
-        index_accu.write(bytes('{"type": "python-delta-tar-index", "version": 1, "backup-type": "full", "extra_data": %s}\n' % extra_data_str, 'UTF-8'))
+        index_sink.write(bytes('{"type": "python-delta-tar-index", "version": 1, "backup-type": "full", "extra_data": %s}\n' % extra_data_str, 'UTF-8'))
 
         s = bytes('{"type": "BEGIN-FILE-LIST"}\n', 'UTF-8')
         # calculate checksum and write into the stream
         crc = binascii.crc32(s) & 0xFFFFffff
-        index_accu.write(s)
+        index_sink.write(s)
 
         # start creating the tarfile
         tarobj = tarfile.TarFile.open(tarfile_path,
@@ -710,21 +711,16 @@ class DeltaTar(object):
             # store the stat dict in the index
             s = bytes(json.dumps(statd) + '\n', 'UTF-8')
             crc = binascii.crc32(s, crc) & 0xffffffff
-            index_accu.write(s)
+            index_sink.write(s)
 
         s = bytes('{"type": "END-FILE-LIST"}\n', 'UTF-8')
         crc = binascii.crc32(s, crc) & 0xffffffff
-        index_accu.write(s)
+        index_sink.write(s)
         s = bytes('{"type": "file-list-checksum", "checksum": %d}\n' % crc, 'UTF-8')
-        index_accu.write(s)
+        index_sink.write(s)
+
         os.chdir(cwd)
         tarobj.close()
-
-        # init index
-        index_name = self.index_name_func(True)
-        index_path = os.path.join(backup_path, index_name)
-        index_sink = self.open_auxiliary_file(index_path, 'w')
-        index_sink.write (index_accu.getvalue ())
         index_sink.close (close_fileobj=True)
 
     def create_diff_backup(self, source_path, backup_path, previous_index_path,
@@ -802,7 +798,8 @@ class DeltaTar(object):
             raise Exception('Unrecognized extension')
 
         # setup for encrypting payload
-        self.initialize_encryption (CRYPTO_MODE_ENCRYPT)
+        if self.encryptor is None:
+            self.encryptor = self.initialize_encryption (CRYPTO_MODE_ENCRYPT)
 
         # some initialization
         self.vol_no = 0
@@ -1238,7 +1235,8 @@ class DeltaTar(object):
                 volume_path = os.path.join(cwd, volume_path)
             tarobj.open_volume(volume_path, encryption=encryption)
 
-        self.initialize_encryption (CRYPTO_MODE_DECRYPT)
+        if self.decryptor is None:
+            self.decryptor = self.initialize_encryption (CRYPTO_MODE_DECRYPT)
 
         backup_path = os.path.dirname(backup_tar_path)
         if not os.path.isabs(backup_path):
@@ -1345,8 +1343,8 @@ class DeltaTar(object):
         os.chdir(target_path)
 
         # setup for decrypting payload
-        if self.password is not None:
-            self.decryptor = crypto.Decrypt (self.password)
+        if self.decryptor is None:
+            self.decryptor = self.initialize_encryption (CRYPTO_MODE_DECRYPT)
 
         if mode == 'tar':
             index_it = self.iterate_tar_path(backup_tar_path)