src/third-party/lzma/Util/Lzma/LzmaUtil.c (view raw)
1/* LzmaUtil.c -- Test application for LZMA compression
22015-11-08 : Igor Pavlov : Public domain */
3
4#include "../../Precomp.h"
5
6#include <stdio.h>
7#include <stdlib.h>
8#include <string.h>
9
10#include "../../Alloc.h"
11#include "../../7zFile.h"
12#include "../../7zVersion.h"
13#include "../../LzmaDec.h"
14#include "../../LzmaEnc.h"
15
16const char *kCantReadMessage = "Can not read input file";
17const char *kCantWriteMessage = "Can not write output file";
18const char *kCantAllocateMessage = "Can not allocate memory";
19const char *kDataErrorMessage = "Data error";
20
21void PrintHelp(char *buffer)
22{
23 strcat(buffer, "\nLZMA Utility " MY_VERSION_COPYRIGHT_DATE "\n"
24 "\nUsage: lzma <e|d> inputFile outputFile\n"
25 " e: encode file\n"
26 " d: decode file\n");
27}
28
29int PrintError(char *buffer, const char *message)
30{
31 strcat(buffer, "\nError: ");
32 strcat(buffer, message);
33 strcat(buffer, "\n");
34 return 1;
35}
36
37int PrintErrorNumber(char *buffer, SRes val)
38{
39 sprintf(buffer + strlen(buffer), "\nError code: %x\n", (unsigned)val);
40 return 1;
41}
42
43int PrintUserError(char *buffer)
44{
45 return PrintError(buffer, "Incorrect command");
46}
47
48#define IN_BUF_SIZE (1 << 16)
49#define OUT_BUF_SIZE (1 << 16)
50
51static SRes Decode2(CLzmaDec *state, ISeqOutStream *outStream, ISeqInStream *inStream,
52 UInt64 unpackSize)
53{
54 int thereIsSize = (unpackSize != (UInt64)(Int64)-1);
55 Byte inBuf[IN_BUF_SIZE];
56 Byte outBuf[OUT_BUF_SIZE];
57 size_t inPos = 0, inSize = 0, outPos = 0;
58 LzmaDec_Init(state);
59 for (;;)
60 {
61 if (inPos == inSize)
62 {
63 inSize = IN_BUF_SIZE;
64 RINOK(inStream->Read(inStream, inBuf, &inSize));
65 inPos = 0;
66 }
67 {
68 SRes res;
69 SizeT inProcessed = inSize - inPos;
70 SizeT outProcessed = OUT_BUF_SIZE - outPos;
71 ELzmaFinishMode finishMode = LZMA_FINISH_ANY;
72 ELzmaStatus status;
73 if (thereIsSize && outProcessed > unpackSize)
74 {
75 outProcessed = (SizeT)unpackSize;
76 finishMode = LZMA_FINISH_END;
77 }
78
79 res = LzmaDec_DecodeToBuf(state, outBuf + outPos, &outProcessed,
80 inBuf + inPos, &inProcessed, finishMode, &status);
81 inPos += inProcessed;
82 outPos += outProcessed;
83 unpackSize -= outProcessed;
84
85 if (outStream)
86 if (outStream->Write(outStream, outBuf, outPos) != outPos)
87 return SZ_ERROR_WRITE;
88
89 outPos = 0;
90
91 if (res != SZ_OK || (thereIsSize && unpackSize == 0))
92 return res;
93
94 if (inProcessed == 0 && outProcessed == 0)
95 {
96 if (thereIsSize || status != LZMA_STATUS_FINISHED_WITH_MARK)
97 return SZ_ERROR_DATA;
98 return res;
99 }
100 }
101 }
102}
103
104static SRes Decode(ISeqOutStream *outStream, ISeqInStream *inStream)
105{
106 UInt64 unpackSize;
107 int i;
108 SRes res = 0;
109
110 CLzmaDec state;
111
112 /* header: 5 bytes of LZMA properties and 8 bytes of uncompressed size */
113 unsigned char header[LZMA_PROPS_SIZE + 8];
114
115 /* Read and parse header */
116
117 RINOK(SeqInStream_Read(inStream, header, sizeof(header)));
118
119 unpackSize = 0;
120 for (i = 0; i < 8; i++)
121 unpackSize += (UInt64)header[LZMA_PROPS_SIZE + i] << (i * 8);
122
123 LzmaDec_Construct(&state);
124 RINOK(LzmaDec_Allocate(&state, header, LZMA_PROPS_SIZE, &g_Alloc));
125 res = Decode2(&state, outStream, inStream, unpackSize);
126 LzmaDec_Free(&state, &g_Alloc);
127 return res;
128}
129
130static SRes Encode(ISeqOutStream *outStream, ISeqInStream *inStream, UInt64 fileSize, char *rs)
131{
132 CLzmaEncHandle enc;
133 SRes res;
134 CLzmaEncProps props;
135
136 UNUSED_VAR(rs);
137
138 enc = LzmaEnc_Create(&g_Alloc);
139 if (enc == 0)
140 return SZ_ERROR_MEM;
141
142 LzmaEncProps_Init(&props);
143 res = LzmaEnc_SetProps(enc, &props);
144
145 if (res == SZ_OK)
146 {
147 Byte header[LZMA_PROPS_SIZE + 8];
148 size_t headerSize = LZMA_PROPS_SIZE;
149 int i;
150
151 res = LzmaEnc_WriteProperties(enc, header, &headerSize);
152 for (i = 0; i < 8; i++)
153 header[headerSize++] = (Byte)(fileSize >> (8 * i));
154 if (outStream->Write(outStream, header, headerSize) != headerSize)
155 res = SZ_ERROR_WRITE;
156 else
157 {
158 if (res == SZ_OK)
159 res = LzmaEnc_Encode(enc, outStream, inStream, NULL, &g_Alloc, &g_Alloc);
160 }
161 }
162 LzmaEnc_Destroy(enc, &g_Alloc, &g_Alloc);
163 return res;
164}
165
166int main2(int numArgs, const char *args[], char *rs)
167{
168 CFileSeqInStream inStream;
169 CFileOutStream outStream;
170 char c;
171 int res;
172 int encodeMode;
173 Bool useOutFile = False;
174
175 FileSeqInStream_CreateVTable(&inStream);
176 File_Construct(&inStream.file);
177
178 FileOutStream_CreateVTable(&outStream);
179 File_Construct(&outStream.file);
180
181 if (numArgs == 1)
182 {
183 PrintHelp(rs);
184 return 0;
185 }
186
187 if (numArgs < 3 || numArgs > 4 || strlen(args[1]) != 1)
188 return PrintUserError(rs);
189
190 c = args[1][0];
191 encodeMode = (c == 'e' || c == 'E');
192 if (!encodeMode && c != 'd' && c != 'D')
193 return PrintUserError(rs);
194
195 {
196 size_t t4 = sizeof(UInt32);
197 size_t t8 = sizeof(UInt64);
198 if (t4 != 4 || t8 != 8)
199 return PrintError(rs, "Incorrect UInt32 or UInt64");
200 }
201
202 if (InFile_Open(&inStream.file, args[2]) != 0)
203 return PrintError(rs, "Can not open input file");
204
205 if (numArgs > 3)
206 {
207 useOutFile = True;
208 if (OutFile_Open(&outStream.file, args[3]) != 0)
209 return PrintError(rs, "Can not open output file");
210 }
211 else if (encodeMode)
212 PrintUserError(rs);
213
214 if (encodeMode)
215 {
216 UInt64 fileSize;
217 File_GetLength(&inStream.file, &fileSize);
218 res = Encode(&outStream.s, &inStream.s, fileSize, rs);
219 }
220 else
221 {
222 res = Decode(&outStream.s, useOutFile ? &inStream.s : NULL);
223 }
224
225 if (useOutFile)
226 File_Close(&outStream.file);
227 File_Close(&inStream.file);
228
229 if (res != SZ_OK)
230 {
231 if (res == SZ_ERROR_MEM)
232 return PrintError(rs, kCantAllocateMessage);
233 else if (res == SZ_ERROR_DATA)
234 return PrintError(rs, kDataErrorMessage);
235 else if (res == SZ_ERROR_WRITE)
236 return PrintError(rs, kCantWriteMessage);
237 else if (res == SZ_ERROR_READ)
238 return PrintError(rs, kCantReadMessage);
239 return PrintErrorNumber(rs, res);
240 }
241 return 0;
242}
243
244int MY_CDECL main(int numArgs, const char *args[])
245{
246 char rs[800] = { 0 };
247 int res = main2(numArgs, args, rs);
248 fputs(rs, stdout);
249 return res;
250}