--- /dev/null
+# SPDX-License-Identifier: GPL-2.0+
+# Copyright 2022 Google LLC
+#
+"""Bintool implementation for lzma_alone
+
+lzma_alone allows compression and decompression of files, using an older version
+of lzma.
+
+Documentation is available via::
+
+ man lzma_alone
+
+Here is the help:
+
+LZMA 9.22 beta : Igor Pavlov : Public domain : 2011-04-18
+
+Usage: LZMA <e|d> inputFile outputFile [<switches>...]
+ e: encode file
+ d: decode file
+ b: Benchmark
+<Switches>
+ -a{N}: set compression mode - [0, 1], default: 1 (max)
+ -d{N}: set dictionary size - [12, 30], default: 23 (8MB)
+ -fb{N}: set number of fast bytes - [5, 273], default: 128
+ -mc{N}: set number of cycles for match finder
+ -lc{N}: set number of literal context bits - [0, 8], default: 3
+ -lp{N}: set number of literal pos bits - [0, 4], default: 0
+ -pb{N}: set number of pos bits - [0, 4], default: 2
+ -mf{MF_ID}: set Match Finder: [bt2, bt3, bt4, hc4], default: bt4
+ -mt{N}: set number of CPU threads
+ -eos: write End Of Stream marker
+ -si: read data from stdin
+ -so: write data to stdout
+"""
+
+import re
+import tempfile
+
+from binman import bintool
+from patman import tools
+
+# pylint: disable=C0103
+class Bintoollzma_alone(bintool.Bintool):
+ """Compression/decompression using the LZMA algorithm
+
+ This bintool supports running `lzma_alone` to compress and decompress data,
+ as used by binman.
+
+ It is also possible to fetch the tool, which uses `apt` to install it.
+
+ Documentation is available via::
+
+ man lzma_alone
+ """
+ def __init__(self, name):
+ super().__init__(name, 'lzma_alone compression')
+
+ def compress(self, indata):
+ """Compress data with lzma_alone
+
+ Args:
+ indata (bytes): Data to compress
+
+ Returns:
+ bytes: Compressed data
+ """
+ with tempfile.NamedTemporaryFile(prefix='comp.tmp',
+ dir=tools.GetOutputDir()) as inf:
+ tools.WriteFile(inf.name, indata)
+ with tempfile.NamedTemporaryFile(prefix='compo.otmp',
+ dir=tools.GetOutputDir()) as outf:
+ args = ['e', inf.name, outf.name, '-lc1', '-lp0', '-pb0', '-d8']
+ self.run_cmd(*args, binary=True)
+ return tools.ReadFile(outf.name)
+
+ def decompress(self, indata):
+ """Decompress data with lzma_alone
+
+ Args:
+ indata (bytes): Data to decompress
+
+ Returns:
+ bytes: Decompressed data
+ """
+ with tempfile.NamedTemporaryFile(prefix='decomp.tmp',
+ dir=tools.GetOutputDir()) as inf:
+ tools.WriteFile(inf.name, indata)
+ with tempfile.NamedTemporaryFile(prefix='compo.otmp',
+ dir=tools.GetOutputDir()) as outf:
+ args = ['d', inf.name, outf.name]
+ self.run_cmd(*args, binary=True)
+ return tools.ReadFile(outf.name, binary=True)
+
+ def fetch(self, method):
+ """Fetch handler for lzma_alone
+
+ This installs the lzma-alone package using the apt utility.
+
+ Args:
+ method (FETCH_...): Method to use
+
+ Returns:
+ True if the file was fetched and now installed, None if a method
+ other than FETCH_BIN was requested
+
+ Raises:
+ Valuerror: Fetching could not be completed
+ """
+ if method != bintool.FETCH_BIN:
+ return None
+ return self.apt_install('lzma-alone')
+
+ def version(self):
+ """Version handler
+
+ Returns:
+ str: Version number of lzma_alone
+ """
+ out = self.run_cmd_result('', raise_on_error=False).stderr.strip()
+ lines = out.splitlines()
+ if not lines:
+ return super().version()
+ out = lines[0]
+ # e.g. LZMA 9.22 beta : Igor Pavlov : Public domain : 2011-04-18
+ m_version = re.match(r'LZMA ([^:]*).*', out)
+ return m_version.group(1).strip() if m_version else out