From: Eric Biggers Date: Thu, 2 Jan 2014 20:20:07 +0000 (-0600) Subject: Update examples X-Git-Tag: v1.6.0~3 X-Git-Url: https://wimlib.net/git/?p=wimlib;a=commitdiff_plain;h=c3a1bd96026fd5a1d43c5f6178f9f0165afdd098 Update examples --- diff --git a/examples/Makefile b/examples/Makefile index ef84a9b2..7a4719e9 100644 --- a/examples/Makefile +++ b/examples/Makefile @@ -1,13 +1,11 @@ -CFLAGS := -Wall -s +CFLAGS := -Wall LDLIBS := -lwim -all:applywim makewim +EXE := applywim capturewim compressfile decompressfile -applywim:applywim.c - -makewim:makewim.c +all:$(EXE) clean: - rm -f applywim makewim + rm -f $(EXE) .PHONY: all clean diff --git a/examples/README b/examples/README index dcf550aa..c6421707 100644 --- a/examples/README +++ b/examples/README @@ -1,2 +1,2 @@ -This directory shows some simple examples of C programs that use the wimlib -library. See programs/imagex.c for a more complete example. +This directory shows some simple examples of C programs that use wimlib. +See programs/imagex.c for a more complete example. diff --git a/examples/applywim.c b/examples/applywim.c index 6d34a432..a92b2637 100644 --- a/examples/applywim.c +++ b/examples/applywim.c @@ -1,41 +1,72 @@ /* - * applywim.c - A simple program to extract all images from a WIM file to a - * directory. + * applywim.c - A program to extract the first image from a WIM file. */ #include #include +#define TO_PERCENT(numerator, denominator) \ + ((float)(((denominator) == 0) ? 0 : ((numerator) * 100 / (float)(denominator)))) + +static int +extract_progress(enum wimlib_progress_msg msg, + const union wimlib_progress_info *info) +{ + switch (msg) { + case WIMLIB_PROGRESS_MSG_EXTRACT_STREAMS: + printf("Extracting files: %.2f%% complete\n", + TO_PERCENT(info->extract.completed_bytes, + info->extract.total_bytes)); + break; + default: + break; + } + return 0; +} + int main(int argc, char **argv) { int ret; - WIMStruct *wim; + WIMStruct *wim = NULL; + const char *wimpath; + const char *destdir; + /* Check for the correct number of arguments. */ if (argc != 3) { fprintf(stderr, "Usage: applywim WIM DIR\n"); - ret = 2; - goto out; + return 2; } - /* Initialize the library. */ - ret = wimlib_global_init(0); - if (ret) - goto out; + wimpath = argv[1]; + destdir = argv[2]; - /* Open the WIM file. */ - ret = wimlib_open_wim(argv[1], 0, &wim, NULL); - if (ret) - goto out_wimlib_global_cleanup; + /* Open the WIM file as a WIMStruct. */ + ret = wimlib_open_wim(wimpath, /* Path of WIM file to open */ + 0, /* WIMLIB_OPEN_FLAG_* flags (0 means all defaults) */ + &wim, /* Return the WIMStruct pointer in this location */ + NULL); /* Progress function (NULL means none) */ + if (ret != 0) /* Always should check the error codes. */ + goto out; - /* Extract all the images. */ - ret = wimlib_extract_image(wim, WIMLIB_ALL_IMAGES, argv[2], 0, NULL); + /* Extract the first image. */ + ret = wimlib_extract_image(wim, /* WIMStruct from which to extract the image */ + 1, /* Image to extract */ + destdir, /* Directory to extract the image to */ + 0, /* WIMLIB_EXTRACT_FLAG_* flags (0 means all defaults) */ + extract_progress); /* Progress function */ - /* Free the WIM file */ +out: + /* Free the WIMStruct. Has no effect if the pointer to it is NULL. */ wimlib_free(wim); -out_wimlib_global_cleanup: - /* Finalize the library */ + /* Check for error status. */ + if (ret != 0) { + fprintf(stderr, "wimlib error %d: %s\n", + ret, wimlib_get_error_string(ret)); + } + + /* Free global memory (optional). */ wimlib_global_cleanup(); -out: + return ret; } diff --git a/examples/capturewim.c b/examples/capturewim.c new file mode 100644 index 00000000..f2719705 --- /dev/null +++ b/examples/capturewim.c @@ -0,0 +1,82 @@ +/* + * capturewim.c - A program to capture a directory tree into a WIM file. + */ + +#include +#include + +#define TO_PERCENT(numerator, denominator) \ + ((float)(((denominator) == 0) ? 0 : ((numerator) * 100 / (float)(denominator)))) + +static int +write_progress(enum wimlib_progress_msg msg, + const union wimlib_progress_info *info) +{ + switch (msg) { + case WIMLIB_PROGRESS_MSG_WRITE_STREAMS: + printf("Writing WIM: %.2f%% complete\n", + TO_PERCENT(info->write_streams.completed_bytes, + info->write_streams.total_bytes)); + break; + default: + break; + } + return 0; +} + +int main(int argc, char **argv) +{ + int ret; + WIMStruct *wim = NULL; + const char *srcdir; + const char *wimpath; + + /* Check for the correct number of arguments. */ + if (argc != 3) { + fprintf(stderr, "Usage: capturewim DIR WIM\n"); + return 2; + } + + srcdir = argv[1]; + wimpath = argv[2]; + + /* Create a WIMStruct for a WIM. */ + ret = wimlib_create_new_wim(WIMLIB_COMPRESSION_TYPE_LZX, &wim); + if (ret != 0) /* Always should check the error codes. */ + goto out; + + /* Add the directory tree to the WIMStruct as an image. */ + + ret = wimlib_add_image(wim, /* WIMStruct to which to add the image */ + srcdir, /* Directory from which to add the image */ + NULL, /* Name to give the image (NULL means none) */ + NULL, /* Capture configuration structure (NULL means none) */ + 0, /* WIMLIB_ADD_FLAG_* flags (0 means all defaults) */ + NULL); /* Progress function (NULL means none) */ + if (ret != 0) + goto out; + + /* Write the WIM file. */ + + ret = wimlib_write(wim, /* WIMStruct from which to write a WIM */ + wimpath, /* Path to write the WIM to */ + WIMLIB_ALL_IMAGES, /* Image(s) in the WIM to write */ + 0, /* WIMLIB_WRITE_FLAG_* flags (0 means all defaults) */ + 0, /* Number of compressor threads (0 means default) */ + write_progress); /* Progress function */ + +out: + /* Free the WIMStruct. Has no effect if the pointer to it is NULL. */ + wimlib_free(wim); + + /* Check for error status. */ + if (ret != 0) { + fprintf(stderr, "wimlib error %d: %s\n", + ret, wimlib_get_error_string(ret)); + } + + /* Free global memory (optional). */ + wimlib_global_cleanup(); + + return ret; +} diff --git a/examples/compressfile.c b/examples/compressfile.c new file mode 100644 index 00000000..824165db --- /dev/null +++ b/examples/compressfile.c @@ -0,0 +1,170 @@ +/* + * compressfile.c + * + * An example of using wimlib's compression API to compress a file. + * + * 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. + * This is purely an example of using the compression API. + * + * Compile with: + * + * $ gcc compressfile.c -o compressfile -lwim + * + * Run with: + * + * $ ./compressfile INFILE OUTFILE [LZX | XPRESS | LZMS] [chunk size] + * + * + * Use the decompressfile.c program to decompress the file. + * + * For example: + * + * $ ./compressfile book.txt book.txt.lzms LZMS 1048576 + * $ rm -f book.txt + * $ ./decompressfile book.txt.lzms book.txt + * + * The compressed file format created here is simply a series of compressed + * chunks. A real format would need to have checksums and other metadata. + */ + +#define _GNU_SOURCE +#define _FILE_OFFSET_BITS 64 + +#include + +#include +#include +#include +#include +#include +#include +#include + +static void +do_compress(int in_fd, const char *in_filename, + int out_fd, const char *out_filename, + uint32_t chunk_size, struct wimlib_compressor *compressor) +{ + char *ubuf = malloc(chunk_size); + char *cbuf = malloc(chunk_size - 1); + uint64_t chunk_num; + + for (chunk_num = 1; ; chunk_num++) { + ssize_t bytes_read; + size_t csize; + char *out_buf; + uint32_t out_size; + uint32_t usize; + + /* Read next chunk of data to compress. */ + bytes_read = read(in_fd, ubuf, chunk_size); + if (bytes_read <= 0) { + if (bytes_read == 0) + break; + error(1, errno, "Error reading \"%s\"", in_filename); + } + + /* Compress the chunk. */ + usize = bytes_read; + + csize = wimlib_compress(ubuf, usize, cbuf, usize - 1, compressor); + if (csize != 0) { + /* Chunk was compressed; use the compressed data. */ + out_buf = cbuf; + out_size = csize; + } else { + /* Chunk did not compress to less than original size; + * use the uncompressed data. */ + out_buf = ubuf; + out_size = usize; + } + + printf("Chunk %"PRIu64": %"PRIu32" => %"PRIu32" bytes\n", + chunk_num, usize, out_size); + + /* 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, &usize, sizeof(uint32_t)) != sizeof(uint32_t) || + write(out_fd, &out_size, sizeof(uint32_t)) != sizeof(uint32_t) || + write(out_fd, out_buf, out_size) != out_size) + { + error(1, errno, "Error writing to \"%s\"", + out_filename); + } + } + free(ubuf); + free(cbuf); +} + +int main(int argc, char **argv) +{ + const char *in_filename; + const char *out_filename; + int in_fd; + int out_fd; + struct wimlib_compressor *compressor; + int ctype = WIMLIB_COMPRESSION_TYPE_LZX; + uint32_t chunk_size = 32768; + int ret; + + if (argc < 3 || argc > 5) { + fprintf(stderr, "Usage: %s INFILE OUTFILE " + "[LZX | XPRESS | LZMS] [chunk size]\n", argv[0]); + return 2; + } + + in_filename = argv[1]; + out_filename = argv[2]; + + /* Parse compression type (optional) */ + if (argc >= 4) { + if (!strcmp(argv[3], "LZX")) + ctype = WIMLIB_COMPRESSION_TYPE_LZX; + else if (!strcmp(argv[3], "XPRESS")) + ctype = WIMLIB_COMPRESSION_TYPE_XPRESS; + else if (!strcmp(argv[3], "LZMS")) + ctype = WIMLIB_COMPRESSION_TYPE_LZMS; + else + error(1, 0, "Unrecognized compression type \"%s\"", argv[3]); + } + /* Parse chunk size (optional). */ + if (argc >= 5) + chunk_size = atoi(argv[4]); + + /* Open input file and output file. */ + in_fd = open(in_filename, O_RDONLY); + 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); + if (out_fd < 0) + error(1, errno, "Failed to open \"%s\"", out_filename); + + /* Create a compressor for the compression type and chunk size with the + * default parameters. */ + ret = wimlib_create_compressor(ctype, chunk_size, NULL, &compressor); + if (ret != 0) + error(1, 0, "Failed to create compressor: %s", + wimlib_get_error_string(ret)); + + uint32_t ctype32 = ctype; + /* Write compression type and chunk size to the file. */ + if (write(out_fd, &ctype32, sizeof(uint32_t)) != sizeof(uint32_t) || + write(out_fd, &chunk_size, sizeof(uint32_t)) != sizeof(uint32_t)) + { + error(1, errno, "Error writing to \"%s\"", + out_filename); + } + + /* Compress and write the data. */ + do_compress(in_fd, in_filename, + out_fd, out_filename, + chunk_size, compressor); + + /* Cleanup and return. */ + if (close(out_fd)) + error(1, errno, "Error closing \"%s\"", out_filename); + wimlib_free_compressor(compressor); + return 0; +} diff --git a/examples/decompressfile.c b/examples/decompressfile.c new file mode 100644 index 00000000..11a20f19 --- /dev/null +++ b/examples/decompressfile.c @@ -0,0 +1,151 @@ +/* + * decompressfile.c + * + * 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. + * This is purely an example of using the compression API. + * + * Compile with: + * + * $ gcc decompressfile.c -o decompressfile -lwim + * + * Run with: + * + * $ ./decompressfile INFILE OUTFILE + * + * For example: + * + * $ ./compressfile book.txt book.txt.lzms LZMS 1048576 + * $ rm -f book.txt + * $ ./decompressfile book.txt.lzms book.txt + * + * The compressed file format created here is simply a series of compressed + * chunks. A real format would need to have checksums and other metadata. + */ + +#define _GNU_SOURCE +#define _FILE_OFFSET_BITS 64 + +#include + +#include +#include +#include +#include +#include +#include +#include + +static void +do_decompress(int in_fd, const char *in_filename, + int out_fd, const char *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); + + for (chunk_num = 1; ; chunk_num++) { + ssize_t bytes_read; + uint32_t usize; + uint32_t csize; + + /* Read chunk uncompressed and compressed sizes. */ + bytes_read = read(in_fd, &usize, sizeof(uint32_t)); + if (bytes_read == 0) + break; + + if (bytes_read != sizeof(uint32_t) || + read(in_fd, &csize, sizeof(uint32_t)) != sizeof(uint32_t)) + { + error(1, errno, "Error reading \"%s\"", in_filename); + } + + if (csize > usize || usize > chunk_size) + error(1, 0, "The data is invalid!"); + + if (usize == csize) { + if (read(in_fd, ubuf, usize) != usize) { + error(1, errno, "Error reading \"%s\"", + in_filename); + } + } else { + if (read(in_fd, cbuf, csize) != csize) { + error(1, errno, "Error reading \"%s\"", + in_filename); + } + + if (wimlib_decompress(cbuf, csize, ubuf, usize, + decompressor)) + { + error(1, 0, "The compressed data is invalid!"); + } + } + + 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); + } + free(ubuf); + free(cbuf); +} + +int main(int argc, char **argv) +{ + const char *in_filename; + const char *out_filename; + int in_fd; + int out_fd; + uint32_t ctype; + uint32_t chunk_size; + int ret; + struct wimlib_decompressor *decompressor; + + if (argc != 3) { + fprintf(stderr, "Usage: %s INFILE OUTFILE\n", argv[0]); + return 2; + } + + in_filename = argv[1]; + out_filename = argv[2]; + + /* Open input file and output file. */ + in_fd = open(in_filename, O_RDONLY); + 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); + if (out_fd < 0) + error(1, errno, "Failed to open \"%s\"", out_filename); + + /* Get compression type and chunk size. */ + if (read(in_fd, &ctype, 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); + + /* Create a decompressor for the compression type and chunk size with + * the default parameters. */ + ret = wimlib_create_decompressor(ctype, chunk_size, NULL, &decompressor); + if (ret != 0) + error(1, 0, "Failed to create decompressor: %s", + wimlib_get_error_string(ret)); + + /* Decompress and write the data. */ + do_decompress(in_fd, in_filename, + out_fd, out_filename, + chunk_size, decompressor); + + /* Cleanup and return. */ + if (close(out_fd)) + error(1, errno, "Error closing \"%s\"", out_filename); + wimlib_free_decompressor(decompressor); + return 0; +} diff --git a/examples/makewim.c b/examples/makewim.c deleted file mode 100644 index 08ed728c..00000000 --- a/examples/makewim.c +++ /dev/null @@ -1,47 +0,0 @@ -/* - * makewim.c - A simple program to make a LZX-compressed WIM file from a - * directory. - */ - -#include -#include - -int main(int argc, char **argv) -{ - int ret; - WIMStruct *wim; - - if (argc != 3) { - fprintf(stderr, "Usage: makewim DIR WIM\n"); - ret = 2; - goto out; - } - - /* Initialize the library. */ - ret = wimlib_global_init(0); - if (ret) - goto out; - - /* Create a WIMStruct for a LZX-compressed WIM. */ - ret = wimlib_create_new_wim(WIMLIB_COMPRESSION_TYPE_LZX, &wim); - if (ret) - goto out_wimlib_global_cleanup; - - /* Add the directory tree to the WIMStruct as an image. */ - ret = wimlib_add_image(wim, argv[1], "1", NULL, 0, NULL); - if (ret) - goto out_wimlib_free; - - /* Write the desired WIM file. */ - ret = wimlib_write(wim, argv[2], WIMLIB_ALL_IMAGES, 0, 0, NULL); - -out_wimlib_free: - /* Free the WIM file */ - wimlib_free(wim); - -out_wimlib_global_cleanup: - /* Finalize the library */ - wimlib_global_cleanup(); -out: - return ret; -}