• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /** @file
2   LZMA Compress/Decompress tool (LzmaCompress)
3 
4   Based on LZMA SDK 16.04:
5     LzmaUtil.c -- Test application for LZMA compression
6     2016-10-04 : Igor Pavlov : Public domain
7 
8   Copyright (c) 2006 - 2016, 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 
46 static Bool mQuietMode = False;
47 static CONVERTER_TYPE mConType = NoConverter;
48 
49 #define UTILITY_NAME "LzmaCompress"
50 #define UTILITY_MAJOR_VERSION 0
51 #define UTILITY_MINOR_VERSION 2
52 #define INTEL_COPYRIGHT \
53   "Copyright (c) 2009-2016, Intel Corporation. All rights reserved."
PrintHelp(char * buffer)54 void PrintHelp(char *buffer)
55 {
56   strcat(buffer,
57       "\n" UTILITY_NAME " - " INTEL_COPYRIGHT "\n"
58       "Based on LZMA Utility " MY_VERSION_COPYRIGHT_DATE "\n"
59       "\nUsage:  LzmaCompress -e|-d [options] <inputFile>\n"
60              "  -e: encode file\n"
61              "  -d: decode file\n"
62              "  -o FileName, --output FileName: specify the output filename\n"
63              "  --f86: enable converter for x86 code\n"
64              "  -v, --verbose: increase output messages\n"
65              "  -q, --quiet: reduce output messages\n"
66              "  --debug [0-9]: set debug level\n"
67              "  --version: display the program version and exit\n"
68              "  -h, --help: display this help text\n"
69              );
70 }
71 
PrintError(char * buffer,const char * message)72 int PrintError(char *buffer, const char *message)
73 {
74   strcat(buffer, "\nError: ");
75   strcat(buffer, message);
76   strcat(buffer, "\n");
77   return 1;
78 }
79 
PrintErrorNumber(char * buffer,SRes val)80 int PrintErrorNumber(char *buffer, SRes val)
81 {
82   sprintf(buffer + strlen(buffer), "\nError code: %x\n", (unsigned)val);
83   return 1;
84 }
85 
PrintUserError(char * buffer)86 int PrintUserError(char *buffer)
87 {
88   return PrintError(buffer, "Incorrect command");
89 }
90 
PrintVersion(char * buffer)91 void PrintVersion(char *buffer)
92 {
93   sprintf (buffer, "%s Version %d.%d %s ", UTILITY_NAME, UTILITY_MAJOR_VERSION, UTILITY_MINOR_VERSION, __BUILD_VERSION);
94 }
95 
Encode(ISeqOutStream * outStream,ISeqInStream * inStream,UInt64 fileSize)96 static SRes Encode(ISeqOutStream *outStream, ISeqInStream *inStream, UInt64 fileSize)
97 {
98   SRes res;
99   size_t inSize = (size_t)fileSize;
100   Byte *inBuffer = 0;
101   Byte *outBuffer = 0;
102   Byte *filteredStream = 0;
103   size_t outSize;
104   CLzmaEncProps props;
105 
106   LzmaEncProps_Init(&props);
107   LzmaEncProps_Normalize(&props);
108 
109   if (inSize != 0) {
110     inBuffer = (Byte *)MyAlloc(inSize);
111     if (inBuffer == 0)
112       return SZ_ERROR_MEM;
113   } else {
114     return SZ_ERROR_INPUT_EOF;
115   }
116 
117   if (SeqInStream_Read(inStream, inBuffer, inSize) != SZ_OK) {
118     res = SZ_ERROR_READ;
119     goto Done;
120   }
121 
122   // we allocate 105% of original size + 64KB for output buffer
123   outSize = (size_t)fileSize / 20 * 21 + (1 << 16);
124   outBuffer = (Byte *)MyAlloc(outSize);
125   if (outBuffer == 0) {
126     res = SZ_ERROR_MEM;
127     goto Done;
128   }
129 
130   {
131     int i;
132     for (i = 0; i < 8; i++)
133       outBuffer[i + LZMA_PROPS_SIZE] = (Byte)(fileSize >> (8 * i));
134   }
135 
136   if (mConType != NoConverter)
137   {
138     filteredStream = (Byte *)MyAlloc(inSize);
139     if (filteredStream == 0) {
140       res = SZ_ERROR_MEM;
141       goto Done;
142     }
143     memcpy(filteredStream, inBuffer, inSize);
144 
145     if (mConType == X86Converter) {
146       {
147         UInt32 x86State;
148         x86_Convert_Init(x86State);
149         x86_Convert(filteredStream, (SizeT) inSize, 0, &x86State, 1);
150       }
151     }
152   }
153 
154   {
155     size_t outSizeProcessed = outSize - LZMA_HEADER_SIZE;
156     size_t outPropsSize = LZMA_PROPS_SIZE;
157 
158     res = LzmaEncode(outBuffer + LZMA_HEADER_SIZE, &outSizeProcessed,
159         mConType != NoConverter ? filteredStream : inBuffer, inSize,
160         &props, outBuffer, &outPropsSize, 0,
161         NULL, &g_Alloc, &g_Alloc);
162 
163     if (res != SZ_OK)
164       goto Done;
165 
166     outSize = LZMA_HEADER_SIZE + outSizeProcessed;
167   }
168 
169   if (outStream->Write(outStream, outBuffer, outSize) != outSize)
170     res = SZ_ERROR_WRITE;
171 
172 Done:
173   MyFree(outBuffer);
174   MyFree(inBuffer);
175   MyFree(filteredStream);
176 
177   return res;
178 }
179 
Decode(ISeqOutStream * outStream,ISeqInStream * inStream,UInt64 fileSize)180 static SRes Decode(ISeqOutStream *outStream, ISeqInStream *inStream, UInt64 fileSize)
181 {
182   SRes res;
183   size_t inSize = (size_t)fileSize;
184   Byte *inBuffer = 0;
185   Byte *outBuffer = 0;
186   size_t outSize = 0;
187   size_t inSizePure;
188   ELzmaStatus status;
189   UInt64 outSize64 = 0;
190 
191   int i;
192 
193   if (inSize < LZMA_HEADER_SIZE)
194     return SZ_ERROR_INPUT_EOF;
195 
196   inBuffer = (Byte *)MyAlloc(inSize);
197   if (inBuffer == 0)
198     return SZ_ERROR_MEM;
199 
200   if (SeqInStream_Read(inStream, inBuffer, inSize) != SZ_OK) {
201     res = SZ_ERROR_READ;
202     goto Done;
203   }
204 
205   for (i = 0; i < 8; i++)
206     outSize64 += ((UInt64)inBuffer[LZMA_PROPS_SIZE + i]) << (i * 8);
207 
208   outSize = (size_t)outSize64;
209   if (outSize != 0) {
210     outBuffer = (Byte *)MyAlloc(outSize);
211     if (outBuffer == 0) {
212       res = SZ_ERROR_MEM;
213       goto Done;
214     }
215   } else {
216     res = SZ_OK;
217     goto Done;
218   }
219 
220   inSizePure = inSize - LZMA_HEADER_SIZE;
221   res = LzmaDecode(outBuffer, &outSize, inBuffer + LZMA_HEADER_SIZE, &inSizePure,
222       inBuffer, LZMA_PROPS_SIZE, LZMA_FINISH_END, &status, &g_Alloc);
223 
224   if (res != SZ_OK)
225     goto Done;
226 
227   if (mConType == X86Converter)
228   {
229     UInt32 x86State;
230     x86_Convert_Init(x86State);
231     x86_Convert(outBuffer, (SizeT) outSize, 0, &x86State, 0);
232   }
233 
234   if (outStream->Write(outStream, outBuffer, outSize) != outSize)
235     res = SZ_ERROR_WRITE;
236 
237 Done:
238   MyFree(outBuffer);
239   MyFree(inBuffer);
240 
241   return res;
242 }
243 
main2(int numArgs,const char * args[],char * rs)244 int main2(int numArgs, const char *args[], char *rs)
245 {
246   CFileSeqInStream inStream;
247   CFileOutStream outStream;
248   int res;
249   int encodeMode = 0;
250   Bool modeWasSet = False;
251   const char *inputFile = NULL;
252   const char *outputFile = "file.tmp";
253   int param;
254   UInt64 fileSize;
255 
256   FileSeqInStream_CreateVTable(&inStream);
257   File_Construct(&inStream.file);
258 
259   FileOutStream_CreateVTable(&outStream);
260   File_Construct(&outStream.file);
261 
262   if (numArgs == 1)
263   {
264     PrintHelp(rs);
265     return 0;
266   }
267 
268   for (param = 1; param < numArgs; param++) {
269     if (strcmp(args[param], "-e") == 0 || strcmp(args[param], "-d") == 0) {
270       encodeMode = (args[param][1] == 'e');
271       modeWasSet = True;
272     } else if (strcmp(args[param], "--f86") == 0) {
273       mConType = X86Converter;
274     } else if (strcmp(args[param], "-o") == 0 ||
275                strcmp(args[param], "--output") == 0) {
276       if (numArgs < (param + 2)) {
277         return PrintUserError(rs);
278       }
279       outputFile = args[++param];
280     } else if (strcmp(args[param], "--debug") == 0) {
281       if (numArgs < (param + 2)) {
282         return PrintUserError(rs);
283       }
284       //
285       // For now we silently ignore this parameter to achieve command line
286       // parameter compatibility with other build tools.
287       //
288       param++;
289     } else if (
290                 strcmp(args[param], "-h") == 0 ||
291                 strcmp(args[param], "--help") == 0
292               ) {
293       PrintHelp(rs);
294       return 0;
295     } else if (
296                 strcmp(args[param], "-v") == 0 ||
297                 strcmp(args[param], "--verbose") == 0
298               ) {
299       //
300       // For now we silently ignore this parameter to achieve command line
301       // parameter compatibility with other build tools.
302       //
303     } else if (
304                 strcmp(args[param], "-q") == 0 ||
305                 strcmp(args[param], "--quiet") == 0
306               ) {
307       mQuietMode = True;
308     } else if (strcmp(args[param], "--version") == 0) {
309       PrintVersion(rs);
310       return 0;
311     } else if (inputFile == NULL) {
312       inputFile = args[param];
313     } else {
314       return PrintUserError(rs);
315     }
316   }
317 
318   if ((inputFile == NULL) || !modeWasSet) {
319     return PrintUserError(rs);
320   }
321 
322   {
323     size_t t4 = sizeof(UInt32);
324     size_t t8 = sizeof(UInt64);
325     if (t4 != 4 || t8 != 8)
326       return PrintError(rs, "Incorrect UInt32 or UInt64");
327   }
328 
329   if (InFile_Open(&inStream.file, inputFile) != 0)
330     return PrintError(rs, "Can not open input file");
331 
332   if (OutFile_Open(&outStream.file, outputFile) != 0) {
333     File_Close(&inStream.file);
334     return PrintError(rs, "Can not open output file");
335   }
336 
337   File_GetLength(&inStream.file, &fileSize);
338 
339   if (encodeMode)
340   {
341     if (!mQuietMode) {
342       printf("Encoding\n");
343     }
344     res = Encode(&outStream.s, &inStream.s, fileSize);
345   }
346   else
347   {
348     if (!mQuietMode) {
349       printf("Decoding\n");
350     }
351     res = Decode(&outStream.s, &inStream.s, fileSize);
352   }
353 
354   File_Close(&outStream.file);
355   File_Close(&inStream.file);
356 
357   if (res != SZ_OK)
358   {
359     if (res == SZ_ERROR_MEM)
360       return PrintError(rs, kCantAllocateMessage);
361     else if (res == SZ_ERROR_DATA)
362       return PrintError(rs, kDataErrorMessage);
363     else if (res == SZ_ERROR_WRITE)
364       return PrintError(rs, kCantWriteMessage);
365     else if (res == SZ_ERROR_READ)
366       return PrintError(rs, kCantReadMessage);
367     return PrintErrorNumber(rs, res);
368   }
369   return 0;
370 }
371 
main(int numArgs,const char * args[])372 int MY_CDECL main(int numArgs, const char *args[])
373 {
374   char rs[2000] = { 0 };
375   int res = main2(numArgs, args, rs);
376   if (strlen(rs) > 0) {
377     puts(rs);
378   }
379   return res;
380 }
381