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