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