catch ESPIPE from ftell () on stream
authorPhilipp Gesang <philipp.gesang@intra2net.com>
Tue, 4 Apr 2017 08:00:17 +0000 (10:00 +0200)
committerPhilipp Gesang <philipp.gesang@intra2net.com>
Fri, 28 Apr 2017 12:40:14 +0000 (14:40 +0200)
The result is only used for status output so defaulting to -1 for
stdin doesn’t hurt. All functional uses of the current position
rely on the value of total_read.

deltatar/crypto.py

index a0dd19a..398ae9f 100755 (executable)
@@ -607,6 +607,14 @@ def depdtcrypt (pw, ins, outs):
     total_ct   = 0               # total ciphertext bytes
     total_read = 0               # total bytes read
 
+    def tell (s):
+        """ESPIPE is normal on stdio stream."""
+        try:
+            return s.tell ()
+        except OSError as exn:
+            if exn.errno == 29:
+                return -1
+
     def out (pt):
         npt = len (pt)
         nonlocal total_pt
@@ -626,7 +634,7 @@ def depdtcrypt (pw, ins, outs):
             # the start of a new header or the end of the input
             if ctleft == 0: # current object requires finalization
                 if PDTCRYPT_VERBOSE is True:
-                    noise ("PDT: %d finalize" % ins.tell ())
+                    noise ("PDT: %d finalize" % tell (ins))
                 ret, pt = decr.done ()
                 if ret is False:
                     raise DecryptionError ("error finalizing object (%s)"
@@ -636,7 +644,7 @@ def depdtcrypt (pw, ins, outs):
                     noise ("PDT:\t· object validated")
 
             if PDTCRYPT_VERBOSE is True:
-                noise ("PDT: %d hdr" % ins.tell ())
+                noise ("PDT: %d hdr" % tell (ins))
             try:
                 hdr = hdr_read_stream (ins)
                 total_read += I2N_HDR_SIZE
@@ -651,7 +659,7 @@ def depdtcrypt (pw, ins, outs):
                 return total_read, total_obj, total_ct, total_pt
             except InvalidHeader as exn:
                 raise PDTDecryptionError ("invalid header at position %d in %r "
-                                          "(%s)" % (exn, ins.tell (), ins))
+                                          "(%s)" % (exn, tell (ins), ins))
             if PDTCRYPT_VERBOSE is True:
                 pretty = hdr_fmt_pretty (hdr)
                 noise (reduce (lambda a, e: (a + "\n" if a else "") + "PDT:\t· " + e,
@@ -662,20 +670,20 @@ def depdtcrypt (pw, ins, outs):
 
             if PDTCRYPT_VERBOSE is True:
                 noise ("PDT: %d decrypt obj no. %d,  %d B"
-                       % (ins.tell (), total_obj, ctleft))
+                       % (tell (ins), total_obj, ctleft))
 
         # always allocate a new buffer since python-cryptography doesn’t allow
         # passing a bytearray :/
         nexpect = min (ctleft, PDTCRYPT_BLOCKSIZE)
         if PDTCRYPT_VERBOSE is True:
             noise ("PDT:\t· [%d] %d%% done, read block (%d B of %d B remaining)"
-                   % (ins.tell (),
+                   % (tell (ins),
                       100 - ctleft * 100 / (ctcurrent > 0 and ctcurrent or 1),
                       nexpect, ctleft))
         ct      = ins.read (nexpect)
         nct     = len (ct)
         if nct < nexpect:
-            off = ins.tell ()
+            off = tell (ins)
             raise EndOfFile ("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,