From e51d6aaf868b7bfa9bb760bf8a3a81ac811bbb60 Mon Sep 17 00:00:00 2001 From: Marko Kreen Date: Fri, 20 May 2016 14:10:46 +0300 Subject: [PATCH] Support solid archives from in-memory file object Those need to be written fully out to tempfile. Fixes: #21 --- dumprar.py | 13 +++++++++++-- rarfile.py | 23 +++++++++++++++++++++++ 2 files changed, 34 insertions(+), 2 deletions(-) diff --git a/dumprar.py b/dumprar.py index 36b5747..cf5014c 100755 --- a/dumprar.py +++ b/dumprar.py @@ -2,6 +2,7 @@ """Dump archive contents, test extraction.""" +import io import sys import rarfile as rf from binascii import crc32, hexlify @@ -190,6 +191,7 @@ def show_item(h): cf_extract = 0 cf_test_read = 0 cf_test_unrar = 0 +cf_test_memory = 0 def check_crc(f, inf): ucrc = f.CRC @@ -242,13 +244,17 @@ def test_real(fn, psw): if cf_verbose > 1: cb = show_item + rfarg = fn + if cf_test_memory: + fnarg = io.BytesIO(open(fn, 'rb').read()) + # check if rar - if not rf.is_rarfile(fn): + if not rf.is_rarfile(rfarg): xprint(" --- %s is not a RAR file ---", fn) return # open - r = rf.RarFile(fn, charset = cf_charset, info_callback = cb) + r = rf.RarFile(rfarg, charset = cf_charset, info_callback = cb) # set password if r.needs_password(): if psw: @@ -302,6 +308,7 @@ def test(fn, psw): def main(): global cf_verbose, cf_show_comment, cf_charset global cf_extract, cf_test_read, cf_test_unrar + global cf_test_memory # parse args args = [] @@ -333,6 +340,8 @@ def main(): cf_test_read += 1 elif a == '-T': cf_test_unrar = 1 + elif a == '-M': + cf_test_memory = 1 elif a[1] == 'C': cf_charset = a[2:] else: diff --git a/rarfile.py b/rarfile.py index 3b8221c..c007e97 100644 --- a/rarfile.py +++ b/rarfile.py @@ -639,6 +639,8 @@ def open(self, fname, mode = 'r', psw = None): return self._open_clear(inf) elif use_hack: return self._open_hack(inf, psw) + elif is_filelike(self.rarfile): + return self._open_unrar_membuf(self.rarfile, inf, psw) else: return self._open_unrar(self.rarfile, inf, psw) @@ -1184,6 +1186,27 @@ def _read_comment_v3(self, inf, psw=None): return self._decode_comment(cmt) + # write in-memory archive to temp file - needed for solid archives + def _open_unrar_membuf(self, memfile, inf, psw): + memfile.seek(0, 0) + + tmpfd, tmpname = mkstemp(suffix='.rar') + tmpf = os.fdopen(tmpfd, "wb") + + try: + BSIZE = 32*1024 + while True: + buf = memfile.read(BSIZE) + if not buf: + break + tmpf.write(buf) + tmpf.close() + except: + tmpf.close() + os.unlink(tmpname) + raise + return self._open_unrar(tmpname, inf, psw, tmpname) + # extract using unrar def _open_unrar(self, rarfile, inf, psw = None, tmpfile = None): if is_filelike(rarfile):