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