2 LZMA Compress/Decompress tool (LzmaCompress)
4 Based on LZMA SDK 4.65:
5 LzmaUtil.c -- Test application for LZMA compression
6 2008-11-23 : Igor Pavlov : Public domain
8 Copyright (c) 2006 - 2009, 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
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.
19 #define _CRT_SECURE_NO_WARNINGS
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"
31 const char *kCantReadMessage
= "Can not read input file";
32 const char *kCantWriteMessage
= "Can not write output file";
33 const char *kCantAllocateMessage
= "Can not allocate memory";
34 const char *kDataErrorMessage
= "Data error";
36 static void *SzAlloc(void *p
, size_t size
) { p
= p
; return MyAlloc(size
); }
37 static void SzFree(void *p
, void *address
) { p
= p
; MyFree(address
); }
38 static ISzAlloc g_Alloc
= { SzAlloc
, SzFree
};
40 static Bool mQuietMode
= False
;
42 #define UTILITY_NAME "LzmaCompress"
43 #define UTILITY_MAJOR_VERSION 0
44 #define UTILITY_MINOR_VERSION 1
45 #define INTEL_COPYRIGHT \
46 "Copyright (c) 2009, Intel Corporation. All rights reserved."
47 void PrintHelp(char *buffer
)
50 "\n" UTILITY_NAME
" - " INTEL_COPYRIGHT
"\n"
51 "Based on LZMA Utility " MY_VERSION_COPYRIGHT_DATE
"\n"
52 "\nUsage: LzmaCompress -e|-d [options] <inputFile>\n"
55 " -o FileName, --output FileName: specify the output filename\n"
56 " -v, --verbose: increase output messages\n"
57 " -q, --quiet: reduce output messages\n"
58 " --debug [0-9]: set debug level\n"
59 " --version: display the program version and exit\n"
60 " -h, --help: display this help text\n"
64 int PrintError(char *buffer
, const char *message
)
66 strcat(buffer
, "\nError: ");
67 strcat(buffer
, message
);
72 int PrintErrorNumber(char *buffer
, SRes val
)
74 sprintf(buffer
+ strlen(buffer
), "\nError code: %x\n", (unsigned)val
);
78 int PrintUserError(char *buffer
)
80 return PrintError(buffer
, "Incorrect command");
83 void PrintVersion(char *buffer
)
85 sprintf (buffer
, "%s Version %d.%d", UTILITY_NAME
, UTILITY_MAJOR_VERSION
, UTILITY_MINOR_VERSION
);
88 #define IN_BUF_SIZE (1 << 16)
89 #define OUT_BUF_SIZE (1 << 16)
91 static SRes
Decode2(CLzmaDec
*state
, ISeqOutStream
*outStream
, ISeqInStream
*inStream
,
94 int thereIsSize
= (unpackSize
!= (UInt64
)(Int64
)-1);
95 Byte inBuf
[IN_BUF_SIZE
];
96 Byte outBuf
[OUT_BUF_SIZE
];
97 size_t inPos
= 0, inSize
= 0, outPos
= 0;
103 inSize
= IN_BUF_SIZE
;
104 RINOK(inStream
->Read(inStream
, inBuf
, &inSize
));
109 SizeT inProcessed
= inSize
- inPos
;
110 SizeT outProcessed
= OUT_BUF_SIZE
- outPos
;
111 ELzmaFinishMode finishMode
= LZMA_FINISH_ANY
;
113 if (thereIsSize
&& outProcessed
> unpackSize
)
115 outProcessed
= (SizeT
)unpackSize
;
116 finishMode
= LZMA_FINISH_END
;
119 res
= LzmaDec_DecodeToBuf(state
, outBuf
+ outPos
, &outProcessed
,
120 inBuf
+ inPos
, &inProcessed
, finishMode
, &status
);
121 inPos
+= inProcessed
;
122 outPos
+= outProcessed
;
123 unpackSize
-= outProcessed
;
126 if (outStream
->Write(outStream
, outBuf
, outPos
) != outPos
)
127 return SZ_ERROR_WRITE
;
131 if (res
!= SZ_OK
|| (thereIsSize
&& unpackSize
== 0))
134 if (inProcessed
== 0 && outProcessed
== 0)
136 if (thereIsSize
|| status
!= LZMA_STATUS_FINISHED_WITH_MARK
)
137 return SZ_ERROR_DATA
;
144 static SRes
Decode(ISeqOutStream
*outStream
, ISeqInStream
*inStream
)
152 /* header: 5 bytes of LZMA properties and 8 bytes of uncompressed size */
153 unsigned char header
[LZMA_PROPS_SIZE
+ 8];
155 /* Read and parse header */
157 RINOK(SeqInStream_Read(inStream
, header
, sizeof(header
)));
160 for (i
= 0; i
< 8; i
++)
161 unpackSize
+= (UInt64
)header
[LZMA_PROPS_SIZE
+ i
] << (i
* 8);
163 LzmaDec_Construct(&state
);
164 RINOK(LzmaDec_Allocate(&state
, header
, LZMA_PROPS_SIZE
, &g_Alloc
));
165 res
= Decode2(&state
, outStream
, inStream
, unpackSize
);
166 LzmaDec_Free(&state
, &g_Alloc
);
170 static SRes
Encode(ISeqOutStream
*outStream
, ISeqInStream
*inStream
, UInt64 fileSize
, char *rs
)
178 enc
= LzmaEnc_Create(&g_Alloc
);
182 LzmaEncProps_Init(&props
);
183 res
= LzmaEnc_SetProps(enc
, &props
);
187 Byte header
[LZMA_PROPS_SIZE
+ 8];
188 size_t headerSize
= LZMA_PROPS_SIZE
;
191 res
= LzmaEnc_WriteProperties(enc
, header
, &headerSize
);
192 for (i
= 0; i
< 8; i
++)
193 header
[headerSize
++] = (Byte
)(fileSize
>> (8 * i
));
194 if (outStream
->Write(outStream
, header
, headerSize
) != headerSize
)
195 res
= SZ_ERROR_WRITE
;
199 res
= LzmaEnc_Encode(enc
, outStream
, inStream
, NULL
, &g_Alloc
, &g_Alloc
);
202 LzmaEnc_Destroy(enc
, &g_Alloc
, &g_Alloc
);
206 int main2(int numArgs
, const char *args
[], char *rs
)
208 CFileSeqInStream inStream
;
209 CFileOutStream outStream
;
212 Bool modeWasSet
= False
;
213 const char *inputFile
= NULL
;
214 const char *outputFile
= "file.tmp";
217 FileSeqInStream_CreateVTable(&inStream
);
218 File_Construct(&inStream
.file
);
220 FileOutStream_CreateVTable(&outStream
);
221 File_Construct(&outStream
.file
);
229 for (param
= 1; param
< numArgs
; param
++) {
230 if (strcmp(args
[param
], "-e") == 0 || strcmp(args
[param
], "-d") == 0) {
231 encodeMode
= (args
[param
][1] == 'e');
233 } else if (strcmp(args
[param
], "-o") == 0 ||
234 strcmp(args
[param
], "--output") == 0) {
235 if (numArgs
< (param
+ 2)) {
236 return PrintUserError(rs
);
238 outputFile
= args
[++param
];
239 } else if (strcmp(args
[param
], "--debug") == 0) {
240 if (numArgs
< (param
+ 2)) {
241 return PrintUserError(rs
);
244 // For now we silently ignore this parameter to achieve command line
245 // parameter compatibility with other build tools.
249 strcmp(args
[param
], "-h") == 0 ||
250 strcmp(args
[param
], "--help") == 0
255 strcmp(args
[param
], "-v") == 0 ||
256 strcmp(args
[param
], "--verbose") == 0
259 // For now we silently ignore this parameter to achieve command line
260 // parameter compatibility with other build tools.
263 strcmp(args
[param
], "-q") == 0 ||
264 strcmp(args
[param
], "--quiet") == 0
267 } else if (strcmp(args
[param
], "--version") == 0) {
270 } else if (inputFile
== NULL
) {
271 inputFile
= args
[param
];
273 return PrintUserError(rs
);
277 if ((inputFile
== NULL
) || !modeWasSet
) {
278 return PrintUserError(rs
);
282 size_t t4
= sizeof(UInt32
);
283 size_t t8
= sizeof(UInt64
);
284 if (t4
!= 4 || t8
!= 8)
285 return PrintError(rs
, "Incorrect UInt32 or UInt64");
288 if (InFile_Open(&inStream
.file
, inputFile
) != 0)
289 return PrintError(rs
, "Can not open input file");
291 if (OutFile_Open(&outStream
.file
, outputFile
) != 0)
292 return PrintError(rs
, "Can not open output file");
297 File_GetLength(&inStream
.file
, &fileSize
);
299 printf("Encoding\n");
301 res
= Encode(&outStream
.s
, &inStream
.s
, fileSize
, rs
);
306 printf("Decoding\n");
308 res
= Decode(&outStream
.s
, &inStream
.s
);
311 File_Close(&outStream
.file
);
312 File_Close(&inStream
.file
);
316 if (res
== SZ_ERROR_MEM
)
317 return PrintError(rs
, kCantAllocateMessage
);
318 else if (res
== SZ_ERROR_DATA
)
319 return PrintError(rs
, kDataErrorMessage
);
320 else if (res
== SZ_ERROR_WRITE
)
321 return PrintError(rs
, kCantWriteMessage
);
322 else if (res
== SZ_ERROR_READ
)
323 return PrintError(rs
, kCantReadMessage
);
324 return PrintErrorNumber(rs
, res
);
329 int MY_CDECL
main(int numArgs
, const char *args
[])
331 char rs
[2000] = { 0 };
332 int res
= main2(numArgs
, args
, rs
);
333 if (strlen(rs
) > 0) {