4 * An example of using wimlib's compression API to compress a file.
6 * This program does *not* have anything to do with WIM files other than the
7 * fact that this makes use of compression formats that are used in WIM files.
8 * This is purely an example of using the compression API.
12 * $ gcc compressfile.c -o compressfile -lwim
16 * $ ./compressfile INFILE OUTFILE [LZX | XPRESS | LZMS] [chunk size]
19 * Use the decompressfile.c program to decompress the file.
23 * $ ./compressfile book.txt book.txt.lzms LZMS 1048576
25 * $ ./decompressfile book.txt.lzms book.txt
27 * The compressed file format created here is simply a series of compressed
28 * chunks. A real format would need to have checksums and other metadata.
30 * The author dedicates this file to the public domain.
31 * You can do whatever you want with this file.
35 #define _FILE_OFFSET_BITS 64
48 do_compress(int in_fd, const char *in_filename,
49 int out_fd, const char *out_filename,
50 uint32_t chunk_size, struct wimlib_compressor *compressor)
52 char *ubuf = malloc(chunk_size);
53 char *cbuf = malloc(chunk_size - 1);
56 for (chunk_num = 1; ; chunk_num++) {
63 /* Read next chunk of data to compress. */
64 bytes_read = read(in_fd, ubuf, chunk_size);
65 if (bytes_read <= 0) {
68 error(1, errno, "Error reading \"%s\"", in_filename);
71 /* Compress the chunk. */
74 csize = wimlib_compress(ubuf, usize, cbuf, usize - 1, compressor);
76 /* Chunk was compressed; use the compressed data. */
80 /* Chunk did not compress to less than original size;
81 * use the uncompressed data. */
86 printf("Chunk %"PRIu64": %"PRIu32" => %"PRIu32" bytes\n",
87 chunk_num, usize, out_size);
89 /* Output the uncompressed chunk size, the compressed chunk
90 * size, then the chunk data. Note: a real program would need
91 * to output the chunk sizes in consistent endianness. */
92 if (write(out_fd, &usize, sizeof(uint32_t)) != sizeof(uint32_t) ||
93 write(out_fd, &out_size, sizeof(uint32_t)) != sizeof(uint32_t) ||
94 write(out_fd, out_buf, out_size) != out_size)
96 error(1, errno, "Error writing to \"%s\"",
104 int main(int argc, char **argv)
106 const char *in_filename;
107 const char *out_filename;
110 struct wimlib_compressor *compressor;
111 int ctype = WIMLIB_COMPRESSION_TYPE_LZX;
112 uint32_t chunk_size = 32768;
115 if (argc < 3 || argc > 5) {
116 fprintf(stderr, "Usage: %s INFILE OUTFILE "
117 "[LZX | XPRESS | LZMS] [chunk size]\n", argv[0]);
121 in_filename = argv[1];
122 out_filename = argv[2];
124 /* Parse compression type (optional) */
126 if (!strcmp(argv[3], "LZX"))
127 ctype = WIMLIB_COMPRESSION_TYPE_LZX;
128 else if (!strcmp(argv[3], "XPRESS"))
129 ctype = WIMLIB_COMPRESSION_TYPE_XPRESS;
130 else if (!strcmp(argv[3], "LZMS"))
131 ctype = WIMLIB_COMPRESSION_TYPE_LZMS;
133 error(1, 0, "Unrecognized compression type \"%s\"", argv[3]);
135 /* Parse chunk size (optional). */
137 chunk_size = atoi(argv[4]);
139 /* Open input file and output file. */
140 in_fd = open(in_filename, O_RDONLY);
142 error(1, errno, "Failed to open \"%s\"", in_filename);
143 out_fd = open(out_filename, O_WRONLY | O_TRUNC | O_CREAT, 0644);
145 error(1, errno, "Failed to open \"%s\"", out_filename);
147 /* Create a compressor for the compression type and chunk size with the
148 * default parameters. */
149 ret = wimlib_create_compressor(ctype, chunk_size, NULL, &compressor);
151 error(1, 0, "Failed to create compressor: %s",
152 wimlib_get_error_string(ret));
154 uint32_t ctype32 = ctype;
155 /* Write compression type and chunk size to the file. */
156 if (write(out_fd, &ctype32, sizeof(uint32_t)) != sizeof(uint32_t) ||
157 write(out_fd, &chunk_size, sizeof(uint32_t)) != sizeof(uint32_t))
159 error(1, errno, "Error writing to \"%s\"",
163 /* Compress and write the data. */
164 do_compress(in_fd, in_filename,
165 out_fd, out_filename,
166 chunk_size, compressor);
168 /* Cleanup and return. */
170 error(1, errno, "Error closing \"%s\"", out_filename);
171 wimlib_free_compressor(compressor);