Simon Glass | 4cd4ee0 | 2022-01-09 20:14:07 -0700 | [diff] [blame] | 1 | # SPDX-License-Identifier: GPL-2.0+ |
| 2 | # Copyright 2022 Google LLC |
| 3 | # |
| 4 | """Bintool implementation for lzma_alone |
| 5 | |
| 6 | lzma_alone allows compression and decompression of files, using an older version |
| 7 | of lzma. |
| 8 | |
| 9 | Documentation is available via:: |
| 10 | |
| 11 | man lzma_alone |
| 12 | |
| 13 | Here is the help: |
| 14 | |
| 15 | LZMA 9.22 beta : Igor Pavlov : Public domain : 2011-04-18 |
| 16 | |
| 17 | Usage: 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 | |
| 36 | import re |
| 37 | import tempfile |
| 38 | |
| 39 | from binman import bintool |
| 40 | from patman import tools |
| 41 | |
| 42 | # pylint: disable=C0103 |
| 43 | class 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', |
Simon Glass | c1aa66e | 2022-01-29 14:14:04 -0700 | [diff] [blame] | 68 | dir=tools.get_output_dir()) as inf: |
| 69 | tools.write_file(inf.name, indata) |
Simon Glass | 4cd4ee0 | 2022-01-09 20:14:07 -0700 | [diff] [blame] | 70 | with tempfile.NamedTemporaryFile(prefix='compo.otmp', |
Simon Glass | c1aa66e | 2022-01-29 14:14:04 -0700 | [diff] [blame] | 71 | dir=tools.get_output_dir()) as outf: |
Simon Glass | 4cd4ee0 | 2022-01-09 20:14:07 -0700 | [diff] [blame] | 72 | args = ['e', inf.name, outf.name, '-lc1', '-lp0', '-pb0', '-d8'] |
| 73 | self.run_cmd(*args, binary=True) |
Simon Glass | c1aa66e | 2022-01-29 14:14:04 -0700 | [diff] [blame] | 74 | return tools.read_file(outf.name) |
Simon Glass | 4cd4ee0 | 2022-01-09 20:14:07 -0700 | [diff] [blame] | 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', |
Simon Glass | c1aa66e | 2022-01-29 14:14:04 -0700 | [diff] [blame] | 86 | dir=tools.get_output_dir()) as inf: |
| 87 | tools.write_file(inf.name, indata) |
Simon Glass | 4cd4ee0 | 2022-01-09 20:14:07 -0700 | [diff] [blame] | 88 | with tempfile.NamedTemporaryFile(prefix='compo.otmp', |
Simon Glass | c1aa66e | 2022-01-29 14:14:04 -0700 | [diff] [blame] | 89 | dir=tools.get_output_dir()) as outf: |
Simon Glass | 4cd4ee0 | 2022-01-09 20:14:07 -0700 | [diff] [blame] | 90 | args = ['d', inf.name, outf.name] |
| 91 | self.run_cmd(*args, binary=True) |
Simon Glass | c1aa66e | 2022-01-29 14:14:04 -0700 | [diff] [blame] | 92 | return tools.read_file(outf.name, binary=True) |
Simon Glass | 4cd4ee0 | 2022-01-09 20:14:07 -0700 | [diff] [blame] | 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 |