2 * decompressfile.c - decompression API example
4 * The following copying information applies to this specific source code file:
6 * Written in 2014-2016 by Eric Biggers <ebiggers3@gmail.com>
8 * To the extent possible under law, the author(s) have dedicated all copyright
9 * and related and neighboring rights to this software to the public domain
10 * worldwide via the Creative Commons Zero 1.0 Universal Public Domain
11 * Dedication (the "CC0").
13 * This software is distributed in the hope that it will be useful, but WITHOUT
14 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
15 * FOR A PARTICULAR PURPOSE. See the CC0 for more details.
17 * You should have received a copy of the CC0 along with this software; if not
18 * see <http://creativecommons.org/publicdomain/zero/1.0/>.
22 * This an example of using wimlib's compression API to decompress a file
23 * compressed with the compressfile.c program.
25 * This program does *not* have anything to do with WIM files other than the
26 * fact that this makes use of compression formats that are used in WIM files.
27 * This is purely an example of using the compression API.
31 * $ gcc decompressfile.c -o decompressfile -lwim
35 * $ ./decompressfile INFILE OUTFILE
39 * $ ./compressfile book.txt book.txt.lzms LZMS 1048576
41 * $ ./decompressfile book.txt.lzms book.txt
43 * The compressed file format created here is simply a series of compressed
44 * chunks. A real format would need to have checksums and other metadata.
47 #define _FILE_OFFSET_BITS 64
49 #if defined(_MSC_VER) && _MSC_VER < 1800 /* VS pre-2013? */
50 # define PRIu64 "I64u"
53 # define __STDC_FORMAT_MACROS 1
54 # include <inttypes.h>
71 * Windows compatibility defines for string encoding. Applications using wimlib
72 * that need to run on both UNIX and Windows will need to do something similar
73 * to this, whereas applications that only need to run on one or the other can
74 * just use their platform's convention directly.
78 typedef wchar_t tchar;
89 fatal_error(int err, const char *format, ...)
94 vfprintf(stderr, format, va);
96 fprintf(stderr, ": %s\n", strerror(err));
104 do_decompress(int in_fd, const tchar *in_filename,
105 int out_fd, const tchar *out_filename,
106 uint32_t chunk_size, struct wimlib_decompressor *decompressor)
110 char *ubuf = (char *)malloc(chunk_size);
111 char *cbuf = (char *)malloc(chunk_size - 1);
113 for (chunk_num = 1; ; chunk_num++) {
118 /* Read chunk uncompressed and compressed sizes. */
119 bytes_read = read(in_fd, &usize, sizeof(uint32_t));
123 if (bytes_read != sizeof(uint32_t) ||
124 read(in_fd, &csize, sizeof(uint32_t)) != sizeof(uint32_t))
126 fatal_error(errno, "Error reading \"%" TS"\"",
130 if (csize > usize || usize > chunk_size)
131 fatal_error(0, "The data is invalid!");
133 if (usize == csize) {
134 if (read(in_fd, ubuf, usize) != (int32_t)usize) {
135 fatal_error(errno, "Error reading \"%" TS"\"",
139 if (read(in_fd, cbuf, csize) != (int32_t)csize) {
140 fatal_error(errno, "Error reading \"%" TS"\"",
144 if (wimlib_decompress(cbuf, csize, ubuf, usize,
148 "The compressed data is invalid!");
152 printf("Chunk %" PRIu64": %" PRIu32" => %" PRIu32" bytes\n",
153 chunk_num, csize, usize);
155 /* Output the uncompressed chunk size, the compressed chunk
156 * size, then the chunk data. Note: a real program would need
157 * to output the chunk sizes in consistent endianness. */
158 if (write(out_fd, ubuf, usize) != (int32_t)usize) {
159 fatal_error(errno, "Error writing to \"%" TS"\"",
167 int main(int argc, tchar **argv)
169 const tchar *in_filename;
170 const tchar *out_filename;
174 enum wimlib_compression_type ctype;
177 struct wimlib_decompressor *decompressor;
180 fprintf(stderr, "Usage: %" TS" INFILE OUTFILE\n", argv[0]);
184 in_filename = argv[1];
185 out_filename = argv[2];
187 /* Open input file and output file. */
188 in_fd = topen(in_filename, O_RDONLY | O_BINARY);
190 fatal_error(errno, "Failed to open \"%" TS"\"", in_filename);
191 out_fd = topen(out_filename, O_WRONLY | O_TRUNC | O_CREAT | O_BINARY,
194 fatal_error(errno, "Failed to open \"%" TS"\"", out_filename);
196 /* Get compression type and chunk size. */
197 if (read(in_fd, &ctype32, sizeof(uint32_t)) != sizeof(uint32_t) ||
198 read(in_fd, &chunk_size, sizeof(uint32_t)) != sizeof(uint32_t))
199 fatal_error(errno, "Error reading from \"%" TS"\"", in_filename);
200 ctype = (enum wimlib_compression_type)ctype32;
202 /* Create a decompressor for the compression type and chunk size with
203 * the default parameters. */
204 ret = wimlib_create_decompressor(ctype, chunk_size, &decompressor);
206 fatal_error(0, "Failed to create decompressor: %" TS,
207 wimlib_get_error_string((enum wimlib_error_code)ret));
209 /* Decompress and write the data. */
210 do_decompress(in_fd, in_filename,
211 out_fd, out_filename,
212 chunk_size, decompressor);
214 /* Cleanup and return. */
216 fatal_error(errno, "Error closing \"%" TS"\"", out_filename);
217 wimlib_free_decompressor(decompressor);