Encodings update (IN PROGRESS)
authorEric Biggers <ebiggers3@gmail.com>
Sat, 23 Mar 2013 03:11:51 +0000 (22:11 -0500)
committerEric Biggers <ebiggers3@gmail.com>
Sat, 23 Mar 2013 03:11:51 +0000 (22:11 -0500)
27 files changed:
src/add_image.c
src/dentry.c
src/dentry.h
src/encoding.c
src/export_image.c
src/extract_image.c
src/integrity.c
src/join.c
src/lookup_table.c
src/lookup_table.h
src/mount_image.c
src/resource.c
src/sha1.c
src/sha1.h
src/split.c
src/symlink.c
src/timestamp.h
src/util.c
src/util.h
src/wim.c
src/wimlib.h
src/wimlib_internal.h
src/win32.c
src/win32.h
src/write.c
src/xml.c
src/xml.h

index cf89e69..c7464d9 100644 (file)
 #include <ctype.h>
 #include <errno.h>
 #include <stdlib.h>
-#include <string.h>
+
+#if TCHAR_IS_UTF16LE
+#  include <wchar.h>
+#else
+#  include <string.h>
+#endif
+
 #include <unistd.h>
 
 #ifdef HAVE_ALLOCA_H
@@ -101,9 +107,9 @@ err:
 
 #ifndef __WIN32__
 /*
- * build_dentry_tree():
+ * unix_build_dentry_tree():
  *     Recursively builds a tree of WIM dentries from an on-disk directory
- *     tree.
+ *     tree (UNIX version; no NTFS-specific data is captured).
  *
  * @root_ret:   Place to return a pointer to the root of the dentry tree.  Only
  *             modified if successful.  Set to NULL if the file or directory was
@@ -136,7 +142,7 @@ err:
  */
 static int
 unix_build_dentry_tree(struct wim_dentry **root_ret,
-                      const mbchar *root_disk_path,
+                      const char *root_disk_path,
                       struct wim_lookup_table *lookup_table,
                       struct wim_security_data *sd,
                       const struct capture_config *config,
@@ -276,7 +282,7 @@ unix_build_dentry_tree(struct wim_dentry **root_ret,
                        DEBUG("Add lte reference %u for `%s'", lte->refcnt,
                              root_disk_path);
                } else {
-                       mbchar *file_on_disk = STRDUP(root_disk_path);
+                       char *file_on_disk = STRDUP(root_disk_path);
                        if (!file_on_disk) {
                                ERROR("Failed to allocate memory for file path");
                                ret = WIMLIB_ERR_NOMEM;
@@ -314,7 +320,7 @@ unix_build_dentry_tree(struct wim_dentry **root_ret,
 
                /* Buffer for names of files in directory. */
                size_t len = strlen(root_disk_path);
-               mbchar name[len + 1 + FILENAME_MAX + 1];
+               char name[len + 1 + FILENAME_MAX + 1];
                memcpy(name, root_disk_path, len);
                name[len] = '/';
 
@@ -358,7 +364,7 @@ unix_build_dentry_tree(struct wim_dentry **root_ret,
                 * drive letter).
                 */
 
-               mbchar deref_name_buf[4096];
+               char deref_name_buf[4096];
                ssize_t deref_name_len;
 
                deref_name_len = readlink(root_disk_path, deref_name_buf,
@@ -410,10 +416,11 @@ enum pattern_type {
 #define COMPAT_DEFAULT_CONFIG
 
 /* Default capture configuration file when none is specified. */
-static const mbchar *default_config =
+static const tchar *default_config =
 #ifdef COMPAT_DEFAULT_CONFIG /* XXX: This policy is being moved to library
                                users.  The next ABI-incompatible library
                                version will default to the empty string here. */
+T(
 "[ExclusionList]\n"
 "\\$ntfs.log\n"
 "\\hiberfil.sys\n"
@@ -426,9 +433,10 @@ static const mbchar *default_config =
 "*.mp3\n"
 "*.zip\n"
 "*.cab\n"
-"\\WINDOWS\\inf\\*.pnf\n";
+"\\WINDOWS\\inf\\*.pnf\n"
+);
 #else
-"";
+T("");
 #endif
 
 static void
@@ -450,9 +458,9 @@ destroy_capture_config(struct capture_config *config)
 }
 
 static int
-pattern_list_add_pattern(struct pattern_list *list, const mbchar *pattern)
+pattern_list_add_pattern(struct pattern_list *list, const tchar *pattern)
 {
-       const mbchar **pats;
+       const tchar **pats;
        if (list->num_pats >= list->num_allocated_pats) {
                pats = REALLOC(list->pats,
                               sizeof(list->pats[0]) * (list->num_allocated_pats + 8));
@@ -469,33 +477,34 @@ pattern_list_add_pattern(struct pattern_list *list, const mbchar *pattern)
  * `struct capture_config'. */
 static int
 init_capture_config(struct capture_config *config,
-                   const mbchar *_config_str, size_t config_len)
+                   const tchar *_config_str,
+                   size_t config_num_tchars)
 {
-       mbchar *config_str;
-       mbchar *p;
-       mbchar *eol;
-       mbchar *next_p;
-       size_t bytes_remaining;
+       tchar *config_str;
+       tchar *p;
+       tchar *eol;
+       tchar *next_p;
+       size_t num_tchars_remaining;
        enum pattern_type type = NONE;
        int ret;
        unsigned long line_no = 0;
 
-       DEBUG("config_len = %zu", config_len);
-       bytes_remaining = config_len;
+       DEBUG("config_num_tchars = %zu", config_num_tchars);
+       num_tchars_remaining = config_num_tchars;
        memset(config, 0, sizeof(*config));
-       config_str = MALLOC(config_len);
+       config_str = TMALLOC(config_num_tchars);
        if (!config_str) {
                ERROR("Could not duplicate capture config string");
                return WIMLIB_ERR_NOMEM;
        }
 
-       memcpy(config_str, _config_str, config_len);
+       tmemcpy(config_str, _config_str, config_num_tchars);
        next_p = config_str;
        config->config_str = config_str;
-       while (bytes_remaining) {
+       while (num_tchars_remaining != 0) {
                line_no++;
                p = next_p;
-               eol = memchr(p, '\n', bytes_remaining);
+               eol = tmemchr(p, T('\n'), num_tchars_remaining);
                if (!eol) {
                        ERROR("Expected end-of-line in capture config file on "
                              "line %lu", line_no);
@@ -504,50 +513,51 @@ init_capture_config(struct capture_config *config,
                }
 
                next_p = eol + 1;
-               bytes_remaining -= (next_p - p);
+               num_tchars_remaining -= (next_p - p);
                if (eol == p)
                        continue;
 
-               if (*(eol - 1) == '\r')
+               if (*(eol - 1) == T('\r'))
                        eol--;
-               *eol = '\0';
+               *eol = T('\0');
 
                /* Translate backslash to forward slash */
-               for (mbchar *pp = p; pp != eol; pp++)
-                       if (*pp == '\\')
-                               *pp = '/';
+               for (tchar *pp = p; pp != eol; pp++)
+                       if (*pp == T('\\'))
+                               *pp = T('/');
 
-               /* Remove drive letter */
-               if (eol - p > 2 && isalpha(*p) && *(p + 1) == ':')
+               /* Remove drive letter 
+                * XXX maybe keep drive letter on Windows */
+               if (eol - p > 2 && istalpha(*p) && *(p + 1) == T(':'))
                        p += 2;
 
                ret = 0;
-               if (strcmp(p, "[ExclusionList]") == 0)
+               if (tstrcmp(p, T("[ExclusionList]")) == 0)
                        type = EXCLUSION_LIST;
-               else if (strcmp(p, "[ExclusionException]") == 0)
+               else if (tstrcmp(p, T("[ExclusionException]")) == 0)
                        type = EXCLUSION_EXCEPTION;
-               else if (strcmp(p, "[CompressionExclusionList]") == 0)
+               else if (tstrcmp(p, T("[CompressionExclusionList]")) == 0)
                        type = COMPRESSION_EXCLUSION_LIST;
-               else if (strcmp(p, "[AlignmentList]") == 0)
+               else if (tstrcmp(p, T("[AlignmentList]")) == 0)
                        type = ALIGNMENT_LIST;
-               else if (p[0] == '[' && strrchr(p, ']')) {
-                       ERROR("Unknown capture configuration section `%s'", p);
+               else if (p[0] == T('[') && tstrrchr(p, T(']'))) {
+                       ERROR("Unknown capture configuration section \"%"TS"\"", p);
                        ret = WIMLIB_ERR_INVALID_CAPTURE_CONFIG;
                } else switch (type) {
                case EXCLUSION_LIST:
-                       DEBUG("Adding pattern \"%s\" to exclusion list", p);
+                       DEBUG("Adding pattern \"%"TS"\" to exclusion list", p);
                        ret = pattern_list_add_pattern(&config->exclusion_list, p);
                        break;
                case EXCLUSION_EXCEPTION:
-                       DEBUG("Adding pattern \"%s\" to exclusion exception list", p);
+                       DEBUG("Adding pattern \"%"TS"\" to exclusion exception list", p);
                        ret = pattern_list_add_pattern(&config->exclusion_exception, p);
                        break;
                case COMPRESSION_EXCLUSION_LIST:
-                       DEBUG("Adding pattern \"%s\" to compression exclusion list", p);
+                       DEBUG("Adding pattern \"%"TS"\" to compression exclusion list", p);
                        ret = pattern_list_add_pattern(&config->compression_exclusion_list, p);
                        break;
                case ALIGNMENT_LIST:
-                       DEBUG("Adding pattern \"%s\" to alignment list", p);
+                       DEBUG("Adding pattern \"%"TS"\" to alignment list", p);
                        ret = pattern_list_add_pattern(&config->alignment_list, p);
                        break;
                default:
@@ -567,30 +577,30 @@ out_destroy:
 }
 
 static int capture_config_set_prefix(struct capture_config *config,
-                                    const mbchar *_prefix)
+                                    const tchar *_prefix)
 {
-       mbchar *prefix = STRDUP(_prefix);
+       tchar *prefix = TSTRDUP(_prefix);
 
        if (!prefix)
                return WIMLIB_ERR_NOMEM;
        FREE(config->prefix);
        config->prefix = prefix;
-       config->prefix_len = strlen(prefix);
+       config->prefix_num_tchars = tstrlen(prefix);
        return 0;
 }
 
-static bool match_pattern(const mbchar *path,
-                         const mbchar *path_basename,
+static bool match_pattern(const tchar *path,
+                         const tchar *path_basename,
                          const struct pattern_list *list)
 {
        for (size_t i = 0; i < list->num_pats; i++) {
-               const mbchar *pat = list->pats[i];
-               const mbchar *string;
+               const tchar *pat = list->pats[i];
+               const tchar *string;
                if (pat[0] == '/')
                        /* Absolute path from root of capture */
                        string = path;
                else {
-                       if (strchr(pat, '/'))
+                       if (tstrchr(pat, T('/')))
                                /* Relative path from root of capture */
                                string = path + 1;
                        else
@@ -606,7 +616,7 @@ static bool match_pattern(const mbchar *path,
                                #endif
                            ) == 0)
                {
-                       DEBUG("`%s' matches the pattern \"%s\"",
+                       DEBUG("\"%"TS"\" matches the pattern \"%"TS"\"",
                              string, pat);
                        return true;
                }
@@ -624,15 +634,15 @@ static bool match_pattern(const mbchar *path,
  * directory.
  */
 bool
-exclude_path(const mbchar *path, const struct capture_config *config,
+exclude_path(const tchar *path, const struct capture_config *config,
             bool exclude_prefix)
 {
-       const mbchar *basename = path_basename(path);
+       const tchar *basename = path_basename(path);
        if (exclude_prefix) {
-               wimlib_assert(strlen(path) >= config->prefix_len);
-               if (memcmp(config->prefix, path, config->prefix_len) == 0
-                    && path[config->prefix_len] == '/')
-                       path += config->prefix_len;
+               wimlib_assert(tstrlen(path) >= config->prefix_num_tchars);
+               if (tmemcmp(config->prefix, path, config->prefix_num_tchars) == 0
+                    && path[config->prefix_num_tchars] == T('/'))
+                       path += config->prefix_num_tchars;
        }
        return match_pattern(path, basename, &config->exclusion_list) &&
                !match_pattern(path, basename, &config->exclusion_exception);
@@ -641,58 +651,56 @@ exclude_path(const mbchar *path, const struct capture_config *config,
 
 /* Strip leading and trailing forward slashes from a string.  Modifies it in
  * place and returns the stripped string. */
-static const char *
-canonicalize_target_path(char *target_path)
+static const tchar *
+canonicalize_target_path(tchar *target_path)
 {
-       char *p;
+       tchar *p;
        if (target_path == NULL)
-               return "";
+               return T("");
        for (;;) {
-               if (*target_path == '\0')
+               if (*target_path == T('\0'))
                        return target_path;
-               else if (*target_path == '/')
+               else if (*target_path == T('/'))
                        target_path++;
                else
                        break;
        }
 
-       p = target_path + strlen(target_path) - 1;
-       while (*p == '/')
-               *p-- = '\0';
+       p = target_path + tstrlen(target_path) - 1;
+       while (*p == T('/'))
+               *p-- = T('\0');
        return target_path;
 }
 
-#ifdef __WIN32__
 static void
-zap_backslashes(char *s)
+zap_backslashes(tchar *s)
 {
        while (*s) {
-               if (*s == '\\')
-                       *s = '/';
+               if (*s == T('\\'))
+                       *s = T('/');
                s++;
        }
 }
-#endif
 
 /* Strip leading and trailing slashes from the target paths */
 static void
 canonicalize_targets(struct wimlib_capture_source *sources, size_t num_sources)
 {
        while (num_sources--) {
-               DEBUG("Canonicalizing { source: \"%s\", target=\"%s\"}",
+               DEBUG("Canonicalizing { source: \"%"TS"\", target=\"%"TS"\"}",
                      sources->fs_source_path,
                      sources->wim_target_path);
-#ifdef __WIN32__
+
                /* The Windows API can handle forward slashes.  Just get rid of
                 * backslashes to avoid confusing other parts of the library
                 * code. */
                zap_backslashes(sources->fs_source_path);
                if (sources->wim_target_path)
                        zap_backslashes(sources->wim_target_path);
-#endif
+
                sources->wim_target_path =
-                       (char*)canonicalize_target_path(sources->wim_target_path);
-               DEBUG("Canonical target: \"%s\"", sources->wim_target_path);
+                       (tchar*)canonicalize_target_path(sources->wim_target_path);
+               DEBUG("Canonical target: \"%"TS"\"", sources->wim_target_path);
                sources++;
        }
 }
@@ -701,7 +709,7 @@ static int
 capture_source_cmp(const void *p1, const void *p2)
 {
        const struct wimlib_capture_source *s1 = p1, *s2 = p2;
-       return strcmp(s1->wim_target_path, s2->wim_target_path);
+       return tstrcmp(s1->wim_target_path, s2->wim_target_path);
 }
 
 /* Sorts the capture sources lexicographically by target path.  This occurs
@@ -772,12 +780,12 @@ check_sorted_sources(struct wimlib_capture_source *sources, size_t num_sources,
 /* Creates a new directory to place in the WIM image.  This is to create parent
  * directories that are not part of any target as needed.  */
 static int
-new_filler_directory(const mbchar *name, struct wim_dentry **dentry_ret)
+new_filler_directory(const tchar *name, struct wim_dentry **dentry_ret)
 {
        int ret;
        struct wim_dentry *dentry;
 
-       DEBUG("Creating filler directory \"%s\"", name);
+       DEBUG("Creating filler directory \"%"TS"\"", name);
        ret = new_dentry_with_inode(name, &dentry);
        if (ret == 0) {
                /* Leave the inode number as 0 for now.  The final inode number
@@ -797,12 +805,12 @@ do_overlay(struct wim_dentry *target, struct wim_dentry *branch)
 {
        struct rb_root *rb_root;
 
-       DEBUG("Doing overlay \"%W\" => \"%W\"",
+       DEBUG("Doing overlay \"%"WS"\" => \"%"WS"\"",
              branch->file_name, target->file_name);
 
        if (!dentry_is_directory(target)) {
-               ERROR("Cannot overlay directory \"%W\" over non-directory",
-                     branch->file_name);
+               ERROR("Cannot overlay directory \"%"WS"\" "
+                     "over non-directory", branch->file_name);
                return WIMLIB_ERR_INVALID_OVERLAY;
        }
 
@@ -815,8 +823,8 @@ do_overlay(struct wim_dentry *target, struct wim_dentry *branch)
                        /* Revert the change to avoid leaking the directory tree
                         * rooted at @child */
                        dentry_add_child(branch, child);
-                       ERROR("Overlay error: file \"%W\" already exists "
-                             "as a child of \"%W\"",
+                       ERROR("Overlay error: file \"%"WS"\" already exists "
+                             "as a child of \"%"WS"\"",
                              child->file_name, target->file_name);
                        return WIMLIB_ERR_INVALID_OVERLAY;
                }
@@ -839,16 +847,16 @@ do_overlay(struct wim_dentry *target, struct wim_dentry *branch)
  */
 static int
 attach_branch(struct wim_dentry **root_p, struct wim_dentry *branch,
-             mbchar *target_path)
+             tchar *target_path)
 {
-       mbchar *slash;
+       tchar *slash;
        struct wim_dentry *dentry, *parent, *target;
        int ret;
 
-       DEBUG("Attaching branch \"%W\" => \"%s\"",
+       DEBUG("Attaching branch \"%"WS"\" => \"%"TS"\"",
              branch->file_name, target_path);
 
-       if (*target_path == '\0') {
+       if (*target_path == T('\0')) {
                /* Target: root directory */
                if (*root_p) {
                        /* Overlay on existing root */
@@ -863,7 +871,7 @@ attach_branch(struct wim_dentry **root_p, struct wim_dentry *branch,
        /* Adding a non-root branch.  Create root if it hasn't been created
         * already. */
        if (!*root_p) {
-               ret  = new_filler_directory("", root_p);
+               ret  = new_filler_directory(T(""), root_p);
                if (ret)
                        return ret;
        }
@@ -871,7 +879,7 @@ attach_branch(struct wim_dentry **root_p, struct wim_dentry *branch,
        /* Walk the path to the branch, creating filler directories as needed.
         * */
        parent = *root_p;
-       while ((slash = strchr(target_path, '/'))) {
+       while ((slash = tstrchr(target_path, T('/')))) {
                *slash = '\0';
                dentry = get_dentry_child_with_name(parent, target_path);
                if (!dentry) {
@@ -887,7 +895,7 @@ attach_branch(struct wim_dentry **root_p, struct wim_dentry *branch,
                 * trailing slashes were tripped.  */
                do {
                        ++target_path;
-               } while (*target_path == '/');
+               } while (*target_path == T('/'));
        }
 
        /* If the target path already existed, overlay the branch onto it.
@@ -906,14 +914,14 @@ WIMLIBAPI int
 wimlib_add_image_multisource(WIMStruct *w,
                             struct wimlib_capture_source *sources,
                             size_t num_sources,
-                            const utf8char *name,
-                            const mbchar *config_str,
+                            const tchar *name,
+                            const tchar *config_str,
                             size_t config_len,
                             int add_image_flags,
                             wimlib_progress_func_t progress_func)
 {
        int (*capture_tree)(struct wim_dentry **,
-                           const mbchar *,
+                           const tchar *,
                            struct wim_lookup_table *,
                            struct wim_security_data *,
                            const struct capture_config *,
@@ -977,7 +985,7 @@ wimlib_add_image_multisource(WIMStruct *w,
        }
 
        if (wimlib_image_name_in_use(w, name)) {
-               ERROR("There is already an image named \"%U\" in the WIM!",
+               ERROR("There is already an image named \"%"TS"\" in the WIM!",
                      name);
                return WIMLIB_ERR_IMAGE_NAME_COLLISION;
        }
@@ -985,7 +993,7 @@ wimlib_add_image_multisource(WIMStruct *w,
        if (!config_str) {
                DEBUG("Using default capture configuration");
                config_str = default_config;
-               config_len = strlen(default_config);
+               config_len = tstrlen(default_config);
        }
        ret = init_capture_config(&config, config_str, config_len);
        if (ret)
@@ -1017,7 +1025,7 @@ wimlib_add_image_multisource(WIMStruct *w,
                union wimlib_progress_info progress;
 
                DEBUG("Building dentry tree for source %zu of %zu "
-                     "(\"%s\" => \"%s\")", i + 1, num_sources,
+                     "(\"%"TS"\" => \"%"TS"\")", i + 1, num_sources,
                      sources[i].fs_source_path,
                      sources[i].wim_target_path);
                if (progress_func) {
@@ -1039,7 +1047,7 @@ wimlib_add_image_multisource(WIMStruct *w,
                                      flags,
                                      progress_func, extra_arg);
                if (ret) {
-                       ERROR("Failed to build dentry tree for `%s'",
+                       ERROR("Failed to build dentry tree for `%"TS"'",
                              sources[i].fs_source_path);
                        goto out_free_dentry_tree;
                }
@@ -1063,7 +1071,7 @@ wimlib_add_image_multisource(WIMStruct *w,
        }
 
        if (root_dentry == NULL) {
-               ret = new_filler_directory("" , &root_dentry);
+               ret = new_filler_directory(T(""), &root_dentry);
                if (ret)
                        goto out_free_dentry_tree;
        }
@@ -1113,9 +1121,9 @@ out:
 
 WIMLIBAPI int
 wimlib_add_image(WIMStruct *w,
-                const mbchar *source,
-                const utf8char *name,
-                const mbchar *config_str,
+                const tchar *source,
+                const tchar *name,
+                const tchar *config_str,
                 size_t config_len,
                 int add_image_flags,
                 wimlib_progress_func_t progress_func)
@@ -1123,7 +1131,7 @@ wimlib_add_image(WIMStruct *w,
        if (!source || !*source)
                return WIMLIB_ERR_INVALID_PARAM;
 
-       mbchar *fs_source_path = STRDUP(source);
+       tchar *fs_source_path = TSTRDUP(source);
        int ret;
        struct wimlib_capture_source capture_src = {
                .fs_source_path = fs_source_path,
index 287551b..503dbba 100644 (file)
 #include "wimlib_internal.h"
 #include <errno.h>
 
+#ifdef TCHAR_IS_UTF16LE
+#  include <wchar.h>
+#endif
+
 /* Calculates the unaligned length, in bytes, of an on-disk WIM dentry that has
  * a file name and short name that take the specified numbers of bytes.  This
  * excludes any alternate data stream entries that may follow the dentry. */
@@ -76,36 +80,46 @@ ads_entry_has_name(const struct wim_ads_entry *entry,
               memcmp(entry->stream_name, name, name_nbytes) == 0;
 }
 
-/* Duplicates a multibyte string into a UTF-16LE string and returns the string
- * and its length, in bytes, in the pointer arguments.  Frees any existing
- * string at the return location before overwriting it. */
+/* Duplicates a string of system-dependent encoding into a UTF-16LE string and
+ * returns the string and its length, in bytes, in the pointer arguments.  Frees
+ * any existing string at the return location before overwriting it. */
 static int
-get_utf16le_name(const mbchar *name, utf16lechar **name_utf16le_ret,
+get_utf16le_name(const tchar *name, utf16lechar **name_utf16le_ret,
                 u16 *name_utf16le_nbytes_ret)
 {
        utf16lechar *name_utf16le;
        size_t name_utf16le_nbytes;
        int ret;
+#if TCHAR_IS_UTF16LE
+       name_utf16le_nbytes = tstrlen(name) * 2;
+       name_utf16le = MALLOC(name_utf16le_nbytes + 2);
+       if (!name_utf16le)
+               return WIMLIB_ERR_NOMEM;
+       memcpy(name_utf16le, name, name_utf16le_nbytes + 2);
+       ret = 0;
+#else
 
-       ret = mbs_to_utf16le(name, strlen(name), &name_utf16le,
-                            &name_utf16le_nbytes);
+       ret = tstr_to_utf16le(name, strlen(name), &name_utf16le,
+                             &name_utf16le_nbytes);
        if (ret == 0) {
                if (name_utf16le_nbytes > 0xffff) {
                        FREE(name_utf16le);
                        ERROR("Multibyte string \"%s\" is too long!", name);
                        ret = WIMLIB_ERR_INVALID_UTF8_STRING;
-               } else {
-                       FREE(*name_utf16le_ret);
-                       *name_utf16le_ret = name_utf16le;
-                       *name_utf16le_nbytes_ret = name_utf16le_nbytes;
                }
        }
+#endif
+       if (ret == 0) {
+               FREE(*name_utf16le_ret);
+               *name_utf16le_ret = name_utf16le;
+               *name_utf16le_nbytes_ret = name_utf16le_nbytes;
+       }
        return ret;
 }
 
 /* Sets the name of a WIM dentry from a multibyte string. */
 int
-set_dentry_name(struct wim_dentry *dentry, const mbchar *new_name)
+set_dentry_name(struct wim_dentry *dentry, const tchar *new_name)
 {
        int ret;
        ret = get_utf16le_name(new_name, &dentry->file_name,
@@ -268,50 +282,60 @@ for_dentry_in_tree_depth(struct wim_dentry *root,
 int
 calculate_dentry_full_path(struct wim_dentry *dentry, void *ignore)
 {
-       char *full_path;
+       tchar *full_path;
        u32 full_path_nbytes;
 
        wimlib_assert(dentry_is_root(dentry) ||
                      dentry->parent->full_path != NULL);
 
        if (dentry_is_root(dentry)) {
-               full_path = MALLOC(2);
+               full_path = TMALLOC(2);
                if (!full_path)
                        return WIMLIB_ERR_NOMEM;
-               full_path[0] = '/';
-               full_path[1] = '\0';
-               full_path_nbytes = 1;
+               full_path[0] = T('/');
+               full_path[1] = T('\0');
+               full_path_nbytes = 1 * sizeof(tchar);
        } else {
-               char *parent_full_path;
+               tchar *parent_full_path;
                u32 parent_full_path_nbytes;
                const struct wim_dentry *parent;
-               size_t name_mbs_nbytes;
+               size_t filename_nbytes;
                int ret;
 
-               ret = utf16le_to_mbs_nbytes(dentry->file_name,
-                                           dentry->file_name_nbytes,
-                                           &name_mbs_nbytes);
-               if (ret)
-                       return ret;
                parent = dentry->parent;
                if (dentry_is_root(parent)) {
-                       parent_full_path = "";
+                       parent_full_path = T("");
                        parent_full_path_nbytes = 0;
                } else {
                        parent_full_path = parent->full_path;
                        parent_full_path_nbytes = parent->full_path_nbytes;
                }
-               full_path_nbytes = parent_full_path_nbytes + 1 +
-                                  name_mbs_nbytes;
-               full_path = MALLOC(full_path_nbytes + 1);
+       #if TCHAR_IS_UTF16LE
+               filename_nbytes = dentry->file_name_nbytes;
+       #else
+               ret = utf16le_to_mbs_nbytes(dentry->file_name,
+                                           dentry->file_name_nbytes,
+                                           &filename_nbytes);
+               if (ret)
+                       return ret;
+       #endif
+
+               full_path_nbytes = parent_full_path_nbytes + sizeof(tchar) +
+                                  dentry->file_name_nbytes;
+               full_path = MALLOC(full_path_nbytes + sizeof(tchar));
                if (!full_path)
                        return WIMLIB_ERR_NOMEM;
                memcpy(full_path, parent_full_path, parent_full_path_nbytes);
-               full_path[parent_full_path_nbytes] = '/';
-
+               full_path[parent_full_path_nbytes] = T('/');
+       #if TCHAR_IS_UTF16LE
+               memcpy(&full_path[parent_full_path_nbytes + 1],
+                      dentry->file_name,
+                      dentry->file_name_nbytes + sizeof(tchar));
+       #else
                utf16le_to_mbs_buf(dentry->file_name,
                                   dentry->file_name_nbytes,
                                   &full_path[parent_full_path_nbytes + 1]);
+       #endif
        }
        FREE(dentry->full_path);
        dentry->full_path = full_path;
@@ -413,15 +437,19 @@ get_dentry_child_with_utf16le_name(const struct wim_dentry *dentry,
 /* Returns the child of @dentry that has the file name @name.  Returns NULL if
  * no child has the name. */
 struct wim_dentry *
-get_dentry_child_with_name(const struct wim_dentry *dentry, const mbchar *name)
+get_dentry_child_with_name(const struct wim_dentry *dentry, const tchar *name)
 {
+#if TCHAR_IS_UTF16LE
+       return get_dentry_child_with_utf16le_name(dentry, name,
+                                                 tstrlen(name) * sizeof(tchar));
+#else
        utf16lechar *utf16le_name;
        size_t utf16le_name_nbytes;
        int ret;
        struct wim_dentry *child;
 
-       ret = mbs_to_utf16le(name, strlen(name),
-                            &utf16le_name, &utf16le_name_nbytes);
+       ret = tstr_to_utf16le(name, strlen(name),
+                             &utf16le_name, &utf16le_name_nbytes);
        if (ret) {
                child = NULL;
        } else {
@@ -431,27 +459,18 @@ get_dentry_child_with_name(const struct wim_dentry *dentry, const mbchar *name)
                FREE(utf16le_name);
        }
        return child;
+#endif
 }
 
-/* Returns the dentry corresponding to the @path, or NULL if there is no such
- * dentry. */
-struct wim_dentry *
-get_dentry(WIMStruct *w, const mbchar *path)
+static struct wim_dentry *
+get_dentry_utf16le(WIMStruct *w, const utf16lechar *path,
+                  size_t path_nbytes)
 {
-       utf16lechar *path_utf16le;
-       size_t path_utf16le_nbytes;
-       int ret;
        struct wim_dentry *cur_dentry, *parent_dentry;
-       utf16lechar *p, *pp;
-
-       ret = mbs_to_utf16le(path, strlen(path), &path_utf16le,
-                            &path_utf16le_nbytes);
-       if (ret)
-               return NULL;
+       const utf16lechar *p, *pp;
 
        parent_dentry = wim_root_dentry(w);
-       p = path_utf16le;
-
+       p = path;
        while (1) {
                while (*p == cpu_to_le16('/'))
                        p++;
@@ -459,7 +478,7 @@ get_dentry(WIMStruct *w, const mbchar *path)
                if (*p == '\0')
                        break;
                pp = p;
-               while (*pp != cpu_to_le16('/') && *pp != '\0')
+               while (*pp != cpu_to_le16('/') && *pp != cpu_to_le16('\0'))
                        pp++;
 
                cur_dentry = get_dentry_child_with_utf16le_name(parent_dentry, p,
@@ -469,7 +488,6 @@ get_dentry(WIMStruct *w, const mbchar *path)
                p = pp;
                parent_dentry = cur_dentry;
        }
-       FREE(path_utf16le);
        if (cur_dentry == NULL) {
                if (dentry_is_directory(parent_dentry))
                        errno = ENOENT;
@@ -479,8 +497,31 @@ get_dentry(WIMStruct *w, const mbchar *path)
        return cur_dentry;
 }
 
+/* Returns the dentry corresponding to the @path, or NULL if there is no such
+ * dentry. */
+struct wim_dentry *
+get_dentry(WIMStruct *w, const tchar *path)
+{
+#if TCHAR_IS_UTF16LE
+       return get_dentry_utf16le(w, path, tstrlen(path) * sizeof(tchar));
+#else
+       utf16lechar *path_utf16le;
+       size_t path_utf16le_nbytes;
+       int ret;
+       struct wim_dentry *dentry;
+
+       ret = tstr_to_utf16le(path, tstrlen(path) * sizeof(tchar),
+                             &path_utf16le, &path_utf16le_nbytes);
+       if (ret)
+               return NULL;
+       dentry = get_dentry_utf16le(w, path_utf16le, path_utf16le_nbytes);
+       FREE(path_utf16le);
+       return cur_dentry;
+#endif
+}
+
 struct wim_inode *
-wim_pathname_to_inode(WIMStruct *w, const mbchar *path)
+wim_pathname_to_inode(WIMStruct *w, const tchar *path)
 {
        struct wim_dentry *dentry;
        dentry = get_dentry(w, path);
@@ -493,12 +534,12 @@ wim_pathname_to_inode(WIMStruct *w, const mbchar *path)
 /* Returns the dentry that corresponds to the parent directory of @path, or NULL
  * if the dentry is not found. */
 struct wim_dentry *
-get_parent_dentry(WIMStruct *w, const mbchar *path)
+get_parent_dentry(WIMStruct *w, const tchar *path)
 {
-       size_t path_len = strlen(path);
-       mbchar buf[path_len + 1];
+       size_t path_len = tstrlen(path);
+       tchar buf[path_len + 1];
 
-       memcpy(buf, path, path_len + 1);
+       tmemcpy(buf, path, path_len + 1);
        to_parent_name(buf, path_len);
        return get_dentry(w, buf);
 }
@@ -508,7 +549,7 @@ int
 print_dentry_full_path(struct wim_dentry *dentry, void *ignore)
 {
        if (dentry->full_path)
-               puts(dentry->full_path);
+               printf("%"TS"\n", dentry->full_path);
        return 0;
 }
 
@@ -516,24 +557,24 @@ print_dentry_full_path(struct wim_dentry *dentry, void *ignore)
  * set. */
 struct file_attr_flag {
        u32 flag;
-       const char *name;
+       const tchar *name;
 };
 struct file_attr_flag file_attr_flags[] = {
-       {FILE_ATTRIBUTE_READONLY,           "READONLY"},
-       {FILE_ATTRIBUTE_HIDDEN,             "HIDDEN"},
-       {FILE_ATTRIBUTE_SYSTEM,             "SYSTEM"},
-       {FILE_ATTRIBUTE_DIRECTORY,          "DIRECTORY"},
-       {FILE_ATTRIBUTE_ARCHIVE,            "ARCHIVE"},
-       {FILE_ATTRIBUTE_DEVICE,             "DEVICE"},
-       {FILE_ATTRIBUTE_NORMAL,             "NORMAL"},
-       {FILE_ATTRIBUTE_TEMPORARY,          "TEMPORARY"},
-       {FILE_ATTRIBUTE_SPARSE_FILE,        "SPARSE_FILE"},
-       {FILE_ATTRIBUTE_REPARSE_POINT,      "REPARSE_POINT"},
-       {FILE_ATTRIBUTE_COMPRESSED,         "COMPRESSED"},
-       {FILE_ATTRIBUTE_OFFLINE,            "OFFLINE"},
-       {FILE_ATTRIBUTE_NOT_CONTENT_INDEXED,"NOT_CONTENT_INDEXED"},
-       {FILE_ATTRIBUTE_ENCRYPTED,          "ENCRYPTED"},
-       {FILE_ATTRIBUTE_VIRTUAL,            "VIRTUAL"},
+       {FILE_ATTRIBUTE_READONLY,           T("READONLY")},
+       {FILE_ATTRIBUTE_HIDDEN,             T("HIDDEN")},
+       {FILE_ATTRIBUTE_SYSTEM,             T("SYSTEM")},
+       {FILE_ATTRIBUTE_DIRECTORY,          T("DIRECTORY")},
+       {FILE_ATTRIBUTE_ARCHIVE,            T("ARCHIVE")},
+       {FILE_ATTRIBUTE_DEVICE,             T("DEVICE")},
+       {FILE_ATTRIBUTE_NORMAL,             T("NORMAL")},
+       {FILE_ATTRIBUTE_TEMPORARY,          T("TEMPORARY")},
+       {FILE_ATTRIBUTE_SPARSE_FILE,        T("SPARSE_FILE")},
+       {FILE_ATTRIBUTE_REPARSE_POINT,      T("REPARSE_POINT")},
+       {FILE_ATTRIBUTE_COMPRESSED,         T("COMPRESSED")},
+       {FILE_ATTRIBUTE_OFFLINE,            T("OFFLINE")},
+       {FILE_ATTRIBUTE_NOT_CONTENT_INDEXED,T("NOT_CONTENT_INDEXED")},
+       {FILE_ATTRIBUTE_ENCRYPTED,          T("ENCRYPTED")},
+       {FILE_ATTRIBUTE_VIRTUAL,            T("VIRTUAL")},
 };
 
 /* Prints a directory entry.  @lookup_table is a pointer to the lookup table, if
@@ -545,37 +586,37 @@ print_dentry(struct wim_dentry *dentry, void *lookup_table)
        const u8 *hash;
        struct wim_lookup_table_entry *lte;
        const struct wim_inode *inode = dentry->d_inode;
-       char buf[50];
+       tchar buf[50];
 
-       printf("[DENTRY]\n");
-       printf("Length            = %"PRIu64"\n", dentry->length);
-       printf("Attributes        = 0x%x\n", inode->i_attributes);
+       tprintf(T("[DENTRY]\n"));
+       tprintf(T("Length            = %"PRIu64"\n"), dentry->length);
+       tprintf(T("Attributes        = 0x%x\n"), inode->i_attributes);
        for (size_t i = 0; i < ARRAY_LEN(file_attr_flags); i++)
                if (file_attr_flags[i].flag & inode->i_attributes)
-                       printf("    FILE_ATTRIBUTE_%s is set\n",
+                       tprintf(T("    FILE_ATTRIBUTE_%"TS" is set\n"),
                                file_attr_flags[i].name);
-       printf("Security ID       = %d\n", inode->i_security_id);
-       printf("Subdir offset     = %"PRIu64"\n", dentry->subdir_offset);
+       tprintf(T("Security ID       = %d\n"), inode->i_security_id);
+       tprintf(T("Subdir offset     = %"PRIu64"\n"), dentry->subdir_offset);
 
        wim_timestamp_to_str(inode->i_creation_time, buf, sizeof(buf));
-       printf("Creation Time     = %s\n", buf);
+       tprintf(T("Creation Time     = %"TS"\n"), buf);
 
        wim_timestamp_to_str(inode->i_last_access_time, buf, sizeof(buf));
-       printf("Last Access Time  = %s\n", buf);
+       tprintf(T("Last Access Time  = %"TS"\n"), buf);
 
        wim_timestamp_to_str(inode->i_last_write_time, buf, sizeof(buf));
-       printf("Last Write Time   = %s\n", buf);
+       tprintf(T("Last Write Time   = %"TS"\n"), buf);
 
-       printf("Reparse Tag       = 0x%"PRIx32"\n", inode->i_reparse_tag);
-       printf("Hard Link Group   = 0x%"PRIx64"\n", inode->i_ino);
-       printf("Hard Link Group Size = %"PRIu32"\n", inode->i_nlink);
-       printf("Number of Alternate Data Streams = %hu\n", inode->i_num_ads);
+       tprintf(T("Reparse Tag       = 0x%"PRIx32"\n"), inode->i_reparse_tag);
+       tprintf(T("Hard Link Group   = 0x%"PRIx64"\n"), inode->i_ino);
+       tprintf(T("Hard Link Group Size = %"PRIu32"\n"), inode->i_nlink);
+       tprintf(T("Number of Alternate Data Streams = %hu\n"), inode->i_num_ads);
        if (dentry_has_long_name(dentry))
-               wimlib_printf("Filename = \"%W\"\n", dentry->file_name);
+               wimlib_printf(T("Filename = \"%"WS"\"\n"), dentry->file_name);
        if (dentry_has_short_name(dentry))
-               wimlib_printf("Short Name \"%W\"\n", dentry->short_name);
+               wimlib_printf(T("Short Name \"%"WS"\"\n"), dentry->short_name);
        if (dentry->full_path)
-               printf("Full Path = \"%s\"\n", dentry->full_path);
+               tprintf(T("Full Path = \"%"WS"\"\n"), dentry->full_path);
 
        lte = inode_stream_lte(dentry->d_inode, 0, lookup_table);
        if (lte) {
@@ -583,22 +624,23 @@ print_dentry(struct wim_dentry *dentry, void *lookup_table)
        } else {
                hash = inode_stream_hash(inode, 0);
                if (hash) {
-                       printf("Hash              = 0x");
+                       tprintf(T("Hash              = 0x"));
                        print_hash(hash);
-                       putchar('\n');
-                       putchar('\n');
+                       tputchar(T('\n'));
+                       tputchar(T('\n'));
                }
        }
        for (u16 i = 0; i < inode->i_num_ads; i++) {
-               printf("[Alternate Stream Entry %u]\n", i);
-               wimlib_printf("Name = \"%W\"\n", inode->i_ads_entries[i].stream_name);
-               printf("Name Length (UTF16 bytes) = %hu\n",
+               tprintf(T("[Alternate Stream Entry %u]\n"), i);
+               wimlib_printf(T("Name = \"%"WS"\"\n"),
+                             inode->i_ads_entries[i].stream_name);
+               tprintf(T("Name Length (UTF16 bytes) = %hu\n"),
                       inode->i_ads_entries[i].stream_name_nbytes);
                hash = inode_stream_hash(inode, i + 1);
                if (hash) {
-                       printf("Hash              = 0x");
+                       tprintf(T("Hash              = 0x"));
                        print_hash(hash);
-                       putchar('\n');
+                       tputchar(T('\n'));
                }
                print_lookup_table_entry(inode_stream_lte(inode, i + 1, lookup_table),
                                         stdout);
@@ -648,7 +690,7 @@ new_inode()
 }
 
 /* Creates an unlinked directory entry. */
-int new_dentry(const mbchar *name, struct wim_dentry **dentry_ret)
+int new_dentry(const tchar *name, struct wim_dentry **dentry_ret)
 {
        struct wim_dentry *dentry;
        int ret;
@@ -664,14 +706,15 @@ int new_dentry(const mbchar *name, struct wim_dentry **dentry_ret)
                *dentry_ret = dentry;
        } else {
                FREE(dentry);
-               ERROR("Failed to set name on new dentry with name \"%s\"", name);
+               ERROR("Failed to set name on new dentry with name \"%"TS"\"",
+                     name);
        }
        return ret;
 }
 
 
 static int
-__new_dentry_with_inode(const mbchar *name, struct wim_dentry **dentry_ret,
+__new_dentry_with_inode(const tchar *name, struct wim_dentry **dentry_ret,
                        bool timeless)
 {
        struct wim_dentry *dentry;
@@ -696,13 +739,13 @@ __new_dentry_with_inode(const mbchar *name, struct wim_dentry **dentry_ret,
 }
 
 int
-new_dentry_with_timeless_inode(const mbchar *name, struct wim_dentry **dentry_ret)
+new_dentry_with_timeless_inode(const tchar *name, struct wim_dentry **dentry_ret)
 {
        return __new_dentry_with_inode(name, dentry_ret, true);
 }
 
 int
-new_dentry_with_inode(const mbchar *name, struct wim_dentry **dentry_ret)
+new_dentry_with_inode(const tchar *name, struct wim_dentry **dentry_ret)
 {
        return __new_dentry_with_inode(name, dentry_ret, false);
 }
@@ -724,7 +767,7 @@ init_ads_entry(struct wim_ads_entry *ads_entry, const void *name,
                ads_entry->stream_name = p;
                ads_entry->stream_name_nbytes = name_nbytes;
        } else {
-               if (name && *(const char*)name) {
+               if (name && *(const tchar*)name == T('\0')) {
                        ret = get_utf16le_name(name, &ads_entry->stream_name,
                                               &ads_entry->stream_name_nbytes);
                }
@@ -889,24 +932,31 @@ unlink_dentry(struct wim_dentry *dentry)
  * stream name @stream_name.
  */
 struct wim_ads_entry *
-inode_get_ads_entry(struct wim_inode *inode, const mbchar *stream_name,
+inode_get_ads_entry(struct wim_inode *inode, const tchar *stream_name,
                    u16 *idx_ret)
 {
        if (inode->i_num_ads == 0) {
                return NULL;
        } else {
                int ret;
-               utf16lechar *stream_name_utf16le;
                size_t stream_name_utf16le_nbytes;
                u16 i;
                struct wim_ads_entry *result;
 
-               ret = mbs_to_utf16le(stream_name, strlen(stream_name),
-                                    &stream_name_utf16le,
-                                    &stream_name_utf16le_nbytes);
+       #if TCHAR_IS_UTF16LE
+               const utf16lechar *stream_name_utf16le;
+
+               stream_name_utf16le = stream_name;
+               stream_name_utf16le_nbytes = tstrlen(stream_name) * sizeof(tchar);
+       #else
+               utf16lechar *stream_name_utf16le;
+
+               ret = tstr_to_utf16le(stream_name, tstrlen(stream_name) * sizeof(tchar),
+                                     &stream_name_utf16le,
+                                     &stream_name_utf16le_nbytes);
                if (ret)
                        return NULL;
-
+       #endif
                i = 0;
                result = NULL;
                do {
@@ -920,7 +970,9 @@ inode_get_ads_entry(struct wim_inode *inode, const mbchar *stream_name,
                                break;
                        }
                } while (++i != inode->i_num_ads);
+       #if !TCHAR_IS_UTF16LE
                FREE(stream_name_utf16le);
+       #endif
                return result;
        }
 }
@@ -933,8 +985,6 @@ do_inode_add_ads(struct wim_inode *inode, const void *stream_name,
        struct wim_ads_entry *ads_entries;
        struct wim_ads_entry *new_entry;
 
-       DEBUG("Add alternate data stream \"%s\"", stream_name);
-
        if (inode->i_num_ads >= 0xfffe) {
                ERROR("Too many alternate data streams in one inode!");
                return NULL;
@@ -963,6 +1013,7 @@ inode_add_ads_utf16le(struct wim_inode *inode,
                      const utf16lechar *stream_name,
                      size_t stream_name_nbytes)
 {
+       DEBUG("Add alternate data stream \"%"WS"\"", stream_name);
        return do_inode_add_ads(inode, stream_name, stream_name_nbytes, true);
 }
 
@@ -971,13 +1022,16 @@ inode_add_ads_utf16le(struct wim_inode *inode,
  * NULL if memory could not be allocated.
  */
 struct wim_ads_entry *
-inode_add_ads(struct wim_inode *inode, const char *stream_name)
+inode_add_ads(struct wim_inode *inode, const tchar *stream_name)
 {
-       return do_inode_add_ads(inode, stream_name, strlen(stream_name), false);
+       DEBUG("Add alternate data stream \"%"TS"\"", stream_name);
+       return do_inode_add_ads(inode, stream_name,
+                               tstrlen(stream_name) * sizeof(tchar),
+                               TCHAR_IS_UTF16LE);
 }
 
 int
-inode_add_ads_with_data(struct wim_inode *inode, const mbchar *name,
+inode_add_ads_with_data(struct wim_inode *inode, const tchar *name,
                        const void *value, size_t size,
                        struct wim_lookup_table *lookup_table)
 {
@@ -1037,7 +1091,7 @@ inode_remove_ads(struct wim_inode *inode, u16 idx,
 
        ads_entry = &inode->i_ads_entries[idx];
 
-       DEBUG("Remove alternate data stream \"%W\"", ads_entry->stream_name);
+       DEBUG("Remove alternate data stream \"%"WS"\"", ads_entry->stream_name);
 
        lte = ads_entry->lte;
        if (lte)
@@ -1080,7 +1134,7 @@ inode_get_unix_data(const struct wim_inode *inode,
        if (size != sizeof(struct wimlib_unix_data))
                return BAD_UNIX_DATA;
 
-       ret = read_full_wim_resource(lte, (u8*)unix_data, 0);
+       ret = read_full_wim_resource(lte, unix_data, 0);
        if (ret)
                return ret;
 
@@ -1114,7 +1168,7 @@ inode_set_unix_data(struct wim_inode *inode, uid_t uid, gid_t gid, mode_t mode,
        if (which & UNIX_DATA_MODE || !have_good_unix_data)
                unix_data.mode = mode;
        ret = inode_add_ads_with_data(inode, WIMLIB_UNIX_DATA_TAG,
-                                     (const u8*)&unix_data,
+                                     &unix_data,
                                      sizeof(struct wimlib_unix_data),
                                      lookup_table);
        if (ret == 0 && have_unix_data)
@@ -1423,7 +1477,7 @@ read_dentry(const u8 metadata_resource[], u64 metadata_resource_len,
                p = get_bytes(p, file_name_nbytes + 2, file_name);
                if (file_name[file_name_nbytes / 2] != 0) {
                        file_name[file_name_nbytes / 2] = 0;
-                       WARNING("File name in WIM dentry \"%W\" is not "
+                       WARNING("File name in WIM dentry \"%"WS"\" is not "
                                "null-terminated!", file_name);
                }
        }
@@ -1473,7 +1527,7 @@ read_dentry(const u8 metadata_resource[], u64 metadata_resource_len,
                p = get_bytes(p, short_name_nbytes + 2, short_name);
                if (short_name[short_name_nbytes / 2] != 0) {
                        short_name[short_name_nbytes / 2] = 0;
-                       WARNING("Short name in WIM dentry \"%W\" is not "
+                       WARNING("Short name in WIM dentry \"%"WS"\" is not "
                                "null-terminated!", file_name);
                }
        }
@@ -1513,7 +1567,7 @@ read_dentry(const u8 metadata_resource[], u64 metadata_resource_len,
                                goto out;
                }
                ERROR("Failed to read alternate data stream "
-                     "entries of WIM dentry \"%W\"", file_name);
+                     "entries of WIM dentry \"%"WS"\"", file_name);
                goto out_free_short_name;
        }
 out:
index 3c59f12..6a3affc 100644 (file)
@@ -141,7 +141,8 @@ struct wim_dentry {
         * the terminating null character. */
        u16 file_name_nbytes;
 
-       /* Length of full path name, in bytes, as a multibyte-encoded string */
+       /* Length of full path name encoded using "tchars", in bytes, not
+        * including the terminating null terminator. */
        u32 full_path_nbytes;
 
        u8 is_extracted : 1;
@@ -195,7 +196,7 @@ struct wim_dentry {
        utf16lechar *file_name;
 
        /* Full path of this dentry */
-       mbchar *full_path;
+       tchar *full_path;
 };
 
 #define rbnode_dentry(node) container_of(node, struct wim_dentry, rb_node)
@@ -271,11 +272,7 @@ struct wim_inode {
 
        struct list_head i_lte_inode_list;
 
-#ifdef __WIN32__
-       utf16lechar *i_extracted_file;
-#else
-       mbchar *i_extracted_file;
-#endif
+       tchar *i_extracted_file;
 
        /* Root of a red-black tree storing the children of this inode (if
         * non-empty, implies the inode is a directory, although that is also
@@ -348,17 +345,17 @@ extern void
 calculate_subdir_offsets(struct wim_dentry *dentry, u64 *subdir_offset_p);
 
 extern int
-set_dentry_name(struct wim_dentry *dentry, const mbchar *new_name);
+set_dentry_name(struct wim_dentry *dentry, const tchar *new_name);
 
 extern struct wim_dentry *
-get_dentry(struct WIMStruct *w, const mbchar *path);
+get_dentry(struct WIMStruct *w, const tchar *path);
 
 extern struct wim_inode *
-wim_pathname_to_inode(struct WIMStruct *w, const mbchar *path);
+wim_pathname_to_inode(struct WIMStruct *w, const tchar *path);
 
 extern struct wim_dentry *
 get_dentry_child_with_name(const struct wim_dentry *dentry,
-                          const mbchar *name);
+                          const tchar *name);
 
 extern struct wim_dentry *
 get_dentry_child_with_utf16le_name(const struct wim_dentry *dentry,
@@ -366,7 +363,7 @@ get_dentry_child_with_utf16le_name(const struct wim_dentry *dentry,
                                   size_t name_nbytes);
 
 extern struct wim_dentry *
-get_parent_dentry(struct WIMStruct *w, const mbchar *path);
+get_parent_dentry(struct WIMStruct *w, const tchar *path);
 
 extern int
 print_dentry(struct wim_dentry *dentry, void *lookup_table);
@@ -375,13 +372,13 @@ extern int
 print_dentry_full_path(struct wim_dentry *entry, void *ignore);
 
 extern int
-new_dentry(const mbchar *name, struct wim_dentry **dentry_ret);
+new_dentry(const tchar *name, struct wim_dentry **dentry_ret);
 
 extern int
-new_dentry_with_inode(const mbchar *name, struct wim_dentry **dentry_ret);
+new_dentry_with_inode(const tchar *name, struct wim_dentry **dentry_ret);
 
 extern int
-new_dentry_with_timeless_inode(const mbchar *name, struct wim_dentry **dentry_ret);
+new_dentry_with_timeless_inode(const tchar *name, struct wim_dentry **dentry_ret);
 
 extern void
 free_inode(struct wim_inode *inode);
@@ -407,7 +404,7 @@ dentry_add_child(struct wim_dentry * restrict parent,
                 struct wim_dentry * restrict child);
 
 extern struct wim_ads_entry *
-inode_get_ads_entry(struct wim_inode *inode, const mbchar *stream_name,
+inode_get_ads_entry(struct wim_inode *inode, const tchar *stream_name,
                    u16 *idx_ret);
 
 extern struct wim_ads_entry *
@@ -416,10 +413,10 @@ inode_add_ads_utf16le(struct wim_inode *inode,
                      size_t stream_name_nbytes);
 
 extern struct wim_ads_entry *
-inode_add_ads(struct wim_inode *dentry, const mbchar *stream_name);
+inode_add_ads(struct wim_inode *dentry, const tchar *stream_name);
 
 extern int
-inode_add_ads_with_data(struct wim_inode *inode, const mbchar *name,
+inode_add_ads_with_data(struct wim_inode *inode, const tchar *name,
                        const void *value, size_t size,
                        struct wim_lookup_table *lookup_table);
 
index ec0bc04..256103a 100644 (file)
@@ -29,8 +29,9 @@
 #include <iconv.h>
 #include <pthread.h>
 #include <stdlib.h>
+#include <string.h>
 
-bool wimlib_mbs_is_utf8 = true;
+bool wimlib_mbs_is_utf8 = !TCHAR_IS_UTF16LE;
 
 /* List of iconv_t conversion descriptors for a specific character conversion.
  * The idea is that it is not thread-safe to have just one conversion
@@ -113,6 +114,7 @@ static bool error_message_being_printed = false;
 
 #define DEFINE_CHAR_CONVERSION_FUNCTIONS(varname1, longname1, chartype1,\
                                         varname2, longname2, chartype2,\
+                                        earlyreturn,                   \
                                         worst_case_len_expr,           \
                                         err_return,                    \
                                         err_msg)                       \
@@ -193,6 +195,18 @@ varname1##_to_##varname2(const chartype1 *in, size_t in_nbytes,            \
        chartype2 *out;                                                 \
        size_t out_nbytes;                                              \
                                                                        \
+       if (earlyreturn) {                                              \
+               /* Out same as in */                                    \
+               out = MALLOC(in_nbytes + sizeof(chartype2));            \
+               if (!out)                                               \
+                       return WIMLIB_ERR_NOMEM;                        \
+               memcpy(out, in, in_nbytes);                             \
+               out[in_nbytes / sizeof(chartype2)] = 0;                 \
+               *out_ret = out;                                         \
+               *out_nbytes_ret = in_nbytes;                            \
+               return 0;                                               \
+       }                                                               \
+                                                                       \
        ret = varname1##_to_##varname2##_nbytes(in, in_nbytes,          \
                                                &out_nbytes);           \
        if (ret)                                                        \
@@ -214,8 +228,10 @@ varname1##_to_##varname2(const chartype1 *in, size_t in_nbytes,            \
        return ret;                                                     \
 }
 
+#if 0
 DEFINE_CHAR_CONVERSION_FUNCTIONS(utf16le, "UTF-16LE", utf16lechar,
                                 mbs, "", mbchar,
+                                false,
                                 in_nbytes / 2 * MB_CUR_MAX,
                                 WIMLIB_ERR_UNICODE_STRING_NOT_REPRESENTABLE,
                                 ERROR("Failed to convert UTF-16LE string "
@@ -223,23 +239,75 @@ DEFINE_CHAR_CONVERSION_FUNCTIONS(utf16le, "UTF-16LE", utf16lechar,
                                 ERROR("This may be because the UTF-16LE data "
                                       "could not be represented in your "
                                       "locale's character encoding."))
+#endif
 
-DEFINE_CHAR_CONVERSION_FUNCTIONS(mbs, "", mbchar,
+#if !TCHAR_IS_UTF16LE
+DEFINE_CHAR_CONVERSION_FUNCTIONS(tstr, "", tchar,
                                 utf16le, "UTF-16LE", utf16lechar,
+                                false,
                                 in_nbytes * 2,
                                 WIMLIB_ERR_INVALID_MULTIBYTE_STRING,
                                 ERROR_WITH_ERRNO("Failed to convert multibyte "
-                                                 "string \"%s\" to UTF-16LE string!", in);
+                                                 "string \"%"TS"\" to UTF-16LE string!", in);
                                 ERROR("If the data you provided was UTF-8, please make sure "
                                       "the character encoding of your current locale is UTF-8."))
+#endif
+
+/* tchar to UTF-8 and back */
+#if TCHAR_IS_UTF16LE
+DEFINE_CHAR_CONVERSION_FUNCTIONS(tstr, "UTF16-LE", tchar,
+                                utf8, "UTF-8", utf8char,
+                                false,
+                                in_nbytes * 2,
+                                WIMLIB_ERR_INVALID_MULTIBYTE_STRING,
+                                ERROR_WITH_ERRNO("Failed to convert UTF-16LE "
+                                                 "string \"%"TS"\" to UTF-8 string!", in);
+                               )
 
 DEFINE_CHAR_CONVERSION_FUNCTIONS(utf8, "UTF-8", utf8char,
-                                mbs, "", mbchar,
-                                in_nbytes,
+                                tstr, "UTF16-LE", tchar,
+                                false,
+                                in_nbytes * 2,
+                                WIMLIB_ERR_INVALID_MULTIBYTE_STRING,
+                                ERROR_WITH_ERRNO("Failed to convert UTF-8 string "
+                                                 "to UTF-16LE string!");
+                               )
+#else
+DEFINE_CHAR_CONVERSION_FUNCTIONS(tstr, "", tchar,
+                                utf8, "UTF-8", utf8char,
+                                wimlib_mbs_is_utf8,
+                                in_nbytes * 4,
+                                WIMLIB_ERR_INVALID_MULTIBYTE_STRING,
+                                ERROR_WITH_ERRNO("Failed to convert multibyte "
+                                                 "string \"%"TS"\" to UTF-8 string!", in);
+                                ERROR("If the data you provided was UTF-8, please make sure "
+                                      "the character encoding of your current locale is UTF-8.");)
+
+DEFINE_CHAR_CONVERSION_FUNCTIONS(utf8, "UTF-8", utf8char,
+                                tstr, "", tchar,
+                                wimlib_mbs_is_utf8,
+                                in_nbytes * 4,
                                 WIMLIB_ERR_UNICODE_STRING_NOT_REPRESENTABLE,
-                                ERROR("Failed to convert UTF-8 string to multibyte string!");
-                                ERROR("This may be because the UTF-8 data could not be represented "
-                                      "in your locale's character encoding."))
+                                ERROR("Failed to convert UTF-8 string to "
+                                      "multibyte string!");
+                                ERROR("This may be because the UTF-8 data "
+                                      "could not be represented in your "
+                                      "locale's character encoding.");)
+#endif
+
+int
+tstr_to_utf8_simple(const tchar *tstr, utf8char **out)
+{
+       size_t out_nbytes;
+       return tstr_to_utf8(tstr, tstrlen(tstr), out, &out_nbytes);
+}
+
+int
+utf8_to_tstr_simple(const utf8char *utf8str, tchar **out)
+{
+       size_t out_nbytes;
+       return utf8_to_tstr(utf8str, strlen(utf8str), out, &out_nbytes);
+}
 
 static void
 iconv_cleanup(struct iconv_list_head *head)
@@ -258,11 +326,14 @@ iconv_cleanup(struct iconv_list_head *head)
 void
 iconv_global_cleanup()
 {
-       iconv_cleanup(&iconv_utf16le_to_mbs);
+       /*iconv_cleanup(&iconv_utf16le_to_mbs);*/
+#if !TCHAR_IS_UTF16LE
        iconv_cleanup(&iconv_mbs_to_utf16le);
-       iconv_cleanup(&iconv_utf8_to_mbs);
+#endif
+       /*iconv_cleanup(&iconv_utf8_to_mbs);*/
 }
 
+#if 0
 bool
 utf8_str_contains_nonascii_chars(const utf8char *utf8_str)
 {
@@ -272,3 +343,4 @@ utf8_str_contains_nonascii_chars(const utf8char *utf8_str)
        } while (*++utf8_str);
        return false;
 }
+#endif
index e291ec1..dfd9f05 100644 (file)
@@ -95,8 +95,8 @@ static void inode_move_ltes_to_table(struct wim_inode *inode,
 WIMLIBAPI int wimlib_export_image(WIMStruct *src_wim,
                                  int src_image,
                                  WIMStruct *dest_wim,
-                                 const utf8char *dest_name,
-                                 const utf8char *dest_description,
+                                 const tchar *dest_name,
+                                 const tchar *dest_description,
                                  int export_flags,
                                  WIMStruct **additional_swms,
                                  unsigned num_additional_swms,
@@ -165,21 +165,21 @@ WIMLIBAPI int wimlib_export_image(WIMStruct *src_wim,
 
        if (!dest_name) {
                dest_name = wimlib_get_image_name(src_wim, src_image);
-               DEBUG("Using name `%s' for source image %d",
+               DEBUG("Using name `%"TS"' for source image %d",
                      dest_name, src_image);
        }
 
        if (!dest_description) {
                dest_description = wimlib_get_image_description(src_wim,
                                                                src_image);
-               DEBUG("Using description `%s' for source image %d",
+               DEBUG("Using description `%"TS"' for source image %d",
                      dest_description, src_image);
        }
 
-       DEBUG("Exporting image %d from `%s'", src_image, src_wim->filename);
+       DEBUG("Exporting image %d from `%"TS"'", src_image, src_wim->filename);
 
        if (wimlib_image_name_in_use(dest_wim, dest_name)) {
-               ERROR("There is already an image named `%s' in the "
+               ERROR("There is already an image named `%"TS"' in the "
                      "destination WIM", dest_name);
                return WIMLIB_ERR_IMAGE_NAME_COLLISION;
        }
@@ -200,7 +200,7 @@ WIMLIBAPI int wimlib_export_image(WIMStruct *src_wim,
 
        ret = select_wim_image(src_wim, src_image);
        if (ret != 0) {
-               ERROR("Could not select image %d from the WIM `%s' "
+               ERROR("Could not select image %d from the WIM `%"TS"' "
                      "to export it", src_image, src_wim->filename);
                goto out;
        }
index 963f40c..17b1280 100644 (file)
 #  include <alloca.h>
 #endif
 
+#if TCHAR_IS_UTF16LE
+#  include <wchar.h>
+#endif
+
 #ifndef __WIN32__
 static int
 extract_regular_file_linked(struct wim_dentry *dentry,
-                           const mbchar *output_path,
+                           const char *output_path,
                            struct apply_args *args,
                            struct wim_lookup_table_entry *lte)
 {
@@ -80,8 +84,8 @@ extract_regular_file_linked(struct wim_dentry *dentry,
                int num_path_components;
                int num_output_dir_path_components;
                size_t extracted_file_len;
-               mbchar *p;
-               const mbchar *p2;
+               char *p;
+               const char *p2;
                size_t i;
 
                num_path_components =
@@ -95,7 +99,7 @@ extract_regular_file_linked(struct wim_dentry *dentry,
                }
                extracted_file_len = strlen(lte->extracted_file);
 
-               mbchar buf[extracted_file_len + 3 * num_path_components + 1];
+               char buf[extracted_file_len + 3 * num_path_components + 1];
                p = &buf[0];
 
                for (i = 0; i < num_path_components; i++) {
@@ -160,7 +164,7 @@ fd_apply_unix_data(int fd, const struct wimlib_unix_data *unix_data)
 }
 
 static int
-dir_apply_unix_data(const mbchar *dir, const struct wimlib_unix_data *unix_data)
+dir_apply_unix_data(const char *dir, const struct wimlib_unix_data *unix_data)
 {
        int dfd = open(dir, O_RDONLY);
        int ret;
@@ -180,7 +184,7 @@ dir_apply_unix_data(const mbchar *dir, const struct wimlib_unix_data *unix_data)
 static int
 extract_regular_file_unlinked(struct wim_dentry *dentry,
                              struct apply_args *args,
-                             const mbchar *output_path,
+                             const char *output_path,
                              struct wim_lookup_table_entry *lte)
 {
        /* Normal mode of extraction.  Regular files and hard links are
@@ -271,7 +275,7 @@ out:
 static int
 extract_regular_file(struct wim_dentry *dentry,
                     struct apply_args *args,
-                    const mbchar *output_path)
+                    const char *output_path)
 {
        struct wim_lookup_table_entry *lte;
        const struct wim_inode *inode = dentry->d_inode;
@@ -295,9 +299,9 @@ extract_regular_file(struct wim_dentry *dentry,
 static int
 extract_symlink(struct wim_dentry *dentry,
                struct apply_args *args,
-               const mbchar *output_path)
+               const char *output_path)
 {
-       mbchar target[4096];
+       char target[4096];
        ssize_t ret = inode_readlink(dentry->d_inode, target,
                                     sizeof(target), args->w, 0);
        struct wim_lookup_table_entry *lte;
@@ -335,31 +339,31 @@ extract_symlink(struct wim_dentry *dentry,
 
 static int
 extract_directory(struct wim_dentry *dentry,
-                 const mbchar *output_path, bool is_root)
+                 const tchar *output_path, bool is_root)
 {
        int ret;
        struct stat stbuf;
 
-       ret = stat(output_path, &stbuf);
+       ret = tstat(output_path, &stbuf);
        if (ret == 0) {
                if (S_ISDIR(stbuf.st_mode)) {
                        /*if (!is_root)*/
                                /*WARNING("`%s' already exists", output_path);*/
                        goto dir_exists;
                } else {
-                       ERROR("`%s' is not a directory", output_path);
+                       ERROR("`%"TS"' is not a directory", output_path);
                        return WIMLIB_ERR_MKDIR;
                }
        } else {
                if (errno != ENOENT) {
-                       ERROR_WITH_ERRNO("Failed to stat `%s'", output_path);
+                       ERROR_WITH_ERRNO("Failed to stat `%"TS"'", output_path);
                        return WIMLIB_ERR_STAT;
                }
        }
 
-       if (mkdir(output_path, S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH))
+       if (tmkdir(output_path, S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH))
        {
-               ERROR_WITH_ERRNO("Cannot create directory `%s'", output_path);
+               ERROR_WITH_ERRNO("Cannot create directory `%"TS"'", output_path);
                return WIMLIB_ERR_MKDIR;
        }
 dir_exists:
@@ -380,7 +384,7 @@ dir_exists:
 }
 
 #ifndef __WIN32__
-static int unix_do_apply_dentry(const mbchar *output_path,
+static int unix_do_apply_dentry(const char *output_path,
                                size_t output_path_len,
                                struct wim_dentry *dentry,
                                struct apply_args *args)
@@ -398,7 +402,7 @@ static int unix_do_apply_dentry(const mbchar *output_path,
 }
 
 static int
-unix_do_apply_dentry_timestamps(const mbchar *output_path,
+unix_do_apply_dentry_timestamps(const char *output_path,
                                size_t output_path_len,
                                const struct wim_dentry *dentry,
                                struct apply_args *args)
@@ -463,18 +467,19 @@ static int
 apply_dentry_normal(struct wim_dentry *dentry, void *arg)
 {
        struct apply_args *args = arg;
+       tchar *output_path;
        size_t len;
-       mbchar *output_path;
 
-       len = strlen(args->target);
+       len = tstrlen(args->target);
        if (dentry_is_root(dentry)) {
-               output_path = (mbchar*)args->target;
+               output_path = (tchar*)args->target;
        } else {
-               output_path = alloca(len + dentry->full_path_nbytes + 1);
-               memcpy(output_path, args->target, len);
+               output_path = alloca(len * sizeof(tchar) + dentry->full_path_nbytes +
+                                    sizeof(tchar));
+               memcpy(output_path, args->target, len * sizeof(tchar));
                memcpy(output_path + len, dentry->full_path, dentry->full_path_nbytes);
-               output_path[len + dentry->full_path_nbytes] = '\0';
-               len += dentry->full_path_nbytes;
+               len += dentry->full_path_nbytes / sizeof(tchar);
+               output_path[len] = T('\0');
        }
 #ifdef __WIN32__
        return win32_do_apply_dentry(output_path, len, dentry, args);
@@ -490,19 +495,21 @@ apply_dentry_timestamps_normal(struct wim_dentry *dentry, void *arg)
 {
        struct apply_args *args = arg;
        size_t len;
-       mbchar *output_path;
+       tchar *output_path;
 
-       len = strlen(args->target);
+       len = tstrlen(args->target);
        if (dentry_is_root(dentry)) {
-               output_path = (mbchar*)args->target;
+               output_path = (tchar*)args->target;
        } else {
-               output_path = alloca(len + dentry->full_path_nbytes + 1);
-               memcpy(output_path, args->target, len);
+               output_path = alloca(len * sizeof(tchar) + dentry->full_path_nbytes +
+                                    sizeof(tchar));
+               memcpy(output_path, args->target, len * sizeof(tchar));
                memcpy(output_path + len, dentry->full_path, dentry->full_path_nbytes);
-               output_path[len + dentry->full_path_nbytes] = '\0';
-               len += dentry->full_path_nbytes;
+               len += dentry->full_path_nbytes / sizeof(tchar);
+               output_path[len] = T('\0');
        }
 
+
 #ifdef __WIN32__
        return win32_do_apply_dentry_timestamps(output_path, len, dentry, args);
 #else
@@ -758,7 +765,7 @@ apply_stream_list(struct list_head *stream_list,
  * @target. */
 static int
 extract_single_image(WIMStruct *w, int image,
-                    const mbchar *target, int extract_flags,
+                    const tchar *target, int extract_flags,
                     wimlib_progress_func_t progress_func)
 {
        int ret;
@@ -788,7 +795,8 @@ extract_single_image(WIMStruct *w, int image,
        if (extract_flags & WIMLIB_EXTRACT_FLAG_NTFS) {
                args.vol = ntfs_mount(target, 0);
                if (!args.vol) {
-                       ERROR_WITH_ERRNO("Failed to mount NTFS volume `%s'", target);
+                       ERROR_WITH_ERRNO("Failed to mount NTFS volume `%"TS"'",
+                                        target);
                        return WIMLIB_ERR_NTFS_3G;
                }
                ops = &ntfs_apply_operations;
@@ -869,7 +877,8 @@ out:
        /* Unmount the NTFS volume */
        if (extract_flags & WIMLIB_EXTRACT_FLAG_NTFS) {
                if (ntfs_umount(args.vol, FALSE) != 0) {
-                       ERROR_WITH_ERRNO("Failed to unmount NTFS volume `%s'", args.target);
+                       ERROR_WITH_ERRNO("Failed to unmount NTFS volume `%"TS"'",
+                                        args.target);
                        if (ret == 0)
                                ret = WIMLIB_ERR_NTFS_3G;
                }
@@ -879,38 +888,50 @@ out:
 }
 
 
+static bool
+image_name_ok_as_dir(const tchar *image_name)
+{
+       if (image_name == NULL)
+               return false;
+       if (image_name[0] == T('\0'))
+               return false;
+       if (tstrchr(image_name, T('/')))
+               return false;
+       if (tstrchr(image_name, T('\\')))
+               return false;
+       return true;
+}
+
 /* Extracts all images from the WIM to the directory @target, with the images
  * placed in subdirectories named by their image names. */
 static int
-extract_all_images(WIMStruct *w, const mbchar *target,
+extract_all_images(WIMStruct *w,
+                  const tchar *target,
                   int extract_flags,
                   wimlib_progress_func_t progress_func)
 {
        size_t image_name_max_len = max(xml_get_max_image_name_len(w), 20);
-       size_t output_path_len = strlen(target);
-       mbchar buf[output_path_len + 1 + image_name_max_len + 1];
+       size_t output_path_len = tstrlen(target);
+       tchar buf[output_path_len + 1 + image_name_max_len + 1];
        int ret;
        int image;
-       const utf8char *image_name;
+       const tchar *image_name;
 
        ret = extract_directory(NULL, target, true);
-       if (ret != 0)
+       if (ret)
                return ret;
 
-       memcpy(buf, target, output_path_len);
-       buf[output_path_len] = '/';
+       wmemcpy(buf, target, output_path_len);
+       buf[output_path_len] = T('/');
        for (image = 1; image <= w->hdr.image_count; image++) {
                image_name = wimlib_get_image_name(w, image);
-               if (image_name && *image_name &&
-                   (wimlib_mbs_is_utf8 || !utf8_str_contains_nonascii_chars(image_name))
-                   && strchr(image_name, '/') == NULL)
-               {
-                       strcpy(buf + output_path_len + 1, image_name);
+               if (image_name_ok_as_dir(image_name)) {
+                       tstrcpy(buf + output_path_len + 1, image_name);
                } else {
                        /* Image name is empty, or may not be representable in
                         * the current locale, or contains path separators.  Use
                         * the image number instead. */
-                       sprintf(buf + output_path_len + 1, "%d", image);
+                       tsprintf(buf + output_path_len + 1, T("%d"), image);
                }
                ret = extract_single_image(w, image, buf, extract_flags,
                                           progress_func);
@@ -925,7 +946,7 @@ extract_all_images(WIMStruct *w, const mbchar *target,
 WIMLIBAPI int
 wimlib_extract_image(WIMStruct *w,
                     int image,
-                    const mbchar *target,
+                    const tchar *target,
                     int extract_flags,
                     WIMStruct **additional_swms,
                     unsigned num_additional_swms,
index e977055..6711921 100644 (file)
@@ -454,7 +454,7 @@ out_free_old_table:
  *     were no inconsistencies.
  *     -1 (WIM_INTEGRITY_NOT_OK) if the WIM failed the integrity check.
  */
-static int verify_integrity(FILE *fp, const mbchar *filename,
+static int verify_integrity(FILE *fp, const tchar *filename,
                            const struct integrity_table *table,
                            u64 bytes_to_check,
                            wimlib_progress_func_t progress_func)
index 205c68d..2902a61 100644 (file)
@@ -118,9 +118,9 @@ join_wims(WIMStruct **swms, unsigned num_swms,
         * part */
        swms[0]->write_metadata = true;
        for (i = 0; i < num_swms; i++) {
-               swms[i]->fp = fopen(swms[i]->filename, "rb");
+               swms[i]->fp = tfopen(swms[i]->filename, T("rb"));
                if (!swms[i]->fp) {
-                       ERROR_WITH_ERRNO("Failed to reopen `%s'",
+                       ERROR_WITH_ERRNO("Failed to reopen `%"TS"'",
                                         swms[i]->filename);
                        return WIMLIB_ERR_OPEN;
                }
@@ -165,8 +165,10 @@ cmp_swms_by_part_number(const void *swm1, const void *swm2)
  * Join a set of split WIMs into a stand-alone WIM.
  */
 WIMLIBAPI int
-wimlib_join(const mbchar * const *swm_names, unsigned num_swms,
-           const mbchar *output_path, int swm_open_flags,
+wimlib_join(const tchar * const *swm_names,
+           unsigned num_swms,
+           const tchar *output_path,
+           int swm_open_flags,
            int wim_write_flags,
            wimlib_progress_func_t progress_func)
 {
index 393c0d6..d1e5061 100644 (file)
@@ -84,23 +84,12 @@ clone_lookup_table_entry(const struct wim_lookup_table_entry *old)
        memcpy(new, old, sizeof(*old));
        new->extracted_file = NULL;
        switch (new->resource_location) {
-#ifdef __WIN32__
        case RESOURCE_WIN32:
-               {
-                       size_t nbytes = utf16le_strlen(old->win32_file_on_disk);
-                       new->win32_file_on_disk = MALLOC(nbytes + 2);
-                       if (!new->win32_file_on_disk)
-                               goto out_free;
-                       memcpy(new->win32_file_on_disk, old->win32_file_on_disk,
-                              nbytes + 2);
-               }
-               break;
-#endif
        case RESOURCE_IN_STAGING_FILE:
        case RESOURCE_IN_FILE_ON_DISK:
                BUILD_BUG_ON((void*)&old->file_on_disk !=
                             (void*)&old->staging_file_name);
-               new->staging_file_name = STRDUP(old->staging_file_name);
+               new->staging_file_name = TSTRDUP(old->staging_file_name);
                if (!new->staging_file_name)
                        goto out_free;
                break;
@@ -494,48 +483,55 @@ void print_lookup_table_entry(const struct wim_lookup_table_entry *lte,
                              FILE *out)
 {
        if (!lte) {
-               putc('\n', out);
+               tputc(T('\n'), out);
                return;
        }
-       fprintf(out, "Offset            = %"PRIu64" bytes\n",
-              lte->resource_entry.offset);
-       fprintf(out, "Size              = %"PRIu64" bytes\n",
-              (u64)lte->resource_entry.size);
-       fprintf(out, "Original size     = %"PRIu64" bytes\n",
-              lte->resource_entry.original_size);
-       fprintf(out, "Part Number       = %hu\n", lte->part_number);
-       fprintf(out, "Reference Count   = %u\n", lte->refcnt);
-       fprintf(out, "Hash              = 0x");
+       tfprintf(out, T("Offset            = %"PRIu64" bytes\n"),
+                lte->resource_entry.offset);
+
+       tfprintf(out, T("Size              = %"PRIu64" bytes\n"),
+                (u64)lte->resource_entry.size);
+
+       tfprintf(out, T("Original size     = %"PRIu64" bytes\n"),
+                lte->resource_entry.original_size);
+
+       tfprintf(out, T("Part Number       = %hu\n"), lte->part_number);
+       tfprintf(out, T("Reference Count   = %u\n"), lte->refcnt);
+
+       tfprintf(out, T("Hash              = 0x"));
        print_hash(lte->hash);
-       putc('\n', out);
-       fprintf(out, "Flags             = ");
+       tputc(T('\n'), out);
+
+       tfprintf(out, T("Flags             = "));
        u8 flags = lte->resource_entry.flags;
        if (flags & WIM_RESHDR_FLAG_COMPRESSED)
-               fputs("WIM_RESHDR_FLAG_COMPRESSED, ", out);
+               tfputs(T("WIM_RESHDR_FLAG_COMPRESSED, "), out);
        if (flags & WIM_RESHDR_FLAG_FREE)
-               fputs("WIM_RESHDR_FLAG_FREE, ", out);
+               tfputs(T("WIM_RESHDR_FLAG_FREE, "), out);
        if (flags & WIM_RESHDR_FLAG_METADATA)
-               fputs("WIM_RESHDR_FLAG_METADATA, ", out);
+               tfputs(T("WIM_RESHDR_FLAG_METADATA, "), out);
        if (flags & WIM_RESHDR_FLAG_SPANNED)
-               fputs("WIM_RESHDR_FLAG_SPANNED, ", out);
-       putc('\n', out);
+               tfputs(T("WIM_RESHDR_FLAG_SPANNED, "), out);
+       tputc(T('\n'), out);
        switch (lte->resource_location) {
        case RESOURCE_IN_WIM:
                if (lte->wim->filename) {
-                       fprintf(out, "WIM file          = `%s'\n",
-                              lte->wim->filename);
+                       tfprintf(out, T("WIM file          = `%"TS"'\n"),
+                                lte->wim->filename);
                }
                break;
        case RESOURCE_IN_FILE_ON_DISK:
-               fprintf(out, "File on Disk      = `%s'\n", lte->file_on_disk);
+               tfprintf(out, T("File on Disk      = `%"TS"'\n"),
+                        lte->file_on_disk);
                break;
        case RESOURCE_IN_STAGING_FILE:
-               fprintf(out, "Staging File      = `%s'\n", lte->staging_file_name);
+               tfprintf(out, T("Staging File      = `%"TS"'\n"),
+                               lte->staging_file_name);
                break;
        default:
                break;
        }
-       putc('\n', out);
+       tputc(T('\n'), out);
 }
 
 static int do_print_lookup_table_entry(struct wim_lookup_table_entry *lte,
@@ -583,7 +579,7 @@ __lookup_resource(const struct wim_lookup_table *table, const u8 hash[])
  */
 int
 lookup_resource(WIMStruct *w,
-               const mbchar *path,
+               const tchar *path,
                int lookup_flags,
                struct wim_dentry **dentry_ret,
                struct wim_lookup_table_entry **lte_ret,
@@ -592,21 +588,21 @@ lookup_resource(WIMStruct *w,
        struct wim_dentry *dentry;
        struct wim_lookup_table_entry *lte;
        u16 stream_idx;
-       const mbchar *stream_name = NULL;
+       const tchar *stream_name = NULL;
        struct wim_inode *inode;
-       mbchar *p = NULL;
+       tchar *p = NULL;
 
        if (lookup_flags & LOOKUP_FLAG_ADS_OK) {
                stream_name = path_stream_name(path);
                if (stream_name) {
-                       p = (mbchar*)stream_name - 1;
-                       *p = '\0';
+                       p = (tchar*)stream_name - 1;
+                       *p = T('\0');
                }
        }
 
        dentry = get_dentry(w, path);
        if (p)
-               *p = ':';
+               *p = T(':');
        if (!dentry)
                return -errno;
 
index 199ae34..1759df4 100644 (file)
@@ -36,7 +36,7 @@ struct wim_lookup_table {
 
 #ifdef WITH_NTFS_3G
 struct ntfs_location {
-       mbchar *path;
+       tchar *path;
        utf16lechar *stream_name;
        u16 stream_name_nchars;
        struct _ntfs_volume **ntfs_vol_p;
@@ -154,18 +154,15 @@ struct wim_lookup_table_entry {
                 * extraction mode.   In these mode, all identical files are linked
                 * together, and @extracted_file will be set to the filename of the
                 * first extracted file containing this stream.  */
-               mbchar *extracted_file;
+               tchar *extracted_file;
        };
 
        /* Pointers to somewhere where the stream is actually located.  See the
         * comments for the @resource_location field above. */
        union {
                WIMStruct *wim;
-               mbchar *file_on_disk;
-               mbchar *staging_file_name;
-       #ifdef __WIN32__
-               wchar_t *win32_file_on_disk;
-       #endif
+               tchar *file_on_disk;
+               tchar *staging_file_name;
                u8 *attached_buffer;
        #ifdef WITH_NTFS_3G
                struct ntfs_location *ntfs_loc;
@@ -302,7 +299,7 @@ extern struct wim_lookup_table_entry *
 __lookup_resource(const struct wim_lookup_table *table, const u8 hash[]);
 
 extern int
-lookup_resource(WIMStruct *w, const mbchar *path,
+lookup_resource(WIMStruct *w, const tchar *path,
                int lookup_flags, struct wim_dentry **dentry_ret,
                struct wim_lookup_table_entry **lte_ret, u16 *stream_idx_ret);
 
index 1e0ec76..04ecbfe 100644 (file)
 
 #ifdef WITH_FUSE
 
+#ifdef __WIN32__
+#  error "FUSE mount not supported on Win32!  Please configure --without-fuse"
+#endif
+
 #include "buffer_io.h"
 #include "lookup_table.h"
 #include "sha1.h"
@@ -78,7 +82,7 @@ struct wimfs_context {
         * file in the WIM is modified, it is extracted to the staging directory.  If
         * changes are commited when the WIM is unmounted, the file resources are merged
         * in from the staging directory when writing the new WIM. */
-       mbchar *staging_dir_name;
+       char *staging_dir_name;
        size_t staging_dir_name_len;
 
        /* Flags passed to wimlib_mount(). */
@@ -106,8 +110,8 @@ struct wimfs_context {
         * wimlib_unmount_image() (i.e. the `imagex unmount' command) needs to
         * communicate with the filesystem daemon running fuse_main() (i.e. the
         * daemon created by the `imagex mount' or `imagex mountrw' commands */
-       mbchar *unmount_to_daemon_mq_name;
-       mbchar *daemon_to_unmount_mq_name;
+       char *unmount_to_daemon_mq_name;
+       char *daemon_to_unmount_mq_name;
        mqd_t unmount_to_daemon_mq;
        mqd_t daemon_to_unmount_mq;
 
@@ -305,12 +309,12 @@ close_wimfs_fd(struct wimfs_fd *fd)
  * Returns 0 on success, or negative error number on failure.
  */
 static int
-create_dentry(struct fuse_context *fuse_ctx, const mbchar *path,
+create_dentry(struct fuse_context *fuse_ctx, const char *path,
              mode_t mode, int attributes, struct wim_dentry **dentry_ret)
 {
        struct wim_dentry *parent;
        struct wim_dentry *new;
-       const mbchar *basename;
+       const char *basename;
        struct wimfs_context *wimfs_ctx = WIMFS_CTX(fuse_ctx);
        int ret;
 
@@ -468,10 +472,10 @@ touch_inode(struct wim_inode *inode)
  * writing.  On failure, returns -1 and sets errno.
  */
 static int
-create_staging_file(mbchar **name_ret, struct wimfs_context *ctx)
+create_staging_file(char **name_ret, struct wimfs_context *ctx)
 {
        size_t name_len;
-       mbchar *name;
+       char *name;
        struct stat stbuf;
        int fd;
        int errno_save;
@@ -542,7 +546,7 @@ extract_resource_to_staging_dir(struct wim_inode *inode,
                                off_t size,
                                struct wimfs_context *ctx)
 {
-       mbchar *staging_file_name;
+       char *staging_file_name;
        int ret;
        int fd;
        struct wim_lookup_table_entry *old_lte, *new_lte;
@@ -695,17 +699,17 @@ out_delete_staging_file:
  * filesystem context structure.
  */
 static int
-make_staging_dir(struct wimfs_context *ctx, const mbchar *user_prefix)
+make_staging_dir(struct wimfs_context *ctx, const char *user_prefix)
 {
        static const size_t random_suffix_len = 10;
-       static const mbchar *common_suffix = ".staging";
+       static const char *common_suffix = ".staging";
        static const size_t common_suffix_len = 8;
 
-       mbchar *staging_dir_name = NULL;
+       char *staging_dir_name = NULL;
        size_t staging_dir_name_len;
        size_t prefix_len;
-       const mbchar *wim_basename;
-       mbchar *real_user_prefix = NULL;
+       const char *wim_basename;
+       char *real_user_prefix = NULL;
        int ret;
 
        if (user_prefix) {
@@ -761,7 +765,7 @@ out:
 }
 
 static int
-remove_file_or_directory(const mbchar *fpath, const struct stat *sb,
+remove_file_or_directory(const char *fpath, const struct stat *sb,
                         int typeflag, struct FTW *ftwbuf)
 {
        if (remove(fpath) == 0)
@@ -906,12 +910,12 @@ strcat_dup(const char *s1, const char *s2, size_t max_len)
 }
 
 static int
-set_message_queue_names(struct wimfs_context *ctx, const mbchar *mount_dir)
+set_message_queue_names(struct wimfs_context *ctx, const char *mount_dir)
 {
-       static const mbchar *u2d_prefix = "/wimlib-unmount-to-daemon-mq";
-       static const mbchar *d2u_prefix = "/wimlib-daemon-to-unmount-mq";
-       mbchar *dir_path;
-       mbchar *p;
+       static const char *u2d_prefix = "/wimlib-unmount-to-daemon-mq";
+       static const char *d2u_prefix = "/wimlib-daemon-to-unmount-mq";
+       char *dir_path;
+       char *p;
        int ret;
 
        dir_path = realpath(mount_dir, NULL);
@@ -1494,7 +1498,7 @@ message_loop(mqd_t mq,
  *  daemon to finish writing the WIM file.
  */
 static int
-execute_fusermount(const mbchar *dir)
+execute_fusermount(const char *dir)
 {
        pid_t pid;
        int ret;
@@ -1572,7 +1576,7 @@ static int wimfs_access(const char *path, int mask)
 #endif
 
 static int
-wimfs_chmod(const mbchar *path, mode_t mask)
+wimfs_chmod(const char *path, mode_t mask)
 {
        struct wim_dentry *dentry;
        struct wimfs_context *ctx = wimfs_get_context();
@@ -1593,7 +1597,7 @@ wimfs_chmod(const mbchar *path, mode_t mask)
 }
 
 static int
-wimfs_chown(const mbchar *path, uid_t uid, gid_t gid)
+wimfs_chown(const char *path, uid_t uid, gid_t gid)
 {
        struct wim_dentry *dentry;
        struct wimfs_context *ctx = wimfs_get_context();
@@ -1644,7 +1648,7 @@ static int wimfs_fallocate(const char *path, int mode,
 #endif
 
 static int
-wimfs_fgetattr(const mbchar *path, struct stat *stbuf,
+wimfs_fgetattr(const char *path, struct stat *stbuf,
               struct fuse_file_info *fi)
 {
        struct wimfs_fd *fd = (struct wimfs_fd*)(uintptr_t)fi->fh;
@@ -1652,7 +1656,7 @@ wimfs_fgetattr(const mbchar *path, struct stat *stbuf,
 }
 
 static int
-wimfs_ftruncate(const mbchar *path, off_t size, struct fuse_file_info *fi)
+wimfs_ftruncate(const char *path, off_t size, struct fuse_file_info *fi)
 {
        struct wimfs_fd *fd = (struct wimfs_fd*)(uintptr_t)fi->fh;
        int ret = ftruncate(fd->staging_fd, size);
@@ -1667,7 +1671,7 @@ wimfs_ftruncate(const mbchar *path, off_t size, struct fuse_file_info *fi)
  * Fills in a `struct stat' that corresponds to a file or directory in the WIM.
  */
 static int
-wimfs_getattr(const mbchar *path, struct stat *stbuf)
+wimfs_getattr(const char *path, struct stat *stbuf)
 {
        struct wim_dentry *dentry;
        struct wim_lookup_table_entry *lte;
@@ -1685,7 +1689,7 @@ wimfs_getattr(const mbchar *path, struct stat *stbuf)
 #ifdef ENABLE_XATTR
 /* Read an alternate data stream through the XATTR interface, or get its size */
 static int
-wimfs_getxattr(const mbchar *path, const mbchar *name, char *value,
+wimfs_getxattr(const char *path, const char *name, char *value,
               size_t size)
 {
        int ret;
@@ -1730,10 +1734,10 @@ wimfs_getxattr(const mbchar *path, const mbchar *name, char *value,
 
 /* Create a hard link */
 static int
-wimfs_link(const mbchar *to, const mbchar *from)
+wimfs_link(const char *to, const char *from)
 {
        struct wim_dentry *from_dentry, *from_dentry_parent;
-       const mbchar *link_name;
+       const char *link_name;
        struct wim_inode *inode;
        struct wim_lookup_table_entry *lte;
        WIMStruct *w = wimfs_get_WIMStruct();
@@ -1777,13 +1781,13 @@ wimfs_link(const mbchar *to, const mbchar *from)
 
 #ifdef ENABLE_XATTR
 static int
-wimfs_listxattr(const mbchar *path, mbchar *list, size_t size)
+wimfs_listxattr(const char *path, char *list, size_t size)
 {
        size_t needed_size;
        struct wim_inode *inode;
        struct wimfs_context *ctx = wimfs_get_context();
        u16 i;
-       mbchar *p;
+       char *p;
        bool size_only = (size == 0);
 
        if (!(ctx->mount_flags & WIMLIB_MOUNT_FLAG_STREAM_INTERFACE_XATTR))
@@ -1797,7 +1801,7 @@ wimfs_listxattr(const mbchar *path, mbchar *list, size_t size)
 
        p = list;
        for (i = 0; i < inode->i_num_ads; i++) {
-               mbchar *stream_name_mbs;
+               char *stream_name_mbs;
                size_t stream_name_mbs_nbytes;
                int ret;
 
@@ -1805,12 +1809,8 @@ wimfs_listxattr(const mbchar *path, mbchar *list, size_t size)
                                     inode->i_ads_entries[i].stream_name_nbytes,
                                     &stream_name_mbs,
                                     &stream_name_mbs_nbytes);
-               if (ret) {
-                       if (ret == WIMLIB_ERR_NOMEM)
-                               return -ENOMEM;
-                       else
-                               return -EIO;
-               }
+               if (ret)
+                       return -errno;
 
                needed_size = stream_name_mbs_nbytes + 6;
                if (!size_only) {
@@ -1831,7 +1831,7 @@ wimfs_listxattr(const mbchar *path, mbchar *list, size_t size)
 
 /* Create a directory in the WIM image. */
 static int
-wimfs_mkdir(const mbchar *path, mode_t mode)
+wimfs_mkdir(const char *path, mode_t mode)
 {
        return create_dentry(fuse_get_context(), path, mode | S_IFDIR,
                             FILE_ATTRIBUTE_DIRECTORY, NULL);
@@ -1839,9 +1839,9 @@ wimfs_mkdir(const mbchar *path, mode_t mode)
 
 /* Create a regular file or alternate data stream in the WIM image. */
 static int
-wimfs_mknod(const mbchar *path, mode_t mode, dev_t rdev)
+wimfs_mknod(const char *path, mode_t mode, dev_t rdev)
 {
-       const mbchar *stream_name;
+       const char *stream_name;
        struct fuse_context *fuse_ctx = fuse_get_context();
        struct wimfs_context *wimfs_ctx = WIMFS_CTX(fuse_ctx);
 
@@ -1854,7 +1854,7 @@ wimfs_mknod(const mbchar *path, mode_t mode, dev_t rdev)
                struct wim_ads_entry *new_entry;
                struct wim_inode *inode;
 
-               mbchar *p = (mbchar*)stream_name - 1;
+               char *p = (char*)stream_name - 1;
                wimlib_assert(*p == ':');
                *p = '\0';
 
@@ -1879,7 +1879,7 @@ wimfs_mknod(const mbchar *path, mode_t mode, dev_t rdev)
 
 /* Open a file.  */
 static int
-wimfs_open(const mbchar *path, struct fuse_file_info *fi)
+wimfs_open(const char *path, struct fuse_file_info *fi)
 {
        struct wim_dentry *dentry;
        struct wim_lookup_table_entry *lte;
@@ -1937,7 +1937,7 @@ wimfs_open(const mbchar *path, struct fuse_file_info *fi)
 
 /* Opens a directory. */
 static int
-wimfs_opendir(const mbchar *path, struct fuse_file_info *fi)
+wimfs_opendir(const char *path, struct fuse_file_info *fi)
 {
        struct wim_inode *inode;
        int ret;
@@ -1960,7 +1960,7 @@ wimfs_opendir(const mbchar *path, struct fuse_file_info *fi)
  * Read data from a file in the WIM or in the staging directory.
  */
 static int
-wimfs_read(const mbchar *path, char *buf, size_t size,
+wimfs_read(const char *path, char *buf, size_t size,
           off_t offset, struct fuse_file_info *fi)
 {
        struct wimfs_fd *fd = (struct wimfs_fd*)(uintptr_t)fi->fh;
@@ -2010,7 +2010,7 @@ dentry_fuse_fill(struct wim_dentry *dentry, void *arg)
 {
        struct fill_params *fill_params = arg;
 
-       mbchar *file_name_mbs;
+       char *file_name_mbs;
        size_t file_name_mbs_nbytes;
        int ret;
 
@@ -2018,12 +2018,9 @@ dentry_fuse_fill(struct wim_dentry *dentry, void *arg)
                             dentry->file_name_nbytes,
                             &file_name_mbs,
                             &file_name_mbs_nbytes);
-       if (ret) {
-               if (ret == WIMLIB_ERR_NOMEM)
-                       return -ENOMEM;
-               else
-                       return -EILSEQ;
-       }
+       if (ret)
+               return -errno;
+
        ret = fill_params->filler(fill_params->buf, file_name_mbs, NULL, 0);
        FREE(file_name_mbs);
        return ret;
@@ -2032,7 +2029,7 @@ dentry_fuse_fill(struct wim_dentry *dentry, void *arg)
 /* Fills in the entries of the directory specified by @path using the
  * FUSE-provided function @filler.  */
 static int
-wimfs_readdir(const mbchar *path, void *buf, fuse_fill_dir_t filler,
+wimfs_readdir(const char *path, void *buf, fuse_fill_dir_t filler,
              off_t offset, struct fuse_file_info *fi)
 {
        struct wimfs_fd *fd = (struct wimfs_fd*)(uintptr_t)fi->fh;
@@ -2057,7 +2054,7 @@ wimfs_readdir(const mbchar *path, void *buf, fuse_fill_dir_t filler,
 
 
 static int
-wimfs_readlink(const mbchar *path, char *buf, size_t buf_len)
+wimfs_readlink(const char *path, char *buf, size_t buf_len)
 {
        struct wimfs_context *ctx = wimfs_get_context();
        struct wim_inode *inode = wim_pathname_to_inode(ctx->wim, path);
@@ -2076,7 +2073,7 @@ wimfs_readlink(const mbchar *path, char *buf, size_t buf_len)
 
 /* Close a file. */
 static int
-wimfs_release(const mbchar *path, struct fuse_file_info *fi)
+wimfs_release(const char *path, struct fuse_file_info *fi)
 {
        struct wimfs_fd *fd = (struct wimfs_fd*)(uintptr_t)fi->fh;
        return close_wimfs_fd(fd);
@@ -2084,7 +2081,7 @@ wimfs_release(const mbchar *path, struct fuse_file_info *fi)
 
 /* Close a directory */
 static int
-wimfs_releasedir(const mbchar *path, struct fuse_file_info *fi)
+wimfs_releasedir(const char *path, struct fuse_file_info *fi)
 {
        struct wimfs_fd *fd = (struct wimfs_fd*)(uintptr_t)fi->fh;
        return close_wimfs_fd(fd);
@@ -2093,7 +2090,7 @@ wimfs_releasedir(const mbchar *path, struct fuse_file_info *fi)
 #ifdef ENABLE_XATTR
 /* Remove an alternate data stream through the XATTR interface */
 static int
-wimfs_removexattr(const mbchar *path, const mbchar *name)
+wimfs_removexattr(const char *path, const char *name)
 {
        struct wim_inode *inode;
        struct wim_ads_entry *ads_entry;
@@ -2121,7 +2118,7 @@ wimfs_removexattr(const mbchar *path, const mbchar *name)
 
 /* Renames a file or directory.  See rename (3) */
 static int
-wimfs_rename(const mbchar *from, const mbchar *to)
+wimfs_rename(const char *from, const char *to)
 {
        struct wim_dentry *src;
        struct wim_dentry *dst;
@@ -2179,7 +2176,7 @@ wimfs_rename(const mbchar *from, const mbchar *to)
 
 /* Remove a directory */
 static int
-wimfs_rmdir(const mbchar *path)
+wimfs_rmdir(const char *path)
 {
        struct wim_dentry *dentry;
        WIMStruct *w = wimfs_get_WIMStruct();
@@ -2201,7 +2198,7 @@ wimfs_rmdir(const mbchar *path)
 #ifdef ENABLE_XATTR
 /* Write an alternate data stream through the XATTR interface */
 static int
-wimfs_setxattr(const mbchar *path, const mbchar *name,
+wimfs_setxattr(const char *path, const char *name,
               const char *value, size_t size, int flags)
 {
        struct wim_ads_entry *existing_ads_entry;
@@ -2243,7 +2240,7 @@ wimfs_setxattr(const mbchar *path, const mbchar *name,
 #endif
 
 static int
-wimfs_symlink(const mbchar *to, const mbchar *from)
+wimfs_symlink(const char *to, const char *from)
 {
        struct fuse_context *fuse_ctx = fuse_get_context();
        struct wimfs_context *wimfs_ctx = WIMFS_CTX(fuse_ctx);
@@ -2267,7 +2264,7 @@ wimfs_symlink(const mbchar *to, const mbchar *from)
 
 /* Reduce the size of a file */
 static int
-wimfs_truncate(const mbchar *path, off_t size)
+wimfs_truncate(const char *path, off_t size)
 {
        struct wim_dentry *dentry;
        struct wim_lookup_table_entry *lte;
@@ -2307,7 +2304,7 @@ wimfs_truncate(const mbchar *path, off_t size)
 
 /* Unlink a non-directory or alternate data stream */
 static int
-wimfs_unlink(const mbchar *path)
+wimfs_unlink(const char *path)
 {
        struct wim_dentry *dentry;
        struct wim_lookup_table_entry *lte;
@@ -2336,7 +2333,7 @@ wimfs_unlink(const mbchar *path)
  * Note that alternate data streams do not have their own timestamps.
  */
 static int
-wimfs_utimens(const mbchar *path, const struct timespec tv[2])
+wimfs_utimens(const char *path, const struct timespec tv[2])
 {
        struct wim_dentry *dentry;
        struct wim_inode *inode;
@@ -2363,7 +2360,7 @@ wimfs_utimens(const mbchar *path, const struct timespec tv[2])
 }
 #else /* HAVE_UTIMENSAT */
 static int
-wimfs_utime(const mbchar *path, struct utimbuf *times)
+wimfs_utime(const char *path, struct utimbuf *times)
 {
        struct wim_dentry *dentry;
        struct wim_inode *inode;
@@ -2384,7 +2381,7 @@ wimfs_utime(const mbchar *path, struct utimbuf *times)
  * It may be an alternate data stream, but here we don't even notice because we
  * just get a lookup table entry. */
 static int
-wimfs_write(const mbchar *path, const char *buf, size_t size,
+wimfs_write(const char *path, const char *buf, size_t size,
            off_t offset, struct fuse_file_info *fi)
 {
        struct wimfs_fd *fd = (struct wimfs_fd*)(uintptr_t)fi->fh;
@@ -2474,15 +2471,15 @@ static struct fuse_operations wimfs_operations = {
 
 /* Mounts an image from a WIM file. */
 WIMLIBAPI int
-wimlib_mount_image(WIMStruct *wim, int image, const mbchar *dir,
+wimlib_mount_image(WIMStruct *wim, int image, const char *dir,
                   int mount_flags, WIMStruct **additional_swms,
                   unsigned num_additional_swms,
-                  const mbchar *staging_dir)
+                  const char *staging_dir)
 {
        int argc;
-       mbchar *argv[16];
+       char *argv[16];
        int ret;
-       mbchar *dir_copy;
+       char *dir_copy;
        struct wim_lookup_table *joined_tab, *wim_tab_save;
        struct wim_image_metadata *imd;
        struct wimfs_context ctx;
@@ -2594,7 +2591,7 @@ wimlib_mount_image(WIMStruct *wim, int image, const mbchar *dir,
        /*
         * We provide the use_ino option to the FUSE mount because we are going
         * to assign inode numbers ourselves. */
-       mbchar optstring[256] =
+       char optstring[256] =
                "use_ino"
                ",subtype=wimfs"
                ",attr_timeout=0"
@@ -2689,7 +2686,7 @@ out:
  * wimlib_mount_image().
  */
 WIMLIBAPI int
-wimlib_unmount_image(const mbchar *dir, int unmount_flags,
+wimlib_unmount_image(const char *dir, int unmount_flags,
                     wimlib_progress_func_t progress_func)
 {
        int ret;
@@ -2752,17 +2749,17 @@ mount_unsupported_error()
 }
 
 WIMLIBAPI int
-wimlib_unmount_image(const mbchar *dir, int unmount_flags,
+wimlib_unmount_image(const tchar *dir, int unmount_flags,
                     wimlib_progress_func_t progress_func)
 {
        return mount_unsupported_error();
 }
 
 WIMLIBAPI int
-wimlib_mount_image(WIMStruct *wim, int image, const mbchar *dir,
+wimlib_mount_image(WIMStruct *wim, int image, const tchar *dir,
                   int mount_flags, WIMStruct **additional_swms,
                   unsigned num_additional_swms,
-                  const mbchar *staging_dir)
+                  const tchar *staging_dir)
 {
        return mount_unsupported_error();
 }
index ee2b294..1ab9124 100644 (file)
@@ -440,10 +440,10 @@ wim_get_fp(WIMStruct *w)
                        goto out;
                }
        }
-       DEBUG("Opening extra file descriptor to `%s'", w->filename);
-       fp = fopen(w->filename, "rb");
+       DEBUG("Opening extra file descriptor to `%"TS"'", w->filename);
+       fp = tfopen(w->filename, T("rb"));
        if (!fp)
-               ERROR_WITH_ERRNO("Failed to open `%s'", w->filename);
+               ERROR_WITH_ERRNO("Failed to open `%"TS"'", w->filename);
 out:
        pthread_mutex_unlock(&w->fp_tab_mutex);
        return fp;
@@ -560,10 +560,10 @@ read_wim_resource(const struct wim_lookup_table_entry *lte, void *buf,
                if (lte->file_on_disk_fp) {
                        fp = lte->file_on_disk_fp;
                } else {
-                       fp = fopen(lte->file_on_disk, "rb");
+                       fp = tfopen(lte->file_on_disk, T("rb"));
                        if (!fp) {
                                ERROR_WITH_ERRNO("Failed to open the file "
-                                                "`%s'", lte->file_on_disk);
+                                                "`%"TS"'", lte->file_on_disk);
                                ret = WIMLIB_ERR_OPEN;
                                break;
                        }
@@ -575,9 +575,9 @@ read_wim_resource(const struct wim_lookup_table_entry *lte, void *buf,
 #ifdef __WIN32__
        case RESOURCE_WIN32:
                wimlib_assert(lte->win32_file_on_disk_fp != INVALID_HANDLE_VALUE);
-               ret = win32_read_file(lte->win32_file_on_disk,
-                                     lte->win32_file_on_disk_fp, offset, size,
-                                     buf);
+               ret = win32_read_file(lte->file_on_disk,
+                                     lte->win32_file_on_disk_fp, offset,
+                                     size, buf);
                break;
 #endif
        case RESOURCE_IN_ATTACHED_BUFFER:
@@ -594,7 +594,7 @@ read_wim_resource(const struct wim_lookup_table_entry *lte, void *buf,
                        offset += 8;
                if (ntfs_attr_pread(lte->attr, offset, size, buf) != size) {
                        ERROR_WITH_ERRNO("Error reading NTFS attribute "
-                                        "at `%s'",
+                                        "at `%"TS"'",
                                         lte->ntfs_loc->path);
                        ret = WIMLIB_ERR_NTFS_3G;
                }
index 0553b63..b787942 100644 (file)
@@ -234,21 +234,21 @@ sha1_stream(FILE *fp, u8 md[SHA1_HASH_SIZE])
 /* Calculates the SHA1 message digest of a file.  @md must point to a buffer of
  * length 20 bytes into which the message digest is written. */
 int
-sha1sum(const mbchar *filename, u8 md[SHA1_HASH_SIZE])
+sha1sum(const tchar *filename, u8 md[SHA1_HASH_SIZE])
 {
        FILE *fp;
        int ret;
 
-       fp = fopen(filename, "rb");
+       fp = tfopen(filename, T("rb"));
        if (!fp) {
-               ERROR_WITH_ERRNO("Cannot open the file `%s' for reading",
+               ERROR_WITH_ERRNO("Cannot open the file `%"TS"' for reading",
                                 filename);
                return WIMLIB_ERR_OPEN;
        }
        ret = sha1_stream(fp, md);
        if (ret != 0) {
                ERROR_WITH_ERRNO("Error calculating SHA1 message digest of "
-                                "`%s'", filename);
+                                "`%"TS"'", filename);
        }
        fclose(fp);
        return ret;
index c8fe87f..6a3406a 100644 (file)
@@ -94,6 +94,6 @@ sha1_final(u8 hash[SHA1_HASH_SIZE], SHA_CTX *ctx);
 #endif /* !WITH_LIBCRYPTO */
 
 extern int
-sha1sum(const mbchar *filename, u8 hash[SHA1_HASH_SIZE]);
+sha1sum(const tchar *filename, u8 hash[SHA1_HASH_SIZE]);
 
 #endif /* _WIMLIB_SHA1_H */
index 6b842f6..385dc2a 100644 (file)
 #include "xml.h"
 #include "buffer_io.h"
 
+#if TCHAR_IS_UTF16LE
+#  include <wchar.h>
+#endif
+
 struct split_args {
        WIMStruct *w;
-       mbchar *swm_base_name;
+       tchar *swm_base_name;
        size_t swm_base_name_len;
-       const mbchar *swm_suffix;
+       const tchar *swm_suffix;
        struct list_head lte_list;
        int cur_part_number;
        int write_flags;
@@ -101,8 +105,8 @@ copy_resource_to_swm(struct wim_lookup_table_entry *lte, void *__args)
                INIT_LIST_HEAD(&args->lte_list);
                args->cur_part_number++;
 
-               sprintf(args->swm_base_name + args->swm_base_name_len, "%d%s",
-                       args->cur_part_number, args->swm_suffix);
+               tsprintf(args->swm_base_name + args->swm_base_name_len, T("%d%"TS),
+                        args->cur_part_number, args->swm_suffix);
 
                w->hdr.part_number = args->cur_part_number;
 
@@ -126,14 +130,14 @@ copy_resource_to_swm(struct wim_lookup_table_entry *lte, void *__args)
 /* Splits the WIM file @w into multiple parts prefixed by @swm_name with size at
  * most @part_size bytes. */
 WIMLIBAPI int
-wimlib_split(WIMStruct *w, const mbchar *swm_name,
+wimlib_split(WIMStruct *w, const tchar *swm_name,
             size_t part_size, int write_flags,
             wimlib_progress_func_t progress_func)
 {
        int ret;
        struct wim_header hdr_save;
        struct split_args args;
-       const mbchar *swm_suffix;
+       const tchar *swm_suffix;
        size_t swm_name_len;
        size_t swm_base_name_len;
 
@@ -145,8 +149,8 @@ wimlib_split(WIMStruct *w, const mbchar *swm_name,
 
        write_flags &= WIMLIB_WRITE_MASK_PUBLIC;
 
-       swm_name_len = strlen(swm_name);
-       mbchar swm_base_name[swm_name_len + 20];
+       swm_name_len = tstrlen(swm_name);
+       tchar swm_base_name[swm_name_len + 20];
 
        memcpy(&hdr_save, &w->hdr, sizeof(struct wim_header));
        w->hdr.flags |= WIM_HDR_FLAG_SPANNED;
@@ -156,15 +160,15 @@ wimlib_split(WIMStruct *w, const mbchar *swm_name,
        if (ret != 0)
                goto out;
 
-       memcpy(swm_base_name, swm_name, swm_name_len + 1);
+       tmemcpy(swm_base_name, swm_name, swm_name_len + 1);
 
-       swm_suffix = strchr(swm_name, '.');
+       swm_suffix = tstrchr(swm_name, T('.'));
        if (swm_suffix) {
                swm_base_name_len = swm_suffix - swm_name;
        } else {
                swm_base_name_len = swm_name_len;
-               swm_base_name[sizeof(swm_base_name) - 1] = '\0';
-               swm_suffix = &swm_base_name[sizeof(swm_base_name) - 1];
+               swm_base_name[ARRAY_LEN(swm_base_name) - 1] = T('\0');
+               swm_suffix = &swm_base_name[ARRAY_LEN(swm_base_name) - 1];
        }
 
        args.w                              = w;
@@ -219,18 +223,18 @@ wimlib_split(WIMStruct *w, const mbchar *swm_name,
         * parts until they are all written).  Fix them. */
        int total_parts = args.cur_part_number;
        for (int i = 1; i <= total_parts; i++) {
-               const mbchar *part_name;
+               const tchar *part_name;
                if (i == 1) {
                        part_name = swm_name;
                } else {
-                       sprintf(swm_base_name + swm_base_name_len, "%d%s",
-                               i, swm_suffix);
+                       tsprintf(swm_base_name + swm_base_name_len, T("%d%"TS),
+                                i, swm_suffix);
                        part_name = swm_base_name;
                }
 
-               FILE *fp = fopen(part_name, "r+b");
+               FILE *fp = tfopen(part_name, T("r+b"));
                if (!fp) {
-                       ERROR_WITH_ERRNO("Failed to open `%s'", part_name);
+                       ERROR_WITH_ERRNO("Failed to open `%"TS"'", part_name);
                        ret = WIMLIB_ERR_OPEN;
                        goto out;
                }
@@ -242,7 +246,7 @@ wimlib_split(WIMStruct *w, const mbchar *swm_name,
                    fwrite(buf, 1, sizeof(buf), fp) != sizeof(buf) ||
                    fclose(fp) != 0)
                {
-                       ERROR_WITH_ERRNO("Error overwriting header of `%s'",
+                       ERROR_WITH_ERRNO("Error overwriting header of `%"TS"'",
                                         part_name);
                        ret = WIMLIB_ERR_WRITE;
                        break;
index 22436cf..1e0109f 100644 (file)
@@ -31,7 +31,7 @@
 
 /* None of this file is ever needed in Win32 builds because the reparse point
  * buffers are not parsed. */
-#if !defined(__WIN32__) || defined(WITH_FUSE)
+#if !defined(__WIN32__)
 
 /*
  * Find the symlink target of a symbolic link or junction point in the WIM.
@@ -45,7 +45,7 @@
  * entry resource length.
  */
 static ssize_t
-get_symlink_name(const void *resource, size_t resource_len, mbchar *buf,
+get_symlink_name(const void *resource, size_t resource_len, char *buf,
                 size_t buf_len, u32 reparse_tag)
 {
        const u8 *p = resource;
@@ -53,11 +53,11 @@ get_symlink_name(const void *resource, size_t resource_len, mbchar *buf,
        u16 substitute_name_len;
        u16 print_name_offset;
        u16 print_name_len;
-       mbchar *link_target;
+       char *link_target;
        size_t link_target_len;
        ssize_t ret;
        unsigned header_size;
-       mbchar *translated_target;
+       char *translated_target;
        bool is_absolute;
        u32 flags;
 
@@ -85,10 +85,8 @@ get_symlink_name(const void *resource, size_t resource_len, mbchar *buf,
        ret = utf16le_to_mbs((const utf16lechar*)(p + substitute_name_offset),
                            substitute_name_len,
                            &link_target, &link_target_len);
-       if (ret == WIMLIB_ERR_INVALID_UTF16_STRING)
-               return -EILSEQ;
-       else if (ret == WIMLIB_ERR_NOMEM)
-               return -ENOMEM;
+       if (ret)
+               return -errno;
 
        wimlib_assert(ret == 0);
 
@@ -133,15 +131,15 @@ out:
 }
 
 static int
-make_symlink_reparse_data_buf(const mbchar *symlink_target,
+make_symlink_reparse_data_buf(const char *symlink_target,
                              size_t *len_ret, void **buf_ret)
 {
        utf16lechar *name_utf16le;
        size_t name_utf16le_nbytes;
        int ret;
 
-       ret = mbs_to_utf16le(symlink_target, strlen(symlink_target),
-                            &name_utf16le, &name_utf16le_nbytes);
+       ret = tstr_to_utf16le(symlink_target, strlen(symlink_target),
+                             &name_utf16le, &name_utf16le_nbytes);
        if (ret != 0)
                return ret;
 
@@ -177,7 +175,7 @@ make_symlink_reparse_data_buf(const mbchar *symlink_target,
  * WIM_IO_REPARSE_TAG_MOUNT_POINT).
  */
 ssize_t
-inode_readlink(const struct wim_inode *inode, mbchar *buf, size_t buf_len,
+inode_readlink(const struct wim_inode *inode, char *buf, size_t buf_len,
               const WIMStruct *w, int read_resource_flags)
 {
        const struct wim_lookup_table_entry *lte;
@@ -213,7 +211,7 @@ inode_readlink(const struct wim_inode *inode, mbchar *buf, size_t buf_len,
  */
 int
 inode_set_symlink(struct wim_inode *inode,
-                 const mbchar *target,
+                 const char *target,
                  struct wim_lookup_table *lookup_table,
                  struct wim_lookup_table_entry **lte_ret)
 
index 4dcc429..0ba6147 100644 (file)
@@ -72,6 +72,6 @@ extern u64
 get_wim_timestamp();
 
 extern void
-wim_timestamp_to_str(u64 timestamp, char *buf, size_t len);
+wim_timestamp_to_str(u64 timestamp, tchar *buf, size_t len);
 
 #endif
index 0c00b2a..bd37720 100644 (file)
 
 #include <unistd.h> /* for getpid() */
 
-/* Windoze compatibility */
-#ifdef __WIN32__
-#  define strerror_r(errnum, buf, bufsize) strerror_s(buf, bufsize, errnum)
-#endif
-
 size_t
 utf16le_strlen(const utf16lechar *s)
 {
@@ -63,24 +58,27 @@ utf16le_strlen(const utf16lechar *s)
  * contains %W and/or %U, then it contains no other format specifiers.
  */
 static int
-wimlib_vfprintf(FILE *fp, const char *format, va_list va)
+wimlib_vfprintf(FILE *fp, const tchar *format, va_list va)
 {
-       const char *p;
+       const tchar *p;
 
        for (p = format; *p; p++)
-               if (*p == '%' && (*(p + 1) == 'W' || *(p + 1) == 'U'))
+               if (*p == '%' && (*(p + 1) == T('W') || *(p + 1) == T('U')))
                        goto special;
-       return vfprintf(fp, format, va);
+       return tvfprintf(fp, format, va);
 special:
+       /* XXX */
+       wimlib_assert(0);
+#if 0
        ;
        int n = 0;
        for (p = format; *p; p++) {
-               if (*p == '%' && (*(p + 1) == 'W' || *(p + 1) == 'U')) {
+               if (*p == T('%') && (*(p + 1) == T('W') || *(p + 1) == T('U'))) {
                        int ret;
-                       mbchar *mbs;
+                       tchar *mbs;
                        size_t mbs_nbytes;
 
-                       if (*(p + 1) == 'W') {
+                       if (*(p + 1) == T('W')) {
                                utf16lechar *ucs = va_arg(va, utf16lechar*);
                                size_t ucs_nbytes = utf16le_strlen(ucs);
                                ret = utf16le_to_mbs(ucs, ucs_nbytes,
@@ -92,9 +90,9 @@ special:
                                                  &mbs, &mbs_nbytes);
                        }
                        if (ret) {
-                               ret = fprintf(fp, "??????");
+                               ret = tfprintf(fp, T("??????"));
                        } else {
-                               ret = fprintf(fp, "%s", mbs);
+                               ret = tfprintf(fp, T("%s"), mbs);
                                FREE(mbs);
                        }
                        if (ret < 0)
@@ -109,10 +107,11 @@ special:
                }
        }
        return n;
+#endif
 }
 
 int
-wimlib_printf(const char *format, ...)
+wimlib_printf(const tchar *format, ...)
 {
        int ret;
        va_list va;
@@ -124,7 +123,7 @@ wimlib_printf(const char *format, ...)
 }
 
 int
-wimlib_fprintf(FILE *fp, const char *format, ...)
+wimlib_fprintf(FILE *fp, const tchar *format, ...)
 {
        int ret;
        va_list va;
@@ -137,7 +136,7 @@ wimlib_fprintf(FILE *fp, const char *format, ...)
 
 #if defined(ENABLE_ERROR_MESSAGES) || defined(ENABLE_DEBUG)
 static void
-wimlib_vmsg(const char *tag, const char *format,
+wimlib_vmsg(const tchar *tag, const tchar *format,
            va_list va, bool perror)
 {
 #ifndef DEBUG
@@ -145,19 +144,20 @@ wimlib_vmsg(const char *tag, const char *format,
 #endif
                int errno_save = errno;
                fflush(stdout);
-               fputs(tag, stderr);
+               tfputs(tag, stderr);
                wimlib_vfprintf(stderr, format, va);
                if (perror && errno_save != 0) {
-                       char buf[50];
+                       tchar buf[50];
                        int res;
-                       res = strerror_r(errno_save, buf, sizeof(buf));
+                       res = tstrerror_r(errno_save, buf, sizeof(buf));
                        if (res) {
-                               snprintf(buf, sizeof(buf),
-                                        "unknown error (errno=%d)", errno_save);
+                               tsprintf(buf,
+                                        T("unknown error (errno=%d)"),
+                                        errno_save);
                        }
-                       fprintf(stderr, ": %s", buf);
+                       tfprintf(stderr, T(": %"TS), buf);
                }
-               putc('\n', stderr);
+               tputc(T('\n'), stderr);
                errno = errno_save;
 #ifndef DEBUG
        }
@@ -172,56 +172,57 @@ static bool wimlib_print_errors = false;
 
 
 void
-wimlib_error(const char *format, ...)
+wimlib_error(const tchar *format, ...)
 {
        va_list va;
 
        va_start(va, format);
-       wimlib_vmsg("[ERROR] ", format, va, false);
+       wimlib_vmsg(T("[ERROR] "), format, va, false);
        va_end(va);
 }
 
 void
-wimlib_error_with_errno(const char *format, ...)
+wimlib_error_with_errno(const tchar *format, ...)
 {
        va_list va;
 
        va_start(va, format);
-       wimlib_vmsg("[ERROR] ", format, va, true);
+       wimlib_vmsg(T("[ERROR] "), format, va, true);
        va_end(va);
 }
 
 void
-wimlib_warning(const char *format, ...)
+wimlib_warning(const tchar *format, ...)
 {
        va_list va;
 
        va_start(va, format);
-       wimlib_vmsg("[WARNING] ", format, va, false);
+       wimlib_vmsg(T("[WARNING] "), format, va, false);
        va_end(va);
 }
 
 void
-wimlib_warning_with_errno(const char *format, ...)
+wimlib_warning_with_errno(const tchar *format, ...)
 {
        va_list va;
 
        va_start(va, format);
-       wimlib_vmsg("[WARNING] ", format, va, true);
+       wimlib_vmsg(T("[WARNING] "), format, va, true);
        va_end(va);
 }
 
 #endif
 
 #if defined(ENABLE_DEBUG) || defined(ENABLE_MORE_DEBUG)
-void wimlib_debug(const char *file, int line, const char *func,
-                 const char *format, ...)
+void wimlib_debug(const tchar *file, int line, const char *func,
+                 const tchar *format, ...)
 {
 
        va_list va;
-       char buf[strlen(file) + strlen(func) + 30];
+       tchar buf[tstrlen(file) + strlen(func) + 30];
+
+       tsprintf(buf, "[%"TS" %d] %s(): ", file, line, func);
 
-       sprintf(buf, "[%s %d] %s(): ", file, line, func);
        va_start(va, format);
        wimlib_vmsg(buf, format, va, false);
        va_end(va);
@@ -242,133 +243,133 @@ wimlib_set_print_errors(bool show_error_messages)
 #endif
 }
 
-static const mbchar *error_strings[] = {
+static const tchar *error_strings[] = {
        [WIMLIB_ERR_SUCCESS]
-               = "Success",
+               = T("Success"),
        [WIMLIB_ERR_ALREADY_LOCKED]
-               = "The WIM is already locked for writing",
+               = T("The WIM is already locked for writing"),
        [WIMLIB_ERR_COMPRESSED_LOOKUP_TABLE]
-               = "Lookup table is compressed",
+               = T("Lookup table is compressed"),
        [WIMLIB_ERR_DECOMPRESSION]
-               = "Failed to decompress compressed data",
+               = T("Failed to decompress compressed data"),
        [WIMLIB_ERR_DELETE_STAGING_DIR]
-               = "Failed to delete staging directory",
+               = T("Failed to delete staging directory"),
        [WIMLIB_ERR_FILESYSTEM_DAEMON_CRASHED]
-               = "The process servicing the mounted WIM has crashed",
+               = T("The process servicing the mounted WIM has crashed"),
        [WIMLIB_ERR_FORK]
-               = "Failed to fork another process",
+               = T("Failed to fork another process"),
        [WIMLIB_ERR_FUSE]
-               = "An error was returned by fuse_main()",
+               = T("An error was returned by fuse_main()"),
        [WIMLIB_ERR_FUSERMOUNT]
-               = "Could not execute the `fusermount' program, or it exited "
-                       "with a failure status",
+               = T("Could not execute the `fusermount' program, or it exited "
+                       "with a failure status"),
        [WIMLIB_ERR_ICONV_NOT_AVAILABLE]
-               = "The iconv() function does not seem to work. "
-                 "Maybe check to make sure the directory /usr/lib/gconv exists",
+               = T("The iconv() function does not seem to work. "
+                 "Maybe check to make sure the directory /usr/lib/gconv exists"),
        [WIMLIB_ERR_IMAGE_COUNT]
-               = "Inconsistent image count among the metadata "
-                       "resources, the WIM header, and/or the XML data",
+               = T("Inconsistent image count among the metadata "
+                       "resources, the WIM header, and/or the XML data"),
        [WIMLIB_ERR_IMAGE_NAME_COLLISION]
-               = "Tried to add an image with a name that is already in use",
+               = T("Tried to add an image with a name that is already in use"),
        [WIMLIB_ERR_INTEGRITY]
-               = "The WIM failed an integrity check",
+               = T("The WIM failed an integrity check"),
        [WIMLIB_ERR_INVALID_CAPTURE_CONFIG]
-               = "The capture configuration string was invalid",
+               = T("The capture configuration string was invalid"),
        [WIMLIB_ERR_INVALID_CHUNK_SIZE]
-               = "The WIM is compressed but does not have a chunk "
-                       "size of 32768",
+               = T("The WIM is compressed but does not have a chunk "
+                       "size of 32768"),
        [WIMLIB_ERR_INVALID_COMPRESSION_TYPE]
-               = "The WIM is compressed, but is not marked as having LZX or "
-                       "XPRESS compression",
+               = T("The WIM is compressed, but is not marked as having LZX or "
+                       "XPRESS compression"),
        [WIMLIB_ERR_INVALID_DENTRY]
-               = "A directory entry in the WIM was invalid",
+               = T("A directory entry in the WIM was invalid"),
        [WIMLIB_ERR_INVALID_HEADER_SIZE]
-               = "The WIM header was not 208 bytes",
+               = T("The WIM header was not 208 bytes"),
        [WIMLIB_ERR_INVALID_IMAGE]
-               = "Tried to select an image that does not exist in the WIM",
+               = T("Tried to select an image that does not exist in the WIM"),
        [WIMLIB_ERR_INVALID_INTEGRITY_TABLE]
-               = "The WIM's integrity table is invalid",
+               = T("The WIM's integrity table is invalid"),
        [WIMLIB_ERR_INVALID_LOOKUP_TABLE_ENTRY]
-               = "An entry in the WIM's lookup table is invalid",
+               = T("An entry in the WIM's lookup table is invalid"),
        [WIMLIB_ERR_INVALID_MULTIBYTE_STRING]
-               = "A string was not valid in the current locale's character encoding",
+               = T("A string was not valid in the current locale's character encoding"),
        [WIMLIB_ERR_INVALID_OVERLAY]
-               = "Conflicting files in overlay when creating a WIM image",
+               = T("Conflicting files in overlay when creating a WIM image"),
        [WIMLIB_ERR_INVALID_PARAM]
-               = "An invalid parameter was given",
+               = T("An invalid parameter was given"),
        [WIMLIB_ERR_INVALID_PART_NUMBER]
-               = "The part number or total parts of the WIM is invalid",
+               = T("The part number or total parts of the WIM is invalid"),
        [WIMLIB_ERR_INVALID_RESOURCE_HASH]
-               = "The SHA1 message digest of a WIM resource did not match the expected value",
+               = T("The SHA1 message digest of a WIM resource did not match the expected value"),
        [WIMLIB_ERR_INVALID_RESOURCE_SIZE]
-               = "A resource entry in the WIM has an invalid size",
+               = T("A resource entry in the WIM has an invalid size"),
        [WIMLIB_ERR_INVALID_SECURITY_DATA]
-               = "The table of security descriptors in the WIM is invalid",
+               = T("The table of security descriptors in the WIM is invalid"),
        [WIMLIB_ERR_INVALID_UNMOUNT_MESSAGE]
-               = "The version of wimlib that has mounted a WIM image is incompatible with the "
-                 "version being used to unmount it",
+               = T("The version of wimlib that has mounted a WIM image is incompatible with the "
+                 "version being used to unmount it"),
        [WIMLIB_ERR_INVALID_UTF8_STRING]
-               = "A string provided as input by the user was not a valid UTF-8 string",
+               = T("A string provided as input by the user was not a valid UTF-8 string"),
        [WIMLIB_ERR_INVALID_UTF16_STRING]
-               = "A string in a WIM dentry is not a valid UTF-16LE string",
+               = T("A string in a WIM dentry is not a valid UTF-16LE string"),
        [WIMLIB_ERR_LIBXML_UTF16_HANDLER_NOT_AVAILABLE]
-               = "libxml2 was unable to find a character encoding conversion handler "
-                 "for UTF-16LE",
+               = T("libxml2 was unable to find a character encoding conversion handler "
+                 "for UTF-16LE"),
        [WIMLIB_ERR_LINK]
-               = "Failed to create a hard or symbolic link when extracting "
-                       "a file from the WIM",
+               = T("Failed to create a hard or symbolic link when extracting "
+                       "a file from the WIM"),
        [WIMLIB_ERR_MKDIR]
-               = "Failed to create a directory",
+               = T("Failed to create a directory"),
        [WIMLIB_ERR_MQUEUE]
-               = "Failed to create or use a POSIX message queue",
+               = T("Failed to create or use a POSIX message queue"),
        [WIMLIB_ERR_NOMEM]
-               = "Ran out of memory",
+               = T("Ran out of memory"),
        [WIMLIB_ERR_NOTDIR]
-               = "Expected a directory",
+               = T("Expected a directory"),
        [WIMLIB_ERR_NOT_A_WIM_FILE]
-               = "The file did not begin with the magic characters that "
-                       "identify a WIM file",
+               = T("The file did not begin with the magic characters that "
+                       "identify a WIM file"),
        [WIMLIB_ERR_NO_FILENAME]
-               = "The WIM is not identified with a filename",
+               = T("The WIM is not identified with a filename"),
        [WIMLIB_ERR_NTFS_3G]
-               = "NTFS-3g encountered an error (check errno)",
+               = T("NTFS-3g encountered an error (check errno)"),
        [WIMLIB_ERR_OPEN]
-               = "Failed to open a file",
+               = T("Failed to open a file"),
        [WIMLIB_ERR_OPENDIR]
-               = "Failed to open a directory",
+               = T("Failed to open a directory"),
        [WIMLIB_ERR_READ]
-               = "Could not read data from a file",
+               = T("Could not read data from a file"),
        [WIMLIB_ERR_READLINK]
-               = "Could not read the target of a symbolic link",
+               = T("Could not read the target of a symbolic link"),
        [WIMLIB_ERR_RENAME]
-               = "Could not rename a file",
+               = T("Could not rename a file"),
        [WIMLIB_ERR_REOPEN]
-               = "Could not re-open the WIM after overwriting it",
+               = T("Could not re-open the WIM after overwriting it"),
        [WIMLIB_ERR_RESOURCE_ORDER]
-               = "The components of the WIM were arranged in an unexpected order",
+               = T("The components of the WIM were arranged in an unexpected order"),
        [WIMLIB_ERR_SPECIAL_FILE]
-               = "Encountered a special file that cannot be archived",
+               = T("Encountered a special file that cannot be archived"),
        [WIMLIB_ERR_SPLIT_INVALID]
-               = "The WIM is part of an invalid split WIM",
+               = T("The WIM is part of an invalid split WIM"),
        [WIMLIB_ERR_SPLIT_UNSUPPORTED]
-               = "The WIM is part of a split WIM, which is not supported for this operation",
+               = T("The WIM is part of a split WIM, which is not supported for this operation"),
        [WIMLIB_ERR_STAT]
-               = "Could not read the metadata for a file or directory",
+               = T("Could not read the metadata for a file or directory"),
        [WIMLIB_ERR_TIMEOUT]
-               = "Timed out while waiting for a message to arrive from another process",
+               = T("Timed out while waiting for a message to arrive from another process"),
        [WIMLIB_ERR_UNICODE_STRING_NOT_REPRESENTABLE]
-               = "A Unicode string could not be represented in the current locale's encoding",
+               = T("A Unicode string could not be represented in the current locale's encoding"),
        [WIMLIB_ERR_UNKNOWN_VERSION]
-               = "The WIM file is marked with an unknown version number",
+               = T("The WIM file is marked with an unknown version number"),
        [WIMLIB_ERR_UNSUPPORTED]
-               = "The requested operation is unsupported",
+               = T("The requested operation is unsupported"),
        [WIMLIB_ERR_WRITE]
-               = "Failed to write data to a file",
+               = T("Failed to write data to a file"),
        [WIMLIB_ERR_XML]
-               = "The XML data of the WIM is invalid",
+               = T("The XML data of the WIM is invalid"),
 };
 
-WIMLIBAPI const mbchar *
+WIMLIBAPI const tchar *
 wimlib_get_error_string(enum wimlib_error_code code)
 {
        if (code < 0 || code >= ARRAY_LEN(error_strings))
@@ -407,6 +408,21 @@ wimlib_strdup(const char *str)
        return p;
 }
 
+#ifdef __WIN32__
+wchar_t *
+wimlib_wcsdup(const wchar_t *str)
+{
+       size_t size;
+       wchar_t *p;
+
+       size = wcslen(str);
+       p = MALLOC((size + 1) * sizeof(wchar_t));
+       if (p)
+               memcpy(p, str, (size + 1) * sizeof(wchar_t));
+       return p;
+}
+#endif
+
 extern void
 xml_set_memory_allocator(void *(*malloc_func)(size_t),
                         void (*free_func)(void *),
@@ -443,9 +459,9 @@ seed_random()
        seeded = true;
 }
 
-/* Fills @n bytes pointed to by @p with random alphanumeric characters. */
+/* Fills @n characters pointed to by @p with random alphanumeric characters. */
 void
-randomize_char_array_with_alnum(char p[], size_t n)
+randomize_char_array_with_alnum(tchar p[], size_t n)
 {
        if (!seeded)
                seed_random();
@@ -473,24 +489,24 @@ randomize_byte_array(u8 *p, size_t n)
 /* Takes in a path of length @len in @buf, and transforms it into a string for
  * the path of its parent directory. */
 void
-to_parent_name(char buf[], size_t len)
+to_parent_name(tchar *buf, size_t len)
 {
        ssize_t i = (ssize_t)len - 1;
-       while (i >= 0 && buf[i] == '/')
+       while (i >= 0 && buf[i] == T('/'))
                i--;
-       while (i >= 0 && buf[i] != '/')
+       while (i >= 0 && buf[i] != T('/'))
                i--;
-       while (i >= 0 && buf[i] == '/')
+       while (i >= 0 && buf[i] == T('/'))
                i--;
-       buf[i + 1] = '\0';
+       buf[i + 1] = T('\0');
 }
 
 /* Like the basename() function, but does not modify @path; it just returns a
  * pointer to it. */
-const char *
-path_basename(const char *path)
+const tchar *
+path_basename(const tchar *path)
 {
-       const char *p = path;
+       const tchar *p = path;
        while (*p)
                p++;
        p--;
@@ -498,13 +514,13 @@ path_basename(const char *path)
        /* Trailing slashes. */
        while (1) {
                if (p == path - 1)
-                       return "";
-               if (*p != '/')
+                       return T("");
+               if (*p != T('/'))
                        break;
                p--;
        }
 
-       while ((p != path - 1) && *p != '/')
+       while ((p != path - 1) && *p != T('/'))
                p--;
 
        return p + 1;
@@ -514,11 +530,11 @@ path_basename(const char *path)
  * Returns a pointer to the part of @path following the first colon in the last
  * path component, or NULL if the last path component does not contain a colon.
  */
-const char *
-path_stream_name(const char *path)
+const tchar *
+path_stream_name(const tchar *path)
 {
-       const char *base = path_basename(path);
-       const char *stream_name = strchr(base, ':');
+       const tchar *base = path_basename(path);
+       const tchar *stream_name = tstrchr(base, T(':'));
        if (!stream_name)
                return NULL;
        else
@@ -536,19 +552,19 @@ path_stream_name(const char *path)
  *                             sequence of '/', or a pointer to the terminating
  *                             null byte in the case of a path without any '/'.
  */
-const char *
-path_next_part(const char *path, size_t *first_part_len_ret)
+const tchar *
+path_next_part(const tchar *path, size_t *first_part_len_ret)
 {
        size_t i;
-       const char *next_part;
+       const tchar *next_part;
 
        i = 0;
-       while (path[i] != '/' && path[i] != '\0')
+       while (path[i] != T('/') && path[i] != T('\0'))
                i++;
        if (first_part_len_ret)
                *first_part_len_ret = i;
        next_part = &path[i];
-       while (*next_part == '/')
+       while (*next_part == T('/'))
                next_part++;
        return next_part;
 }
@@ -597,10 +613,10 @@ get_wim_timestamp()
 }
 
 void
-wim_timestamp_to_str(u64 timestamp, char *buf, size_t len)
+wim_timestamp_to_str(u64 timestamp, tchar *buf, size_t len)
 {
        struct tm tm;
        time_t t = wim_timestamp_to_unix(timestamp);
        gmtime_r(&t, &tm);
-       strftime(buf, len, "%a %b %d %H:%M:%S %Y UTC", &tm);
+       tstrftime(buf, len, T("%a %b %d %H:%M:%S %Y UTC"), &tm);
 }
index 77c4b35..14d620c 100644 (file)
@@ -16,8 +16,9 @@
 #      endif
 #      define ALWAYS_INLINE inline __attribute__((always_inline))
 #      define PACKED __attribute__((packed))
-#      define FORMAT(type, format_str, args_start) \
-                       __attribute__((format(type, format_str, args_start)))
+//#    define FORMAT(type, format_str, args_start) \
+                       //__attribute__((format(type, format_str, args_start)))
+#      define FORMAT(type, format_str, args_start)
 #      if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 4)
 #              define COLD     __attribute__((cold))
 #      else
@@ -49,25 +50,102 @@ typedef uint32_t u32;
 typedef uint64_t u64;
 #endif
 
-/* A pointer to 'mbchar' indicates a string of "multibyte characters" provided
- * in the default encoding of the user's locale, which may be "UTF-8",
- * "ISO-8859-1", "C", or any other ASCII-compatible encoding.
- * "ASCII-compatible" here means any encoding where all ASCII-representable
- * characters have the same representation as in ASCII itself, and any non-ASCII
- * character is represented as a sequence of one or more bytes not already used
- * by any ASCII character. */
-typedef char mbchar;
-
-/* A pointer to 'utf8char' indicates a UTF-8 encoded string */
-typedef char utf8char;
-
-/* Note: in some places in the code, strings of plain old 'char' are still used.
- * This means that the string is being operated on in an ASCII-compatible way,
- * and may be either a multibyte or UTF-8 string.  */
 
 /* A pointer to 'utf16lechar' indicates a UTF-16LE encoded string */
 typedef u16 utf16lechar;
 
+typedef u8 utf8char;
+
+#ifdef __WIN32__
+/* For Windows builds, the "tchar" type will be 2 bytes and will be equivalent
+ * to "wchar_t" and "utf16lechar".  All indicate one code unit of a UTF16-LE
+ * string. */
+typedef wchar_t tchar;
+#  define TCHAR_IS_UTF16LE 1
+#  define T(text) L##text /* Make a string literal into a wide string */
+#  define TS "ls" /* Format a string of "tchar" */
+#  define WS "ls" /* Format a UTF-16LE string (same as above) */
+
+/* For Windows builds, the following definitions replace the "tchar" functions
+ * with the "wide-character" functions. */
+#  define tmemchr  wmemchr
+#  define tmemcpy  wmemcpy
+#  define tstrcpy  wcscpy
+#  define tprintf  wprintf
+#  define tsprintf swprintf
+#  define tfprintf fwprintf
+#  define tvfprintf vfwprintf
+#  define istalpha iswalpha
+#  define tstrcmp  wcscmp
+#  define tstrchr  wcschr
+#  define tstrrchr wcsrchr
+#  define tstrlen  wcslen
+#  define tmemcmp  wmemcmp
+#  define tstrftime wcsftime
+#  define tputchar putwchar
+#  define tputc    putwc
+#  define tputs    _putws
+#  define tfputs   fputws
+#  define tfopen   _wfopen
+#  define tstat    _wstati64
+#  define tstrtol  wcstol
+#  define tunlink  _wunlink
+/* The following "tchar" functions do not have exact wide-character equivalents
+ * on Windows so require parameter rearrangement or redirection to a replacement
+ * function defined ourselves. */
+#  define TSTRDUP  WSTRDUP
+#  define tmkdir(path, mode) _wmkdir(path)
+#  define tstrerror_r(errnum, buf, bufsize) _wcserror_s(buf, bufsize, errnum)
+#  define trename  win32_rename_replacement
+#  define ttruncate win32_truncate_replacement
+#else
+/* For non-Windows builds, the "tchar" type will be one byte and will specify a
+ * string in the locale-dependent multibyte encoding.  However, only UTF-8 is
+ * well supported in this library. */
+typedef char tchar;
+#  define TCHAR_IS_UTF16LE 0
+#  define T(text) text /* In this case, strings of "tchar" are simply strings of
+                         char */
+#  define TS "s"       /* Similarly, a string of "tchar" is printed just as a
+                         normal string. */
+#  define WS "W"       /* UTF-16LE strings must be printed using a special
+                         extension implemented by wimlib itself.  Note that
+                         "ls" will not work here because a string of wide
+                         characters on non-Windows systems is typically not
+                         UTF-16LE. */
+/* For non-Windows builds, replace the "tchar" functions with the regular old
+ * string functions. */
+#  define tmemchr  memchr
+#  define tmemcpy  memcpy
+#  define tstrcpy  strcpy
+#  define tprintf  printf
+#  define tsprintf sprintf
+#  define tfprintf fprintf
+#  define tvfprintf vfprintf
+#  define istalpha isalpha
+#  define tstrcmp  strcmp
+#  define tstrchr  strchr
+#  define tstrrchr strrchr
+#  define tstrlen  strlen
+#  define tmemcmp  memcmp
+#  define tstrftime strftime
+#  define tputchar putchar
+#  define tputc    putc
+#  define tputs    puts
+#  define tfputs   fputs
+#  define tfopen   fopen
+#  define tstat    stat
+#  define tunlink  unlink
+#  define tstrtol  strtol
+#  define tmkdir   mkdir
+#  define TSTRDUP  STRDUP
+#  define tstrerror_r strerror_r
+#  define trename  rename
+#  define ttruncate truncate
+#endif
+
+#define TMALLOC(n) MALLOC((n) * sizeof(tchar))
+
 extern size_t
 utf16le_strlen(const utf16lechar *s);
 
@@ -93,17 +171,15 @@ varname1##_to_##varname2(const chartype1 *in, size_t in_nbytes,            \
                         chartype2 **out_ret,                           \
                         size_t *out_nbytes_ret);                       \
 
-/* multi-byte string to UTF16-LE string */
-DECLARE_CHAR_CONVERSION_FUNCTIONS(mbs, utf16le, mbchar, utf16lechar);
-
-/* UTF16-LE string to multi-byte string */
-DECLARE_CHAR_CONVERSION_FUNCTIONS(utf16le, mbs, utf16lechar, mbchar);
+#if !TCHAR_IS_UTF16LE
+DECLARE_CHAR_CONVERSION_FUNCTIONS(utf16le, tstr, utf16lechar, tchar);
+#endif
 
-/* UTF-8 string to multi-byte string */
-DECLARE_CHAR_CONVERSION_FUNCTIONS(utf8, mbs, utf8char, mbchar);
+extern int
+utf8_to_tstr_simple(const utf8char *utf8str, tchar **out);
 
-extern bool
-utf8_str_contains_nonascii_chars(const utf8char *utf8_str);
+extern int
+tstr_to_utf8_simple(const tchar *tstr, utf8char **out);
 
 #ifndef min
 #define min(a, b) ({ typeof(a) __a = (a); typeof(b) __b = (b); \
@@ -152,20 +228,20 @@ dummy_printf(const char *format, ...)
 
 #ifdef ENABLE_ERROR_MESSAGES
 extern void
-wimlib_error(const char *format, ...) FORMAT(printf, 1, 2) COLD;
+wimlib_error(const tchar *format, ...) FORMAT(printf, 1, 2) COLD;
 
 extern void
-wimlib_error_with_errno(const char *format, ...) FORMAT(printf, 1, 2) COLD;
+wimlib_error_with_errno(const tchar *format, ...) FORMAT(printf, 1, 2) COLD;
 
 extern void
-wimlib_warning(const char *format, ...) FORMAT(printf, 1, 2) COLD;
+wimlib_warning(const tchar *format, ...) FORMAT(printf, 1, 2) COLD;
 
 extern void
-wimlib_warning_with_errno(const char *format, ...) FORMAT(printf, 1, 2) COLD;
-#  define ERROR                        wimlib_error
-#  define ERROR_WITH_ERRNO     wimlib_error_with_errno
-#  define WARNING              wimlib_warning
-#  define WARNING_WITH_ERRNO   wimlib_warning
+wimlib_warning_with_errno(const tchar *format, ...) FORMAT(printf, 1, 2) COLD;
+#  define ERROR(format, ...)                   wimlib_error(T(format), ## __VA_ARGS__)
+#  define ERROR_WITH_ERRNO(format, ...)        wimlib_error_with_errno(T(format), ## __VA_ARGS__)
+#  define WARNING(format, ...)                 wimlib_warning(T(format), ## __VA_ARGS__)
+#  define WARNING_WITH_ERRNO(format, ...)      wimlib_warning(T(format), ## __VA_ARGS__)
 #else /* ENABLE_ERROR_MESSAGES */
 #  define ERROR(format, ...)                   dummy_printf(format, ## __VA_ARGS__)
 #  define ERROR_WITH_ERRNO(format, ...)                dummy_printf(format, ## __VA_ARGS__)
@@ -183,10 +259,10 @@ wimlib_warning_with_errno(const char *format, ...) FORMAT(printf, 1, 2) COLD;
 
 #ifdef ENABLE_DEBUG
 extern void
-wimlib_debug(const char *file, int line, const char *func,
-            const char *format, ...);
+wimlib_debug(const tchar *file, int line, const char *func,
+            const tchar *format, ...);
 #  define DEBUG(format, ...) \
-               wimlib_debug(__FILE__, __LINE__, __func__, format, ## __VA_ARGS__);
+               wimlib_debug(T(__FILE__), __LINE__, __func__, T(format), ## __VA_ARGS__);
 
 #else
 #  define DEBUG(format, ...) dummy_printf(format, ## __VA_ARGS__)
@@ -218,12 +294,16 @@ extern void *(*wimlib_malloc_func)(size_t);
 extern void (*wimlib_free_func)(void *);
 extern void *(*wimlib_realloc_func)(void *, size_t);
 extern void *wimlib_calloc(size_t nmemb, size_t size);
+#ifdef __WIN32__
+extern wchar_t *wimlib_wcsdup(const wchar_t *str);
+#endif
 extern char *wimlib_strdup(const char *str);
 #  define      MALLOC  wimlib_malloc_func
 #  define      FREE    wimlib_free_func
 #  define      REALLOC wimlib_realloc_func
 #  define      CALLOC  wimlib_calloc
 #  define      STRDUP  wimlib_strdup
+#  define      WSTRDUP wimlib_wcsdup
 #else /* ENABLE_CUSTOM_MEMORY_ALLOCATOR */
 #  include <stdlib.h>
 #  include <string.h>
@@ -232,6 +312,7 @@ extern char *wimlib_strdup(const char *str);
 #  define      REALLOC realloc
 #  define      CALLOC  calloc
 #  define      STRDUP  strdup
+#  define       WSTRDUP wcsdup
 #endif /* !ENABLE_CUSTOM_MEMORY_ALLOCATOR */
 
 
@@ -240,19 +321,19 @@ extern void
 randomize_byte_array(u8 *p, size_t n);
 
 extern void
-randomize_char_array_with_alnum(char p[], size_t n);
+randomize_char_array_with_alnum(tchar p[], size_t n);
 
-extern const char *
-path_next_part(const char *path, size_t *first_part_len_ret);
+extern const tchar *
+path_next_part(const tchar *path, size_t *first_part_len_ret);
 
-extern const char *
-path_basename(const char *path);
+const tchar *
+path_basename(const tchar *path);
 
-extern const char *
-path_stream_name(const char *path);
+extern const tchar *
+path_stream_name(const tchar *path);
 
 extern void
-to_parent_name(char buf[], size_t len);
+to_parent_name(tchar *buf, size_t len);
 
 extern void
 print_string(const void *string, size_t len);
@@ -264,7 +345,7 @@ static inline void
 print_byte_field(const u8 field[], size_t len)
 {
        while (len--)
-               printf("%02hhx", *field++);
+               tprintf(T("%02hhx"), *field++);
 }
 
 static inline u32
@@ -284,12 +365,12 @@ bsr32(u32 n)
 }
 
 extern int
-wimlib_fprintf(FILE *fp, const char *format, ...)
+wimlib_fprintf(FILE *fp, const tchar *format, ...)
        //FORMAT(printf, 2, 3)
        ;
 
 extern int
-wimlib_printf(const char *format, ...)
+wimlib_printf(const tchar *format, ...)
        //FORMAT(printf, 1, 2)
        ;
 
index 823d3a4..bba8487 100644 (file)
--- a/src/wim.c
+++ b/src/wim.c
@@ -274,18 +274,18 @@ wimlib_get_compression_type(const WIMStruct *w)
        return wim_hdr_flags_compression_type(w->hdr.flags);
 }
 
-WIMLIBAPI const char *
+WIMLIBAPI const tchar *
 wimlib_get_compression_type_string(int ctype)
 {
        switch (ctype) {
                case WIMLIB_COMPRESSION_TYPE_NONE:
-                       return "None";
+                       return T("None");
                case WIMLIB_COMPRESSION_TYPE_LZX:
-                       return "LZX";
+                       return T("LZX");
                case WIMLIB_COMPRESSION_TYPE_XPRESS:
-                       return "XPRESS";
+                       return T("XPRESS");
                default:
-                       return "Invalid";
+                       return T("Invalid");
        }
 }
 
@@ -295,34 +295,33 @@ wimlib_get_compression_type_string(int ctype)
  * starting at 1.
  */
 WIMLIBAPI int
-wimlib_resolve_image(WIMStruct *w, const utf8char *image_name_or_num)
+wimlib_resolve_image(WIMStruct *w, const tchar *image_name_or_num)
 {
-       char *p;
+       tchar *p;
        int image;
        int i;
 
        if (!image_name_or_num || !*image_name_or_num)
                return WIMLIB_NO_IMAGE;
 
-       if (strcmp(image_name_or_num, "all") == 0
-           || strcmp(image_name_or_num, "*") == 0)
+       if (tstrcmp(image_name_or_num, T("all")) == 0
+           || tstrcmp(image_name_or_num, T("*")) == 0)
                return WIMLIB_ALL_IMAGES;
-       image = strtol(image_name_or_num, &p, 10);
-       if (p != image_name_or_num && *p == '\0' && image > 0) {
+       image = tstrtol(image_name_or_num, &p, 10);
+       if (p != image_name_or_num && *p == T('\0') && image > 0) {
                if (image > w->hdr.image_count)
                        return WIMLIB_NO_IMAGE;
                return image;
        } else {
                for (i = 1; i <= w->hdr.image_count; i++) {
-                       if (strcmp(image_name_or_num,
-                                  wimlib_get_image_name(w, i)) == 0)
+                       if (tstrcmp(image_name_or_num,
+                                   wimlib_get_image_name(w, i)) == 0)
                                return i;
                }
                return WIMLIB_NO_IMAGE;
        }
 }
 
-
 /* Prints some basic information about a WIM file. */
 WIMLIBAPI void
 wimlib_print_wim_information(const WIMStruct *w)
@@ -330,21 +329,22 @@ wimlib_print_wim_information(const WIMStruct *w)
        const struct wim_header *hdr;
 
        hdr = &w->hdr;
-       puts("WIM Information:");
-       puts("----------------");
-       printf("Path:           %s\n", w->filename);
-       fputs ("GUID:           0x", stdout);
+       tputs(T("WIM Information:"));
+       tputs(T("----------------"));
+       tprintf(T("Path:           %"TS"\n"), w->filename);
+       tfputs(T("GUID:           0x"), stdout);
        print_byte_field(hdr->guid, WIM_GID_LEN);
-       putchar('\n');
-       printf("Image Count:    %d\n", hdr->image_count);
-       printf("Compression:    %s\n", wimlib_get_compression_type_string(
-                                               wimlib_get_compression_type(w)));
-       printf("Part Number:    %d/%d\n", hdr->part_number, hdr->total_parts);
-       printf("Boot Index:     %d\n", hdr->boot_idx);
-       printf("Size:           %"PRIu64" bytes\n",
-                               wim_info_get_total_bytes(w->wim_info));
-       printf("Integrity Info: %s\n", (w->hdr.integrity.offset != 0) ? "yes" : "no");
-       putchar('\n');
+       tputchar(T('\n'));
+       tprintf(T("Image Count:    %d\n"), hdr->image_count);
+       tprintf(T("Compression:    %"TS"\n"),
+               wimlib_get_compression_type_string(wimlib_get_compression_type(w)));
+       tprintf(T("Part Number:    %d/%d\n"), hdr->part_number, hdr->total_parts);
+       tprintf(T("Boot Index:     %d\n"), hdr->boot_idx);
+       tprintf(T("Size:           %"PRIu64" bytes\n"),
+               wim_info_get_total_bytes(w->wim_info));
+       tprintf(T("Integrity Info: %"TS"\n"),
+               (w->hdr.integrity.offset != 0) ? T("yes") : T("no"));
+       tputchar(T('\n'));
 }
 
 WIMLIBAPI bool
@@ -361,21 +361,21 @@ wimlib_print_available_images(const WIMStruct *w, int image)
        int i;
        int n;
        if (image == WIMLIB_ALL_IMAGES) {
-               n = printf("Available Images:\n");
+               n = tprintf(T("Available Images:\n"));
                first = 1;
                last = w->hdr.image_count;
        } else if (image >= 1 && image <= w->hdr.image_count) {
-               n = printf("Information for Image %d\n", image);
+               n = tprintf(T("Information for Image %d\n"), image);
                first = image;
                last = image;
        } else {
-               printf("wimlib_print_available_images(): Invalid image %d",
-                      image);
+               tprintf(T("wimlib_print_available_images(): Invalid image %d"),
+                       image);
                return;
        }
        for (i = 0; i < n - 1; i++)
-               putchar('-');
-       putchar('\n');
+               tputchar(T('-'));
+       tputchar(T('\n'));
        for (i = first; i <= last; i++)
                print_image_info(w->wim_info, i);
 }
@@ -452,17 +452,17 @@ wimlib_get_boot_idx(const WIMStruct *w)
  * lookup table, and optionally checks the integrity.
  */
 static int
-begin_read(WIMStruct *w, const mbchar *in_wim_path, int open_flags,
+begin_read(WIMStruct *w, const tchar *in_wim_path, int open_flags,
           wimlib_progress_func_t progress_func)
 {
        int ret;
        int xml_num_images;
 
-       DEBUG("Reading the WIM file `%s'", in_wim_path);
+       DEBUG("Reading the WIM file `%"TS"'", in_wim_path);
 
-       w->fp = fopen(in_wim_path, "rb");
+       w->fp = tfopen(in_wim_path, T("rb"));
        if (!w->fp) {
-               ERROR_WITH_ERRNO("Failed to open `%s' for reading",
+               ERROR_WITH_ERRNO("Failed to open `%"TS"' for reading",
                                 in_wim_path);
                return WIMLIB_ERR_OPEN;
        }
@@ -496,7 +496,7 @@ begin_read(WIMStruct *w, const mbchar *in_wim_path, int open_flags,
 
        /* If the boot index is invalid, print a warning and set it to 0 */
        if (w->hdr.boot_idx > w->hdr.image_count) {
-               WARNING("In `%s', image %u is marked as bootable, "
+               WARNING("In `%"TS"', image %u is marked as bootable, "
                        "but there are only %u images in the WIM",
                        in_wim_path, w->hdr.boot_idx, w->hdr.image_count);
                w->hdr.boot_idx = 0;
@@ -511,7 +511,7 @@ begin_read(WIMStruct *w, const mbchar *in_wim_path, int open_flags,
        if (open_flags & WIMLIB_OPEN_FLAG_CHECK_INTEGRITY) {
                ret = check_wim_integrity(w, progress_func);
                if (ret == WIM_INTEGRITY_NONEXISTENT) {
-                       WARNING("No integrity information for `%s'; skipping "
+                       WARNING("No integrity information for `%"TS"'; skipping "
                                "integrity check.", in_wim_path);
                } else if (ret == WIM_INTEGRITY_NOT_OK) {
                        ERROR("WIM is not intact! (Failed integrity check)");
@@ -574,14 +574,14 @@ begin_read(WIMStruct *w, const mbchar *in_wim_path, int open_flags,
 
        xml_num_images = wim_info_get_num_images(w->wim_info);
        if (xml_num_images != w->hdr.image_count) {
-               ERROR("In the file `%s', there are %u <IMAGE> elements "
+               ERROR("In the file `%"TS"', there are %u <IMAGE> elements "
                      "in the XML data,", in_wim_path, xml_num_images);
                ERROR("but %u images in the WIM!  There must be exactly one "
                      "<IMAGE> element per image.", w->hdr.image_count);
                return WIMLIB_ERR_IMAGE_COUNT;
        }
 
-       DEBUG("Done beginning read of WIM file `%s'.", in_wim_path);
+       DEBUG("Done beginning read of WIM file `%"TS"'.", in_wim_path);
        return 0;
 }
 
@@ -589,7 +589,7 @@ begin_read(WIMStruct *w, const mbchar *in_wim_path, int open_flags,
  * Opens a WIM file and creates a WIMStruct for it.
  */
 WIMLIBAPI int
-wimlib_open_wim(const mbchar *wim_file, int open_flags,
+wimlib_open_wim(const tchar *wim_file, int open_flags,
                WIMStruct **w_ret,
                wimlib_progress_func_t progress_func)
 {
index 18417d1..d1b22cd 100644 (file)
  */
 typedef struct WIMStruct WIMStruct;
 
-/** Byte of a string encoded in the locale-dependent encoding */
-typedef char wimlib_mbchar;
-
-/** Byte of a string encoded in UTF-8 */
-typedef char wimlib_utf8char;
+#ifdef __WIN32__
+typedef wchar_t wimlib_tchar;
+#else
+typedef char wimlib_tchar;
+#endif
 
 /**
  * Specifies the compression type of a WIM file.
@@ -435,12 +435,12 @@ union wimlib_progress_info {
         * ::WIMLIB_PROGRESS_MSG_SCAN_END. */
        struct wimlib_progress_info_scan {
                /** Directory or NTFS volume that is being scanned. */
-               const wimlib_mbchar *source;
+               const wimlib_tchar *source;
 
                /** Path to the file or directory that is about to be scanned,
                 * relative to the root of the image capture or the NTFS volume.
                 * */
-               const wimlib_mbchar *cur_path;
+               const wimlib_tchar *cur_path;
 
                /** True iff @a cur_path is being excluded from the image
                 * capture due to the capture configuration file. */
@@ -449,7 +449,7 @@ union wimlib_progress_info {
                /** Target path in the WIM.  Only valid on messages
                 * ::WIMLIB_PROGRESS_MSG_SCAN_BEGIN and
                 * ::WIMLIB_PROGRESS_MSG_SCAN_END. */
-               const wimlib_mbchar *wim_target_path;
+               const wimlib_tchar *wim_target_path;
        } scan;
 
        /** Valid on messages ::WIMLIB_PROGRESS_MSG_EXTRACT_IMAGE_BEGIN,
@@ -465,18 +465,18 @@ union wimlib_progress_info {
                int extract_flags;
 
                /** Full path to the WIM file being extracted. */
-               const wimlib_mbchar *wimfile_name;
+               const wimlib_tchar *wimfile_name;
 
                /** Name of the image being extracted. */
-               const wimlib_utf8char *image_name;
+               const wimlib_tchar *image_name;
 
                /** Directory or NTFS volume to which the image is being
                 * extracted. */
-               const wimlib_mbchar *target;
+               const wimlib_tchar *target;
 
                /** Current dentry being extracted.  (Valid only if message is
                 * ::WIMLIB_PROGRESS_MSG_EXTRACT_DENTRY.) */
-               const wimlib_mbchar *cur_path;
+               const wimlib_tchar *cur_path;
 
                /** Number of bytes of uncompressed data that will be extracted.
                 * Takes into account hard links (they are not counted for each
@@ -498,11 +498,11 @@ union wimlib_progress_info {
        /** Valid on messages ::WIMLIB_PROGRESS_MSG_RENAME. */
        struct wimlib_progress_info_rename {
                /** Name of the temporary file that the WIM was written to. */
-               const wimlib_mbchar *from;
+               const wimlib_tchar *from;
 
                /** Name of the original WIM file to which the temporary file is
                 * being renamed. */
-               const wimlib_mbchar *to;
+               const wimlib_tchar *to;
        } rename;
 
        /** Valid on messages ::WIMLIB_PROGRESS_MSG_VERIFY_INTEGRITY and
@@ -530,7 +530,7 @@ union wimlib_progress_info {
 
                /** Filename of the WIM (only valid if the message is
                 * ::WIMLIB_PROGRESS_MSG_VERIFY_INTEGRITY). */
-               const wimlib_mbchar *filename;
+               const wimlib_tchar *filename;
        } integrity;
 
        /** Valid on messages ::WIMLIB_PROGRESS_MSG_JOIN_STREAMS. */
@@ -572,7 +572,7 @@ union wimlib_progress_info {
                /** Name of the split WIM part that is about to be started
                 * (::WIMLIB_PROGRESS_MSG_SPLIT_BEGIN_PART) or has just been
                 * finished (::WIMLIB_PROGRESS_MSG_SPLIT_END_PART). */
-               const wimlib_mbchar *part_name;
+               const wimlib_tchar *part_name;
        } split;
 };
 
@@ -593,12 +593,12 @@ typedef int (*wimlib_progress_func_t)(enum wimlib_progress_msg msg_type,
 struct wimlib_capture_source {
        /** Absolute or relative path to a file or directory on the external
         * filesystem to be included in the WIM image. */
-       wimlib_mbchar *fs_source_path;
+       wimlib_tchar *fs_source_path;
 
        /** Destination path in the WIM image.  Leading and trailing slashes are
         * ignored.  The empty string or @c NULL means the root directory of the
         * WIM image. */
-       wimlib_mbchar *wim_target_path;
+       wimlib_tchar *wim_target_path;
 
        /** Reserved; set to 0. */
        long reserved;
@@ -764,6 +764,68 @@ struct wimlib_capture_source {
  * deleting an image in this way. */
 #define WIMLIB_WRITE_FLAG_SOFT_DELETE                  0x00000010
 
+
+#if 0
+/****************************************************************
+ * Definition of struct wimlib_modify_command, with various flags
+ ****************************************************************/
+
+enum {
+       WIMLIB_MOVE_TREE_FLAG_OVERWRITE_ALL                     = 0x1,
+       WIMLIB_MOVE_TREE_FLAG_OVERWRITE_NONDIRECTORIES          = 0x2,
+       WIMLIB_MOVE_TREE_FLAG_OVERWRITE_EMPTY_DIRECTORIES       = 0x4,
+       WIMLIB_MOVE_TREE_FLAG_OVERWRITE_DIRECTORIES             = 0x8,
+};
+
+enum {
+       WIMLIB_DELETE_TREE_FLAG_FORCE                   = 0x1,
+       WIMLIB_DELETE_TREE_FLAG_RECURSIVE               = 0x2,
+       WIMLIB_DELETE_TREE_FLAG_REMOVE_EMPTY_DIR        = 0x4,
+};
+
+enum {
+       WIMLIB_ADD_TREE_FLAG_DEREFERENCE                = 0x1,
+       WIMLIB_ADD_TREE_FLAG_VERBOSE                    = 0x2,
+       WIMLIB_ADD_TREE_FLAG_UNIX_DATA                  = 0x4,
+       WIMLIB_ADD_TREE_FLAG_NOACLS                     = 0x8,
+       WIMLIB_ADD_TREE_FLAG_NTFS_VOLUME                = 0x01,
+       WIMLIB_ADD_TREE_FLAG_OVERLAY                    = 0x02,
+       WIMLIB_ADD_TREE_FLAG_MAKE_NECESSARY_DIRS        = 0x04,
+};
+
+enum wimlib_modify_op {
+       WIMLIB_MODIFY_OP_DELETE_TREE,
+       WIMLIB_MODIFY_OP_ADD_TREE,
+       WIMLIB_MODIFY_OP_MOVE_TREE,
+};
+
+struct wimlib_modify_command {
+       enum wimlib_modify_op op;
+       union {
+               struct wimlib_modify_command_delete_tree {
+                       int delete_tree_flags;
+                       const wimlib_tchar *tree_wim_path;
+                       unsigned long reserved;
+               } delete_tree;
+
+               struct wimlib_modify_command_add_tree {
+                       int add_tree_flags;
+                       const wimlib_tchar *fs_source_path;
+                       const wimlib_tchar *wim_target_path;
+                       unsigned long reserved;
+               } add_tree;
+
+               struct wimlib_modify_command_move_tree {
+                       int move_tree_flags;
+                       const wimlib_tchar *wim_source_path;
+                       const wimlib_tchar *wim_target_path;
+                       unsigned long reserved;
+               } move_tree;
+       };
+};
+#endif
+
+
 /**
  * Possible values of the error code returned by many functions in wimlib.
  *
@@ -924,10 +986,12 @@ enum wimlib_error_code {
  *     wimlib was configured with the @c --without-ntfs-3g flag.
  */
 extern int
-wimlib_add_image(WIMStruct *wim, const wimlib_mbchar *source,
-                const wimlib_utf8char *name,
-                const wimlib_mbchar *config,
-                size_t config_len, int add_image_flags,
+wimlib_add_image(WIMStruct *wim,
+                const wimlib_tchar *source,
+                const wimlib_tchar *name,
+                const wimlib_tchar *config,
+                size_t config_len,
+                int add_image_flags,
                 wimlib_progress_func_t progress_func);
 
 /** This function is equivalent to wimlib_add_image() except it allows for
@@ -956,8 +1020,8 @@ extern int
 wimlib_add_image_multisource(WIMStruct *w,
                             struct wimlib_capture_source *sources,
                             size_t num_sources,
-                            const wimlib_utf8char *name,
-                            const wimlib_mbchar *config_str,
+                            const wimlib_tchar *name,
+                            const wimlib_tchar *config_str,
                             size_t config_len,
                             int add_image_flags,
                             wimlib_progress_func_t progress_func);
@@ -1141,8 +1205,8 @@ wimlib_delete_image(WIMStruct *wim, int image);
 extern int
 wimlib_export_image(WIMStruct *src_wim, int src_image,
                    WIMStruct *dest_wim,
-                   const wimlib_utf8char *dest_name,
-                   const wimlib_utf8char *dest_description,
+                   const wimlib_tchar *dest_name,
+                   const wimlib_tchar *dest_description,
                    int export_flags,
                    WIMStruct **additional_swms,
                    unsigned num_additional_swms,
@@ -1272,7 +1336,7 @@ wimlib_export_image(WIMStruct *src_wim, int src_image,
  */
 extern int
 wimlib_extract_image(WIMStruct *wim, int image,
-                    const wimlib_mbchar *target,
+                    const wimlib_tchar *target,
                     int extract_flags,
                     WIMStruct **additional_swms,
                     unsigned num_additional_swms,
@@ -1346,7 +1410,7 @@ wimlib_get_compression_type(const WIMStruct *wim);
  *     A statically allocated string: "None", "LZX", "XPRESS", or "Invalid",
  *     respectively.
  */
-extern const wimlib_mbchar *
+extern const wimlib_tchar *
 wimlib_get_compression_type_string(int ctype);
 
 /**
@@ -1359,7 +1423,7 @@ wimlib_get_compression_type_string(int ctype);
  *     Pointer to a statically allocated string describing the error code,
  *     or @c NULL if the error code is not valid.
  */
-extern const wimlib_mbchar *
+extern const wimlib_tchar *
 wimlib_get_error_string(enum wimlib_error_code code);
 
 /**
@@ -1378,7 +1442,7 @@ wimlib_get_error_string(enum wimlib_error_code code);
  *     in addition, the string will become invalid if the description of the
  *     image is changed, the image is deleted, or the ::WIMStruct is destroyed.
  */
-extern const wimlib_utf8char *
+extern const wimlib_tchar *
 wimlib_get_image_description(const WIMStruct *wim, int image);
 
 /**
@@ -1400,7 +1464,7 @@ wimlib_get_image_description(const WIMStruct *wim, int image);
  *     the WIM to be unnamed, in which case an empty string will be returned
  *     when the corresponding name is requested.
  */
-extern const wimlib_utf8char *
+extern const wimlib_tchar *
 wimlib_get_image_name(const WIMStruct *wim, int image);
 
 
@@ -1482,7 +1546,7 @@ wimlib_has_integrity_table(const WIMStruct *wim);
  *     the empty string, @c false is returned.
  */
 extern bool
-wimlib_image_name_in_use(const WIMStruct *wim, const wimlib_utf8char *name);
+wimlib_image_name_in_use(const WIMStruct *wim, const wimlib_tchar *name);
 
 /**
  * Joins a split WIM into a stand-alone one-part WIM.
@@ -1522,9 +1586,9 @@ wimlib_image_name_in_use(const WIMStruct *wim, const wimlib_utf8char *name);
  * wimlib_join(), since it is possible to export all images from a split WIM.
  */
 extern int
-wimlib_join(const wimlib_mbchar * const *swms,
+wimlib_join(const wimlib_tchar * const *swms,
            unsigned num_swms,
-           const wimlib_mbchar *output_path,
+           const wimlib_tchar *output_path,
            int swm_open_flags,
            int wim_write_flags,
            wimlib_progress_func_t progress_func);
@@ -1628,10 +1692,13 @@ wimlib_join(const wimlib_mbchar * const *swms,
  *     support mounting a split WIM read-only.
  */
 extern int
-wimlib_mount_image(WIMStruct *wim, int image, const wimlib_mbchar *dir,
-                  int mount_flags, WIMStruct **additional_swms,
+wimlib_mount_image(WIMStruct *wim,
+                  int image,
+                  const wimlib_tchar *dir,
+                  int mount_flags,
+                  WIMStruct **additional_swms,
                   unsigned num_additional_swms,
-                  const wimlib_mbchar *staging_dir);
+                  const wimlib_tchar *staging_dir);
 
 /**
  * Opens a WIM file and creates a ::WIMStruct for it.
@@ -1712,8 +1779,10 @@ wimlib_mount_image(WIMStruct *wim, int image, const wimlib_mbchar *dir,
  *     The XML data for @a wim_file is invalid.
  */
 extern int
-wimlib_open_wim(const wimlib_mbchar *wim_file, int open_flags,
-               WIMStruct **wim_ret, wimlib_progress_func_t progress_func);
+wimlib_open_wim(const wimlib_tchar *wim_file,
+               int open_flags,
+               WIMStruct **wim_ret,
+               wimlib_progress_func_t progress_func);
 
 /**
  * Overwrites the file that the WIM was originally read from, with changes made.
@@ -1950,7 +2019,7 @@ wimlib_print_wim_information(const WIMStruct *wim);
  */
 extern int
 wimlib_resolve_image(WIMStruct *wim,
-                    const wimlib_utf8char *image_name_or_num);
+                    const wimlib_tchar *image_name_or_num);
 
 /**
  * Sets which image in the WIM is marked as bootable.
@@ -1993,7 +2062,7 @@ wimlib_set_boot_idx(WIMStruct *wim, int boot_idx);
  */
 extern int
 wimlib_set_image_descripton(WIMStruct *wim, int image,
-                           const wimlib_utf8char *description);
+                           const wimlib_tchar *description);
 
 /**
  * Changes what is written in the \<FLAGS\> element in the WIM XML data
@@ -2016,7 +2085,7 @@ wimlib_set_image_descripton(WIMStruct *wim, int image,
  *     Failed to allocate the memory needed to duplicate the @a flags string.
  */
 extern int wimlib_set_image_flags(WIMStruct *wim, int image,
-                                 const wimlib_utf8char *flags);
+                                 const wimlib_tchar *flags);
 
 /**
  * Changes the name of an image in the WIM.
@@ -2041,7 +2110,7 @@ extern int wimlib_set_image_flags(WIMStruct *wim, int image,
  *     Failed to allocate the memory needed to duplicate the @a name string.
  */
 extern int wimlib_set_image_name(WIMStruct *wim, int image,
-                                const wimlib_utf8char *name);
+                                const wimlib_tchar *name);
 
 /**
  * Set the functions that wimlib uses to allocate and free memory.
@@ -2134,8 +2203,10 @@ wimlib_set_print_errors(bool show_messages);
  * compressed resources re-compressed.
  */
 extern int
-wimlib_split(WIMStruct *wim, const wimlib_mbchar *swm_name,
-            size_t part_size, int write_flags,
+wimlib_split(WIMStruct *wim,
+            const wimlib_tchar *swm_name,
+            size_t part_size,
+            int write_flags,
             wimlib_progress_func_t progress_func);
 
 /**
@@ -2196,7 +2267,8 @@ wimlib_split(WIMStruct *wim, const wimlib_mbchar *swm_name,
  *     been made to files in the staging directory.
  */
 extern int
-wimlib_unmount_image(const wimlib_mbchar *dir, int unmount_flags,
+wimlib_unmount_image(const wimlib_tchar *dir,
+                    int unmount_flags,
                     wimlib_progress_func_t progress_func);
 
 /**
@@ -2268,8 +2340,11 @@ wimlib_unmount_image(const wimlib_mbchar *dir, int unmount_flags,
  *     path.
  */
 extern int
-wimlib_write(WIMStruct *wim, const wimlib_mbchar *path, int image,
-            int write_flags, unsigned num_threads,
+wimlib_write(WIMStruct *wim,
+            const wimlib_tchar *path,
+            int image,
+            int write_flags,
+            unsigned num_threads,
             wimlib_progress_func_t progress_func);
 
 #endif /* _WIMLIB_H */
index 43331e2..1df3bf7 100644 (file)
@@ -281,7 +281,7 @@ struct WIMStruct {
        FILE *out_fp;
 
        /* The name of the WIM file (if any) that has been opened. */
-       mbchar *filename;
+       tchar *filename;
 
        /* The lookup table for the WIM file. */
        struct wim_lookup_table *lookup_table;
@@ -354,7 +354,7 @@ resource_is_compressed(const struct resource_entry *entry)
 /* add_image.c */
 
 struct pattern_list {
-       const mbchar **pats;
+       const tchar **pats;
        size_t num_pats;
        size_t num_allocated_pats;
 };
@@ -364,12 +364,12 @@ struct capture_config {
        struct pattern_list exclusion_exception;
        struct pattern_list compression_exclusion_list;
        struct pattern_list alignment_list;
-       mbchar *config_str;
-       mbchar *prefix;
-       size_t prefix_len;
+       tchar *config_str;
+       tchar *prefix;
+       size_t prefix_num_tchars;
 };
 extern bool
-exclude_path(const mbchar *path, const struct capture_config *config,
+exclude_path(const tchar *path, const struct capture_config *config,
             bool exclude_prefix);
 
 extern int
@@ -438,7 +438,7 @@ write_metadata_resource(WIMStruct *w);
 
 struct apply_args {
        WIMStruct *w;
-       const mbchar *target;
+       const tchar *target;
        int extract_flags;
        unsigned num_utime_warnings;
        struct list_head *stream_list;
@@ -462,7 +462,7 @@ libntfs3g_global_init();
 /* ntfs-capture.c */
 extern int
 build_dentry_tree_ntfs(struct wim_dentry **root_p,
-                      const mbchar *device,
+                      const tchar *device,
                       struct wim_lookup_table *lookup_table,
                       struct wim_security_data *sd,
                       const struct capture_config *config,
@@ -545,14 +545,17 @@ extern void
 free_security_data(struct wim_security_data *sd);
 
 /* symlink.c */
+
+#ifndef __WIN32__
 ssize_t
 inode_readlink(const struct wim_inode *inode, char *buf, size_t buf_len,
               const WIMStruct *w, int read_resource_flags);
 
 extern int
-inode_set_symlink(struct wim_inode *inode, const mbchar *target,
+inode_set_symlink(struct wim_inode *inode, const char *target,
                  struct wim_lookup_table *lookup_table,
                  struct wim_lookup_table_entry **lte_ret);
+#endif
 
 /* verify.c */
 
@@ -591,7 +594,7 @@ destroy_image_metadata(struct wim_image_metadata *imd,
 
 
 extern int
-begin_write(WIMStruct *w, const mbchar *path, int write_flags);
+begin_write(WIMStruct *w, const tchar *path, int write_flags);
 
 extern void
 close_wim_writable(WIMStruct *w);
index 0c5c51c..78b7167 100644 (file)
@@ -837,9 +837,9 @@ out:
 
 /* Replacement for POSIX fnmatch() (partial functionality only) */
 int
-fnmatch(const char *pattern, const char *string, int flags)
+fnmatch(const wchar_t *pattern, const wchar_t *string, int flags)
 {
-       if (PathMatchSpecA(string, pattern))
+       if (PathMatchSpecW(string, pattern))
                return 0;
        else
                return FNM_NOMATCH;
@@ -1125,32 +1125,22 @@ out:
 
 /* Extract a file, directory, reparse point, or hard link to an
  * already-extracted file using the Win32 API */
-int win32_do_apply_dentry(const mbchar *output_path,
-                         size_t output_path_nbytes,
+int win32_do_apply_dentry(const wchar_t *output_path,
+                         size_t output_path_num_wchars,
                          struct wim_dentry *dentry,
                          struct apply_args *args)
 {
-       wchar_t *utf16le_path;
-       size_t utf16le_path_nbytes;
-       DWORD err;
-       int ret;
-       struct wim_inode *inode = dentry->d_inode;
-
-       ret = mbs_to_utf16le(output_path, output_path_nbytes,
-                            &utf16le_path, &utf16le_path_nbytes);
-       if (ret)
-               return ret;
-
+       ret = 0;
        if (inode->i_nlink > 1 && inode->i_extracted_file != NULL) {
                /* Linked file, with another name already extracted.  Create a
                 * hard link. */
                DEBUG("Creating hard link \"%ls => %ls\"",
-                     utf16le_path, inode->i_extracted_file);
+                     output_path, inode->i_extracted_file);
                if (!CreateHardLinkW(utf16le_path, inode->i_extracted_file, NULL))
                {
                        err = GetLastError();
                        ERROR("Can't create hard link \"%ls => %ls\"",
-                             utf16le_path, inode->i_extracted_file);
+                             output_path, inode->i_extracted_file);
                        ret = WIMLIB_ERR_LINK;
                        win32_error(err);
                }
@@ -1163,23 +1153,21 @@ int win32_do_apply_dentry(const mbchar *output_path,
                else
                        security_data = wim_const_security_data(args->w);
 
-               ret = win32_extract_streams(inode, utf16le_path,
+               ret = win32_extract_streams(inode, output_path,
                                            &args->progress.extract.completed_bytes,
                                            security_data);
                if (ret)
-                       goto out_free_utf16_path;
+                       return ret;
 
                if (inode->i_nlink > 1) {
                        /* Save extracted path for a later call to
                         * CreateHardLinkW() if this inode has multiple links.
                         * */
-                       inode->i_extracted_file = utf16le_path;
-                       goto out;
+                       inode->i_extracted_file = WSTRDUP(utf16le_path);
+                       if (!inode->i_extracted_file)
+                               ret = WIMLIB_ERR_NOMEM;
                }
        }
-out_free_utf16_path:
-       FREE(utf16le_path);
-out:
        return ret;
 }
 
@@ -1271,20 +1259,20 @@ win32_get_number_of_processors()
 /* Replacement for POSIX-2008 realpath().  Warning: partial functionality only
  * (resolved_path must be NULL).   Also I highly doubt that GetFullPathName
  * really does the right thing under all circumstances. */
-mbchar *
-realpath(const mbchar *path, mbchar *resolved_path)
+wchar_t *
+realpath(const wchar_t *path, wchar_t *resolved_path)
 {
        DWORD ret;
        wimlib_assert(resolved_path == NULL);
 
-       ret = GetFullPathNameA(path, 0, NULL, NULL);
+       ret = GetFullPathNameW(path, 0, NULL, NULL);
        if (!ret)
                goto fail_win32;
 
-       resolved_path = MALLOC(ret);
+       resolved_path = TMALLOC(ret);
        if (!resolved_path)
                goto fail;
-       ret = GetFullPathNameA(path, ret, resolved_path, NULL);
+       ret = GetFullPathNameW(path, ret, resolved_path, NULL);
        if (!ret) {
                free(resolved_path);
                goto fail_win32;
@@ -1305,19 +1293,28 @@ nl_langinfo(nl_item item)
        return buf;
 }
 
-/* rename() on Windows fails if the destination file exists.  Fix it. */
+/* rename() on Windows fails if the destination file exists.  And we need to
+ * make it work on wide characters.  Fix it. */
 int
-rename_replacement(const char *oldpath, const char *newpath)
+win32_rename_replacement(const wchar_t *oldpath, const wchar_t *newpath)
 {
-       if (MoveFileExA(oldpath, newpath, MOVEFILE_REPLACE_EXISTING)) {
+       if (MoveFileExW(oldpath, newpath, MOVEFILE_REPLACE_EXISTING)) {
                return 0;
        } else {
                /* As usual, the possible error values are not documented */
                DWORD err = GetLastError();
-               ERROR("MoveFileExA(): Can't rename \"%s\" to \"%s\"",
+               ERROR("MoveFileEx(): Can't rename \"%ls\" to \"%ls\"",
                      oldpath, newpath);
                win32_error(err);
                errno = 0;
                return -1;
        }
 }
+
+/* truncate for wide-character paths */
+int
+win32_truncate_replacement(const char *path, off_t size)
+{
+       /* TODO */
+       wimlib_assert(0);
+}
index 1039236..5810caf 100644 (file)
@@ -7,7 +7,7 @@
 
 extern int
 win32_build_dentry_tree(struct wim_dentry **root_ret,
-                       const mbchar *root_disk_path,
+                       const tchar *root_disk_path,
                        struct wim_lookup_table *lookup_table,
                        struct wim_security_data *sd,
                        const struct capture_config *config,
@@ -16,7 +16,7 @@ win32_build_dentry_tree(struct wim_dentry **root_ret,
                        void *extra_arg);
 
 extern int
-win32_read_file(const utf16lechar *win32_filename, void *handle,
+win32_read_file(const tchar *filename, HANDLE handle,
                u64 offset, size_t size, void *buf);
 
 extern HANDLE
@@ -36,17 +36,17 @@ extern void win32_error_last();
 #define FNM_PATHNAME 0x1
 #define FNM_NOMATCH 1
 extern int
-fnmatch(const mbchar *pattern, const mbchar *string, int flags);
+fnmatch(const tchar *pattern, const tchar *string, int flags);
 
 extern int
-win32_do_apply_dentry(const mbchar *output_path,
-                     size_t output_path_len,
+win32_do_apply_dentry(const tchar *output_path,
+                     size_t output_path_nbytes,
                      struct wim_dentry *dentry,
                      struct apply_args *args);
 
 extern int
-win32_do_apply_dentry_timestamps(const mbchar *output_path,
-                                size_t output_path_len,
+win32_do_apply_dentry_timestamps(const tchar *output_path,
+                                size_t output_path_nbytes,
                                 const struct wim_dentry *dentry,
                                 const struct apply_args *args);
 
@@ -56,15 +56,8 @@ fsync(int fd);
 extern unsigned
 win32_get_number_of_processors();
 
-extern mbchar *
-realpath(const mbchar *path, mbchar *resolved_path);
-
-/* Microsoft's swprintf() violates the C standard and they require programmers
- * to do this weird define to get the correct function.  */
-#define swprintf _snwprintf
-
-/* Use Microsoft's weird _mkdir() function instead of mkdir() */
-#define mkdir(name, mode) _mkdir(name)
+extern tchar *
+realpath(const tchar *path, tchar *resolved_path);
 
 typedef enum {
        CODESET
@@ -74,8 +67,10 @@ extern char *
 nl_langinfo(nl_item item);
 
 extern int
-rename_replacement(const char *oldpath, const char *newpath);
-#define rename(oldpath, newpath) rename_replacement(oldpath, newpath)
+win32_rename_replacement(const tchar *oldpath, const tchar *newpath);
+
+extern int
+win32_truncate_replacement(const tchar *path, off_t size);
 
 extern void
 win32_global_init();
index 1982ea0..1c57405 100644 (file)
 #  define INVALID_HANDLE_VALUE ((HANDLE)(-1))
 #endif
 
+#if TCHAR_IS_UTF16LE
+#  include <wchar.h>
+#endif
+
 static int
 fflush_and_ftruncate(FILE *fp, off_t size)
 {
@@ -275,10 +279,10 @@ prepare_resource_for_read(struct wim_lookup_table_entry *lte
        switch (lte->resource_location) {
        case RESOURCE_IN_FILE_ON_DISK:
                if (!lte->file_on_disk_fp) {
-                       lte->file_on_disk_fp = fopen(lte->file_on_disk, "rb");
+                       lte->file_on_disk_fp = tfopen(lte->file_on_disk, T("rb"));
                        if (!lte->file_on_disk_fp) {
                                ERROR_WITH_ERRNO("Failed to open the file "
-                                                "`%s'", lte->file_on_disk);
+                                                "`%"TS"'", lte->file_on_disk);
                                return WIMLIB_ERR_OPEN;
                        }
                }
@@ -291,7 +295,7 @@ prepare_resource_for_read(struct wim_lookup_table_entry *lte
                        wimlib_assert(loc);
                        ni = ntfs_pathname_to_inode(*loc->ntfs_vol_p, NULL, loc->path);
                        if (!ni) {
-                               ERROR_WITH_ERRNO("Failed to open inode `%s' in NTFS "
+                               ERROR_WITH_ERRNO("Failed to open inode `%"TS"' in NTFS "
                                                 "volume", loc->path);
                                return WIMLIB_ERR_NTFS_3G;
                        }
@@ -300,7 +304,7 @@ prepare_resource_for_read(struct wim_lookup_table_entry *lte
                                                   loc->stream_name,
                                                   loc->stream_name_nchars);
                        if (!lte->attr) {
-                               ERROR_WITH_ERRNO("Failed to open attribute of `%s' in "
+                               ERROR_WITH_ERRNO("Failed to open attribute of `%"TS"' in "
                                                 "NTFS volume", loc->path);
                                ntfs_inode_close(ni);
                                return WIMLIB_ERR_NTFS_3G;
@@ -313,9 +317,9 @@ prepare_resource_for_read(struct wim_lookup_table_entry *lte
        case RESOURCE_WIN32:
                if (lte->win32_file_on_disk_fp == INVALID_HANDLE_VALUE) {
                        lte->win32_file_on_disk_fp =
-                               win32_open_file_data_only(lte->win32_file_on_disk);
+                               win32_open_file_data_only(lte->file_on_disk);
                        if (lte->win32_file_on_disk_fp == INVALID_HANDLE_VALUE) {
-                               ERROR("Win32 API: Can't open %ls", lte->win32_file_on_disk);
+                               ERROR("Win32 API: Can't open %"TS, lte->file_on_disk);
                                win32_error_last();
                                return WIMLIB_ERR_OPEN;
                        }
@@ -936,7 +940,7 @@ main_writer_thread_proc(struct list_head *stream_list,
                                                if (next_lte->resource_location ==
                                                    RESOURCE_IN_FILE_ON_DISK)
                                                {
-                                                       ERROR("We were reading it from `%s'; "
+                                                       ERROR("We were reading it from `%"TS"'; "
                                                              "maybe it changed while we were "
                                                              "reading it.",
                                                              next_lte->file_on_disk);
@@ -1669,12 +1673,12 @@ lock_wim(WIMStruct *w, FILE *fp)
                ret = flock(fileno(fp), LOCK_EX | LOCK_NB);
                if (ret != 0) {
                        if (errno == EWOULDBLOCK) {
-                               ERROR("`%s' is already being modified or has been "
+                               ERROR("`%"TS"' is already being modified or has been "
                                      "mounted read-write\n"
                                      "        by another process!", w->filename);
                                ret = WIMLIB_ERR_ALREADY_LOCKED;
                        } else {
-                               WARNING_WITH_ERRNO("Failed to lock `%s'",
+                               WARNING_WITH_ERRNO("Failed to lock `%"TS"'",
                                                   w->filename);
                                ret = 0;
                        }
@@ -1687,24 +1691,24 @@ lock_wim(WIMStruct *w, FILE *fp)
 #endif
 
 static int
-open_wim_writable(WIMStruct *w, const mbchar *path,
+open_wim_writable(WIMStruct *w, const tchar *path,
                  bool trunc, bool readable)
 {
-       const char *mode;
+       const tchar *mode;
        if (trunc)
                if (readable)
-                       mode = "w+b";
+                       mode = T("w+b");
                else
-                       mode = "wb";
+                       mode = T("wb");
        else
-               mode = "r+b";
+               mode = T("r+b");
 
        wimlib_assert(w->out_fp == NULL);
-       w->out_fp = fopen(path, mode);
+       w->out_fp = tfopen(path, mode);
        if (w->out_fp) {
                return 0;
        } else {
-               ERROR_WITH_ERRNO("Failed to open `%s' for writing", path);
+               ERROR_WITH_ERRNO("Failed to open `%"TS"' for writing", path);
                return WIMLIB_ERR_OPEN;
        }
 }
@@ -1723,7 +1727,7 @@ close_wim_writable(WIMStruct *w)
 
 /* Open file stream and write dummy header for WIM. */
 int
-begin_write(WIMStruct *w, const mbchar *path, int write_flags)
+begin_write(WIMStruct *w, const tchar *path, int write_flags)
 {
        int ret;
        ret = open_wim_writable(w, path, true,
@@ -1736,7 +1740,7 @@ begin_write(WIMStruct *w, const mbchar *path, int write_flags)
 
 /* Writes a stand-alone WIM to a file.  */
 WIMLIBAPI int
-wimlib_write(WIMStruct *w, const mbchar *path,
+wimlib_write(WIMStruct *w, const tchar *path,
             int image, int write_flags, unsigned num_threads,
             wimlib_progress_func_t progress_func)
 {
@@ -1778,7 +1782,7 @@ wimlib_write(WIMStruct *w, const mbchar *path,
        ret = finish_write(w, image, write_flags, progress_func);
 out:
        close_wim_writable(w);
-       DEBUG("wimlib_write(path=%s) = %d", path, ret);
+       DEBUG("wimlib_write(path=%"TS") = %d", path, ret);
        return ret;
 }
 
@@ -1858,7 +1862,7 @@ overwrite_wim_inplace(WIMStruct *w, int write_flags,
        off_t old_wim_end;
        bool found_modified_image;
 
-       DEBUG("Overwriting `%s' in-place", w->filename);
+       DEBUG("Overwriting `%"TS"' in-place", w->filename);
 
        /* Make sure that the integrity table (if present) is after the XML
         * data, and that there are no stream resources, metadata resources, or
@@ -1944,11 +1948,11 @@ overwrite_wim_inplace(WIMStruct *w, int write_flags,
 out_ftruncate:
        close_wim_writable(w);
        if (ret != 0 && !(write_flags & WIMLIB_WRITE_FLAG_NO_LOOKUP_TABLE)) {
-               WARNING("Truncating `%s' to its original size (%"PRIu64" bytes)",
+               WARNING("Truncating `%"TS"' to its original size (%"PRIu64" bytes)",
                        w->filename, old_wim_end);
                /* Return value of truncate() is ignored because this is already
                 * an error path. */
-               (void)truncate(w->filename, old_wim_end);
+               (void)ttruncate(w->filename, old_wim_end);
        }
        w->wim_locked = 0;
        return ret;
@@ -1962,25 +1966,25 @@ overwrite_wim_via_tmpfile(WIMStruct *w, int write_flags,
        size_t wim_name_len;
        int ret;
 
-       DEBUG("Overwriting `%s' via a temporary file", w->filename);
+       DEBUG("Overwriting `%"TS"' via a temporary file", w->filename);
 
        /* Write the WIM to a temporary file in the same directory as the
         * original WIM. */
-       wim_name_len = strlen(w->filename);
-       mbchar tmpfile[wim_name_len + 10];
-       memcpy(tmpfile, w->filename, wim_name_len);
+       wim_name_len = tstrlen(w->filename);
+       tchar tmpfile[wim_name_len + 10];
+       tmemcpy(tmpfile, w->filename, wim_name_len);
        randomize_char_array_with_alnum(tmpfile + wim_name_len, 9);
-       tmpfile[wim_name_len + 9] = '\0';
+       tmpfile[wim_name_len + 9] = T('\0');
 
        ret = wimlib_write(w, tmpfile, WIMLIB_ALL_IMAGES,
                           write_flags | WIMLIB_WRITE_FLAG_FSYNC,
                           num_threads, progress_func);
        if (ret != 0) {
-               ERROR("Failed to write the WIM file `%s'", tmpfile);
+               ERROR("Failed to write the WIM file `%"TS"'", tmpfile);
                goto err;
        }
 
-       DEBUG("Renaming `%s' to `%s'", tmpfile, w->filename);
+       DEBUG("Renaming `%"TS"' to `%"TS"'", tmpfile, w->filename);
 
 #ifdef __WIN32__
        /* Windows won't let you delete open files unless FILE_SHARE_DELETE was
@@ -1994,8 +1998,8 @@ overwrite_wim_via_tmpfile(WIMStruct *w, int write_flags,
 #endif
 
        /* Rename the new file to the old file .*/
-       if (rename(tmpfile, w->filename) != 0) {
-               ERROR_WITH_ERRNO("Failed to rename `%s' to `%s'",
+       if (trename(tmpfile, w->filename) != 0) {
+               ERROR_WITH_ERRNO("Failed to rename `%"TS"' to `%"TS"'",
                                 tmpfile, w->filename);
                ret = WIMLIB_ERR_RENAME;
                goto err;
@@ -2015,10 +2019,10 @@ overwrite_wim_via_tmpfile(WIMStruct *w, int write_flags,
        }
 
        /* Re-open the WIM read-only. */
-       w->fp = fopen(w->filename, "rb");
+       w->fp = tfopen(w->filename, T("rb"));
        if (w->fp == NULL) {
                ret = WIMLIB_ERR_REOPEN;
-               WARNING_WITH_ERRNO("Failed to re-open `%s' read-only",
+               WARNING_WITH_ERRNO("Failed to re-open `%"TS"' read-only",
                                   w->filename);
                FREE(w->filename);
                w->filename = NULL;
@@ -2026,8 +2030,8 @@ overwrite_wim_via_tmpfile(WIMStruct *w, int write_flags,
        return ret;
 err:
        /* Remove temporary file. */
-       if (unlink(tmpfile) != 0)
-               WARNING_WITH_ERRNO("Failed to remove `%s'", tmpfile);
+       if (tunlink(tmpfile) != 0)
+               WARNING_WITH_ERRNO("Failed to remove `%"TS"'", tmpfile);
        return ret;
 }
 
index 268b9d9..73ce120 100644 (file)
--- a/src/xml.c
+++ b/src/xml.c
@@ -49,16 +49,16 @@ struct windows_version {
 
 struct windows_info {
        u64        arch;
-       utf8char  *product_name;
-       utf8char  *edition_id;
-       utf8char  *installation_type;
-       utf8char  *hal;
-       utf8char  *product_type;
-       utf8char  *product_suite;
-       utf8char **languages;
-       utf8char  *default_language;
+       tchar  *product_name;
+       tchar  *edition_id;
+       tchar  *installation_type;
+       tchar  *hal;
+       tchar  *product_type;
+       tchar  *product_suite;
+       tchar **languages;
+       tchar  *default_language;
        size_t     num_languages;
-       utf8char  *system_root;
+       tchar  *system_root;
        bool       windows_version_exists;
        struct     windows_version windows_version;
 };
@@ -73,12 +73,12 @@ struct image_info {
        u64 creation_time;
        u64 last_modification_time;
        struct windows_info windows_info;
-       utf8char *name;
-       utf8char *description;
-       utf8char *display_name;
-       utf8char *display_description;
+       tchar *name;
+       tchar *description;
+       tchar *display_name;
+       tchar *display_description;
        union {
-               utf8char *flags;
+               tchar *flags;
                struct wim_lookup_table *lookup_table;
        };
 };
@@ -86,16 +86,16 @@ struct image_info {
 
 /* Returns a statically allocated string that is a string representation of the
  * architecture number. */
-static const char *
+static const tchar *
 get_arch(int arch)
 {
        switch (arch) {
        case 0:
-               return "x86";
+               return T("x86");
        case 6:
-               return "ia64";
+               return T("ia64");
        case 9:
-               return "x86_64";
+               return T("x86_64");
        /* XXX Are there other arch values? */
        default:
                return NULL;
@@ -499,42 +499,50 @@ print_windows_info(const struct windows_info *windows_info)
 {
        const struct windows_version *windows_version;
 
-       wimlib_printf("Architecture:           %s\n",
-                     get_arch(windows_info->arch) ?: "unknown");
+       tprintf(T("Architecture:           %"TS"\n"),
+               get_arch(windows_info->arch) ?: T("unknown"));
 
-       if (windows_info->product_name)
-               wimlib_printf("Product Name:           %U\n",
-                             windows_info->product_name);
+       if (windows_info->product_name) {
+               tprintf(T("Product Name:           %"TS"\n"),
+                       windows_info->product_name);
+       }
 
-       if (windows_info->edition_id)
-               wimlib_printf("Edition ID:             %U\n",
-                             windows_info->edition_id);
+       if (windows_info->edition_id) {
+               tprintf(T("Edition ID:             %"TS"\n"),
+                       windows_info->edition_id);
+       }
 
-       if (windows_info->installation_type)
-               wimlib_printf("Installation Type:      %U\n",
-                             windows_info->installation_type);
+       if (windows_info->installation_type) {
+               tprintf(T("Installation Type:      %"TS"\n"),
+                       windows_info->installation_type);
+       }
 
-       if (windows_info->hal)
-               wimlib_printf("HAL:                    %U\n",
+       if (windows_info->hal) {
+               tprintf(T("HAL:                    %"TS"\n"),
                              windows_info->hal);
+       }
 
-       if (windows_info->product_type)
-               wimlib_printf("Product Type:           %U\n",
-                             windows_info->product_type);
+       if (windows_info->product_type) {
+               tprintf(T("Product Type:           %"TS"\n"),
+                       windows_info->product_type);
+       }
 
-       if (windows_info->product_suite)
-               wimlib_printf("Product Suite:          %U\n",
-                             windows_info->product_suite);
+       if (windows_info->product_suite) {
+               tprintf(T("Product Suite:          %"TS"\n"),
+                       windows_info->product_suite);
+       }
 
-       printf("Languages:              ");
+       tprintf(T("Languages:              "));
        for (size_t i = 0; i < windows_info->num_languages; i++) {
-               wimlib_printf("%U", windows_info->languages[i]);
-               putchar(' ');
+
+               tfputs(windows_info->languages[i], stdout);
+               tputchar(T(' '));
+       }
+       tputchar(T('\n'));
+       if (windows_info->default_language) {
+               tprintf("Default Language:       %U\n",
+                       windows_info->default_language);
        }
-       putchar('\n');
-       if (windows_info->default_language)
-               wimlib_printf("Default Language:       %U\n",
-                      windows_info->default_language);
        if (windows_info->system_root)
                wimlib_printf("System Root:            %U\n",
                              windows_info->system_root);
@@ -553,6 +561,67 @@ print_windows_info(const struct windows_info *windows_info)
        }
 }
 
+const struct xml_string_spec {
+       const char *name;
+       size_t offset;
+};
+
+#define ELEM(STRING_NAME, MEMBER_NAME) \
+       {STRING_NAME, offsetof(struct image_info, MEMBER_NAME)}
+static const struct xml_string_spec image_info_xml_string_specs[] =
+       ELEM("NAME", name),
+       ELEM("DESCRIPTION", description),
+       ELEM("DISPLAYNAME", display_name),
+       ELEM("DISPLAYDESCRIPTION", display_description),
+       ELEM("FLAGS", flags),
+};
+#undef ELEM
+
+#define ELEM(STRING_NAME, MEMBER_NAME) \
+       {STRING_NAME, offsetof(struct windows_info, MEMBER_NAME)}
+static const struct xml_string_spec windows_info_xml_string_specs[] = {
+       ELEM("PRODUCTNAME", product_name),
+       ELEM("EDITIONID", edition_id),
+       ELEM("INSTALLATIONTYPE", installation_type),
+       ELEM("HAL", hal),
+       ELEM("PRODUCTTYPE", product_type),
+       ELEM("PRODUCTSUITE", product_suite),
+       ELEM("DEFAULT", default_language),
+       ELEM("SYSTEMROOT", system_root),
+};
+
+static int
+xml_write_string(xmlTextWriter *writer, const char *name,
+                const tchar *tstr)
+{
+       if (tstr) {
+               const utf8char *utf8_str;
+               int rc = tstr_to_utf8_simple(tstr, &utf8_str);
+               if (rc)
+                       return rc;
+               rc = xmlTextWriterWriteElement(writer, name, utf8_str);
+               FREE(utf8_str);
+               if (rc < 0)
+                       return rc;
+       }
+       return 0;
+}
+
+static int
+xml_write_strings_from_specs(xmlTextWriter *writer, const void *struct_with_strings,
+                            const struct xml_string_spec *specs, size_t num_specs)
+{
+       for (size_t i = 0; i < num_specs; i++) {
+               int rc = xml_write_string(writer, specs[i].name,
+                                     *(const tchar * const *)
+                                       (struct_with_strings + specs[i].offset));
+               if (rc)
+                       return rc;
+       }
+       return 0;
+}
+
+
 
 /* Writes the information contained in a `struct windows_version' to the XML
  * document being written.  This is the <VERSION> element inside the <WINDOWS>
@@ -763,40 +832,16 @@ xml_write_image_info(xmlTextWriter *writer, const struct image_info *image_info)
                        return rc;
        }
 
-       if (image_info->name) {
-               rc = xmlTextWriterWriteElement(writer, "NAME",
-                                              image_info->name);
-               if (rc < 0)
-                       return rc;
-       }
-
-       if (image_info->description) {
-               rc = xmlTextWriterWriteElement(writer, "DESCRIPTION",
-                                              image_info->description);
-               if (rc < 0)
-                       return rc;
-       }
-       if (image_info->display_name) {
-               rc = xmlTextWriterWriteElement(writer, "DISPLAYNAME",
-                                              image_info->display_name);
-               if (rc < 0)
-                       return rc;
-       }
-       if (image_info->display_description) {
-               rc = xmlTextWriterWriteElement(writer, "DISPLAYDESCRIPTION",
-                                              image_info->display_description);
-               if (rc < 0)
-                       return rc;
-       }
-
-       if (image_info->flags) {
-               rc = xmlTextWriterWriteElement(writer, "FLAGS",
-                                              image_info->flags);
-               if (rc < 0)
-                       return rc;
-       }
+       rc = xml_write_strings_from_specs(writer, image_info,
+                                         image_info_xml_string_specs,
+                                         ARRAY_LEN(image_info_xml_string_specs));
+       if (rc)
+               return rc;
 
-       return xmlTextWriterEndElement(writer); /* </IMAGE> */
+       rc = xmlTextWriterEndElement(writer); /* </IMAGE> */
+       if (rc < 0)
+               return rc;
+       return 0;
 }
 
 
@@ -912,8 +957,8 @@ int
 xml_export_image(const struct wim_info *old_wim_info,
                 int image,
                 struct wim_info **new_wim_info_p,
-                const utf8char *dest_image_name,
-                const utf8char *dest_image_description)
+                const tchar *dest_image_name,
+                const tchar *dest_image_description)
 {
        struct wim_info *new_wim_info;
        struct image_info *image_info;
@@ -1404,7 +1449,10 @@ write_xml_data(const struct wim_info *wim_info, int image, FILE *out,
                DEBUG("Writing %d <IMAGE> elements", last - first + 1);
                for (int i = first; i <= last; i++) {
                        ret = xml_write_image_info(writer, &wim_info->images[i - 1]);
-                       CHECK_RET;
+                       if (ret) {
+                               CHECK_RET;
+                               goto out_free_text_writer;
+                       }
                }
        }
 
@@ -1445,7 +1493,7 @@ out:
 }
 
 /* Returns the name of the specified image. */
-WIMLIBAPI const utf8char *
+WIMLIBAPI const tchar *
 wimlib_get_image_name(const WIMStruct *w, int image)
 {
        if (image < 1 || image > w->hdr.image_count)
@@ -1454,7 +1502,7 @@ wimlib_get_image_name(const WIMStruct *w, int image)
 }
 
 /* Returns the description of the specified image. */
-WIMLIBAPI const utf8char *
+WIMLIBAPI const tchar *
 wimlib_get_image_description(const WIMStruct *w, int image)
 {
        if (image < 1 || image > w->hdr.image_count)
@@ -1474,6 +1522,7 @@ wimlib_image_name_in_use(const WIMStruct *w, const utf8char *name)
        return false;
 }
 
+
 /* Extracts the raw XML data to a file stream. */
 WIMLIBAPI int
 wimlib_extract_xml_data(WIMStruct *w, FILE *fp)
index 6356613..070dada 100644 (file)
--- a/src/xml.h
+++ b/src/xml.h
@@ -16,8 +16,8 @@ struct wim_info {
 extern int
 xml_export_image(const struct wim_info *old_wim_info, int image,
                 struct wim_info **new_wim_info_p,
-                const utf8char *dest_image_name,
-                const utf8char *dest_image_description);
+                const tchar *dest_image_name,
+                const tchar *dest_image_description);
 
 extern size_t
 xml_get_max_image_name_len(const WIMStruct *w);
@@ -29,7 +29,7 @@ extern void
 xml_delete_image(struct wim_info **wim_info_p, int image);
 
 extern int
-xml_add_image(WIMStruct *w, const utf8char *name);
+xml_add_image(WIMStruct *w, const tchar *name);
 
 extern void
 free_wim_info(struct wim_info *info);