X-Git-Url: https://wimlib.net/git/?p=wimlib;a=blobdiff_plain;f=examples%2Fdecompressfile.c;h=e5a03b44512b4bd5e7a3223fb64d25237f0ff8dc;hp=8e461d43f86d33110c1171a8325b3d1ca96012c8;hb=HEAD;hpb=629719b7d5cad7fc6f2eca7ca11cb99100ed8764 diff --git a/examples/decompressfile.c b/examples/decompressfile.c index 8e461d43..561557a1 100644 --- a/examples/decompressfile.c +++ b/examples/decompressfile.c @@ -1,8 +1,33 @@ /* - * decompressfile.c + * decompressfile.c - decompression API example * - * An example of using wimlib's compression API to decompress a file compressed - * with the compressfile.c program. + * Copyright 2022 Eric Biggers + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +/* + * This an example of using wimlib's compression API to decompress a file + * compressed with the compressfile.c program. * * This program does *not* have anything to do with WIM files other than the * fact that this makes use of compression formats that are used in WIM files. @@ -24,36 +49,76 @@ * * The compressed file format created here is simply a series of compressed * chunks. A real format would need to have checksums and other metadata. - * - * The author dedicates this file to the public domain. - * You can do whatever you want with this file. */ -#define _GNU_SOURCE #define _FILE_OFFSET_BITS 64 +#if defined(_MSC_VER) && _MSC_VER < 1800 /* VS pre-2013? */ +# define PRIu64 "I64u" +# define PRIu32 "u" +#else +# define __STDC_FORMAT_MACROS 1 +# include +#endif + #include #include -#include #include -#include +#include #include #include -#include +#ifdef _WIN32 +# include +#else +# include +#endif + +/* + * Windows compatibility defines for string encoding. Applications using wimlib + * that need to run on both UNIX and Windows will need to do something similar + * to this, whereas applications that only need to run on one or the other can + * just use their platform's convention directly. + */ +#ifdef _WIN32 +# define main wmain + typedef wchar_t tchar; +# define TS "ls" +# define topen _wopen +#else + typedef char tchar; +# define TS "s" +# define topen open +# define O_BINARY 0 +#endif + +static void +fatal_error(int err, const char *format, ...) +{ + va_list va; + + va_start(va, format); + vfprintf(stderr, format, va); + if (err != 0) + fprintf(stderr, ": %s\n", strerror(err)); + else + fputc('\n', stderr); + va_end(va); + exit(1); +} static void -do_decompress(int in_fd, const char *in_filename, - int out_fd, const char *out_filename, +do_decompress(int in_fd, const tchar *in_filename, + int out_fd, const tchar *out_filename, uint32_t chunk_size, struct wimlib_decompressor *decompressor) { uint64_t chunk_num; - char *ubuf = malloc(chunk_size); - char *cbuf = malloc(chunk_size - 1); + char *ubuf = (char *)malloc(chunk_size); + char *cbuf = (char *)malloc(chunk_size - 1); for (chunk_num = 1; ; chunk_num++) { - ssize_t bytes_read; + int32_t bytes_read; uint32_t usize; uint32_t csize; @@ -65,56 +130,61 @@ do_decompress(int in_fd, const char *in_filename, if (bytes_read != sizeof(uint32_t) || read(in_fd, &csize, sizeof(uint32_t)) != sizeof(uint32_t)) { - error(1, errno, "Error reading \"%s\"", in_filename); + fatal_error(errno, "Error reading \"%" TS"\"", + in_filename); } if (csize > usize || usize > chunk_size) - error(1, 0, "The data is invalid!"); + fatal_error(0, "The data is invalid!"); if (usize == csize) { - if (read(in_fd, ubuf, usize) != usize) { - error(1, errno, "Error reading \"%s\"", - in_filename); + if (read(in_fd, ubuf, usize) != (int32_t)usize) { + fatal_error(errno, "Error reading \"%" TS"\"", + in_filename); } } else { - if (read(in_fd, cbuf, csize) != csize) { - error(1, errno, "Error reading \"%s\"", - in_filename); + if (read(in_fd, cbuf, csize) != (int32_t)csize) { + fatal_error(errno, "Error reading \"%" TS"\"", + in_filename); } if (wimlib_decompress(cbuf, csize, ubuf, usize, decompressor)) { - error(1, 0, "The compressed data is invalid!"); + fatal_error(0, + "The compressed data is invalid!"); } } - printf("Chunk %"PRIu64": %"PRIu32" => %"PRIu32" bytes\n", + printf("Chunk %" PRIu64": %" PRIu32" => %" PRIu32" bytes\n", chunk_num, csize, usize); /* Output the uncompressed chunk size, the compressed chunk * size, then the chunk data. Note: a real program would need * to output the chunk sizes in consistent endianness. */ - if (write(out_fd, ubuf, usize) != usize) - error(1, errno, "Error writing to \"%s\"", out_filename); + if (write(out_fd, ubuf, usize) != (int32_t)usize) { + fatal_error(errno, "Error writing to \"%" TS"\"", + out_filename); + } } free(ubuf); free(cbuf); } -int main(int argc, char **argv) +int main(int argc, tchar **argv) { - const char *in_filename; - const char *out_filename; + const tchar *in_filename; + const tchar *out_filename; int in_fd; int out_fd; - uint32_t ctype; + uint32_t ctype32; + enum wimlib_compression_type ctype; uint32_t chunk_size; int ret; struct wimlib_decompressor *decompressor; if (argc != 3) { - fprintf(stderr, "Usage: %s INFILE OUTFILE\n", argv[0]); + fprintf(stderr, "Usage: %" TS" INFILE OUTFILE\n", argv[0]); return 2; } @@ -122,24 +192,26 @@ int main(int argc, char **argv) out_filename = argv[2]; /* Open input file and output file. */ - in_fd = open(in_filename, O_RDONLY); + in_fd = topen(in_filename, O_RDONLY | O_BINARY); if (in_fd < 0) - error(1, errno, "Failed to open \"%s\"", in_filename); - out_fd = open(out_filename, O_WRONLY | O_TRUNC | O_CREAT, 0644); + fatal_error(errno, "Failed to open \"%" TS"\"", in_filename); + out_fd = topen(out_filename, O_WRONLY | O_TRUNC | O_CREAT | O_BINARY, + 0644); if (out_fd < 0) - error(1, errno, "Failed to open \"%s\"", out_filename); + fatal_error(errno, "Failed to open \"%" TS"\"", out_filename); /* Get compression type and chunk size. */ - if (read(in_fd, &ctype, sizeof(uint32_t)) != sizeof(uint32_t) || + if (read(in_fd, &ctype32, sizeof(uint32_t)) != sizeof(uint32_t) || read(in_fd, &chunk_size, sizeof(uint32_t)) != sizeof(uint32_t)) - error(1, errno, "Error reading from \"%s\"", in_filename); + fatal_error(errno, "Error reading from \"%" TS"\"", in_filename); + ctype = (enum wimlib_compression_type)ctype32; /* Create a decompressor for the compression type and chunk size with * the default parameters. */ - ret = wimlib_create_decompressor(ctype, chunk_size, NULL, &decompressor); + ret = wimlib_create_decompressor(ctype, chunk_size, &decompressor); if (ret != 0) - error(1, 0, "Failed to create decompressor: %s", - wimlib_get_error_string(ret)); + fatal_error(0, "Failed to create decompressor: %" TS, + wimlib_get_error_string((enum wimlib_error_code)ret)); /* Decompress and write the data. */ do_decompress(in_fd, in_filename, @@ -148,7 +220,7 @@ int main(int argc, char **argv) /* Cleanup and return. */ if (close(out_fd)) - error(1, errno, "Error closing \"%s\"", out_filename); + fatal_error(errno, "Error closing \"%" TS"\"", out_filename); wimlib_free_decompressor(decompressor); return 0; }