1# SPDX-License-Identifier: GPL-2.0+ 2# Copyright 2022 Google LLC 3# 4"""Bintool implementation for lzma_alone 5 6lzma_alone allows compression and decompression of files, using an older version 7of lzma. 8 9Documentation is available via:: 10 11 man lzma_alone 12 13Here is the help: 14 15LZMA 9.22 beta : Igor Pavlov : Public domain : 2011-04-18 16 17Usage: LZMA <e|d> inputFile outputFile [<switches>...] 18 e: encode file 19 d: decode file 20 b: Benchmark 21<Switches> 22 -a{N}: set compression mode - [0, 1], default: 1 (max) 23 -d{N}: set dictionary size - [12, 30], default: 23 (8MB) 24 -fb{N}: set number of fast bytes - [5, 273], default: 128 25 -mc{N}: set number of cycles for match finder 26 -lc{N}: set number of literal context bits - [0, 8], default: 3 27 -lp{N}: set number of literal pos bits - [0, 4], default: 0 28 -pb{N}: set number of pos bits - [0, 4], default: 2 29 -mf{MF_ID}: set Match Finder: [bt2, bt3, bt4, hc4], default: bt4 30 -mt{N}: set number of CPU threads 31 -eos: write End Of Stream marker 32 -si: read data from stdin 33 -so: write data to stdout 34""" 35 36import re 37import tempfile 38 39from binman import bintool 40from u_boot_pylib import tools 41 42# pylint: disable=C0103 43class Bintoollzma_alone(bintool.Bintool): 44 """Compression/decompression using the LZMA algorithm 45 46 This bintool supports running `lzma_alone` to compress and decompress data, 47 as used by binman. 48 49 It is also possible to fetch the tool, which uses `apt` to install it. 50 51 Documentation is available via:: 52 53 man lzma_alone 54 """ 55 def __init__(self, name): 56 super().__init__(name, 'lzma_alone compression') 57 58 def compress(self, indata): 59 """Compress data with lzma_alone 60 61 Args: 62 indata (bytes): Data to compress 63 64 Returns: 65 bytes: Compressed data 66 """ 67 with tempfile.NamedTemporaryFile(prefix='comp.tmp', 68 dir=tools.get_output_dir()) as inf: 69 tools.write_file(inf.name, indata) 70 with tempfile.NamedTemporaryFile(prefix='compo.otmp', 71 dir=tools.get_output_dir()) as outf: 72 args = ['e', inf.name, outf.name, '-lc1', '-lp0', '-pb0', '-d8'] 73 self.run_cmd(*args, binary=True) 74 return tools.read_file(outf.name) 75 76 def decompress(self, indata): 77 """Decompress data with lzma_alone 78 79 Args: 80 indata (bytes): Data to decompress 81 82 Returns: 83 bytes: Decompressed data 84 """ 85 with tempfile.NamedTemporaryFile(prefix='decomp.tmp', 86 dir=tools.get_output_dir()) as inf: 87 tools.write_file(inf.name, indata) 88 with tempfile.NamedTemporaryFile(prefix='compo.otmp', 89 dir=tools.get_output_dir()) as outf: 90 args = ['d', inf.name, outf.name] 91 self.run_cmd(*args, binary=True) 92 return tools.read_file(outf.name, binary=True) 93 94 def fetch(self, method): 95 """Fetch handler for lzma_alone 96 97 This installs the lzma-alone package using the apt utility. 98 99 Args: 100 method (FETCH_...): Method to use 101 102 Returns: 103 True if the file was fetched and now installed, None if a method 104 other than FETCH_BIN was requested 105 106 Raises: 107 Valuerror: Fetching could not be completed 108 """ 109 if method != bintool.FETCH_BIN: 110 return None 111 return self.apt_install('lzma-alone') 112 113 def version(self): 114 """Version handler 115 116 Returns: 117 str: Version number of lzma_alone 118 """ 119 out = self.run_cmd_result('', raise_on_error=False).stderr.strip() 120 lines = out.splitlines() 121 if not lines: 122 return super().version() 123 out = lines[0] 124 # e.g. LZMA 9.22 beta : Igor Pavlov : Public domain : 2011-04-18 125 m_version = re.match(r'LZMA ([^:]*).*', out) 126 return m_version.group(1).strip() if m_version else out 127