Windows native build
authorEric Biggers <ebiggers3@gmail.com>
Sun, 17 Mar 2013 19:38:41 +0000 (14:38 -0500)
committerEric Biggers <ebiggers3@gmail.com>
Sun, 17 Mar 2013 19:38:41 +0000 (14:38 -0500)
12 files changed:
Makefile.am
configure.ac
programs/imagex.c
src/add_image.c
src/dentry.c
src/dentry.h
src/encoding.c
src/extract_image.c
src/util.c
src/util.h
src/wim.c
src/write.c

index 70f4287..5dc694b 100644 (file)
@@ -7,7 +7,7 @@ AM_CFLAGS       = -std=gnu99 -D_LARGEFILE_SOURCE \
 
 lib_LTLIBRARIES = libwim.la
 
-libwim_la_LDFLAGS = -version-info 4:0:2 $(CYGWIN_EXTRA_LDFLAGS)
+libwim_la_LDFLAGS = -version-info 4:0:2 $(WINDOWS_EXTRA_LDFLAGS)
 
 libwim_la_SOURCES =            \
        src/add_image.c         \
@@ -83,7 +83,8 @@ libwim_la_LIBADD =            \
        $(LTLIBICONV)           \
        $(LIBCRYPTO_LDADD)      \
        $(SSSE3_SHA1_OBJ)       \
-       $(PTHREAD_LDADD)
+       $(PTHREAD_LDADD)        \
+       $(WINDOWS_LDADD)
 
 libwim_la_CFLAGS =             \
        $(AM_CFLAGS)            \
@@ -98,6 +99,10 @@ bin_PROGRAMS  = imagex
 imagex_SOURCES   = programs/imagex.c
 imagex_LDADD    = $(top_builddir)/libwim.la
 
+if WINDOWS_BUILD
+imagex_SOURCES += programs/imagex-win32.c programs/imagex-win32.h
+endif
+
 dist_bin_SCRIPTS = programs/mkwinpeimg
 
 include_HEADERS = src/wimlib.h
index 1b90c48..ad04b47 100644 (file)
@@ -28,11 +28,12 @@ AC_CONFIG_FILES([Makefile
                ])
 AC_PROG_CC
 AM_PROG_CC_C_O
+AC_CANONICAL_HOST
 
 AC_CHECK_FUNCS([utimensat lutimes utime flock])
 AC_CHECK_HEADERS([endian.h byteswap.h sys/byteorder.h sys/endian.h \
                  sys/param.h machine/endian.h alloca.h stdlib.h stdarg.h \
-                 errno.h attr/xattr.h utime.h sys/file.h])
+                 errno.h attr/xattr.h utime.h sys/file.h glob.h])
 
 AC_CHECK_MEMBER([struct stat.st_mtim],
                [AC_DEFINE([HAVE_STAT_NANOSECOND_PRECISION], [1],
@@ -41,15 +42,6 @@ AC_CHECK_MEMBER([struct stat.st_mtim],
                [],
                [[#include <sys/stat.h>]])
 
-AM_ICONV
-if test "x$am_cv_func_iconv" != "xyes"; then
-       AC_MSG_ERROR([Cannot find the iconv() function.
-       iconv() is used to convert between UTF-8 and UTF-16 encodings of WIM
-       filenames and XML data.  Wimlib cannot be compiled without it.  iconv()
-       is available in the latest version of glibc and sometimes in other
-       libraries.])
-fi
-
 
 AC_ARG_WITH(pkgconfigdir,
             [  --with-pkgconfigdir=DIR      pkgconfig file in DIR @<:@LIBDIR/pkgconfig@:>@],
@@ -172,29 +164,38 @@ fi
 AC_SUBST([PTHREAD_LDADD], [$PTHREAD_LDADD])
 
 case "$host" in
-       *-*-cygwin*)
-               dnl -no-undefined is needed to build a DLL in a Cygwin environment.
-               CYGWIN_EXTRA_LDFLAGS="-no-undefined"
-
-               dnl -fvisibility=hidden should not be used when building PE
-               dnl binaries on Windows
+       *-*-mingw*)
+               # Native Windows
+               WINDOWS_EXTRA_LDFLAGS="-no-undefined"
                VISIBILITY_CFLAGS=""
-
                WITH_NTFS_3G_DEFAULT="no"
                WITH_FUSE_DEFAULT="no"
                WINDOWS_BUILD="yes"
+               WINDOWS_LDADD="-lshlwapi"
+               ;;
+       *-*-cygwin*)
+               # Cygwin (WARNING: not well supported)
+               WINDOWS_EXTRA_LDFLAGS="-no-undefined"
+               VISIBILITY_CFLAGS=""
+               WITH_NTFS_3G_DEFAULT="no"
+               WITH_FUSE_DEFAULT="no"
+               WINDOWS_BUILD="yes"
+               WINDOWS_LDADD=""
                ;;
        *)
-               CYGWIN_EXTRA_LDFLAGS=""
+               # UNIX / other
+               WINDOWS_EXTRA_LDFLAGS=""
                VISIBILITY_CFLAGS="-fvisibility=hidden"
                WITH_NTFS_3G_DEFAULT="yes"
                WITH_FUSE_DEFAULT="yes"
                WINDOWS_BUILD="no"
+               WINDOWS_LDADD=""
                ;;
 esac
 
-AC_SUBST([CYGWIN_EXTRA_LDFLAGS], [$CYGWIN_EXTRA_LDFLAGS])
+AC_SUBST([WINDOWS_EXTRA_LDFLAGS], [$WINDOWS_EXTRA_LDFLAGS])
 AC_SUBST([VISIBILITY_CFLAGS], [$VISIBILITY_CFLAGS])
+AC_SUBST([WINDOWS_LDADD], [$WINDOWS_LDADD])
 AM_CONDITIONAL([WINDOWS_BUILD], [test "x$WINDOWS_BUILD" = "xyes"])
 
 AC_MSG_CHECKING([whether to include support for ntfs-3g])
@@ -234,6 +235,17 @@ if test "x$WITH_NTFS_3G" = "xyes"; then
 else
        LIBNTFS_3G_LDADD=
        LIBNTFS_3G_CFLAGS=
+
+       if test "x$WINDOWS_BUILD" != "xyes"; then
+               AM_ICONV
+               if test "x$am_cv_func_iconv" != "xyes"; then
+                       AC_MSG_ERROR([Cannot find the iconv() function.
+                       iconv() is used to convert between UTF-8 and UTF-16 encodings of WIM
+                       filenames and XML data.  Wimlib cannot be compiled without it.  iconv()
+                       is available in the latest version of glibc and sometimes in other
+                       libraries.])
+               fi
+       fi
 fi
 AM_CONDITIONAL([WITH_NTFS_3G], [test "x$WITH_NTFS_3G" = "xyes"])
 
index d6d2617..1972505 100644 (file)
@@ -29,7 +29,7 @@
 #include <ctype.h>
 #include <errno.h>
 #include <getopt.h>
-#include <glob.h>
+
 #include <inttypes.h>
 #include <libgen.h>
 #include <limits.h>
 #include <alloca.h>
 #endif
 
+#ifdef __WIN32__
+#  include "imagex-win32.h"
+#else
+#  include <glob.h>
+#endif
+
 #define ARRAY_LEN(array) (sizeof(array) / sizeof(array[0]))
 
 #define for_opt(c, opts) while ((c = getopt_long_only(argc, (char**)argv, "", \
@@ -733,6 +739,7 @@ static int open_swms_from_glob(const char *swm_glob,
        glob_t globbuf;
        int ret;
 
+       /* Warning: glob() is replaced in Windows native builds */
        ret = glob(swm_glob, GLOB_ERR | GLOB_NOSORT, NULL, &globbuf);
        if (ret != 0) {
                if (ret == GLOB_NOMATCH) {
@@ -1322,9 +1329,10 @@ static int imagex_export(int argc, char **argv)
 
                wim_is_new = false;
                /* Destination file exists. */
-               if (!S_ISREG(stbuf.st_mode) && !S_ISLNK(stbuf.st_mode)) {
+
+               if (!S_ISREG(stbuf.st_mode)) {
                        imagex_error("`%s' is not a regular file",
-                                       dest_wimfile);
+                                    dest_wimfile);
                        ret = -1;
                        goto out;
                }
index b5f8c06..a57541f 100644 (file)
 #      include "timestamp.h"
 #endif
 
+#ifdef __WIN32__
+#include <shlwapi.h>
+#endif
+
 #include "wimlib_internal.h"
 #include "dentry.h"
 #include "lookup_table.h"
 #include "xml.h"
 #include <ctype.h>
 #include <errno.h>
+
+#ifndef __WIN32__
 #include <fnmatch.h>
+#endif
+
 #include <stdlib.h>
 #include <string.h>
 #include <unistd.h>
@@ -162,7 +170,7 @@ static int win32_get_security_descriptor(struct wim_dentry *dentry,
                DWORD len = lenNeeded;
                char buf[len];
                if (GetFileSecurityW(path_utf16, requestedInformation,
-                                    buf, len, &lenNeeded))
+                                    (PSECURITY_DESCRIPTOR)buf, len, &lenNeeded))
                {
                        int security_id = sd_set_add_sd(sd_set, buf, len);
                        if (security_id < 0)
@@ -1138,6 +1146,19 @@ static int capture_config_set_prefix(struct capture_config *config,
        return 0;
 }
 
+static bool path_matches_pattern(const char *path, const char *pattern)
+{
+#ifdef __WIN32__
+       return PathMatchSpecA(path, pattern);
+#else
+       return fnmatch(pattern, path, FNM_PATHNAME
+                       #ifdef FNM_CASEFOLD
+                                       | FNM_CASEFOLD
+                       #endif
+               ) == 0;
+#endif
+}
+
 static bool match_pattern(const char *path, const char *path_basename,
                          const struct pattern_list *list)
 {
@@ -1155,12 +1176,8 @@ static bool match_pattern(const char *path, const char *path_basename,
                                /* A file name pattern */
                                string = path_basename;
                }
-               if (fnmatch(pat, string, FNM_PATHNAME
-                       #ifdef FNM_CASEFOLD
-                                       | FNM_CASEFOLD
-                       #endif
-                       ) == 0)
-               {
+
+               if (path_matches_pattern(string, pat)) {
                        DEBUG("`%s' matches the pattern \"%s\"",
                              string, pat);
                        return true;
index 58869af..15a44ce 100644 (file)
@@ -974,6 +974,7 @@ void inode_remove_ads(struct wim_inode *inode, u16 idx,
        inode->i_num_ads--;
 }
 
+#ifndef __WIN32__
 int inode_get_unix_data(const struct wim_inode *inode,
                        struct wimlib_unix_data *unix_data,
                        u16 *stream_idx_ret)
@@ -1043,6 +1044,7 @@ int inode_set_unix_data(struct wim_inode *inode,
                inode_remove_ads(inode, stream_idx, lookup_table);
        return ret;
 }
+#endif /* !__WIN32__ */
 
 /*
  * Reads the alternate data stream entries of a WIM dentry.
index f5e4687..7608732 100644 (file)
@@ -413,6 +413,9 @@ struct wimlib_unix_data {
        u16 gid;
        u16 mode;
 } PACKED;
+
+#ifndef __WIN32__
+
 #define NO_UNIX_DATA (-1)
 #define BAD_UNIX_DATA (-2)
 extern int inode_get_unix_data(const struct wim_inode *inode,
@@ -428,6 +431,7 @@ extern int inode_set_unix_data(struct wim_inode *inode,
                               uid_t uid, gid_t gid, mode_t mode,
                               struct wim_lookup_table *lookup_table,
                               int which);
+#endif
 
 extern int read_dentry(const u8 metadata_resource[], u64 metadata_resource_len,
                       u64 offset, struct wim_dentry *dentry);
index d823f1d..bddb181 100644 (file)
@@ -21,6 +21,7 @@
  * along with wimlib; if not, see http://www.gnu.org/licenses/.
  */
 
+#include "config.h"
 #include "wimlib.h"
 #include "util.h"
 #include "endianness.h"
 #include <errno.h>
 
 #ifdef WITH_NTFS_3G
-#include <ntfs-3g/volume.h>
-#include <ntfs-3g/unistr.h>
+#  include <ntfs-3g/volume.h>
+#  include <ntfs-3g/unistr.h>
+#elif defined(__WIN32__)
+#  include <wchar.h>
+#  include <stdlib.h>
 #else
-#include <iconv.h>
+#  include <iconv.h>
 #endif
 
 /*
@@ -41,7 +45,7 @@
  * libntfs-3g/unistr.c in the NTFS-3g sources.  (Modified slightly to remove
  * unneeded functionality.)
  */
-#ifndef WITH_NTFS_3G
+#if !defined(WITH_NTFS_3G) && !defined(__WIN32__)
 /*
  * Return the amount of 8-bit elements in UTF-8 needed (without the terminating
  * null) to store a given UTF-16LE string.
@@ -130,9 +134,7 @@ static int utf8_to_utf16_size(const char *s)
        }
        return count;
 }
-#endif /* !WITH_NTFS_3G */
 
-#ifndef WITH_NTFS_3G
 static iconv_t cd_utf8_to_utf16 = (iconv_t)(-1);
 static iconv_t cd_utf16_to_utf8 = (iconv_t)(-1);
 
@@ -171,7 +173,7 @@ void iconv_global_cleanup()
        if (cd_utf16_to_utf8 != (iconv_t)(-1))
                iconv_close(cd_utf16_to_utf8);
 }
-#endif
+#endif /* !WITH_NTFS_3G && !__WIN32__ */
 
 /* Converts a string in the UTF-16LE encoding to a newly allocated string in the
  * UTF-8 encoding.
@@ -208,8 +210,24 @@ int utf16_to_utf8(const char *utf16_str, size_t utf16_nbytes,
                else
                        ret = WIMLIB_ERR_INVALID_UTF16_STRING;
        }
-#else /* !WITH_NTFS_3G */
-
+#elif defined(__WIN32__)
+       char *utf8_str;
+       size_t utf8_nbytes;
+       utf8_nbytes = wcstombs(NULL, (const wchar_t*)utf16_str, 0);
+       if (utf8_nbytes == (size_t)(-1)) {
+               ret = WIMLIB_ERR_INVALID_UTF16_STRING;
+       } else {
+               utf8_str = MALLOC(utf8_nbytes + 1);
+               if (!utf8_str) {
+                       ret = WIMLIB_ERR_NOMEM;
+               } else {
+                       wcstombs(utf8_str, (const wchar_t*)utf16_str, utf8_nbytes + 1);
+                       *utf8_str_ret = utf8_str;
+                       *utf8_nbytes_ret = utf8_nbytes;
+                       ret = 0;
+               }
+       }
+#else
        ret = iconv_global_init();
        if (ret != 0)
                return ret;
@@ -296,8 +314,27 @@ int utf8_to_utf16(const char *utf8_str, size_t utf8_nbytes,
                else
                        ret = WIMLIB_ERR_INVALID_UTF8_STRING;
        }
-#else /* !WITH_NTFS_3G */
+#elif defined(__WIN32__)
 
+       char *utf16_str;
+       size_t utf16_nchars;
+       utf16_nchars = mbstowcs(NULL, utf8_str, 0);
+       if (utf16_nchars == (size_t)(-1)) {
+               ret = WIMLIB_ERR_INVALID_UTF8_STRING;
+       } else {
+               utf16_str = MALLOC((utf16_nchars + 1) * sizeof(wchar_t));
+               if (!utf16_str) {
+                       ret = WIMLIB_ERR_NOMEM;
+               } else {
+                       mbstowcs((wchar_t*)utf16_str, utf8_str,
+                                utf16_nchars + 1);
+                       *utf16_str_ret = utf16_str;
+                       *utf16_nbytes_ret = utf16_nchars * sizeof(wchar_t);
+                       ret = 0;
+               }
+       }
+       
+#else
        ret = iconv_global_init();
        if (ret != 0)
                return ret;
index 8e5d130..8606381 100644 (file)
 #include <alloca.h>
 #endif
 
+#if defined(__WIN32__)
+#      define swprintf _snwprintf
+#      define mkdir(path, mode) (!CreateDirectoryA(path, NULL))
+#endif
+
 #if defined(__CYGWIN__) || defined(__WIN32__)
 
 static int win32_set_reparse_data(HANDLE h,
index 9db817a..31b51ff 100644 (file)
  * along with wimlib; if not, see http://www.gnu.org/licenses/.
  */
 
+#include "config.h"
+
+#define MINGW_HAS_SECURE_API
+
 #undef _GNU_SOURCE
 /* Make sure the POSIX-compatible strerror_r() is declared, rather than the GNU
  * version, which has a different return type. */
 
 #include <unistd.h> /* for getpid() */
 
+/* Windoze compatibility */
+#ifdef __WIN32__
+#  define strerror_r(errnum, buf, bufsize) strerror_s(buf, bufsize, errnum)
+#endif
+
 /* True if wimlib is to print an informational message when an error occurs.
  * This can be turned off by calling wimlib_set_print_errors(false). */
 #ifdef ENABLE_ERROR_MESSAGES
@@ -54,7 +63,8 @@ static void wimlib_vmsg(const char *tag, const char *format,
                vfprintf(stderr, format, va);
                if (perror && errno_save != 0) {
                        char buf[50];
-                       int res = strerror_r(errno_save, buf, sizeof(buf));
+                       int res;
+                       res = strerror_r(errno_save, buf, sizeof(buf));
                        if (res) {
                                snprintf(buf, sizeof(buf),
                                         "unknown error (errno=%d)", errno_save);
index 2dc7943..b56fa4f 100644 (file)
@@ -175,7 +175,7 @@ extern char *wimlib_strdup(const char *str);
 
 /* encoding.c */
 
-#ifdef WITH_NTFS_3G
+#if defined(WITH_NTFS_3G) || defined(__WIN32__)
 static inline int iconv_global_init()
 {
        return 0;
index bd31c5b..1ffc3fe 100644 (file)
--- a/src/wim.c
+++ b/src/wim.c
  */
 
 #include "config.h"
+
+#ifdef __WIN32__
+#      include <windows.h>
+#      ifdef ERROR
+#              undef ERROR
+#      endif
+#endif
+
 #include <limits.h>
 #include <stdlib.h>
 #include <stdarg.h>
 #include "lookup_table.h"
 #include "xml.h"
 
+#ifdef __WIN32__
+static char *realpath(const char *path, char *resolved_path)
+{
+       DWORD ret;
+       wimlib_assert(resolved_path == NULL);
+
+       ret = GetFullPathNameA(path, 0, NULL, NULL);
+       if (!ret)
+               goto fail_win32;
+
+       resolved_path = MALLOC(ret + 1);
+       if (!resolved_path)
+               goto fail;
+       ret = GetFullPathNameA(path, ret, resolved_path, NULL);
+       if (!ret) {
+               free(resolved_path);
+               goto fail_win32;
+       }
+       return resolved_path;
+fail_win32:
+       win32_error(GetLastError());
+fail:
+       return NULL;
+}
+#endif
+
 static int image_print_metadata(WIMStruct *w)
 {
        DEBUG("Printing metadata for image %d", w->current_image);
index 4e59b85..ea3f583 100644 (file)
 #include <sys/file.h>
 #endif
 
+#ifdef __WIN32__
+#      include <windows.h>
+#      ifdef ERROR
+#              undef ERROR
+#      endif
+#endif
+
 #include "list.h"
 #include "wimlib_internal.h"
 #include "buffer_io.h"
 #include <stdlib.h>
 #endif
 
+#ifdef __WIN32__
+#      ifdef fsync
+#              undef fsync
+#      endif
+#      define fsync(fd) 0
+#endif
+
 static int fflush_and_ftruncate(FILE *fp, off_t size)
 {
        int ret;
@@ -1205,6 +1219,16 @@ out:
        return ret;
 }
 
+static long get_default_num_threads()
+{
+#ifdef __WIN32__
+       SYSTEM_INFO sysinfo;
+       GetSystemInfo(&sysinfo);
+       return sysinfo.dwNumberOfProcessors;
+#else
+       return sysconf(_SC_NPROCESSORS_ONLN);
+#endif
+}
 
 static int write_stream_list_parallel(struct list_head *stream_list,
                                      FILE *out_fp,
@@ -1220,8 +1244,8 @@ static int write_stream_list_parallel(struct list_head *stream_list,
        pthread_t *compressor_threads = NULL;
 
        if (num_threads == 0) {
-               long nthreads = sysconf(_SC_NPROCESSORS_ONLN);
-               if (nthreads < 1) {
+               long nthreads = get_default_num_threads();
+               if (nthreads < 1 || nthreads > UINT_MAX) {
                        WARNING("Could not determine number of processors! Assuming 1");
                        goto out_serial;
                } else {