blob: 1fda2f68c7b4cc74b5754c6de1e6f86e892467a4 [file] [log] [blame]
Simon Glass4cd4ee02022-01-09 20:14:07 -07001# 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
Simon Glass4583c002023-02-23 18:18:04 -070040from u_boot_pylib import tools
Simon Glass4cd4ee02022-01-09 20:14:07 -070041
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',
Simon Glassc1aa66e2022-01-29 14:14:04 -070068 dir=tools.get_output_dir()) as inf:
69 tools.write_file(inf.name, indata)
Simon Glass4cd4ee02022-01-09 20:14:07 -070070 with tempfile.NamedTemporaryFile(prefix='compo.otmp',
Simon Glassc1aa66e2022-01-29 14:14:04 -070071 dir=tools.get_output_dir()) as outf:
Simon Glass4cd4ee02022-01-09 20:14:07 -070072 args = ['e', inf.name, outf.name, '-lc1', '-lp0', '-pb0', '-d8']
73 self.run_cmd(*args, binary=True)
Simon Glassc1aa66e2022-01-29 14:14:04 -070074 return tools.read_file(outf.name)
Simon Glass4cd4ee02022-01-09 20:14:07 -070075
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 Glassc1aa66e2022-01-29 14:14:04 -070086 dir=tools.get_output_dir()) as inf:
87 tools.write_file(inf.name, indata)
Simon Glass4cd4ee02022-01-09 20:14:07 -070088 with tempfile.NamedTemporaryFile(prefix='compo.otmp',
Simon Glassc1aa66e2022-01-29 14:14:04 -070089 dir=tools.get_output_dir()) as outf:
Simon Glass4cd4ee02022-01-09 20:14:07 -070090 args = ['d', inf.name, outf.name]
91 self.run_cmd(*args, binary=True)
Simon Glassc1aa66e2022-01-29 14:14:04 -070092 return tools.read_file(outf.name, binary=True)
Simon Glass4cd4ee02022-01-09 20:14:07 -070093
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