Fixed aes deltatar restoring
authorDaniel Garcia Moreno <danigm@wadobo.com>
Sun, 1 Sep 2013 08:03:10 +0000 (10:03 +0200)
committerDaniel Garcia Moreno <danigm@wadobo.com>
Sun, 1 Sep 2013 08:03:10 +0000 (10:03 +0200)
Test DeltaTarGzipAes256ConcatTest.test_restore_from_index_diff_backup3 was
failing and this patch fixed it.

The encryption was initialized on every call to _init_read_gz and every
time we found a new encryption chunk (something that starts with
"Salted__"). The correct way to do it is to initialize at the beginning and
every time we find a new encryption chunk, it's not needed to initialize
the encryption on every call to _init_read_gz.

There was an exception trying to decompress a chunk of data in the line:

buf = self.cmp.decompress(buf)

This happened because at the end of the file the call to _init_read_gz
fails and the exception is controlled by a try-except, but sometimes just
after this fail there is a call to read the trailing data with the gzip and
a try to decompress and it fails because the self.cmp is not initialized,
this data is garbage, so I catch this exception and everything works okay.

deltatar/tarfile.py

index ede5175..e93ef1f 100644 (file)
@@ -447,6 +447,9 @@ class _Stream:
                 raise CompressionError("zlib module is not available")
             self.zlib = zlib
             if mode == "r":
+                if self.enctype == 'aes':
+                    self.encryption = aescrypto.AESCrypt(self.password,
+                                                         key_length=self.key_length)
                 self._init_read_gz()
             else:
                 self._init_write_gz()
@@ -527,7 +530,6 @@ class _Stream:
             self.__write_to_file(self.encryption.salt_str)
         elif set_last_block_offset:
             self.last_block_offset = self.fileobj.tell()
-        self.fileobj
 
         timestamp = struct.pack("<L", long(time.time()))
         self.__write("\037\213\010\000%s\002\377" % timestamp)
@@ -613,13 +615,6 @@ class _Stream:
         """
         self.cmp = self.zlib.decompressobj(-self.zlib.MAX_WBITS)
 
-        # if aes, we decrypt before the compression
-        if self.enctype == 'aes':
-            self.encryption = aescrypto.AESCrypt(self.password,
-                                                 key_length=self.key_length)
-            self.encryption.get_salt(self.fileobj)
-            self.encryption.init()
-
         # taken from gzip.GzipFile with some alterations
         read2 = self.__read(2)
         if read2 != "\037\213":
@@ -726,6 +721,11 @@ class _Stream:
                     buf = self.cmp.decompress(buf)
                 except IOError:
                     raise ReadError("invalid compressed data")
+                except Exception, e:
+                    # happens at the end of the file
+                    # _init_read_gz failed in the previous iteration so
+                    # sel.cmp.descompress fails here
+                    pass
 
                 if self.comptype == "gz" and hasattr(self, "crc"):
                     self.crc = self.zlib.crc32(buf, self.crc) & 0xffffffffL
@@ -780,7 +780,10 @@ class _Stream:
         else:
             b1 = buf[:idx]
             b2 = buf[idx:]
-            buf = self.encryption.decrypt(b1, True)
+            if b1:
+                buf = self.encryption.decrypt(b1, True)
+            else:
+                buf = ''
             self.encryption.get_salt_str(b2)
             self.encryption.init()
             b2 = b2[len(self.encryption.salt_str):]