1 /* LzmaUtil.c -- Test application for LZMA compression
\r
2 2015-11-08 : Igor Pavlov : Public domain */
\r
4 #include "../../Precomp.h"
\r
10 #include "../../Alloc.h"
\r
11 #include "../../7zFile.h"
\r
12 #include "../../7zVersion.h"
\r
13 #include "../../LzmaDec.h"
\r
14 #include "../../LzmaEnc.h"
\r
16 const char *kCantReadMessage = "Can not read input file";
\r
17 const char *kCantWriteMessage = "Can not write output file";
\r
18 const char *kCantAllocateMessage = "Can not allocate memory";
\r
19 const char *kDataErrorMessage = "Data error";
\r
21 void PrintHelp(char *buffer)
\r
23 strcat(buffer, "\nLZMA Utility " MY_VERSION_COPYRIGHT_DATE "\n"
\r
24 "\nUsage: lzma <e|d> inputFile outputFile\n"
\r
26 " d: decode file\n");
\r
29 int PrintError(char *buffer, const char *message)
\r
31 strcat(buffer, "\nError: ");
\r
32 strcat(buffer, message);
\r
33 strcat(buffer, "\n");
\r
37 int PrintErrorNumber(char *buffer, SRes val)
\r
39 sprintf(buffer + strlen(buffer), "\nError code: %x\n", (unsigned)val);
\r
43 int PrintUserError(char *buffer)
\r
45 return PrintError(buffer, "Incorrect command");
\r
48 #define IN_BUF_SIZE (1 << 16)
\r
49 #define OUT_BUF_SIZE (1 << 16)
\r
51 static SRes Decode2(CLzmaDec *state, ISeqOutStream *outStream, ISeqInStream *inStream,
\r
54 int thereIsSize = (unpackSize != (UInt64)(Int64)-1);
\r
55 Byte inBuf[IN_BUF_SIZE];
\r
56 Byte outBuf[OUT_BUF_SIZE];
\r
57 size_t inPos = 0, inSize = 0, outPos = 0;
\r
58 LzmaDec_Init(state);
\r
61 if (inPos == inSize)
\r
63 inSize = IN_BUF_SIZE;
\r
64 RINOK(inStream->Read(inStream, inBuf, &inSize));
\r
69 SizeT inProcessed = inSize - inPos;
\r
70 SizeT outProcessed = OUT_BUF_SIZE - outPos;
\r
71 ELzmaFinishMode finishMode = LZMA_FINISH_ANY;
\r
73 if (thereIsSize && outProcessed > unpackSize)
\r
75 outProcessed = (SizeT)unpackSize;
\r
76 finishMode = LZMA_FINISH_END;
\r
79 res = LzmaDec_DecodeToBuf(state, outBuf + outPos, &outProcessed,
\r
80 inBuf + inPos, &inProcessed, finishMode, &status);
\r
81 inPos += inProcessed;
\r
82 outPos += outProcessed;
\r
83 unpackSize -= outProcessed;
\r
86 if (outStream->Write(outStream, outBuf, outPos) != outPos)
\r
87 return SZ_ERROR_WRITE;
\r
91 if (res != SZ_OK || (thereIsSize && unpackSize == 0))
\r
94 if (inProcessed == 0 && outProcessed == 0)
\r
96 if (thereIsSize || status != LZMA_STATUS_FINISHED_WITH_MARK)
\r
97 return SZ_ERROR_DATA;
\r
104 static SRes Decode(ISeqOutStream *outStream, ISeqInStream *inStream)
\r
112 /* header: 5 bytes of LZMA properties and 8 bytes of uncompressed size */
\r
113 unsigned char header[LZMA_PROPS_SIZE + 8];
\r
115 /* Read and parse header */
\r
117 RINOK(SeqInStream_Read(inStream, header, sizeof(header)));
\r
120 for (i = 0; i < 8; i++)
\r
121 unpackSize += (UInt64)header[LZMA_PROPS_SIZE + i] << (i * 8);
\r
123 LzmaDec_Construct(&state);
\r
124 RINOK(LzmaDec_Allocate(&state, header, LZMA_PROPS_SIZE, &g_Alloc));
\r
125 res = Decode2(&state, outStream, inStream, unpackSize);
\r
126 LzmaDec_Free(&state, &g_Alloc);
\r
130 static SRes Encode(ISeqOutStream *outStream, ISeqInStream *inStream, UInt64 fileSize, char *rs)
\r
132 CLzmaEncHandle enc;
\r
134 CLzmaEncProps props;
\r
138 enc = LzmaEnc_Create(&g_Alloc);
\r
140 return SZ_ERROR_MEM;
\r
142 LzmaEncProps_Init(&props);
\r
143 res = LzmaEnc_SetProps(enc, &props);
\r
147 Byte header[LZMA_PROPS_SIZE + 8];
\r
148 size_t headerSize = LZMA_PROPS_SIZE;
\r
151 res = LzmaEnc_WriteProperties(enc, header, &headerSize);
\r
152 for (i = 0; i < 8; i++)
\r
153 header[headerSize++] = (Byte)(fileSize >> (8 * i));
\r
154 if (outStream->Write(outStream, header, headerSize) != headerSize)
\r
155 res = SZ_ERROR_WRITE;
\r
159 res = LzmaEnc_Encode(enc, outStream, inStream, NULL, &g_Alloc, &g_Alloc);
\r
162 LzmaEnc_Destroy(enc, &g_Alloc, &g_Alloc);
\r
166 int main2(int numArgs, const char *args[], char *rs)
\r
168 CFileSeqInStream inStream;
\r
169 CFileOutStream outStream;
\r
173 Bool useOutFile = False;
\r
175 FileSeqInStream_CreateVTable(&inStream);
\r
176 File_Construct(&inStream.file);
\r
178 FileOutStream_CreateVTable(&outStream);
\r
179 File_Construct(&outStream.file);
\r
187 if (numArgs < 3 || numArgs > 4 || strlen(args[1]) != 1)
\r
188 return PrintUserError(rs);
\r
191 encodeMode = (c == 'e' || c == 'E');
\r
192 if (!encodeMode && c != 'd' && c != 'D')
\r
193 return PrintUserError(rs);
\r
196 size_t t4 = sizeof(UInt32);
\r
197 size_t t8 = sizeof(UInt64);
\r
198 if (t4 != 4 || t8 != 8)
\r
199 return PrintError(rs, "Incorrect UInt32 or UInt64");
\r
202 if (InFile_Open(&inStream.file, args[2]) != 0)
\r
203 return PrintError(rs, "Can not open input file");
\r
208 if (OutFile_Open(&outStream.file, args[3]) != 0)
\r
209 return PrintError(rs, "Can not open output file");
\r
211 else if (encodeMode)
\r
212 PrintUserError(rs);
\r
217 File_GetLength(&inStream.file, &fileSize);
\r
218 res = Encode(&outStream.s, &inStream.s, fileSize, rs);
\r
222 res = Decode(&outStream.s, useOutFile ? &inStream.s : NULL);
\r
226 File_Close(&outStream.file);
\r
227 File_Close(&inStream.file);
\r
231 if (res == SZ_ERROR_MEM)
\r
232 return PrintError(rs, kCantAllocateMessage);
\r
233 else if (res == SZ_ERROR_DATA)
\r
234 return PrintError(rs, kDataErrorMessage);
\r
235 else if (res == SZ_ERROR_WRITE)
\r
236 return PrintError(rs, kCantWriteMessage);
\r
237 else if (res == SZ_ERROR_READ)
\r
238 return PrintError(rs, kCantReadMessage);
\r
239 return PrintErrorNumber(rs, res);
\r
244 int MY_CDECL main(int numArgs, const char *args[])
\r
246 char rs[800] = { 0 };
\r
247 int res = main2(numArgs, args, rs);
\r