aboutsummaryrefslogtreecommitdiff
path: root/C/Util/Lzma/LzmaUtil.c
diff options
context:
space:
mode:
Diffstat (limited to 'C/Util/Lzma/LzmaUtil.c')
-rw-r--r--C/Util/Lzma/LzmaUtil.c286
1 files changed, 286 insertions, 0 deletions
diff --git a/C/Util/Lzma/LzmaUtil.c b/C/Util/Lzma/LzmaUtil.c
new file mode 100644
index 0000000..62a5907
--- /dev/null
+++ b/C/Util/Lzma/LzmaUtil.c
@@ -0,0 +1,286 @@
1/* LzmaUtil.c -- Test application for LZMA compression
22021-11-01 : 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 "../../CpuArch.h"
11
12#include "../../Alloc.h"
13#include "../../7zFile.h"
14#include "../../7zVersion.h"
15#include "../../LzFind.h"
16#include "../../LzmaDec.h"
17#include "../../LzmaEnc.h"
18
19static const char * const kCantReadMessage = "Cannot read input file";
20static const char * const kCantWriteMessage = "Cannot write output file";
21static const char * const kCantAllocateMessage = "Cannot allocate memory";
22static const char * const kDataErrorMessage = "Data error";
23
24static void PrintHelp(char *buffer)
25{
26 strcat(buffer,
27 "\nLZMA-C " MY_VERSION_CPU " : " MY_COPYRIGHT_DATE "\n\n"
28 "Usage: lzma <e|d> inputFile outputFile\n"
29 " e: encode file\n"
30 " d: decode file\n");
31}
32
33static int PrintError(char *buffer, const char *message)
34{
35 strcat(buffer, "\nError: ");
36 strcat(buffer, message);
37 strcat(buffer, "\n");
38 return 1;
39}
40
41static int PrintError_WRes(char *buffer, const char *message, WRes wres)
42{
43 strcat(buffer, "\nError: ");
44 strcat(buffer, message);
45 sprintf(buffer + strlen(buffer), "\nSystem error code: %d", (unsigned)wres);
46 #ifndef _WIN32
47 {
48 const char *s = strerror(wres);
49 if (s)
50 sprintf(buffer + strlen(buffer), " : %s", s);
51 }
52 #endif
53 strcat(buffer, "\n");
54 return 1;
55}
56
57static int PrintErrorNumber(char *buffer, SRes val)
58{
59 sprintf(buffer + strlen(buffer), "\n7-Zip error code: %d\n", (unsigned)val);
60 return 1;
61}
62
63static int PrintUserError(char *buffer)
64{
65 return PrintError(buffer, "Incorrect command");
66}
67
68
69#define IN_BUF_SIZE (1 << 16)
70#define OUT_BUF_SIZE (1 << 16)
71
72
73static SRes Decode2(CLzmaDec *state, ISeqOutStream *outStream, ISeqInStream *inStream,
74 UInt64 unpackSize)
75{
76 int thereIsSize = (unpackSize != (UInt64)(Int64)-1);
77 Byte inBuf[IN_BUF_SIZE];
78 Byte outBuf[OUT_BUF_SIZE];
79 size_t inPos = 0, inSize = 0, outPos = 0;
80 LzmaDec_Init(state);
81 for (;;)
82 {
83 if (inPos == inSize)
84 {
85 inSize = IN_BUF_SIZE;
86 RINOK(inStream->Read(inStream, inBuf, &inSize));
87 inPos = 0;
88 }
89 {
90 SRes res;
91 SizeT inProcessed = inSize - inPos;
92 SizeT outProcessed = OUT_BUF_SIZE - outPos;
93 ELzmaFinishMode finishMode = LZMA_FINISH_ANY;
94 ELzmaStatus status;
95 if (thereIsSize && outProcessed > unpackSize)
96 {
97 outProcessed = (SizeT)unpackSize;
98 finishMode = LZMA_FINISH_END;
99 }
100
101 res = LzmaDec_DecodeToBuf(state, outBuf + outPos, &outProcessed,
102 inBuf + inPos, &inProcessed, finishMode, &status);
103 inPos += inProcessed;
104 outPos += outProcessed;
105 unpackSize -= outProcessed;
106
107 if (outStream)
108 if (outStream->Write(outStream, outBuf, outPos) != outPos)
109 return SZ_ERROR_WRITE;
110
111 outPos = 0;
112
113 if (res != SZ_OK || (thereIsSize && unpackSize == 0))
114 return res;
115
116 if (inProcessed == 0 && outProcessed == 0)
117 {
118 if (thereIsSize || status != LZMA_STATUS_FINISHED_WITH_MARK)
119 return SZ_ERROR_DATA;
120 return res;
121 }
122 }
123 }
124}
125
126
127static SRes Decode(ISeqOutStream *outStream, ISeqInStream *inStream)
128{
129 UInt64 unpackSize;
130 int i;
131 SRes res = 0;
132
133 CLzmaDec state;
134
135 /* header: 5 bytes of LZMA properties and 8 bytes of uncompressed size */
136 unsigned char header[LZMA_PROPS_SIZE + 8];
137
138 /* Read and parse header */
139
140 RINOK(SeqInStream_Read(inStream, header, sizeof(header)));
141
142 unpackSize = 0;
143 for (i = 0; i < 8; i++)
144 unpackSize += (UInt64)header[LZMA_PROPS_SIZE + i] << (i * 8);
145
146 LzmaDec_Construct(&state);
147 RINOK(LzmaDec_Allocate(&state, header, LZMA_PROPS_SIZE, &g_Alloc));
148 res = Decode2(&state, outStream, inStream, unpackSize);
149 LzmaDec_Free(&state, &g_Alloc);
150 return res;
151}
152
153static SRes Encode(ISeqOutStream *outStream, ISeqInStream *inStream, UInt64 fileSize, char *rs)
154{
155 CLzmaEncHandle enc;
156 SRes res;
157 CLzmaEncProps props;
158
159 UNUSED_VAR(rs);
160
161 enc = LzmaEnc_Create(&g_Alloc);
162 if (enc == 0)
163 return SZ_ERROR_MEM;
164
165 LzmaEncProps_Init(&props);
166 res = LzmaEnc_SetProps(enc, &props);
167
168 if (res == SZ_OK)
169 {
170 Byte header[LZMA_PROPS_SIZE + 8];
171 size_t headerSize = LZMA_PROPS_SIZE;
172 int i;
173
174 res = LzmaEnc_WriteProperties(enc, header, &headerSize);
175 for (i = 0; i < 8; i++)
176 header[headerSize++] = (Byte)(fileSize >> (8 * i));
177 if (outStream->Write(outStream, header, headerSize) != headerSize)
178 res = SZ_ERROR_WRITE;
179 else
180 {
181 if (res == SZ_OK)
182 res = LzmaEnc_Encode(enc, outStream, inStream, NULL, &g_Alloc, &g_Alloc);
183 }
184 }
185 LzmaEnc_Destroy(enc, &g_Alloc, &g_Alloc);
186 return res;
187}
188
189
190static int main2(int numArgs, const char *args[], char *rs)
191{
192 CFileSeqInStream inStream;
193 CFileOutStream outStream;
194 char c;
195 int res;
196 int encodeMode;
197 BoolInt useOutFile = False;
198
199 LzFindPrepare();
200
201 FileSeqInStream_CreateVTable(&inStream);
202 File_Construct(&inStream.file);
203 inStream.wres = 0;
204
205 FileOutStream_CreateVTable(&outStream);
206 File_Construct(&outStream.file);
207 outStream.wres = 0;
208
209 if (numArgs == 1)
210 {
211 PrintHelp(rs);
212 return 0;
213 }
214
215 if (numArgs < 3 || numArgs > 4 || strlen(args[1]) != 1)
216 return PrintUserError(rs);
217
218 c = args[1][0];
219 encodeMode = (c == 'e' || c == 'E');
220 if (!encodeMode && c != 'd' && c != 'D')
221 return PrintUserError(rs);
222
223 {
224 size_t t4 = sizeof(UInt32);
225 size_t t8 = sizeof(UInt64);
226 if (t4 != 4 || t8 != 8)
227 return PrintError(rs, "Incorrect UInt32 or UInt64");
228 }
229
230 {
231 WRes wres = InFile_Open(&inStream.file, args[2]);
232 if (wres != 0)
233 return PrintError_WRes(rs, "Cannot open input file", wres);
234 }
235
236 if (numArgs > 3)
237 {
238 WRes wres;
239 useOutFile = True;
240 wres = OutFile_Open(&outStream.file, args[3]);
241 if (wres != 0)
242 return PrintError_WRes(rs, "Cannot open output file", wres);
243 }
244 else if (encodeMode)
245 PrintUserError(rs);
246
247 if (encodeMode)
248 {
249 UInt64 fileSize;
250 WRes wres = File_GetLength(&inStream.file, &fileSize);
251 if (wres != 0)
252 return PrintError_WRes(rs, "Cannot get file length", wres);
253 res = Encode(&outStream.vt, &inStream.vt, fileSize, rs);
254 }
255 else
256 {
257 res = Decode(&outStream.vt, useOutFile ? &inStream.vt : NULL);
258 }
259
260 if (useOutFile)
261 File_Close(&outStream.file);
262 File_Close(&inStream.file);
263
264 if (res != SZ_OK)
265 {
266 if (res == SZ_ERROR_MEM)
267 return PrintError(rs, kCantAllocateMessage);
268 else if (res == SZ_ERROR_DATA)
269 return PrintError(rs, kDataErrorMessage);
270 else if (res == SZ_ERROR_WRITE)
271 return PrintError_WRes(rs, kCantWriteMessage, outStream.wres);
272 else if (res == SZ_ERROR_READ)
273 return PrintError_WRes(rs, kCantReadMessage, inStream.wres);
274 return PrintErrorNumber(rs, res);
275 }
276 return 0;
277}
278
279
280int MY_CDECL main(int numArgs, const char *args[])
281{
282 char rs[1000] = { 0 };
283 int res = main2(numArgs, args, rs);
284 fputs(rs, stdout);
285 return res;
286}