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