-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
-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.
/*
- * 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 <wimlib.h>
#include <stdio.h>
+#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;
}
--- /dev/null
+/*
+ * capturewim.c - A program to capture a directory tree into a WIM file.
+ */
+
+#include <wimlib.h>
+#include <stdio.h>
+
+#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;
+}
--- /dev/null
+/*
+ * 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 <wimlib.h>
+
+#include <errno.h>
+#include <error.h>
+#include <fcntl.h>
+#include <inttypes.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+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;
+}
--- /dev/null
+/*
+ * 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 <wimlib.h>
+
+#include <errno.h>
+#include <error.h>
+#include <fcntl.h>
+#include <inttypes.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+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;
+}
+++ /dev/null
-/*
- * makewim.c - A simple program to make a LZX-compressed WIM file from a
- * directory.
- */
-
-#include <wimlib.h>
-#include <stdio.h>
-
-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;
-}