Update examples
authorEric Biggers <ebiggers3@gmail.com>
Thu, 2 Jan 2014 20:20:07 +0000 (14:20 -0600)
committerEric Biggers <ebiggers3@gmail.com>
Thu, 2 Jan 2014 20:20:36 +0000 (14:20 -0600)
examples/Makefile
examples/README
examples/applywim.c
examples/capturewim.c [new file with mode: 0644]
examples/compressfile.c [new file with mode: 0644]
examples/decompressfile.c [new file with mode: 0644]
examples/makewim.c [deleted file]

index ef84a9b..7a4719e 100644 (file)
@@ -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
index dcf550a..c642170 100644 (file)
@@ -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.
index 6d34a43..a92b263 100644 (file)
@@ -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 <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;
 }
diff --git a/examples/capturewim.c b/examples/capturewim.c
new file mode 100644 (file)
index 0000000..f271970
--- /dev/null
@@ -0,0 +1,82 @@
+/*
+ * 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;
+}
diff --git a/examples/compressfile.c b/examples/compressfile.c
new file mode 100644 (file)
index 0000000..824165d
--- /dev/null
@@ -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 <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;
+}
diff --git a/examples/decompressfile.c b/examples/decompressfile.c
new file mode 100644 (file)
index 0000000..11a20f1
--- /dev/null
@@ -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 <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;
+}
diff --git a/examples/makewim.c b/examples/makewim.c
deleted file mode 100644 (file)
index 08ed728..0000000
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * 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;
-}