• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
SzAlloc(void * p,size_t size)46 static void *SzAlloc(void *p, size_t size) { (void)p; return MyAlloc(size); }
SzFree(void * p,void * address)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."
PrintHelp(char * buffer)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 
PrintError(char * buffer,const char * message)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 
PrintErrorNumber(char * buffer,SRes val)84 int PrintErrorNumber(char *buffer, SRes val)
85 {
86   sprintf(buffer + strlen(buffer), "\nError code: %x\n", (unsigned)val);
87   return 1;
88 }
89 
PrintUserError(char * buffer)90 int PrintUserError(char *buffer)
91 {
92   return PrintError(buffer, "Incorrect command");
93 }
94 
PrintVersion(char * buffer)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 
Encode(ISeqOutStream * outStream,ISeqInStream * inStream,UInt64 fileSize)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 
Decode(ISeqOutStream * outStream,ISeqInStream * inStream,UInt64 fileSize)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 
main2(int numArgs,const char * args[],char * rs)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 
main(int numArgs,const char * args[])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 }
383