]> git.proxmox.com Git - mirror_edk2.git/blob - BaseTools/Source/C/LzmaCompress/LzmaCompress.c
BaseTools/LzmaCompress: Add two switches
[mirror_edk2.git] / BaseTools / Source / C / LzmaCompress / LzmaCompress.c
1 /** @file
2 LZMA Compress/Decompress tool (LzmaCompress)
3
4 Based on LZMA SDK 18.05:
5 LzmaUtil.c -- Test application for LZMA compression
6 2018-04-30 : Igor Pavlov : Public domain
7
8 Copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.<BR>
9 SPDX-License-Identifier: BSD-2-Clause-Patent
10
11 **/
12
13 #define _CRT_SECURE_NO_WARNINGS
14
15 #include <stdio.h>
16 #include <stdlib.h>
17 #include <string.h>
18
19 #include "Sdk/C/Alloc.h"
20 #include "Sdk/C/7zFile.h"
21 #include "Sdk/C/7zVersion.h"
22 #include "Sdk/C/LzmaDec.h"
23 #include "Sdk/C/LzmaEnc.h"
24 #include "Sdk/C/Bra.h"
25 #include "CommonLib.h"
26 #include "ParseInf.h"
27
28 #define LZMA_HEADER_SIZE (LZMA_PROPS_SIZE + 8)
29
30 typedef enum {
31 NoConverter,
32 X86Converter,
33 MaxConverter
34 } CONVERTER_TYPE;
35
36 const char *kCantReadMessage = "Can not read input file";
37 const char *kCantWriteMessage = "Can not write output file";
38 const char *kCantAllocateMessage = "Can not allocate memory";
39 const char *kDataErrorMessage = "Data error";
40 const char *kInvalidParamValMessage = "Invalid parameter value";
41
42 static Bool mQuietMode = False;
43 static CONVERTER_TYPE mConType = NoConverter;
44
45 UINT64 mDictionarySize = 31;
46 UINT64 mCompressionMode = 2;
47
48 #define UTILITY_NAME "LzmaCompress"
49 #define UTILITY_MAJOR_VERSION 0
50 #define UTILITY_MINOR_VERSION 2
51 #define INTEL_COPYRIGHT \
52 "Copyright (c) 2009-2018, Intel Corporation. All rights reserved."
53 void PrintHelp(char *buffer)
54 {
55 strcat(buffer,
56 "\n" UTILITY_NAME " - " INTEL_COPYRIGHT "\n"
57 "Based on LZMA Utility " MY_VERSION_COPYRIGHT_DATE "\n"
58 "\nUsage: LzmaCompress -e|-d [options] <inputFile>\n"
59 " -e: encode file\n"
60 " -d: decode file\n"
61 " -o FileName, --output FileName: specify the output filename\n"
62 " --f86: enable converter for x86 code\n"
63 " -v, --verbose: increase output messages\n"
64 " -q, --quiet: reduce output messages\n"
65 " --debug [0-9]: set debug level\n"
66 " -a: set compression mode 0 = fast, 1 = normal, default: 1 (normal)\n"
67 " d: sets Dictionary size - [0, 30], default: 23 (8MB)\n"
68 " --version: display the program version and exit\n"
69 " -h, --help: display this help text\n"
70 );
71 }
72
73 int PrintError(char *buffer, const char *message)
74 {
75 strcat(buffer, "\nError: ");
76 strcat(buffer, message);
77 strcat(buffer, "\n");
78 return 1;
79 }
80
81 int PrintErrorNumber(char *buffer, SRes val)
82 {
83 sprintf(buffer + strlen(buffer), "\nError code: %x\n", (unsigned)val);
84 return 1;
85 }
86
87 int PrintUserError(char *buffer)
88 {
89 return PrintError(buffer, "Incorrect command");
90 }
91
92 void PrintVersion(char *buffer)
93 {
94 sprintf (buffer, "%s Version %d.%d %s ", UTILITY_NAME, UTILITY_MAJOR_VERSION, UTILITY_MINOR_VERSION, __BUILD_VERSION);
95 }
96
97 static SRes Encode(ISeqOutStream *outStream, ISeqInStream *inStream, UInt64 fileSize, CLzmaEncProps *props)
98 {
99 SRes res;
100 size_t inSize = (size_t)fileSize;
101 Byte *inBuffer = 0;
102 Byte *outBuffer = 0;
103 Byte *filteredStream = 0;
104 size_t outSize;
105
106 if (inSize != 0) {
107 inBuffer = (Byte *)MyAlloc(inSize);
108 if (inBuffer == 0)
109 return SZ_ERROR_MEM;
110 } else {
111 return SZ_ERROR_INPUT_EOF;
112 }
113
114 if (SeqInStream_Read(inStream, inBuffer, inSize) != SZ_OK) {
115 res = SZ_ERROR_READ;
116 goto Done;
117 }
118
119 // we allocate 105% of original size + 64KB for output buffer
120 outSize = (size_t)fileSize / 20 * 21 + (1 << 16);
121 outBuffer = (Byte *)MyAlloc(outSize);
122 if (outBuffer == 0) {
123 res = SZ_ERROR_MEM;
124 goto Done;
125 }
126
127 {
128 int i;
129 for (i = 0; i < 8; i++)
130 outBuffer[i + LZMA_PROPS_SIZE] = (Byte)(fileSize >> (8 * i));
131 }
132
133 if (mConType != NoConverter)
134 {
135 filteredStream = (Byte *)MyAlloc(inSize);
136 if (filteredStream == 0) {
137 res = SZ_ERROR_MEM;
138 goto Done;
139 }
140 memcpy(filteredStream, inBuffer, inSize);
141
142 if (mConType == X86Converter) {
143 {
144 UInt32 x86State;
145 x86_Convert_Init(x86State);
146 x86_Convert(filteredStream, (SizeT) inSize, 0, &x86State, 1);
147 }
148 }
149 }
150
151 {
152 size_t outSizeProcessed = outSize - LZMA_HEADER_SIZE;
153 size_t outPropsSize = LZMA_PROPS_SIZE;
154
155 res = LzmaEncode(outBuffer + LZMA_HEADER_SIZE, &outSizeProcessed,
156 mConType != NoConverter ? filteredStream : inBuffer, inSize,
157 props, outBuffer, &outPropsSize, 0,
158 NULL, &g_Alloc, &g_Alloc);
159
160 if (res != SZ_OK)
161 goto Done;
162
163 outSize = LZMA_HEADER_SIZE + outSizeProcessed;
164 }
165
166 if (outStream->Write(outStream, outBuffer, outSize) != outSize)
167 res = SZ_ERROR_WRITE;
168
169 Done:
170 MyFree(outBuffer);
171 MyFree(inBuffer);
172 MyFree(filteredStream);
173
174 return res;
175 }
176
177 static SRes Decode(ISeqOutStream *outStream, ISeqInStream *inStream, UInt64 fileSize)
178 {
179 SRes res;
180 size_t inSize = (size_t)fileSize;
181 Byte *inBuffer = 0;
182 Byte *outBuffer = 0;
183 size_t outSize = 0;
184 size_t inSizePure;
185 ELzmaStatus status;
186 UInt64 outSize64 = 0;
187
188 int i;
189
190 if (inSize < LZMA_HEADER_SIZE)
191 return SZ_ERROR_INPUT_EOF;
192
193 inBuffer = (Byte *)MyAlloc(inSize);
194 if (inBuffer == 0)
195 return SZ_ERROR_MEM;
196
197 if (SeqInStream_Read(inStream, inBuffer, inSize) != SZ_OK) {
198 res = SZ_ERROR_READ;
199 goto Done;
200 }
201
202 for (i = 0; i < 8; i++)
203 outSize64 += ((UInt64)inBuffer[LZMA_PROPS_SIZE + i]) << (i * 8);
204
205 outSize = (size_t)outSize64;
206 if (outSize != 0) {
207 outBuffer = (Byte *)MyAlloc(outSize);
208 if (outBuffer == 0) {
209 res = SZ_ERROR_MEM;
210 goto Done;
211 }
212 } else {
213 res = SZ_OK;
214 goto Done;
215 }
216
217 inSizePure = inSize - LZMA_HEADER_SIZE;
218 res = LzmaDecode(outBuffer, &outSize, inBuffer + LZMA_HEADER_SIZE, &inSizePure,
219 inBuffer, LZMA_PROPS_SIZE, LZMA_FINISH_END, &status, &g_Alloc);
220
221 if (res != SZ_OK)
222 goto Done;
223
224 if (mConType == X86Converter)
225 {
226 UInt32 x86State;
227 x86_Convert_Init(x86State);
228 x86_Convert(outBuffer, (SizeT) outSize, 0, &x86State, 0);
229 }
230
231 if (outStream->Write(outStream, outBuffer, outSize) != outSize)
232 res = SZ_ERROR_WRITE;
233
234 Done:
235 MyFree(outBuffer);
236 MyFree(inBuffer);
237
238 return res;
239 }
240
241 int main2(int numArgs, const char *args[], char *rs)
242 {
243 CFileSeqInStream inStream;
244 CFileOutStream outStream;
245 int res;
246 int encodeMode = 0;
247 Bool modeWasSet = False;
248 const char *inputFile = NULL;
249 const char *outputFile = "file.tmp";
250 int param;
251 UInt64 fileSize;
252 CLzmaEncProps props;
253
254 LzmaEncProps_Init(&props);
255 LzmaEncProps_Normalize(&props);
256
257 FileSeqInStream_CreateVTable(&inStream);
258 File_Construct(&inStream.file);
259
260 FileOutStream_CreateVTable(&outStream);
261 File_Construct(&outStream.file);
262
263 if (numArgs == 1)
264 {
265 PrintHelp(rs);
266 return 0;
267 }
268
269 for (param = 1; param < numArgs; param++) {
270 if (strcmp(args[param], "-e") == 0 || strcmp(args[param], "-d") == 0) {
271 encodeMode = (args[param][1] == 'e');
272 modeWasSet = True;
273 } else if (strcmp(args[param], "--f86") == 0) {
274 mConType = X86Converter;
275 } else if (strcmp(args[param], "-o") == 0 ||
276 strcmp(args[param], "--output") == 0) {
277 if (numArgs < (param + 2)) {
278 return PrintUserError(rs);
279 }
280 outputFile = args[++param];
281 } else if (strcmp(args[param], "--debug") == 0) {
282 if (numArgs < (param + 2)) {
283 return PrintUserError(rs);
284 }
285 //
286 // For now we silently ignore this parameter to achieve command line
287 // parameter compatibility with other build tools.
288 //
289 param++;
290 } else if (strcmp(args[param], "-a") == 0) {
291 AsciiStringToUint64(args[param + 1],FALSE,&mCompressionMode);
292 if ((mCompressionMode == 0)||(mCompressionMode == 1)){
293 props.algo = (int)mCompressionMode;
294 param++;
295 continue;
296 } else {
297 return PrintError(rs, kInvalidParamValMessage);
298 }
299 } else if (strcmp(args[param], "d") == 0) {
300 AsciiStringToUint64(args[param + 1],FALSE,&mDictionarySize);
301 if (mDictionarySize <= 30){
302 props.dictSize = (UINT32)mDictionarySize;
303 param++;
304 continue;
305 } else {
306 return PrintError(rs, kInvalidParamValMessage);
307 }
308 } else if (
309 strcmp(args[param], "-h") == 0 ||
310 strcmp(args[param], "--help") == 0
311 ) {
312 PrintHelp(rs);
313 return 0;
314 } else if (
315 strcmp(args[param], "-v") == 0 ||
316 strcmp(args[param], "--verbose") == 0
317 ) {
318 //
319 // For now we silently ignore this parameter to achieve command line
320 // parameter compatibility with other build tools.
321 //
322 } else if (
323 strcmp(args[param], "-q") == 0 ||
324 strcmp(args[param], "--quiet") == 0
325 ) {
326 mQuietMode = True;
327 } else if (strcmp(args[param], "--version") == 0) {
328 PrintVersion(rs);
329 return 0;
330 } else if (inputFile == NULL) {
331 inputFile = args[param];
332 } else {
333 return PrintUserError(rs);
334 }
335 }
336
337 if ((inputFile == NULL) || !modeWasSet) {
338 return PrintUserError(rs);
339 }
340
341 {
342 size_t t4 = sizeof(UInt32);
343 size_t t8 = sizeof(UInt64);
344 if (t4 != 4 || t8 != 8)
345 return PrintError(rs, "Incorrect UInt32 or UInt64");
346 }
347
348 if (InFile_Open(&inStream.file, inputFile) != 0)
349 return PrintError(rs, "Can not open input file");
350
351 if (OutFile_Open(&outStream.file, outputFile) != 0) {
352 File_Close(&inStream.file);
353 return PrintError(rs, "Can not open output file");
354 }
355
356 File_GetLength(&inStream.file, &fileSize);
357
358 if (encodeMode)
359 {
360 if (!mQuietMode) {
361 printf("Encoding\n");
362 }
363 res = Encode(&outStream.vt, &inStream.vt, fileSize, &props);
364 }
365 else
366 {
367 if (!mQuietMode) {
368 printf("Decoding\n");
369 }
370 res = Decode(&outStream.vt, &inStream.vt, fileSize);
371 }
372
373 File_Close(&outStream.file);
374 File_Close(&inStream.file);
375
376 if (res != SZ_OK)
377 {
378 if (res == SZ_ERROR_MEM)
379 return PrintError(rs, kCantAllocateMessage);
380 else if (res == SZ_ERROR_DATA)
381 return PrintError(rs, kDataErrorMessage);
382 else if (res == SZ_ERROR_WRITE)
383 return PrintError(rs, kCantWriteMessage);
384 else if (res == SZ_ERROR_READ)
385 return PrintError(rs, kCantReadMessage);
386 return PrintErrorNumber(rs, res);
387 }
388 return 0;
389 }
390
391 int MY_CDECL main(int numArgs, const char *args[])
392 {
393 char rs[2000] = { 0 };
394 int res = main2(numArgs, args, rs);
395 if (strlen(rs) > 0) {
396 puts(rs);
397 }
398 return res;
399 }