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