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"
30 #include "CommonLib.h"
32 const char *kCantReadMessage
= "Can not read input file";
33 const char *kCantWriteMessage
= "Can not write output file";
34 const char *kCantAllocateMessage
= "Can not allocate memory";
35 const char *kDataErrorMessage
= "Data error";
37 static void *SzAlloc(void *p
, size_t size
) { p
= p
; return MyAlloc(size
); }
38 static void SzFree(void *p
, void *address
) { p
= p
; MyFree(address
); }
39 static ISzAlloc g_Alloc
= { SzAlloc
, SzFree
};
41 static Bool mQuietMode
= False
;
43 #define UTILITY_NAME "LzmaCompress"
44 #define UTILITY_MAJOR_VERSION 0
45 #define UTILITY_MINOR_VERSION 1
46 #define INTEL_COPYRIGHT \
47 "Copyright (c) 2009, Intel Corporation. All rights reserved."
48 void PrintHelp(char *buffer
)
51 "\n" UTILITY_NAME
" - " INTEL_COPYRIGHT
"\n"
52 "Based on LZMA Utility " MY_VERSION_COPYRIGHT_DATE
"\n"
53 "\nUsage: LzmaCompress -e|-d [options] <inputFile>\n"
56 " -o FileName, --output FileName: specify the output filename\n"
57 " -v, --verbose: increase output messages\n"
58 " -q, --quiet: reduce output messages\n"
59 " --debug [0-9]: set debug level\n"
60 " --version: display the program version and exit\n"
61 " -h, --help: display this help text\n"
65 int PrintError(char *buffer
, const char *message
)
67 strcat(buffer
, "\nError: ");
68 strcat(buffer
, message
);
73 int PrintErrorNumber(char *buffer
, SRes val
)
75 sprintf(buffer
+ strlen(buffer
), "\nError code: %x\n", (unsigned)val
);
79 int PrintUserError(char *buffer
)
81 return PrintError(buffer
, "Incorrect command");
84 void PrintVersion(char *buffer
)
86 sprintf (buffer
, "%s Version %d.%d %s ", UTILITY_NAME
, UTILITY_MAJOR_VERSION
, UTILITY_MINOR_VERSION
, __BUILD_VERSION
);
89 #define IN_BUF_SIZE (1 << 16)
90 #define OUT_BUF_SIZE (1 << 16)
92 static SRes
Decode2(CLzmaDec
*state
, ISeqOutStream
*outStream
, ISeqInStream
*inStream
,
95 int thereIsSize
= (unpackSize
!= (UInt64
)(Int64
)-1);
96 Byte inBuf
[IN_BUF_SIZE
];
97 Byte outBuf
[OUT_BUF_SIZE
];
98 size_t inPos
= 0, inSize
= 0, outPos
= 0;
104 inSize
= IN_BUF_SIZE
;
105 RINOK(inStream
->Read(inStream
, inBuf
, &inSize
));
110 SizeT inProcessed
= inSize
- inPos
;
111 SizeT outProcessed
= OUT_BUF_SIZE
- outPos
;
112 ELzmaFinishMode finishMode
= LZMA_FINISH_ANY
;
114 if (thereIsSize
&& outProcessed
> unpackSize
)
116 outProcessed
= (SizeT
)unpackSize
;
117 finishMode
= LZMA_FINISH_END
;
120 res
= LzmaDec_DecodeToBuf(state
, outBuf
+ outPos
, &outProcessed
,
121 inBuf
+ inPos
, &inProcessed
, finishMode
, &status
);
122 inPos
+= inProcessed
;
123 outPos
+= outProcessed
;
124 unpackSize
-= outProcessed
;
127 if (outStream
->Write(outStream
, outBuf
, outPos
) != outPos
)
128 return SZ_ERROR_WRITE
;
132 if (res
!= SZ_OK
|| (thereIsSize
&& unpackSize
== 0))
135 if (inProcessed
== 0 && outProcessed
== 0)
137 if (thereIsSize
|| status
!= LZMA_STATUS_FINISHED_WITH_MARK
)
138 return SZ_ERROR_DATA
;
145 static SRes
Decode(ISeqOutStream
*outStream
, ISeqInStream
*inStream
)
153 /* header: 5 bytes of LZMA properties and 8 bytes of uncompressed size */
154 unsigned char header
[LZMA_PROPS_SIZE
+ 8];
156 /* Read and parse header */
158 RINOK(SeqInStream_Read(inStream
, header
, sizeof(header
)));
161 for (i
= 0; i
< 8; i
++)
162 unpackSize
+= (UInt64
)header
[LZMA_PROPS_SIZE
+ i
] << (i
* 8);
164 LzmaDec_Construct(&state
);
165 RINOK(LzmaDec_Allocate(&state
, header
, LZMA_PROPS_SIZE
, &g_Alloc
));
166 res
= Decode2(&state
, outStream
, inStream
, unpackSize
);
167 LzmaDec_Free(&state
, &g_Alloc
);
171 static SRes
Encode(ISeqOutStream
*outStream
, ISeqInStream
*inStream
, UInt64 fileSize
, char *rs
)
179 enc
= LzmaEnc_Create(&g_Alloc
);
183 LzmaEncProps_Init(&props
);
184 res
= LzmaEnc_SetProps(enc
, &props
);
188 Byte header
[LZMA_PROPS_SIZE
+ 8];
189 size_t headerSize
= LZMA_PROPS_SIZE
;
192 res
= LzmaEnc_WriteProperties(enc
, header
, &headerSize
);
193 for (i
= 0; i
< 8; i
++)
194 header
[headerSize
++] = (Byte
)(fileSize
>> (8 * i
));
195 if (outStream
->Write(outStream
, header
, headerSize
) != headerSize
)
196 res
= SZ_ERROR_WRITE
;
200 res
= LzmaEnc_Encode(enc
, outStream
, inStream
, NULL
, &g_Alloc
, &g_Alloc
);
203 LzmaEnc_Destroy(enc
, &g_Alloc
, &g_Alloc
);
207 int main2(int numArgs
, const char *args
[], char *rs
)
209 CFileSeqInStream inStream
;
210 CFileOutStream outStream
;
213 Bool modeWasSet
= False
;
214 const char *inputFile
= NULL
;
215 const char *outputFile
= "file.tmp";
218 FileSeqInStream_CreateVTable(&inStream
);
219 File_Construct(&inStream
.file
);
221 FileOutStream_CreateVTable(&outStream
);
222 File_Construct(&outStream
.file
);
230 for (param
= 1; param
< numArgs
; param
++) {
231 if (strcmp(args
[param
], "-e") == 0 || strcmp(args
[param
], "-d") == 0) {
232 encodeMode
= (args
[param
][1] == 'e');
234 } else if (strcmp(args
[param
], "-o") == 0 ||
235 strcmp(args
[param
], "--output") == 0) {
236 if (numArgs
< (param
+ 2)) {
237 return PrintUserError(rs
);
239 outputFile
= args
[++param
];
240 } else if (strcmp(args
[param
], "--debug") == 0) {
241 if (numArgs
< (param
+ 2)) {
242 return PrintUserError(rs
);
245 // For now we silently ignore this parameter to achieve command line
246 // parameter compatibility with other build tools.
250 strcmp(args
[param
], "-h") == 0 ||
251 strcmp(args
[param
], "--help") == 0
256 strcmp(args
[param
], "-v") == 0 ||
257 strcmp(args
[param
], "--verbose") == 0
260 // For now we silently ignore this parameter to achieve command line
261 // parameter compatibility with other build tools.
264 strcmp(args
[param
], "-q") == 0 ||
265 strcmp(args
[param
], "--quiet") == 0
268 } else if (strcmp(args
[param
], "--version") == 0) {
271 } else if (inputFile
== NULL
) {
272 inputFile
= args
[param
];
274 return PrintUserError(rs
);
278 if ((inputFile
== NULL
) || !modeWasSet
) {
279 return PrintUserError(rs
);
283 size_t t4
= sizeof(UInt32
);
284 size_t t8
= sizeof(UInt64
);
285 if (t4
!= 4 || t8
!= 8)
286 return PrintError(rs
, "Incorrect UInt32 or UInt64");
289 if (InFile_Open(&inStream
.file
, inputFile
) != 0)
290 return PrintError(rs
, "Can not open input file");
292 if (OutFile_Open(&outStream
.file
, outputFile
) != 0)
293 return PrintError(rs
, "Can not open output file");
298 File_GetLength(&inStream
.file
, &fileSize
);
300 printf("Encoding\n");
302 res
= Encode(&outStream
.s
, &inStream
.s
, fileSize
, rs
);
307 printf("Decoding\n");
309 res
= Decode(&outStream
.s
, &inStream
.s
);
312 File_Close(&outStream
.file
);
313 File_Close(&inStream
.file
);
317 if (res
== SZ_ERROR_MEM
)
318 return PrintError(rs
, kCantAllocateMessage
);
319 else if (res
== SZ_ERROR_DATA
)
320 return PrintError(rs
, kDataErrorMessage
);
321 else if (res
== SZ_ERROR_WRITE
)
322 return PrintError(rs
, kCantWriteMessage
);
323 else if (res
== SZ_ERROR_READ
)
324 return PrintError(rs
, kCantReadMessage
);
325 return PrintErrorNumber(rs
, res
);
330 int MY_CDECL
main(int numArgs
, const char *args
[])
332 char rs
[2000] = { 0 };
333 int res
= main2(numArgs
, args
, rs
);
334 if (strlen(rs
) > 0) {