examples: C++ and Windows compatibility
authorEric Biggers <ebiggers3@gmail.com>
Mon, 28 Nov 2016 03:19:41 +0000 (19:19 -0800)
committerEric Biggers <ebiggers3@gmail.com>
Mon, 28 Nov 2016 03:54:00 +0000 (19:54 -0800)
examples/applywim.c
examples/capturewim.c
examples/compressfile.c
examples/decompressfile.c
examples/updatewim.c
tools/msvc-test-examples.bat [new file with mode: 0755]
tools/test-examples [new file with mode: 0755]

index ffcff14..cd6d340 100644 (file)
@@ -3,7 +3,7 @@
  *
  * The following copying information applies to this specific source code file:
  *
- * Written in 2013-2014 by Eric Biggers <ebiggers3@gmail.com>
+ * Written in 2013-2016 by Eric Biggers <ebiggers3@gmail.com>
  *
  * To the extent possible under law, the author(s) have dedicated all copyright
  * and related and neighboring rights to this software to the public domain
 #include <wimlib.h>
 #include <stdio.h>
 
+/*
+ * 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"
+#else
+   typedef char                tchar;
+#  define TS           "s"
+#endif
+
 #define TO_PERCENT(numerator, denominator) \
        ((float)(((denominator) == 0) ? 0 : ((numerator) * 100 / (float)(denominator))))
 
@@ -40,12 +55,12 @@ extract_progress(enum wimlib_progress_msg msg,
        return WIMLIB_PROGRESS_STATUS_CONTINUE;
 }
 
-int main(int argc, char **argv)
+int main(int argc, tchar **argv)
 {
        int ret;
        WIMStruct *wim = NULL;
-       const char *wimpath;
-       const char *destdir;
+       const tchar *wimpath;
+       const tchar *destdir;
 
        /* Check for the correct number of arguments.  */
        if (argc != 3) {
@@ -78,8 +93,8 @@ out:
 
        /* Check for error status.  */
        if (ret != 0) {
-               fprintf(stderr, "wimlib error %d: %s\n",
-                       ret, wimlib_get_error_string(ret));
+               fprintf(stderr, "wimlib error %d: %" TS"\n",
+                       ret, wimlib_get_error_string((enum wimlib_error_code)ret));
        }
 
        /* Free global memory (optional).  */
index 2d89e51..ae99acb 100644 (file)
@@ -3,7 +3,7 @@
  *
  * The following copying information applies to this specific source code file:
  *
- * Written in 2014 by Eric Biggers <ebiggers3@gmail.com>
+ * Written in 2014-2016 by Eric Biggers <ebiggers3@gmail.com>
  *
  * To the extent possible under law, the author(s) have dedicated all copyright
  * and related and neighboring rights to this software to the public domain
 #include <wimlib.h>
 #include <stdio.h>
 
+/*
+ * 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"
+#else
+   typedef char                tchar;
+#  define TS           "s"
+#endif
+
 #define TO_PERCENT(numerator, denominator) \
        ((float)(((denominator) == 0) ? 0 : ((numerator) * 100 / (float)(denominator))))
 
@@ -40,12 +55,12 @@ write_progress(enum wimlib_progress_msg msg,
        return WIMLIB_PROGRESS_STATUS_CONTINUE;
 }
 
-int main(int argc, char **argv)
+int main(int argc, tchar **argv)
 {
        int ret;
        WIMStruct *wim = NULL;
-       const char *srcdir;
-       const char *wimpath;
+       const tchar *srcdir;
+       const tchar *wimpath;
 
        /* Check for the correct number of arguments.  */
        if (argc != 3) {
@@ -88,8 +103,8 @@ out:
 
        /* Check for error status.  */
        if (ret != 0) {
-               fprintf(stderr, "wimlib error %d: %s\n",
-                       ret, wimlib_get_error_string(ret));
+               fprintf(stderr, "wimlib error %d: %" TS"\n",
+                       ret, wimlib_get_error_string((enum wimlib_error_code)ret));
        }
 
        /* Free global memory (optional).  */
index bc7ed18..7f1ca99 100644 (file)
@@ -3,7 +3,7 @@
  *
  * The following copying information applies to this specific source code file:
  *
- * Written in 2014 by Eric Biggers <ebiggers3@gmail.com>
+ * Written in 2014-2016 by Eric Biggers <ebiggers3@gmail.com>
  *
  * To the extent possible under law, the author(s) have dedicated all copyright
  * and related and neighboring rights to this software to the public domain
  * chunks.  A real format would need to have checksums and other metadata.
  */
 
-#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 <inttypes.h>
+#endif
+
 #include <wimlib.h>
 
 #include <errno.h>
-#include <error.h>
 #include <fcntl.h>
-#include <inttypes.h>
+#include <stdarg.h>
 #include <stdlib.h>
 #include <string.h>
-#include <unistd.h>
+#ifdef _WIN32
+#  include <io.h>
+#else
+#  include <unistd.h>
+#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 _T(text)     L##text
+#  define T(text)      _T(text)
+#  define TS           "ls"
+#  define topen                _wopen
+#  define tstrcmp      wcscmp
+#  define tstrtol      wcstol
+#else
+   typedef char                tchar;
+#  define T(text)      text
+#  define TS           "s"
+#  define topen                open
+#  define O_BINARY     0
+#  define tstrcmp      strcmp
+#  define tstrtol      strtol
+#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_compress(int in_fd, const char *in_filename,
-           int out_fd, const char *out_filename,
+do_compress(int in_fd, const tchar *in_filename,
+           int out_fd, const tchar *out_filename,
            uint32_t chunk_size, struct wimlib_compressor *compressor)
 {
-       char *ubuf = malloc(chunk_size);
-       char *cbuf = malloc(chunk_size - 1);
+       char *ubuf = (char *)malloc(chunk_size);
+       char *cbuf = (char *)malloc(chunk_size - 1);
        uint64_t chunk_num;
 
        for (chunk_num = 1; ; chunk_num++) {
-               ssize_t bytes_read;
+               int32_t bytes_read;
                size_t csize;
                char *out_buf;
                uint32_t out_size;
@@ -80,7 +130,8 @@ do_compress(int in_fd, const char *in_filename,
                if (bytes_read <= 0) {
                        if (bytes_read == 0)
                                break;
-                       error(1, errno, "Error reading \"%s\"", in_filename);
+                       fatal_error(errno, "Error reading \"%" TS"\"",
+                                   in_filename);
                }
 
                /* Compress the chunk.  */
@@ -98,7 +149,7 @@ do_compress(int in_fd, const char *in_filename,
                        out_size = usize;
                }
 
-               printf("Chunk %"PRIu64": %"PRIu32" => %"PRIu32" bytes\n",
+               printf("Chunk %" PRIu64" %" PRIu32" => %" PRIu32" bytes\n",
                       chunk_num, usize, out_size);
 
                /* Output the uncompressed chunk size, the compressed chunk
@@ -106,29 +157,30 @@ do_compress(int in_fd, const char *in_filename,
                 * 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)
+                   write(out_fd, out_buf, out_size) != (int32_t)out_size)
                {
-                       error(1, errno, "Error writing to \"%s\"",
-                             out_filename);
+                       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;
        struct wimlib_compressor *compressor;
-       int ctype = WIMLIB_COMPRESSION_TYPE_LZX;
+       enum wimlib_compression_type ctype = WIMLIB_COMPRESSION_TYPE_LZX;
+       uint32_t ctype32;
        uint32_t chunk_size = 32768;
        int ret;
 
        if (argc < 3 || argc > 5) {
-               fprintf(stderr, "Usage: %s INFILE OUTFILE "
+               fprintf(stderr, "Usage: %" TS" INFILE OUTFILE "
                        "[LZX | XPRESS | LZMS] [chunk size]\n", argv[0]);
                return 2;
        }
@@ -138,41 +190,43 @@ int main(int argc, char **argv)
 
        /* Parse compression type (optional)  */
        if (argc >= 4) {
-               if (!strcmp(argv[3], "LZX"))
+               if (!tstrcmp(argv[3], T("LZX")))
                        ctype = WIMLIB_COMPRESSION_TYPE_LZX;
-               else if (!strcmp(argv[3], "XPRESS"))
+               else if (!tstrcmp(argv[3], T("XPRESS")))
                        ctype = WIMLIB_COMPRESSION_TYPE_XPRESS;
-               else if (!strcmp(argv[3], "LZMS"))
+               else if (!tstrcmp(argv[3], T("LZMS")))
                        ctype = WIMLIB_COMPRESSION_TYPE_LZMS;
                else
-                       error(1, 0, "Unrecognized compression type \"%s\"", argv[3]);
+                       fatal_error(0,
+                                   "Unrecognized compression type \"%" TS"\"",
+                                   argv[3]);
        }
        /* Parse chunk size (optional).  */
        if (argc >= 5)
-               chunk_size = atoi(argv[4]);
+               chunk_size = tstrtol(argv[4], NULL, 10);
 
        /* 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"s\"", out_filename);
 
        /* Create a compressor for the compression type and chunk size with the
         * default parameters.  */
        ret = wimlib_create_compressor(ctype, chunk_size, 0, &compressor);
        if (ret != 0)
-               error(1, 0, "Failed to create compressor: %s",
-                     wimlib_get_error_string(ret));
+               fatal_error(0, "Failed to create compressor: %" TS,
+                           wimlib_get_error_string((enum wimlib_error_code)ret));
 
-       uint32_t ctype32 = ctype;
+       ctype32 = (uint32_t)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);
+               fatal_error(errno, "Error writing to \"%" TS"\"", out_filename);
        }
 
        /* Compress and write the data.  */
@@ -182,7 +236,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_compressor(compressor);
        return 0;
 }
index cc2b758..e5a03b4 100644 (file)
@@ -3,7 +3,7 @@
  *
  * The following copying information applies to this specific source code file:
  *
- * Written in 2014 by Eric Biggers <ebiggers3@gmail.com>
+ * Written in 2014-2016 by Eric Biggers <ebiggers3@gmail.com>
  *
  * To the extent possible under law, the author(s) have dedicated all copyright
  * and related and neighboring rights to this software to the public domain
  * chunks.  A real format would need to have checksums and other metadata.
  */
 
-#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 <inttypes.h>
+#endif
+
 #include <wimlib.h>
 
 #include <errno.h>
-#include <error.h>
 #include <fcntl.h>
-#include <inttypes.h>
+#include <stdarg.h>
 #include <stdlib.h>
 #include <string.h>
-#include <unistd.h>
+#ifdef _WIN32
+#  include <io.h>
+#else
+#  include <unistd.h>
+#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
-do_decompress(int in_fd, const char *in_filename,
-             int out_fd, const char *out_filename,
+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 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;
 
@@ -80,56 +123,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;
        }
 
@@ -137,24 +185,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, &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,
@@ -163,7 +213,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;
 }
index d46f24d..0483d5e 100644 (file)
@@ -4,7 +4,7 @@
  *
  * The following copying information applies to this specific source code file:
  *
- * Written in 2014 by Eric Biggers <ebiggers3@gmail.com>
+ * Written in 2014-2016 by Eric Biggers <ebiggers3@gmail.com>
  *
  * To the extent possible under law, the author(s) have dedicated all copyright
  * and related and neighboring rights to this software to the public domain
 #include <wimlib.h>
 #include <string.h>
 
-int main(int argc, char **argv)
+/*
+ * 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"
+#else
+   typedef char                tchar;
+#  define TS           "s"
+#endif
+
+int main(int argc, tchar **argv)
 {
        int ret;
-       char *wimfile;
-       char *wim_target_path;
-       char *fs_source_path;
+       tchar *wimfile;
+       tchar *wim_target_path;
+       tchar *fs_source_path;
        WIMStruct *wim = NULL;
+       struct wimlib_update_command cmds[1];
 
        /* Check for the correct number of arguments.  */
        if (argc != 4) {
@@ -53,8 +69,6 @@ int main(int argc, char **argv)
         * sake of demonstration we will use the more general function
         * wimlib_update_image().  */
 
-       struct wimlib_update_command cmds[1];
-
        memset(cmds, 0, sizeof(cmds));
 
        /* Set up an "add" operation.
@@ -99,8 +113,8 @@ out:
 
        /* Check for error status.  */
        if (ret != 0) {
-               fprintf(stderr, "wimlib error %d: %s\n",
-                       ret, wimlib_get_error_string(ret));
+               fprintf(stderr, "wimlib error %d: %" TS"\n",
+                       ret, wimlib_get_error_string((enum wimlib_error_code)ret));
        }
 
        /* Free global memory (optional).  */
diff --git a/tools/msvc-test-examples.bat b/tools/msvc-test-examples.bat
new file mode 100755 (executable)
index 0000000..f95297b
--- /dev/null
@@ -0,0 +1,56 @@
+REM
+REM Try building and running the example programs on Windows with Visual Studio.
+REM
+
+@echo off
+setlocal EnableDelayedExpansion
+
+copy .libs\libwim.dll.a libwim.lib
+copy .libs\libwim-15.dll libwim-15.dll
+for %%a in (examples\*.c) do (
+       cl %%a libwim.lib /Iinclude /link /opt:noref
+       if errorlevel 1 exit /b
+)
+call :do_test
+
+
+cd examples
+rename *.c *.cc
+cd ..
+for %%a in (examples\*.cc) do (
+       cl %%a libwim.lib /Iinclude /link /opt:noref
+       if errorlevel 1 exit /b
+)
+call :do_test
+cd examples
+rename *.cc *.c
+cd ..
+
+del *.exe *.obj *.dll *.lib
+
+exit /b 0
+
+:do_test
+.\applywim.exe j:\test.wim e:\tmp1
+if errorlevel 1 exit /b
+.\capturewim.exe e:\tmp1 e:\tmp1.wim
+if errorlevel 1 exit /b
+REM Windows likes to give UAC prompts for programs with "update" in their name.
+move /y updatewim.exe updat3wim.exe
+.\updat3wim.exe e:\tmp1.wim examples examples
+if errorlevel 1 exit /b
+
+.\compressfile.exe j:\testdata e:\testdata.lzx
+if errorlevel 1 exit /b
+.\decompressfile.exe e:\testdata.lzx e:\testdata.orig
+if errorlevel 1 exit /b
+fc /b j:\testdata e:\testdata.orig
+if errorlevel 1 exit /b
+
+.\compressfile.exe j:\testdata e:\testdata.lzx XPRESS 16384
+if errorlevel 1 exit /b
+.\decompressfile.exe e:\testdata.lzx e:\testdata.orig
+if errorlevel 1 exit /b
+fc /b j:\testdata e:\testdata.orig
+if errorlevel 1 exit /b
+goto :eof
diff --git a/tools/test-examples b/tools/test-examples
new file mode 100755 (executable)
index 0000000..8e4ac66
--- /dev/null
@@ -0,0 +1,57 @@
+#!/bin/sh
+#
+# Try building the example programs: in 32-bit and 64-bit mode, in C and C++
+# mode, and for Linux and for Windows.  Also run the Linux versions to make sure
+# they work.
+#
+
+set -eu
+
+cd examples
+make clean
+
+COMMON_FLAGS="-Wall -Wextra -Werror -Wundef -Wno-unused-parameter -Wvla"
+COMMON_CFLAGS="$COMMON_FLAGS -std=gnu99 -Wdeclaration-after-statement -Wstrict-prototypes"
+COMMON_CXXFLAGS="$COMMON_FLAGS"
+
+TEST_WIM="$HOME/data/test.wim"
+TESTDATA="$HOME/data/testdata"
+
+tmpdir="$(mktemp -d)"
+tmpfile="$(mktemp)"
+tmpfile2="$(mktemp)"
+
+trap "rm -rf \"$tmpdir\" \"$tmpfile\" \"$tmpfile2\"" EXIT
+
+do_test() {
+       rm -rf "$tmpdir"
+
+       ./applywim "$TEST_WIM" "$tmpdir"
+       ./capturewim "$tmpdir" "$tmpfile"
+       ./updatewim "$tmpfile" "examples" .
+
+       ./compressfile "$TESTDATA" "$tmpfile"
+       ./decompressfile "$tmpfile" "$tmpfile2"
+       cmp "$tmpfile2" "$TESTDATA"
+
+       ./compressfile "$TESTDATA" "$tmpfile" XPRESS 16384
+       ./decompressfile "$tmpfile" "$tmpfile2"
+       cmp "$tmpfile2" "$TESTDATA"
+}
+
+make CC=gcc CFLAGS="$COMMON_CFLAGS"
+do_test
+make clean
+make CC=g++ CFLAGS="$COMMON_CXXFLAGS"
+do_test
+make clean
+
+make CC=i686-w64-mingw32-gcc CFLAGS="$COMMON_CFLAGS -I../include -municode" LDLIBS="-lwim-15" LDFLAGS="-L/j/wimlib"
+make clean
+make CC=i686-w64-mingw32-g++ CFLAGS="$COMMON_CXXFLAGS -I../include -municode" LDLIBS="-lwim-15" LDFLAGS="-L/j/wimlib"
+make clean
+
+make CC=x86_64-w64-mingw32-gcc CFLAGS="$COMMON_CFLAGS -I../include -municode" LDLIBS="-lwim-15" LDFLAGS="-L/j/x64"
+make clean
+make CC=x86_64-w64-mingw32-g++ CFLAGS="$COMMON_CXXFLAGS -I../include -municode" LDLIBS="-lwim-15" LDFLAGS="-L/j/x64"
+make clean