diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 38d753e6..481b7c5f 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -9,6 +9,9 @@ Changelog version 1.10.0-dev ------------------ ++ Fix the gzip header that ``igzip_threaded.open`` writes when ``threads`` is + not 0. It had the XFL and OS bytes swapped, so the ``file`` command reported + the output as coming from VM/CMS or a FAT file system. + Fix pickling of ``isal_zlib.error`` (``igzip_lib.IsalError``). An error raised in a ``multiprocessing`` worker process did not reach the parent process. Tracebacks now show ``isal.igzip_lib.IsalError`` instead of diff --git a/src/isal/igzip_threaded.py b/src/isal/igzip_threaded.py index 8968e5eb..570605b5 100644 --- a/src/isal/igzip_threaded.py +++ b/src/isal/igzip_threaded.py @@ -299,7 +299,7 @@ def _write_gzip_header(self): os = 0xff xfl = 4 if self.level == 0 else 0 self.raw.write(struct.pack( - "BBBBIBB", magic1, magic2, method, flags, mtime, os, xfl)) + "BBBBIBB", magic1, magic2, method, flags, mtime, xfl, os)) def start(self): self.running = True diff --git a/tests/test_igzip_threaded.py b/tests/test_igzip_threaded.py index b4f43e04..d9b7570c 100644 --- a/tests/test_igzip_threaded.py +++ b/tests/test_igzip_threaded.py @@ -59,6 +59,19 @@ def test_threaded_write(tmp_path, mode, threads, block_size): assert test_data == out_data +@pytest.mark.parametrize(["level", "threads"], + list(itertools.product([0, 1, 2, 3], [1, 2]))) +def test_threaded_write_header_xfl_os(level, threads): + buffer = io.BytesIO() + with igzip_threaded.open(buffer, "wb", compresslevel=level, + threads=threads) as f: + f.write(b"thisisatest") + # RFC 1952 puts XFL before OS. IGzipFile writes the same two bytes: + # XFL 4 (fastest) at level 0, else 0, and OS 255 (unknown). + xfl = 4 if level == 0 else 0 + assert buffer.getvalue()[8:10] == bytes([xfl, 255]) + + def test_threaded_open_no_threads(): with tempfile.TemporaryFile("rb") as tmp: klass = igzip_threaded.open(tmp, "rb", threads=0)