blob: f09c5c8904bb296fdb503fb6b79c7427a3ce707a [file] [log] [blame]
Simon Glassa5c0a422022-01-09 20:14:05 -07001# SPDX-License-Identifier: GPL-2.0+
2# Copyright 2022 Google LLC
3#
4"""Bintool implementation for lz4
5
6lz4 allows compression and decompression of files.
7
8Documentation is available via::
9
10 man lz4
11
12Here is the help:
13
14*** LZ4 command line interface 64-bits v1.9.3, by Yann Collet ***
15Usage :
16 lz4 [arg] [input] [output]
17
18input : a filename
19 with no FILE, or when FILE is - or stdin, read standard input
20Arguments :
21 -1 : Fast compression (default)
22 -9 : High compression
23 -d : decompression (default for .lz4 extension)
24 -z : force compression
25 -D FILE: use FILE as dictionary
26 -f : overwrite output without prompting
27 -k : preserve source files(s) (default)
28--rm : remove source file(s) after successful de/compression
29 -h/-H : display help/long help and exit
30
31Advanced arguments :
32 -V : display Version number and exit
33 -v : verbose mode
34 -q : suppress warnings; specify twice to suppress errors too
35 -c : force write to standard output, even if it is the console
36 -t : test compressed file integrity
37 -m : multiple input files (implies automatic output filenames)
38 -r : operate recursively on directories (sets also -m)
39 -l : compress using Legacy format (Linux kernel compression)
40 -B# : cut file into blocks of size # bytes [32+]
41 or predefined block size [4-7] (default: 7)
42 -BI : Block Independence (default)
43 -BD : Block dependency (improves compression ratio)
44 -BX : enable block checksum (default:disabled)
45--no-frame-crc : disable stream checksum (default:enabled)
46--content-size : compressed frame includes original size (default:not present)
47--list FILE : lists information about .lz4 files (useful for files compressed
48 with --content-size flag)
49--[no-]sparse : sparse mode (default:enabled on file, disabled on stdout)
50--favor-decSpeed: compressed files decompress faster, but are less compressed
51--fast[=#]: switch to ultra fast compression level (default: 1)
52--best : same as -12
53Benchmark arguments :
54 -b# : benchmark file(s), using # compression level (default : 1)
55 -e# : test all compression levels from -bX to # (default : 1)
56 -i# : minimum evaluation time in seconds (default : 3s)
57"""
58
59import re
60import tempfile
61
62from binman import bintool
63from patman import tools
64
65# pylint: disable=C0103
66class Bintoollz4(bintool.Bintool):
67 """Compression/decompression using the LZ4 algorithm
68
69 This bintool supports running `lz4` to compress and decompress data, as
70 used by binman.
71
72 It is also possible to fetch the tool, which uses `apt` to install it.
73
74 Documentation is available via::
75
76 man lz4
77 """
78 def __init__(self, name):
79 super().__init__(name, 'lz4 compression')
80
81 def compress(self, indata):
82 """Compress data with lz4
83
84 Args:
85 indata (bytes): Data to compress
86
87 Returns:
88 bytes: Compressed data
89 """
90 with tempfile.NamedTemporaryFile(prefix='comp.tmp',
Simon Glass80025522022-01-29 14:14:04 -070091 dir=tools.get_output_dir()) as tmp:
92 tools.write_file(tmp.name, indata)
Simon Glassa5c0a422022-01-09 20:14:05 -070093 args = ['--no-frame-crc', '-B4', '-5', '-c', tmp.name]
94 return self.run_cmd(*args, binary=True)
95
96 def decompress(self, indata):
97 """Decompress data with lz4
98
99 Args:
100 indata (bytes): Data to decompress
101
102 Returns:
103 bytes: Decompressed data
104 """
105 with tempfile.NamedTemporaryFile(prefix='decomp.tmp',
Simon Glass80025522022-01-29 14:14:04 -0700106 dir=tools.get_output_dir()) as inf:
107 tools.write_file(inf.name, indata)
Simon Glassa5c0a422022-01-09 20:14:05 -0700108 args = ['-cd', inf.name]
109 return self.run_cmd(*args, binary=True)
110
111 def fetch(self, method):
112 """Fetch handler for lz4
113
114 This installs the lz4 package using the apt utility.
115
116 Args:
117 method (FETCH_...): Method to use
118
119 Returns:
120 True if the file was fetched and now installed, None if a method
121 other than FETCH_BIN was requested
122
123 Raises:
124 Valuerror: Fetching could not be completed
125 """
126 if method != bintool.FETCH_BIN:
127 return None
128 return self.apt_install('lz4')
129
130 def version(self):
131 """Version handler
132
133 Returns:
134 str: Version number of lz4
135 """
136 out = self.run_cmd('-V').strip()
137 if not out:
138 return super().version()
139 m_version = re.match(r'.* (v[0-9.]*),.*', out)
140 return m_version.group(1) if m_version else out