communicate remainder to caller when hitting EOF from crypto
authorPhilipp Gesang <philipp.gesang@intra2net.com>
Mon, 10 Apr 2017 11:43:53 +0000 (13:43 +0200)
committerThomas Jarosch <thomas.jarosch@intra2net.com>
Mon, 2 Apr 2018 11:34:08 +0000 (13:34 +0200)
deltatar/crypto.py
deltatar/tarfile.py

index bcc89b8..99eaf3a 100755 (executable)
@@ -93,7 +93,11 @@ __all__ = [ "hdr_make", "hdr_read", "hdr_fmt", "hdr_fmt_pretty"
 
 class EndOfFile (Exception):
     """Reached EOF."""
-    pass
+    remainder = 0
+    msg       = 0
+    def __init__ (self, n, msg=None):
+        self.remainder = n
+        self.msg       = msg
 
 
 class InvalidParameter (Exception):
@@ -251,8 +255,10 @@ def hdr_read (data):
 
 def hdr_read_stream (instr):
     data = instr.read(PDTCRYPT_HDR_SIZE)
-    if len (data) != PDTCRYPT_HDR_SIZE:
-        raise EndOfFile ("read: expected %d B, received %d B"
+    ldata = len (data)
+    if ldata != PDTCRYPT_HDR_SIZE:
+        raise EndOfFile (ldata,
+                         "read: expected %d B, received %d B"
                          % (PDTCRYPT_HDR_SIZE, len (data)))
     return hdr_read (data)
 
@@ -772,7 +778,8 @@ def depdtcrypt (pw, ins, outs):
             try:
                 hdr = hdr_read_stream (ins)
                 total_read += PDTCRYPT_HDR_SIZE
-            except EndOfFile:
+            except EndOfFile as exn:
+                total_read += exn.remainder
                 if total_ct + total_obj * PDTCRYPT_HDR_SIZE != total_read:
                     raise PDTDecryptionError ("ciphertext processed (%d B) plus "
                                               "overhead (%d Ć— %d B) does not match "
@@ -808,7 +815,8 @@ def depdtcrypt (pw, ins, outs):
         nct     = len (ct)
         if nct < nexpect:
             off = tell (ins)
-            raise EndOfFile ("hit EOF after %d of %d B in block [%d:%d); "
+            raise EndOfFile (nct,
+                             "hit EOF after %d of %d B in block [%d:%d); "
                              "%d B ciphertext remaining for object no %d"
                              % (nct, nexpect, off, off + nexpect, ctleft,
                                 total_obj))
index 23968fc..704ecc6 100644 (file)
@@ -707,7 +707,9 @@ class _Stream:
             self.__enc_write(self.buf)
 
         if close_fileobj is True:
-            fixed = self._finalize_write_encrypt ()
+            if self.mode == "w":
+                # end of Tar archive marker (two empty blocks) was written
+                fixed = self._finalize_write_encrypt ()
             if not self._extfileobj:
                 self.fileobj.close()
         else:
@@ -765,12 +767,16 @@ class _Stream:
             self.lasthdr = self.fileobj.tell ()
             try:
                 hdr = crypto.hdr_read_stream (self.fileobj)
-            except crypto.EndOfFile:
+            except crypto.EndOfFile as exn:
+                if exn.remainder == 0:
+                    raise EOFHeaderError("end of file header")
                 raise DecryptionError ("Crypto.hdr_read_stream(): hit EOF "
-                                       "reading header %r" % (self.fileobj))
+                                       "reading header %r" % (self.fileobj)) \
+                      from exn
             except crypto.InvalidHeader:
                 raise DecryptionError ("Crypto.hdr_read_stream(): error ā€œ%sā€ "
-                                       "processing %r" % (hdr, self.fileobj))
+                                       "processing %r" % (hdr, self.fileobj)) \
+                      from exn
             self.remainder = hdr ["ctsize"] # distance to next header
             return self.encryption.next (hdr)
 
@@ -903,9 +909,7 @@ class _Stream:
         """
         c = len(self.buf)
         t = [self.buf]
-        i = 0
         while c < size:
-            i += 1
             todo = size
             if self.encryption is not None:
                 if self.remainder <= 0: