2 * compressfile.c - compression API example
4 * The following copying information applies to this specific source code file:
6 * Written in 2014 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 compress a file.
24 * This program does *not* have anything to do with WIM files other than the
25 * fact that this makes use of compression formats that are used in WIM files.
26 * This is purely an example of using the compression API.
30 * $ gcc compressfile.c -o compressfile -lwim
34 * $ ./compressfile INFILE OUTFILE [LZX | XPRESS | LZMS] [chunk size]
37 * Use the decompressfile.c program to decompress the file.
41 * $ ./compressfile book.txt book.txt.lzms LZMS 1048576
43 * $ ./decompressfile book.txt.lzms book.txt
45 * The compressed file format created here is simply a series of compressed
46 * chunks. A real format would need to have checksums and other metadata.
50 #define _FILE_OFFSET_BITS 64
63 do_compress(int in_fd, const char *in_filename,
64 int out_fd, const char *out_filename,
65 uint32_t chunk_size, struct wimlib_compressor *compressor)
67 char *ubuf = malloc(chunk_size);
68 char *cbuf = malloc(chunk_size - 1);
71 for (chunk_num = 1; ; chunk_num++) {
78 /* Read next chunk of data to compress. */
79 bytes_read = read(in_fd, ubuf, chunk_size);
80 if (bytes_read <= 0) {
83 error(1, errno, "Error reading \"%s\"", in_filename);
86 /* Compress the chunk. */
89 csize = wimlib_compress(ubuf, usize, cbuf, usize - 1, compressor);
91 /* Chunk was compressed; use the compressed data. */
95 /* Chunk did not compress to less than original size;
96 * use the uncompressed data. */
101 printf("Chunk %"PRIu64": %"PRIu32" => %"PRIu32" bytes\n",
102 chunk_num, usize, out_size);
104 /* Output the uncompressed chunk size, the compressed chunk
105 * size, then the chunk data. Note: a real program would need
106 * to output the chunk sizes in consistent endianness. */
107 if (write(out_fd, &usize, sizeof(uint32_t)) != sizeof(uint32_t) ||
108 write(out_fd, &out_size, sizeof(uint32_t)) != sizeof(uint32_t) ||
109 write(out_fd, out_buf, out_size) != out_size)
111 error(1, errno, "Error writing to \"%s\"",
119 int main(int argc, char **argv)
121 const char *in_filename;
122 const char *out_filename;
125 struct wimlib_compressor *compressor;
126 int ctype = WIMLIB_COMPRESSION_TYPE_LZX;
127 uint32_t chunk_size = 32768;
130 if (argc < 3 || argc > 5) {
131 fprintf(stderr, "Usage: %s INFILE OUTFILE "
132 "[LZX | XPRESS | LZMS] [chunk size]\n", argv[0]);
136 in_filename = argv[1];
137 out_filename = argv[2];
139 /* Parse compression type (optional) */
141 if (!strcmp(argv[3], "LZX"))
142 ctype = WIMLIB_COMPRESSION_TYPE_LZX;
143 else if (!strcmp(argv[3], "XPRESS"))
144 ctype = WIMLIB_COMPRESSION_TYPE_XPRESS;
145 else if (!strcmp(argv[3], "LZMS"))
146 ctype = WIMLIB_COMPRESSION_TYPE_LZMS;
148 error(1, 0, "Unrecognized compression type \"%s\"", argv[3]);
150 /* Parse chunk size (optional). */
152 chunk_size = atoi(argv[4]);
154 /* Open input file and output file. */
155 in_fd = open(in_filename, O_RDONLY);
157 error(1, errno, "Failed to open \"%s\"", in_filename);
158 out_fd = open(out_filename, O_WRONLY | O_TRUNC | O_CREAT, 0644);
160 error(1, errno, "Failed to open \"%s\"", out_filename);
162 /* Create a compressor for the compression type and chunk size with the
163 * default parameters. */
164 ret = wimlib_create_compressor(ctype, chunk_size, 0, &compressor);
166 error(1, 0, "Failed to create compressor: %s",
167 wimlib_get_error_string(ret));
169 uint32_t ctype32 = ctype;
170 /* Write compression type and chunk size to the file. */
171 if (write(out_fd, &ctype32, sizeof(uint32_t)) != sizeof(uint32_t) ||
172 write(out_fd, &chunk_size, sizeof(uint32_t)) != sizeof(uint32_t))
174 error(1, errno, "Error writing to \"%s\"",
178 /* Compress and write the data. */
179 do_compress(in_fd, in_filename,
180 out_fd, out_filename,
181 chunk_size, compressor);
183 /* Cleanup and return. */
185 error(1, errno, "Error closing \"%s\"", out_filename);
186 wimlib_free_compressor(compressor);