]> git.proxmox.com Git - mirror_edk2.git/blob - BaseTools/Source/C/LzmaCompress/LzmaCompress.c
Sync BaseTools Branch (version r2321) to EDKII main trunk.
[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 - 2009, 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 "CommonLib.h"
31
32 const char *kCantReadMessage = "Can not read input file";
33 const char *kCantWriteMessage = "Can not write output file";
34 const char *kCantAllocateMessage = "Can not allocate memory";
35 const char *kDataErrorMessage = "Data error";
36
37 static void *SzAlloc(void *p, size_t size) { p = p; return MyAlloc(size); }
38 static void SzFree(void *p, void *address) { p = p; MyFree(address); }
39 static ISzAlloc g_Alloc = { SzAlloc, SzFree };
40
41 static Bool mQuietMode = False;
42
43 #define UTILITY_NAME "LzmaCompress"
44 #define UTILITY_MAJOR_VERSION 0
45 #define UTILITY_MINOR_VERSION 1
46 #define INTEL_COPYRIGHT \
47 "Copyright (c) 2009, Intel Corporation. All rights reserved."
48 void PrintHelp(char *buffer)
49 {
50 strcat(buffer,
51 "\n" UTILITY_NAME " - " INTEL_COPYRIGHT "\n"
52 "Based on LZMA Utility " MY_VERSION_COPYRIGHT_DATE "\n"
53 "\nUsage: LzmaCompress -e|-d [options] <inputFile>\n"
54 " -e: encode file\n"
55 " -d: decode file\n"
56 " -o FileName, --output FileName: specify the output filename\n"
57 " -v, --verbose: increase output messages\n"
58 " -q, --quiet: reduce output messages\n"
59 " --debug [0-9]: set debug level\n"
60 " --version: display the program version and exit\n"
61 " -h, --help: display this help text\n"
62 );
63 }
64
65 int PrintError(char *buffer, const char *message)
66 {
67 strcat(buffer, "\nError: ");
68 strcat(buffer, message);
69 strcat(buffer, "\n");
70 return 1;
71 }
72
73 int PrintErrorNumber(char *buffer, SRes val)
74 {
75 sprintf(buffer + strlen(buffer), "\nError code: %x\n", (unsigned)val);
76 return 1;
77 }
78
79 int PrintUserError(char *buffer)
80 {
81 return PrintError(buffer, "Incorrect command");
82 }
83
84 void PrintVersion(char *buffer)
85 {
86 sprintf (buffer, "%s Version %d.%d %s ", UTILITY_NAME, UTILITY_MAJOR_VERSION, UTILITY_MINOR_VERSION, __BUILD_VERSION);
87 }
88
89 #define IN_BUF_SIZE (1 << 16)
90 #define OUT_BUF_SIZE (1 << 16)
91
92 static SRes Decode2(CLzmaDec *state, ISeqOutStream *outStream, ISeqInStream *inStream,
93 UInt64 unpackSize)
94 {
95 int thereIsSize = (unpackSize != (UInt64)(Int64)-1);
96 Byte inBuf[IN_BUF_SIZE];
97 Byte outBuf[OUT_BUF_SIZE];
98 size_t inPos = 0, inSize = 0, outPos = 0;
99 LzmaDec_Init(state);
100 for (;;)
101 {
102 if (inPos == inSize)
103 {
104 inSize = IN_BUF_SIZE;
105 RINOK(inStream->Read(inStream, inBuf, &inSize));
106 inPos = 0;
107 }
108 {
109 SRes res;
110 SizeT inProcessed = inSize - inPos;
111 SizeT outProcessed = OUT_BUF_SIZE - outPos;
112 ELzmaFinishMode finishMode = LZMA_FINISH_ANY;
113 ELzmaStatus status;
114 if (thereIsSize && outProcessed > unpackSize)
115 {
116 outProcessed = (SizeT)unpackSize;
117 finishMode = LZMA_FINISH_END;
118 }
119
120 res = LzmaDec_DecodeToBuf(state, outBuf + outPos, &outProcessed,
121 inBuf + inPos, &inProcessed, finishMode, &status);
122 inPos += inProcessed;
123 outPos += outProcessed;
124 unpackSize -= outProcessed;
125
126 if (outStream)
127 if (outStream->Write(outStream, outBuf, outPos) != outPos)
128 return SZ_ERROR_WRITE;
129
130 outPos = 0;
131
132 if (res != SZ_OK || (thereIsSize && unpackSize == 0))
133 return res;
134
135 if (inProcessed == 0 && outProcessed == 0)
136 {
137 if (thereIsSize || status != LZMA_STATUS_FINISHED_WITH_MARK)
138 return SZ_ERROR_DATA;
139 return res;
140 }
141 }
142 }
143 }
144
145 static SRes Decode(ISeqOutStream *outStream, ISeqInStream *inStream)
146 {
147 UInt64 unpackSize;
148 int i;
149 SRes res = 0;
150
151 CLzmaDec state;
152
153 /* header: 5 bytes of LZMA properties and 8 bytes of uncompressed size */
154 unsigned char header[LZMA_PROPS_SIZE + 8];
155
156 /* Read and parse header */
157
158 RINOK(SeqInStream_Read(inStream, header, sizeof(header)));
159
160 unpackSize = 0;
161 for (i = 0; i < 8; i++)
162 unpackSize += (UInt64)header[LZMA_PROPS_SIZE + i] << (i * 8);
163
164 LzmaDec_Construct(&state);
165 RINOK(LzmaDec_Allocate(&state, header, LZMA_PROPS_SIZE, &g_Alloc));
166 res = Decode2(&state, outStream, inStream, unpackSize);
167 LzmaDec_Free(&state, &g_Alloc);
168 return res;
169 }
170
171 static SRes Encode(ISeqOutStream *outStream, ISeqInStream *inStream, UInt64 fileSize, char *rs)
172 {
173 CLzmaEncHandle enc;
174 SRes res;
175 CLzmaEncProps props;
176
177 rs = rs;
178
179 enc = LzmaEnc_Create(&g_Alloc);
180 if (enc == 0)
181 return SZ_ERROR_MEM;
182
183 LzmaEncProps_Init(&props);
184 res = LzmaEnc_SetProps(enc, &props);
185
186 if (res == SZ_OK)
187 {
188 Byte header[LZMA_PROPS_SIZE + 8];
189 size_t headerSize = LZMA_PROPS_SIZE;
190 int i;
191
192 res = LzmaEnc_WriteProperties(enc, header, &headerSize);
193 for (i = 0; i < 8; i++)
194 header[headerSize++] = (Byte)(fileSize >> (8 * i));
195 if (outStream->Write(outStream, header, headerSize) != headerSize)
196 res = SZ_ERROR_WRITE;
197 else
198 {
199 if (res == SZ_OK)
200 res = LzmaEnc_Encode(enc, outStream, inStream, NULL, &g_Alloc, &g_Alloc);
201 }
202 }
203 LzmaEnc_Destroy(enc, &g_Alloc, &g_Alloc);
204 return res;
205 }
206
207 int main2(int numArgs, const char *args[], char *rs)
208 {
209 CFileSeqInStream inStream;
210 CFileOutStream outStream;
211 int res;
212 int encodeMode = 0;
213 Bool modeWasSet = False;
214 const char *inputFile = NULL;
215 const char *outputFile = "file.tmp";
216 int param;
217
218 FileSeqInStream_CreateVTable(&inStream);
219 File_Construct(&inStream.file);
220
221 FileOutStream_CreateVTable(&outStream);
222 File_Construct(&outStream.file);
223
224 if (numArgs == 1)
225 {
226 PrintHelp(rs);
227 return 0;
228 }
229
230 for (param = 1; param < numArgs; param++) {
231 if (strcmp(args[param], "-e") == 0 || strcmp(args[param], "-d") == 0) {
232 encodeMode = (args[param][1] == 'e');
233 modeWasSet = True;
234 } else if (strcmp(args[param], "-o") == 0 ||
235 strcmp(args[param], "--output") == 0) {
236 if (numArgs < (param + 2)) {
237 return PrintUserError(rs);
238 }
239 outputFile = args[++param];
240 } else if (strcmp(args[param], "--debug") == 0) {
241 if (numArgs < (param + 2)) {
242 return PrintUserError(rs);
243 }
244 //
245 // For now we silently ignore this parameter to achieve command line
246 // parameter compatibility with other build tools.
247 //
248 param++;
249 } else if (
250 strcmp(args[param], "-h") == 0 ||
251 strcmp(args[param], "--help") == 0
252 ) {
253 PrintHelp(rs);
254 return 0;
255 } else if (
256 strcmp(args[param], "-v") == 0 ||
257 strcmp(args[param], "--verbose") == 0
258 ) {
259 //
260 // For now we silently ignore this parameter to achieve command line
261 // parameter compatibility with other build tools.
262 //
263 } else if (
264 strcmp(args[param], "-q") == 0 ||
265 strcmp(args[param], "--quiet") == 0
266 ) {
267 mQuietMode = True;
268 } else if (strcmp(args[param], "--version") == 0) {
269 PrintVersion(rs);
270 return 0;
271 } else if (inputFile == NULL) {
272 inputFile = args[param];
273 } else {
274 return PrintUserError(rs);
275 }
276 }
277
278 if ((inputFile == NULL) || !modeWasSet) {
279 return PrintUserError(rs);
280 }
281
282 {
283 size_t t4 = sizeof(UInt32);
284 size_t t8 = sizeof(UInt64);
285 if (t4 != 4 || t8 != 8)
286 return PrintError(rs, "Incorrect UInt32 or UInt64");
287 }
288
289 if (InFile_Open(&inStream.file, inputFile) != 0)
290 return PrintError(rs, "Can not open input file");
291
292 if (OutFile_Open(&outStream.file, outputFile) != 0)
293 return PrintError(rs, "Can not open output file");
294
295 if (encodeMode)
296 {
297 UInt64 fileSize;
298 File_GetLength(&inStream.file, &fileSize);
299 if (!mQuietMode) {
300 printf("Encoding\n");
301 }
302 res = Encode(&outStream.s, &inStream.s, fileSize, rs);
303 }
304 else
305 {
306 if (!mQuietMode) {
307 printf("Decoding\n");
308 }
309 res = Decode(&outStream.s, &inStream.s);
310 }
311
312 File_Close(&outStream.file);
313 File_Close(&inStream.file);
314
315 if (res != SZ_OK)
316 {
317 if (res == SZ_ERROR_MEM)
318 return PrintError(rs, kCantAllocateMessage);
319 else if (res == SZ_ERROR_DATA)
320 return PrintError(rs, kDataErrorMessage);
321 else if (res == SZ_ERROR_WRITE)
322 return PrintError(rs, kCantWriteMessage);
323 else if (res == SZ_ERROR_READ)
324 return PrintError(rs, kCantReadMessage);
325 return PrintErrorNumber(rs, res);
326 }
327 return 0;
328 }
329
330 int MY_CDECL main(int numArgs, const char *args[])
331 {
332 char rs[2000] = { 0 };
333 int res = main2(numArgs, args, rs);
334 if (strlen(rs) > 0) {
335 puts(rs);
336 }
337 return res;
338 }