|
@@ -331,14 +331,52 @@ class ZSTD(DecidingCompressor):
|
|
|
return dest[:osize]
|
|
|
|
|
|
|
|
|
-class ZLIB(CompressorBase):
|
|
|
+class ZLIB(DecidingCompressor):
|
|
|
"""
|
|
|
zlib compression / decompression (python stdlib)
|
|
|
"""
|
|
|
- ID = b'\x08\x00' # not used here, see detect()
|
|
|
- # avoid all 0x.8.. IDs elsewhere!
|
|
|
+ ID = b'\x05\x00'
|
|
|
name = 'zlib'
|
|
|
|
|
|
+ def __init__(self, level=6, **kwargs):
|
|
|
+ super().__init__(**kwargs)
|
|
|
+ self.level = level
|
|
|
+
|
|
|
+ def _decide(self, data):
|
|
|
+ """
|
|
|
+ Decides what to do with *data*. Returns (compressor, zlib_data).
|
|
|
+
|
|
|
+ *zlib_data* is the ZLIB result if *compressor* is ZLIB as well, otherwise it is None.
|
|
|
+ """
|
|
|
+ zlib_data = zlib.compress(data, self.level)
|
|
|
+ if len(zlib_data) < len(data):
|
|
|
+ return self, zlib_data
|
|
|
+ else:
|
|
|
+ return NONE_COMPRESSOR, None
|
|
|
+
|
|
|
+ def decompress(self, data):
|
|
|
+ data = super().decompress(data)
|
|
|
+ try:
|
|
|
+ return zlib.decompress(data)
|
|
|
+ except zlib.error as e:
|
|
|
+ raise DecompressionError(str(e)) from None
|
|
|
+
|
|
|
+
|
|
|
+class ZLIB_legacy(CompressorBase):
|
|
|
+ """
|
|
|
+ zlib compression / decompression (python stdlib)
|
|
|
+
|
|
|
+ Note: This is the legacy ZLIB support as used by borg < 1.3.
|
|
|
+ It still suffers from attic *only* supporting zlib and not having separate
|
|
|
+ ID bytes to differentiate between differently compressed chunks.
|
|
|
+ This just works because zlib compressed stuff always starts with 0x.8.. bytes.
|
|
|
+ Newer borg uses the ZLIB class that has separate ID bytes (as all the other
|
|
|
+ compressors) and does not need this hack.
|
|
|
+ """
|
|
|
+ ID = b'\x08\x00' # not used here, see detect()
|
|
|
+ # avoid all 0x.8.. IDs elsewhere!
|
|
|
+ name = 'zlib_legacy'
|
|
|
+
|
|
|
@classmethod
|
|
|
def detect(cls, data):
|
|
|
# matches misc. patterns 0x.8.. used by zlib
|
|
@@ -502,13 +540,14 @@ COMPRESSOR_TABLE = {
|
|
|
CNONE.name: CNONE,
|
|
|
LZ4.name: LZ4,
|
|
|
ZLIB.name: ZLIB,
|
|
|
+ ZLIB_legacy.name: ZLIB_legacy,
|
|
|
LZMA.name: LZMA,
|
|
|
Auto.name: Auto,
|
|
|
ZSTD.name: ZSTD,
|
|
|
ObfuscateSize.name: ObfuscateSize,
|
|
|
}
|
|
|
# List of possible compression types. Does not include Auto, since it is a meta-Compressor.
|
|
|
-COMPRESSOR_LIST = [LZ4, ZSTD, CNONE, ZLIB, LZMA, ObfuscateSize, ] # check fast stuff first
|
|
|
+COMPRESSOR_LIST = [LZ4, ZSTD, CNONE, ZLIB, ZLIB_legacy, LZMA, ObfuscateSize, ] # check fast stuff first
|
|
|
|
|
|
def get_compressor(name, **kwargs):
|
|
|
cls = COMPRESSOR_TABLE[name]
|
|
@@ -554,7 +593,7 @@ class CompressionSpec:
|
|
|
self.name = values[0]
|
|
|
if self.name in ('none', 'lz4', ):
|
|
|
return
|
|
|
- elif self.name in ('zlib', 'lzma', ):
|
|
|
+ elif self.name in ('zlib', 'lzma', 'zlib_legacy'): # zlib_legacy just for testing
|
|
|
if count < 2:
|
|
|
level = 6 # default compression level in py stdlib
|
|
|
elif count == 2:
|
|
@@ -597,7 +636,7 @@ class CompressionSpec:
|
|
|
def compressor(self):
|
|
|
if self.name in ('none', 'lz4', ):
|
|
|
return get_compressor(self.name)
|
|
|
- elif self.name in ('zlib', 'lzma', 'zstd', ):
|
|
|
+ elif self.name in ('zlib', 'lzma', 'zstd', 'zlib_legacy'):
|
|
|
return get_compressor(self.name, level=self.level)
|
|
|
elif self.name == 'auto':
|
|
|
return get_compressor(self.name, compressor=self.inner.compressor)
|