Improve char encoding support (IN PROGRESS)
authorEric Biggers <ebiggers3@gmail.com>
Wed, 20 Mar 2013 02:24:33 +0000 (21:24 -0500)
committerEric Biggers <ebiggers3@gmail.com>
Wed, 20 Mar 2013 02:24:33 +0000 (21:24 -0500)
25 files changed:
src/add_image.c
src/buffer_io.h
src/delete_image.c
src/dentry.c
src/dentry.h
src/encoding.c
src/extract_image.c
src/hardlink.c
src/lookup_table.c
src/lookup_table.h
src/mount_image.c
src/resource.c
src/security.c
src/sha1.c
src/sha1.h
src/symlink.c
src/util.c
src/util.h
src/wim.c
src/wimlib.h
src/wimlib_internal.h
src/win32.c
src/win32.h
src/xml.c
src/xml.h

index 67a354e..4dce5bb 100644 (file)
@@ -51,8 +51,9 @@
  * Adds the dentry tree and security data for a new image to the image metadata
  * array of the WIMStruct.
  */
-int add_new_dentry_tree(WIMStruct *w, struct wim_dentry *root_dentry,
-                       struct wim_security_data *sd)
+int
+add_new_dentry_tree(WIMStruct *w, struct wim_dentry *root_dentry,
+                   struct wim_security_data *sd)
 {
        struct wim_lookup_table_entry *metadata_lte;
        struct wim_image_metadata *imd;
@@ -133,14 +134,15 @@ err:
  *             the on-disk files during a call to wimlib_write() or
  *             wimlib_overwrite().
  */
-static int unix_build_dentry_tree(struct wim_dentry **root_ret,
-                                 const char *root_disk_path,
-                                 struct wim_lookup_table *lookup_table,
-                                 struct wim_security_data *sd,
-                                 const struct capture_config *config,
-                                 int add_image_flags,
-                                 wimlib_progress_func_t progress_func,
-                                 void *extra_arg)
+static int
+unix_build_dentry_tree(struct wim_dentry **root_ret,
+                      const mbchar *root_disk_path,
+                      struct wim_lookup_table *lookup_table,
+                      struct wim_security_data *sd,
+                      const struct capture_config *config,
+                      int add_image_flags,
+                      wimlib_progress_func_t progress_func,
+                      void *extra_arg)
 {
        struct wim_dentry *root = NULL;
        int ret = 0;
@@ -280,7 +282,7 @@ static int unix_build_dentry_tree(struct wim_dentry **root_ret,
                        DEBUG("Add lte reference %u for `%s'", lte->refcnt,
                              root_disk_path);
                } else {
-                       char *file_on_disk = STRDUP(root_disk_path);
+                       mbchar *file_on_disk = STRDUP(root_disk_path);
                        if (!file_on_disk) {
                                ERROR("Failed to allocate memory for file path");
                                ret = WIMLIB_ERR_NOMEM;
@@ -318,7 +320,7 @@ static int unix_build_dentry_tree(struct wim_dentry **root_ret,
 
                /* Buffer for names of files in directory. */
                size_t len = strlen(root_disk_path);
-               char name[len + 1 + FILENAME_MAX + 1];
+               mbchar name[len + 1 + FILENAME_MAX + 1];
                memcpy(name, root_disk_path, len);
                name[len] = '/';
 
@@ -362,7 +364,7 @@ static int unix_build_dentry_tree(struct wim_dentry **root_ret,
                 * drive letter).
                 */
 
-               char deref_name_buf[4096];
+               mbchar deref_name_buf[4096];
                ssize_t deref_name_len;
 
                deref_name_len = readlink(root_disk_path, deref_name_buf,
@@ -414,7 +416,7 @@ enum pattern_type {
 #define COMPAT_DEFAULT_CONFIG
 
 /* Default capture configuration file when none is specified. */
-static const char *default_config =
+static const mbchar *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. */
@@ -435,12 +437,14 @@ static const char *default_config =
 "";
 #endif
 
-static void destroy_pattern_list(struct pattern_list *list)
+static void
+destroy_pattern_list(struct pattern_list *list)
 {
        FREE(list->pats);
 }
 
-static void destroy_capture_config(struct capture_config *config)
+static void
+destroy_capture_config(struct capture_config *config)
 {
        destroy_pattern_list(&config->exclusion_list);
        destroy_pattern_list(&config->exclusion_exception);
@@ -451,8 +455,8 @@ static void destroy_capture_config(struct capture_config *config)
        memset(config, 0, sizeof(*config));
 }
 
-static int pattern_list_add_pattern(struct pattern_list *list,
-                                   const char *pattern)
+static int
+pattern_list_add_pattern(struct pattern_list *list, const mbchar *pattern)
 {
        const char **pats;
        if (list->num_pats >= list->num_allocated_pats) {
@@ -469,13 +473,14 @@ static int pattern_list_add_pattern(struct pattern_list *list,
 
 /* Parses the contents of the image capture configuration file and fills in a
  * `struct capture_config'. */
-static int init_capture_config(struct capture_config *config,
-                              const char *_config_str, size_t config_len)
+static int
+init_capture_config(struct capture_config *config,
+                   const mbchar *_config_str, size_t config_len)
 {
-       char *config_str;
-       char *p;
-       char *eol;
-       char *next_p;
+       mbchar *config_str;
+       mbchar *p;
+       mbchar *eol;
+       mbchar *next_p;
        size_t bytes_remaining;
        enum pattern_type type = NONE;
        int ret;
@@ -514,7 +519,7 @@ static int init_capture_config(struct capture_config *config,
                *eol = '\0';
 
                /* Translate backslash to forward slash */
-               for (char *pp = p; pp != eol; pp++)
+               for (mbchar *pp = p; pp != eol; pp++)
                        if (*pp == '\\')
                                *pp = '/';
 
@@ -568,9 +573,9 @@ out_destroy:
 }
 
 static int capture_config_set_prefix(struct capture_config *config,
-                                    const char *_prefix)
+                                    const mbchar *_prefix)
 {
-       char *prefix = STRDUP(_prefix);
+       mbchar *prefix = STRDUP(_prefix);
 
        if (!prefix)
                return WIMLIB_ERR_NOMEM;
@@ -580,7 +585,8 @@ static int capture_config_set_prefix(struct capture_config *config,
        return 0;
 }
 
-static bool match_pattern(const char *path, const char *path_basename,
+static bool match_pattern(const mbchar *path,
+                         const mbchar *path_basename,
                          const struct pattern_list *list)
 {
        for (size_t i = 0; i < list->num_pats; i++) {
@@ -623,10 +629,11 @@ static bool match_pattern(const char *path, const char *path_basename,
  * file /mnt/windows7/hiberfil.sys if we are capturing the /mnt/windows7
  * directory.
  */
-bool exclude_path(const char *path, const struct capture_config *config,
-                 bool exclude_prefix)
+bool
+exclude_path(const mbchar *path, const struct capture_config *config,
+            bool exclude_prefix)
 {
-       const char *basename = path_basename(path);
+       const mbchar *basename = path_basename(path);
        if (exclude_prefix) {
                wimlib_assert(strlen(path) >= config->prefix_len);
                if (memcmp(config->prefix, path, config->prefix_len) == 0
@@ -640,7 +647,8 @@ bool exclude_path(const char *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 char *
+canonicalize_target_path(char *target_path)
 {
        char *p;
        if (target_path == NULL)
@@ -661,7 +669,8 @@ static const char *canonicalize_target_path(char *target_path)
 }
 
 #ifdef __WIN32__
-static void zap_backslashes(char *s)
+static void
+zap_backslashes(char *s)
 {
        while (*s) {
                if (*s == '\\')
@@ -672,8 +681,8 @@ static void zap_backslashes(char *s)
 #endif
 
 /* Strip leading and trailing slashes from the target paths */
-static void canonicalize_targets(struct wimlib_capture_source *sources,
-                                size_t num_sources)
+static void
+canonicalize_targets(struct wimlib_capture_source *sources, size_t num_sources)
 {
        while (num_sources--) {
                DEBUG("Canonicalizing { source: \"%s\", target=\"%s\"}",
@@ -694,7 +703,8 @@ static void canonicalize_targets(struct wimlib_capture_source *sources,
        }
 }
 
-static int capture_source_cmp(const void *p1, const void *p2)
+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);
@@ -705,14 +715,15 @@ static int capture_source_cmp(const void *p1, const void *p2)
  *
  * One purpose of this is to make sure that target paths that are inside other
  * target paths are added after the containing target paths. */
-static void sort_sources(struct wimlib_capture_source *sources,
-                        size_t num_sources)
+static void
+sort_sources(struct wimlib_capture_source *sources, size_t num_sources)
 {
        qsort(sources, num_sources, sizeof(sources[0]), capture_source_cmp);
 }
 
-static int check_sorted_sources(struct wimlib_capture_source *sources,
-                               size_t num_sources, int add_image_flags)
+static int
+check_sorted_sources(struct wimlib_capture_source *sources, size_t num_sources,
+                    int add_image_flags)
 {
        if (add_image_flags & WIMLIB_ADD_IMAGE_FLAG_NTFS) {
                if (num_sources != 1) {
@@ -767,7 +778,7 @@ static int check_sorted_sources(struct wimlib_capture_source *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 struct wim_dentry *
-new_filler_directory(const char *name)
+new_filler_directory(const mbchar *name)
 {
        struct wim_dentry *dentry;
        DEBUG("Creating filler directory \"%s\"", name);
@@ -784,16 +795,17 @@ new_filler_directory(const char *name)
 /* Transfers the children of @branch to @target.  It is an error if @target is
  * not a directory or if both @branch and @target contain a child dentry with
  * the same name. */
-static int do_overlay(struct wim_dentry *target, struct wim_dentry *branch)
+static int
+do_overlay(struct wim_dentry *target, struct wim_dentry *branch)
 {
        struct rb_root *rb_root;
 
-       DEBUG("Doing overlay %s => %s",
-             branch->file_name_utf8, target->file_name_utf8);
+       DEBUG("Doing overlay \"%W\" => \"%W\"",
+             branch->file_name, target->file_name);
 
        if (!dentry_is_directory(target)) {
-               ERROR("Cannot overlay directory `%s' over non-directory",
-                     branch->file_name_utf8);
+               ERROR("Cannot overlay directory \"%W\" over non-directory",
+                     branch->file_name);
                return WIMLIB_ERR_INVALID_OVERLAY;
        }
 
@@ -806,9 +818,9 @@ static int 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 `%s' already exists "
-                             "as a child of `%s'",
-                             child->file_name_utf8, target->file_name_utf8);
+                       ERROR("Overlay error: file \"%W\" already exists "
+                             "as a child of \"%W\"",
+                             child->file_name, target->file_name);
                        return WIMLIB_ERR_INVALID_OVERLAY;
                }
        }
@@ -828,15 +840,15 @@ static int do_overlay(struct wim_dentry *target, struct wim_dentry *branch)
  *     Path in the WIM image to add the branch, with leading and trailing
  *     slashes stripped.
  */
-static int attach_branch(struct wim_dentry **root_p,
-                        struct wim_dentry *branch,
-                        char *target_path)
+static int
+attach_branch(struct wim_dentry **root_p, struct wim_dentry *branch,
+             mbchar *target_path)
 {
        char *slash;
        struct wim_dentry *dentry, *parent, *target;
 
-       DEBUG("Attaching branch \"%s\" => \"%s\"",
-             branch->file_name_utf8, target_path);
+       DEBUG("Attaching branch \"%W\" => \"%s\"",
+             branch->file_name, target_path);
 
        if (*target_path == '\0') {
                /* Target: root directory */
@@ -882,7 +894,7 @@ static int attach_branch(struct wim_dentry **root_p,
 
        /* If the target path already existed, overlay the branch onto it.
         * Otherwise, set the branch as the target path. */
-       target = get_dentry_child_with_name(parent, branch->file_name_utf8);
+       target = get_dentry_child_with_utf16le_name(parent, branch->file_name);
        if (target) {
                return do_overlay(target, branch);
        } else {
@@ -891,20 +903,24 @@ static int attach_branch(struct wim_dentry **root_p,
        }
 }
 
-WIMLIBAPI int wimlib_add_image_multisource(WIMStruct *w,
-                                          struct wimlib_capture_source *sources,
-                                          size_t num_sources,
-                                          const char *name,
-                                          const char *config_str,
-                                          size_t config_len,
-                                          int add_image_flags,
-                                          wimlib_progress_func_t progress_func)
+WIMLIBAPI int
+wimlib_add_image_multisource(WIMStruct *w,
+                            struct wimlib_capture_source *sources,
+                            size_t num_sources,
+                            const utf8char *name,
+                            const mbchar *config_str,
+                            size_t config_len,
+                            int add_image_flags,
+                            wimlib_progress_func_t progress_func)
 {
-       int (*capture_tree)(struct wim_dentry **, const char *,
+       int (*capture_tree)(struct wim_dentry **,
+                           const mbchar *,
                            struct wim_lookup_table *,
                            struct wim_security_data *,
                            const struct capture_config *,
-                           int, wimlib_progress_func_t, void *);
+                           int,
+                           wimlib_progress_func_t,
+                           void *);
        void *extra_arg;
        struct wim_dentry *root_dentry;
        struct wim_dentry *branch;
@@ -1063,24 +1079,24 @@ WIMLIBAPI int wimlib_add_image_multisource(WIMStruct *w,
 
        DEBUG("Calculating full paths of dentries.");
        ret = for_dentry_in_tree(root_dentry, calculate_dentry_full_path, NULL);
-       if (ret != 0)
+       if (ret)
                goto out_free_dentry_tree;
 
        ret = add_new_dentry_tree(w, root_dentry, sd);
-       if (ret != 0)
+       if (ret)
                goto out_free_dentry_tree;
 
        imd = &w->image_metadata[w->hdr.image_count - 1];
 
        ret = dentry_tree_fix_inodes(root_dentry, &imd->inode_list);
-       if (ret != 0)
+       if (ret)
                goto out_destroy_imd;
 
        DEBUG("Assigning hard link group IDs");
        assign_inode_numbers(&imd->inode_list);
 
        ret = xml_add_image(w, name);
-       if (ret != 0)
+       if (ret)
                goto out_destroy_imd;
 
        if (add_image_flags & WIMLIB_ADD_IMAGE_FLAG_BOOT)
@@ -1107,10 +1123,14 @@ out:
        return ret;
 }
 
-WIMLIBAPI int wimlib_add_image(WIMStruct *w, const char *source,
-                              const char *name, const char *config_str,
-                              size_t config_len, int add_image_flags,
-                              wimlib_progress_func_t progress_func)
+WIMLIBAPI int
+wimlib_add_image(WIMStruct *w,
+                const mbchar *source,
+                const utf8char *name,
+                const mbchar *config_str,
+                size_t config_len,
+                int add_image_flags,
+                wimlib_progress_func_t progress_func)
 {
        if (!source || !*source)
                return WIMLIB_ERR_INVALID_PARAM;
index 9dd88a0..685ffa8 100644 (file)
@@ -113,7 +113,7 @@ static inline u8 *put_zeroes(u8 *p, size_t num_bytes)
        return (u8*)memset(p, 0, num_bytes) + num_bytes;
 }
 
-static inline u8 *put_bytes(u8 *p, size_t num_bytes, const u8 *input)
+static inline u8 *put_bytes(u8 *p, size_t num_bytes, const void *input)
 {
        return (u8*)memcpy(p, input, num_bytes) + num_bytes;
 }
index 3a33751..389d230 100644 (file)
@@ -28,7 +28,8 @@
 /*
  * Deletes an image from the WIM.
  */
-WIMLIBAPI int wimlib_delete_image(WIMStruct *w, int image)
+WIMLIBAPI int
+wimlib_delete_image(WIMStruct *w, int image)
 {
        int i;
        int ret;
index 15a44ce..ea2cdb1 100644 (file)
 /* 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. */
-static u64 __dentry_correct_length_unaligned(u16 file_name_len,
-                                            u16 short_name_len)
+static u64
+__dentry_correct_length_unaligned(u16 file_name_nbytes, u16 short_name_nbytes)
 {
        u64 length = WIM_DENTRY_DISK_SIZE;
-       if (file_name_len)
-               length += file_name_len + 2;
-       if (short_name_len)
-               length += short_name_len + 2;
+       if (file_name_nbytes)
+               length += file_name_nbytes + 2;
+       if (short_name_nbytes)
+               length += short_name_nbytes + 2;
        return length;
 }
 
@@ -51,102 +51,91 @@ static u64 __dentry_correct_length_unaligned(u16 file_name_len,
  * the file name length and short name length.  Note that dentry->length is
  * ignored; also, this excludes any alternate data stream entries that may
  * follow the dentry. */
-static u64 dentry_correct_length_unaligned(const struct wim_dentry *dentry)
+static u64
+dentry_correct_length_unaligned(const struct wim_dentry *dentry)
 {
-       return __dentry_correct_length_unaligned(dentry->file_name_len,
-                                                dentry->short_name_len);
+       return __dentry_correct_length_unaligned(dentry->file_name_nbytes,
+                                                dentry->short_name_nbytes);
 }
 
 /* Return the "correct" value to write in the length field of a WIM dentry,
  * based on the file name length and short name length. */
-static u64 dentry_correct_length(const struct wim_dentry *dentry)
+static u64
+dentry_correct_length(const struct wim_dentry *dentry)
 {
        return (dentry_correct_length_unaligned(dentry) + 7) & ~7;
 }
 
-/* Return %true iff the alternate data stream entry @entry has the UTF-8 stream
- * name @name that has length @name_len bytes. */
-static inline bool ads_entry_has_name(const struct wim_ads_entry *entry,
-                                     const char *name, size_t name_len)
+/* Return %true iff the alternate data stream entry @entry has the UTF-16LE
+ * stream name @name that has length @name_nbytes bytes. */
+static inline bool
+ads_entry_has_name(const struct wim_ads_entry *entry,
+                  const utf16lechar *name, size_t name_nbytes)
 {
-       if (entry->stream_name_utf8_len != name_len)
-               return false;
-       return memcmp(entry->stream_name_utf8, name, name_len) == 0;
+       return entry->stream_name_nbytes == name_nbytes &&
+              memcmp(entry->stream_name, name, name_nbytes) == 0;
 }
 
-/* Duplicates a UTF-8 string into UTF-8 and UTF-16 strings and returns the
- * strings and their lengths in the pointer arguments.  (Frees existing strings
- * first.) */
-static int get_names(char **name_utf16_ret, char **name_utf8_ret,
-                    u16 *name_utf16_len_ret, u16 *name_utf8_len_ret,
-                    const char *name)
+/* 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. */
+static int
+get_utf16le_name(const mbchar *name, utf16lechar **name_utf16le_ret,
+                u16 *name_utf16le_nbytes_ret)
 {
-       size_t utf8_len;
-       size_t utf16_len;
-       char *name_utf16, *name_utf8;
+       utf16lechar *name_utf16le;
+       size_t name_utf16le_nbytes;
        int ret;
 
-       utf8_len = strlen(name);
-       ret = utf8_to_utf16(name, utf8_len, &name_utf16, &utf16_len);
-       if (ret != 0)
-               return ret;
-
-       name_utf8 = MALLOC(utf8_len + 1);
-       if (!name_utf8) {
-               FREE(name_utf16);
-               return WIMLIB_ERR_NOMEM;
+       ret = mbs_to_utf16le(name, strlen(name), &name_utf16le,
+                            &name_utf16le_nbytes);
+       if (name_utf16le_nbytes > 0xffff) {
+               FREE(name_utf16le);
+               ERROR("Multibyte string \"%s\" is too long!", name);
+               ret = WIMLIB_ERR_INVALID_UTF8_STRING;
        }
-       memcpy(name_utf8, name, utf8_len + 1);
-       FREE(*name_utf8_ret);
-       FREE(*name_utf16_ret);
-       *name_utf8_ret      = name_utf8;
-       *name_utf16_ret     = name_utf16;
-       *name_utf8_len_ret  = utf8_len;
-       *name_utf16_len_ret = utf16_len;
-       return 0;
+       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. */
-int set_dentry_name(struct wim_dentry *dentry, const char *new_name)
+/* Sets the name of a WIM dentry from a multibyte string. */
+int
+set_dentry_name(struct wim_dentry *dentry, const mbchar *new_name)
 {
        int ret;
-
-       ret = get_names(&dentry->file_name, &dentry->file_name_utf8,
-                       &dentry->file_name_len, &dentry->file_name_utf8_len,
-                       new_name);
+       ret = get_utf16le_name(new_name, &dentry->file_name,
+                              &dentry->file_name_nbytes);
        if (ret == 0) {
-               if (dentry->short_name_len) {
+               /* Clear the short name and recalculate the dentry length */
+               if (dentry->short_name_nbytes) {
                        FREE(dentry->short_name);
-                       dentry->short_name_len = 0;
+                       dentry->short_name = NULL;
+                       dentry->short_name_nbytes = 0;
                }
                dentry->length = dentry_correct_length(dentry);
        }
        return ret;
 }
 
-/*
- * Changes the name of an alternate data stream */
-static int change_ads_name(struct wim_ads_entry *entry, const char *new_name)
-{
-       return get_names(&entry->stream_name, &entry->stream_name_utf8,
-                        &entry->stream_name_len,
-                        &entry->stream_name_utf8_len,
-                        new_name);
-}
-
 /* Returns the total length of a WIM alternate data stream entry on-disk,
  * including the stream name, the null terminator, AND the padding after the
  * entry to align the next ADS entry or dentry on an 8-byte boundary. */
-static u64 ads_entry_total_length(const struct wim_ads_entry *entry)
+static u64
+ads_entry_total_length(const struct wim_ads_entry *entry)
 {
        u64 len = WIM_ADS_ENTRY_DISK_SIZE;
-       if (entry->stream_name_len)
-               len += entry->stream_name_len + 2;
+       if (entry->stream_name_nbytes)
+               len += entry->stream_name_nbytes + 2;
        return (len + 7) & ~7;
 }
 
 
-static u64 __dentry_total_length(const struct wim_dentry *dentry, u64 length)
+static u64
+__dentry_total_length(const struct wim_dentry *dentry, u64 length)
 {
        const struct wim_inode *inode = dentry->d_inode;
        for (u16 i = 0; i < inode->i_num_ads; i++)
@@ -156,7 +145,8 @@ static u64 __dentry_total_length(const struct wim_dentry *dentry, u64 length)
 
 /* Calculate the aligned *total* length of an on-disk WIM dentry.  This includes
  * all alternate data streams. */
-u64 dentry_correct_total_length(const struct wim_dentry *dentry)
+u64
+dentry_correct_total_length(const struct wim_dentry *dentry)
 {
        return __dentry_total_length(dentry,
                                     dentry_correct_length_unaligned(dentry));
@@ -164,14 +154,16 @@ u64 dentry_correct_total_length(const struct wim_dentry *dentry)
 
 /* Like dentry_correct_total_length(), but use the existing dentry->length field
  * instead of calculating its "correct" value. */
-static u64 dentry_total_length(const struct wim_dentry *dentry)
+static u64
+dentry_total_length(const struct wim_dentry *dentry)
 {
        return __dentry_total_length(dentry, dentry->length);
 }
 
-int for_dentry_in_rbtree(struct rb_node *root,
-                        int (*visitor)(struct wim_dentry *, void *),
-                        void *arg)
+int
+for_dentry_in_rbtree(struct rb_node *root,
+                    int (*visitor)(struct wim_dentry *, void *),
+                    void *arg)
 {
        int ret;
        struct rb_node *node = root;
@@ -197,9 +189,10 @@ int for_dentry_in_rbtree(struct rb_node *root,
        }
 }
 
-static int for_dentry_tree_in_rbtree_depth(struct rb_node *node,
-                                          int (*visitor)(struct wim_dentry*, void*),
-                                          void *arg)
+static int
+for_dentry_tree_in_rbtree_depth(struct rb_node *node,
+                               int (*visitor)(struct wim_dentry*, void*),
+                               void *arg)
 {
        int ret;
        if (node) {
@@ -218,9 +211,10 @@ static int for_dentry_tree_in_rbtree_depth(struct rb_node *node,
        return 0;
 }
 
-static int for_dentry_tree_in_rbtree(struct rb_node *node,
-                                    int (*visitor)(struct wim_dentry*, void*),
-                                    void *arg)
+static int
+for_dentry_tree_in_rbtree(struct rb_node *node,
+                         int (*visitor)(struct wim_dentry*, void*),
+                         void *arg)
 {
        int ret;
        if (node) {
@@ -237,97 +231,103 @@ static int for_dentry_tree_in_rbtree(struct rb_node *node,
        return 0;
 }
 
-/*
- * Calls a function on all directory entries in a WIM dentry tree.  Logically,
+/* Calls a function on all directory entries in a WIM dentry tree.  Logically,
  * this is a pre-order traversal (the function is called on a parent dentry
  * before its children), but sibling dentries will be visited in order as well.
- *
- * In reality, the data structures are more complicated than the above might
- * suggest because there is a separate red-black tree for each dentry that
- * contains its direct children.
- */
-int for_dentry_in_tree(struct wim_dentry *root,
-                      int (*visitor)(struct wim_dentry*, void*), void *arg)
+ * */
+int
+for_dentry_in_tree(struct wim_dentry *root,
+                  int (*visitor)(struct wim_dentry*, void*), void *arg)
 {
        int ret = visitor(root, arg);
-       if (ret != 0)
-               return ret;
-       return for_dentry_tree_in_rbtree(root->d_inode->i_children.rb_node, visitor, arg);
+       if (ret == 0) {
+               ret = for_dentry_tree_in_rbtree(root->d_inode->i_children.rb_node,
+                                               visitor,
+                                               arg);
+       }
+       return ret;
 }
 
-/*
- * Like for_dentry_in_tree(), but the visitor function is always called on a
- * dentry's children before on itself.
- */
-int for_dentry_in_tree_depth(struct wim_dentry *root,
-                            int (*visitor)(struct wim_dentry*, void*), void *arg)
+/* Like for_dentry_in_tree(), but the visitor function is always called on a
+ * dentry's children before on itself. */
+int
+for_dentry_in_tree_depth(struct wim_dentry *root,
+                        int (*visitor)(struct wim_dentry*, void*), void *arg)
 {
        int ret;
        ret = for_dentry_tree_in_rbtree_depth(root->d_inode->i_children.rb_node,
                                              visitor, arg);
-       if (ret != 0)
-               return ret;
-       return visitor(root, arg);
+       if (ret == 0)
+               ret = visitor(root, arg);
+       return ret;
 }
 
-/*
- * Calculate the full path of @dentry, based on its parent's full path and on
- * its UTF-8 file name.
- */
-int calculate_dentry_full_path(struct wim_dentry *dentry, void *ignore)
+/* Calculate the full path of @dentry.  The full path of its parent must have
+ * already been calculated. */
+int
+calculate_dentry_full_path(struct wim_dentry *dentry, void *ignore)
 {
        char *full_path;
-       u32 full_path_len;
+       u32 full_path_nbytes;
+
+       wimlib_assert(dentry_is_root(dentry) ||
+                     dentry->parent->full_path != NULL);
+
        if (dentry_is_root(dentry)) {
                full_path = MALLOC(2);
                if (!full_path)
-                       goto oom;
+                       return WIMLIB_ERR_NOMEM;
                full_path[0] = '/';
                full_path[1] = '\0';
-               full_path_len = 1;
+               full_path_nbytes = 1;
        } else {
                char *parent_full_path;
-               u32 parent_full_path_len;
-               const struct wim_dentry *parent = dentry->parent;
-
+               u32 parent_full_path_nbytes;
+               const struct wim_dentry *parent;
+               char *name_mbs;
+               size_t name_mbs_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_len = 0;
+                       parent_full_path_nbytes = 0;
                } else {
-                       parent_full_path = parent->full_path_utf8;
-                       parent_full_path_len = parent->full_path_utf8_len;
+                       parent_full_path = parent->full_path;
+                       parent_full_path_nbytes = parent->full_path_nbytes;
                }
-
-               full_path_len = parent_full_path_len + 1 +
-                               dentry->file_name_utf8_len;
-               full_path = MALLOC(full_path_len + 1);
+               full_path_nbytes = parent_full_path_nbytes + 1 +
+                                  name_mbs_nbytes;
+               full_path = MALLOC(full_path_nbytes + 1);
                if (!full_path)
-                       goto oom;
-
-               memcpy(full_path, parent_full_path, parent_full_path_len);
-               full_path[parent_full_path_len] = '/';
-               memcpy(full_path + parent_full_path_len + 1,
-                      dentry->file_name_utf8,
-                      dentry->file_name_utf8_len);
-               full_path[full_path_len] = '\0';
+                       return WIMLIB_ERR_NOMEM;
+               memcpy(full_path, parent_full_path, parent_full_path_nbytes);
+               full_path[parent_full_path_nbytes] = '/';
+
+               utf16le_to_mbs_buf(dentry->file_name,
+                                  dentry->file_name_nbytes,
+                                  &full_path[parent_full_path_nbytes + 1]);
        }
-       FREE(dentry->full_path_utf8);
-       dentry->full_path_utf8 = full_path;
-       dentry->full_path_utf8_len = full_path_len;
+       FREE(dentry->full_path);
+       dentry->full_path = full_path;
+       dentry->full_path_nbytes= full_path_nbytes;
        return 0;
-oom:
-       ERROR("Out of memory while calculating dentry full path");
-       return WIMLIB_ERR_NOMEM;
 }
 
-static int increment_subdir_offset(struct wim_dentry *dentry, void *subdir_offset_p)
+static int
+increment_subdir_offset(struct wim_dentry *dentry, void *subdir_offset_p)
 {
        *(u64*)subdir_offset_p += dentry_correct_total_length(dentry);
        return 0;
 }
 
-static int call_calculate_subdir_offsets(struct wim_dentry *dentry,
-                                        void *subdir_offset_p)
+static int
+call_calculate_subdir_offsets(struct wim_dentry *dentry, void *subdir_offset_p)
 {
        calculate_subdir_offsets(dentry, subdir_offset_p);
        return 0;
@@ -340,7 +340,8 @@ static int call_calculate_subdir_offsets(struct wim_dentry *dentry,
  * @subdir_offset_p:  The current subdirectory offset; i.e., the subdirectory
  *                   offset for @dentry.
  */
-void calculate_subdir_offsets(struct wim_dentry *dentry, u64 *subdir_offset_p)
+void
+calculate_subdir_offsets(struct wim_dentry *dentry, u64 *subdir_offset_p)
 {
        struct rb_node *node;
 
@@ -368,96 +369,110 @@ void calculate_subdir_offsets(struct wim_dentry *dentry, u64 *subdir_offset_p)
        }
 }
 
-static int compare_names(const char *name_1, u16 len_1,
-                        const char *name_2, u16 len_2)
+static int
+dentry_compare_names(const struct wim_dentry *d1, const struct wim_dentry *d2)
 {
-       int result = strncmp(name_1, name_2, min(len_1, len_2));
-       if (result) {
+       int result = memcmp(d1->file_name, d2->file_name,
+                           min(d1->file_name_nbytes, d2->file_name_nbytes));
+       if (result)
                return result;
-       } else {
-               return (int)len_1 - (int)len_2;
-       }
-}
-
-static int dentry_compare_names(const struct wim_dentry *d1, const struct wim_dentry *d2)
-{
-       return compare_names(d1->file_name_utf8, d1->file_name_utf8_len,
-                            d2->file_name_utf8, d2->file_name_utf8_len);
+       else
+               return d1->file_name_nbytes - d2->file_name_nbytes;
 }
 
 
-static struct wim_dentry *
-get_rbtree_child_with_name(const struct rb_node *node,
-                          const char *name, size_t name_len)
+struct wim_dentry *
+get_dentry_child_with_utf16le_name(const struct wim_dentry *dentry,
+                                  const utf16lechar *name)
 {
-       do {
+       struct rb_node *node = dentry->d_inode->i_children.rb_node;
+       while (node) {
                struct wim_dentry *child = rbnode_dentry(node);
-               int result = compare_names(name, name_len,
-                                          child->file_name_utf8,
-                                          child->file_name_utf8_len);
+               int result = dentry_compare_names(dentry, child);
                if (result < 0)
                        node = node->rb_left;
                else if (result > 0)
                        node = node->rb_right;
                else
                        return child;
-       } while (node);
+       }
        return NULL;
 }
 
-/* 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 char *name)
+/* 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)
 {
-       struct rb_node *node = dentry->d_inode->i_children.rb_node;
-       if (node)
-               return get_rbtree_child_with_name(node, name, strlen(name));
-       else
-               return NULL;
+       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);
+       if (ret) {
+               child = NULL;
+       } else {
+               child = get_dentry_child_with_utf16le_name(dentry,
+                                                          utf16le_name);
+               FREE(utf16le_name);
+       }
+       return child;
 }
 
-/* Retrieves the dentry that has the UTF-8 @path relative to the dentry
- * @cur_dentry.  Returns NULL if no dentry having the path is found. */
-static struct wim_dentry *get_dentry_relative_path(struct wim_dentry *cur_dentry,
-                                                  const char *path)
+/* 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)
 {
-       if (*path == '\0')
-               return cur_dentry;
-
-       struct rb_node *node = cur_dentry->d_inode->i_children.rb_node;
-       if (node) {
-               struct wim_dentry *child;
-               size_t base_len;
-               const char *new_path;
+       utf16lechar *path_utf16le;
+       size_t path_utf16le_nbytes;
+       int ret;
+       struct wim_dentry *cur_dentry, *parent_dentry;
+       utf16lechar *p, *pp;
+       utf16lechar save;
+
+       ret = mbs_to_utf16le(path, strlen(path), &path_utf16le,
+                            &path_utf16le_nbytes);
+       if (ret) {
+               errno = ENOMEM;
+               return NULL;
+       }
 
-               new_path = path_next_part(path, &base_len);
+       parent_dentry = wim_root_dentry(w);
+       p = path_utf16le;
 
-               child = get_rbtree_child_with_name(node, path, base_len);
-               if (child)
-                       return get_dentry_relative_path(child, new_path);
+       while (1) {
+               while (*p == '/')
+                       p++;
+               cur_dentry = parent_dentry;
+               if (*p == '\0')
+                       break;
+               pp = p;
+               while (*pp != '/' && *pp != '\0')
+                       pp++;
+
+               save = *pp;
+               *pp = '\0';
+               cur_dentry = get_dentry_child_with_utf16le_name(parent_dentry, p);
+               if (cur_dentry == NULL)
+                       break;
+               *pp = save;
+               p = pp;
        }
-       /* errno is set to ENOTDIR if the lookup failed due to reaching a
-        * non-directory, or ENOENT if the lookup failed otherwise.  This maybe
-        * should be factored out somehow. */
-       if (dentry_is_directory(cur_dentry))
-               errno = ENOENT;
-       else
-               errno = ENOTDIR;
-       return NULL;
-}
-
-/* Returns the dentry corresponding to the UTF-8 @path, or NULL if there is no
- * such dentry. */
-struct wim_dentry *get_dentry(WIMStruct *w, const char *path)
-{
-       struct wim_dentry *root = wim_root_dentry(w);
-       while (*path == '/')
-               path++;
-       return get_dentry_relative_path(root, path);
+       FREE(path_utf16le);
+       if (cur_dentry == NULL) {
+               if (dentry_is_directory(parent_dentry))
+                       errno = ENOENT;
+               else
+                       errno = ENOTDIR;
+       }
+       return cur_dentry;
 }
 
-struct wim_inode *wim_pathname_to_inode(WIMStruct *w, const char *path)
+struct wim_inode *
+wim_pathname_to_inode(WIMStruct *w, const mbchar *path)
 {
        struct wim_dentry *dentry;
        dentry = get_dentry(w, path);
@@ -469,23 +484,21 @@ struct wim_inode *wim_pathname_to_inode(WIMStruct *w, const char *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 char *path)
+struct wim_dentry *get_parent_dentry(WIMStruct *w, const mbchar *path)
 {
        size_t path_len = strlen(path);
-       char buf[path_len + 1];
+       mbchar buf[path_len + 1];
 
        memcpy(buf, path, path_len + 1);
-
        to_parent_name(buf, path_len);
-
        return get_dentry(w, buf);
 }
 
 /* Prints the full path of a dentry. */
 int print_dentry_full_path(struct wim_dentry *dentry, void *ignore)
 {
-       if (dentry->full_path_utf8)
-               puts(dentry->full_path_utf8);
+       if (dentry->full_path)
+               puts(dentry->full_path);
        return 0;
 }
 
@@ -546,13 +559,10 @@ int print_dentry(struct wim_dentry *dentry, void *lookup_table)
        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);
-       printf("Filename (UTF-8)  = \"%s\"\n", dentry->file_name_utf8);
-       /*printf("Filename (UTF-8) Length = %hu\n", dentry->file_name_utf8_len);*/
-       printf("Short Name (UTF-16LE) = \"");
-       print_string(dentry->short_name, dentry->short_name_len);
-       puts("\"");
-       /*printf("Short Name Length = %hu\n", dentry->short_name_len);*/
-       printf("Full Path (UTF-8) = \"%s\"\n", dentry->full_path_utf8);
+       wimlib_printf("Filename = \"%W\"\n", dentry->file_name);
+       wimlib_printf("Short Name \"%W\"\n", dentry->short_name);
+       printf("Full Path = \"%s\"\n", dentry->full_path);
+
        lte = inode_stream_lte(dentry->d_inode, 0, lookup_table);
        if (lte) {
                print_lookup_table_entry(lte, stdout);
@@ -567,9 +577,9 @@ int print_dentry(struct wim_dentry *dentry, void *lookup_table)
        }
        for (u16 i = 0; i < inode->i_num_ads; i++) {
                printf("[Alternate Stream Entry %u]\n", i);
-               printf("Name = \"%s\"\n", inode->i_ads_entries[i].stream_name_utf8);
-               printf("Name Length (UTF-16) = %u\n",
-                       inode->i_ads_entries[i].stream_name_len);
+               wimlib_printf("Name = \"%W\"\n", inode->i_ads_entries[i].stream_name);
+               printf("Name Length (UTF16) = %u\n",
+                      inode->i_ads_entries[i].stream_name_nbytes);
                hash = inode_stream_hash(inode, i + 1);
                if (hash) {
                        printf("Hash              = 0x");
@@ -627,7 +637,7 @@ static struct wim_inode *new_inode()
  *
  * Returns a pointer to the new dentry, or NULL if out of memory.
  */
-struct wim_dentry *new_dentry(const char *name)
+struct wim_dentry *new_dentry(const mbchar *name)
 {
        struct wim_dentry *dentry;
 
@@ -650,7 +660,7 @@ err:
 
 
 static struct wim_dentry *
-__new_dentry_with_inode(const char *name, bool timeless)
+__new_dentry_with_inode(const mbchar *name, bool timeless)
 {
        struct wim_dentry *dentry;
        dentry = new_dentry(name);
@@ -669,33 +679,37 @@ __new_dentry_with_inode(const char *name, bool timeless)
        return dentry;
 }
 
-struct wim_dentry *new_dentry_with_timeless_inode(const char *name)
+struct wim_dentry *
+new_dentry_with_timeless_inode(const mbchar *name)
 {
        return __new_dentry_with_inode(name, true);
 }
 
-struct wim_dentry *new_dentry_with_inode(const char *name)
+struct wim_dentry *
+new_dentry_with_inode(const mbchar *name)
 {
        return __new_dentry_with_inode(name, false);
 }
 
 
-static int init_ads_entry(struct wim_ads_entry *ads_entry, const char *name)
+static int
+init_ads_entry(struct wim_ads_entry *ads_entry, const mbchar *name)
 {
        int ret = 0;
        memset(ads_entry, 0, sizeof(*ads_entry));
-       if (name && *name)
-               ret = change_ads_name(ads_entry, name);
+       if (name && *name) {
+               ret = get_utf16le_name(name, &ads_entry->stream_name,
+                                      &ads_entry->stream_name_nbytes);
+       }
        return ret;
 }
 
-static void destroy_ads_entry(struct wim_ads_entry *ads_entry)
+static void
+destroy_ads_entry(struct wim_ads_entry *ads_entry)
 {
        FREE(ads_entry->stream_name);
-       FREE(ads_entry->stream_name_utf8);
 }
 
-
 /* Frees an inode. */
 void free_inode(struct wim_inode *inode)
 {
@@ -740,9 +754,8 @@ static void put_inode(struct wim_inode *inode)
 void free_dentry(struct wim_dentry *dentry)
 {
        FREE(dentry->file_name);
-       FREE(dentry->file_name_utf8);
        FREE(dentry->short_name);
-       FREE(dentry->full_path_utf8);
+       FREE(dentry->full_path);
        if (dentry->d_inode)
                put_inode(dentry->d_inode);
        FREE(dentry);
@@ -804,8 +817,9 @@ int increment_dentry_refcnt(struct wim_dentry *dentry, void *ignore)
  * @parent: The dentry that will be the parent of @dentry.
  * @dentry: The dentry to link.
  */
-bool dentry_add_child(struct wim_dentry * restrict parent,
-                     struct wim_dentry * restrict child)
+bool
+dentry_add_child(struct wim_dentry * restrict parent,
+                struct wim_dentry * restrict child)
 {
        wimlib_assert(dentry_is_directory(parent));
 
@@ -833,7 +847,8 @@ bool dentry_add_child(struct wim_dentry * restrict parent,
 }
 
 /* Unlink a WIM dentry from the directory entry tree. */
-void unlink_dentry(struct wim_dentry *dentry)
+void
+unlink_dentry(struct wim_dentry *dentry)
 {
        struct wim_dentry *parent = dentry->parent;
        if (parent == dentry)
@@ -845,31 +860,49 @@ void unlink_dentry(struct wim_dentry *dentry)
  * Returns the alternate data stream entry belonging to @inode that has the
  * stream name @stream_name.
  */
-struct wim_ads_entry *inode_get_ads_entry(struct wim_inode *inode,
-                                     const char *stream_name,
-                                     u16 *idx_ret)
+struct wim_ads_entry *
+inode_get_ads_entry(struct wim_inode *inode, const mbchar *stream_name,
+                   u16 *idx_ret)
 {
-       if (inode->i_num_ads != 0) {
-               u16 i = 0;
-               size_t stream_name_len = strlen(stream_name);
+       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 (ret)
+                       return NULL;
+
+               i = 0;
+               result = NULL;
                do {
                        if (ads_entry_has_name(&inode->i_ads_entries[i],
-                                              stream_name, stream_name_len))
+                                              stream_name_utf16le,
+                                              stream_name_utf16le_nbytes))
                        {
                                if (idx_ret)
                                        *idx_ret = i;
-                               return &inode->i_ads_entries[i];
+                               result = &inode->i_ads_entries[i];
+                               break;
                        }
                } while (++i != inode->i_num_ads);
+               FREE(stream_name_utf16le);
+               return result;
        }
-       return NULL;
 }
 
 /*
  * Add an alternate stream entry to a WIM inode and return a pointer to it, or
  * NULL if memory could not be allocated.
  */
-struct wim_ads_entry *inode_add_ads(struct wim_inode *inode, const char *stream_name)
+struct wim_ads_entry *
+inode_add_ads(struct wim_inode *inode, const char *stream_name)
 {
        u16 num_ads;
        struct wim_ads_entry *ads_entries;
@@ -900,9 +933,10 @@ struct wim_ads_entry *inode_add_ads(struct wim_inode *inode, const char *stream_
        return new_entry;
 }
 
-int inode_add_ads_with_data(struct wim_inode *inode, const char *name,
-                           const u8 *value, size_t size,
-                           struct wim_lookup_table *lookup_table)
+int
+inode_add_ads_with_data(struct wim_inode *inode, const mbchar *name,
+                       const void *value, size_t size,
+                       struct wim_lookup_table *lookup_table)
 {
        int ret = WIMLIB_ERR_NOMEM;
        struct wim_ads_entry *new_ads_entry;
@@ -949,8 +983,9 @@ out:
 }
 
 /* Remove an alternate data stream from a WIM inode  */
-void inode_remove_ads(struct wim_inode *inode, u16 idx,
-                     struct wim_lookup_table *lookup_table)
+void
+inode_remove_ads(struct wim_inode *inode, u16 idx,
+                struct wim_lookup_table *lookup_table)
 {
        struct wim_ads_entry *ads_entry;
        struct wim_lookup_table_entry *lte;
@@ -960,7 +995,7 @@ void inode_remove_ads(struct wim_inode *inode, u16 idx,
 
        ads_entry = &inode->i_ads_entries[idx];
 
-       DEBUG("Remove alternate data stream \"%s\"", ads_entry->stream_name_utf8);
+       DEBUG("Remove alternate data stream \"%W\"", ads_entry->stream_name);
 
        lte = ads_entry->lte;
        if (lte)
@@ -975,9 +1010,10 @@ void inode_remove_ads(struct wim_inode *inode, u16 idx,
 }
 
 #ifndef __WIN32__
-int inode_get_unix_data(const struct wim_inode *inode,
-                       struct wimlib_unix_data *unix_data,
-                       u16 *stream_idx_ret)
+int
+inode_get_unix_data(const struct wim_inode *inode,
+                   struct wimlib_unix_data *unix_data,
+                   u16 *stream_idx_ret)
 {
        const struct wim_ads_entry *ads_entry;
        const struct wim_lookup_table_entry *lte;
@@ -1011,10 +1047,9 @@ int inode_get_unix_data(const struct wim_inode *inode,
        return 0;
 }
 
-int inode_set_unix_data(struct wim_inode *inode,
-                       uid_t uid, gid_t gid, mode_t mode,
-                       struct wim_lookup_table *lookup_table,
-                       int which)
+int
+inode_set_unix_data(struct wim_inode *inode, uid_t uid, gid_t gid, mode_t mode,
+                   struct wim_lookup_table *lookup_table, int which)
 {
        struct wimlib_unix_data unix_data;
        int ret;
@@ -1086,8 +1121,8 @@ int inode_set_unix_data(struct wim_inode *inode,
  * is set to an array of `struct wim_ads_entry's of length inode->i_num_ads.  On
  * failure, @inode is not modified.
  */
-static int read_ads_entries(const u8 *p, struct wim_inode *inode,
-                           u64 remaining_size)
+static int
+read_ads_entries(const u8 *p, struct wim_inode *inode, u64 remaining_size)
 {
        u16 num_ads;
        struct wim_ads_entry *ads_entries;
@@ -1126,15 +1161,14 @@ static int read_ads_entries(const u8 *p, struct wim_inode *inode,
                p = get_u64(p, &length);
                p += 8; /* Skip the reserved field */
                p = get_bytes(p, SHA1_HASH_SIZE, (u8*)cur_entry->hash);
-               p = get_u16(p, &cur_entry->stream_name_len);
+               p = get_u16(p, &cur_entry->stream_name_nbytes);
 
                cur_entry->stream_name = NULL;
-               cur_entry->stream_name_utf8 = NULL;
 
                /* Length including neither the null terminator nor the padding
                 * */
                length_no_padding = WIM_ADS_ENTRY_DISK_SIZE +
-                                   cur_entry->stream_name_len;
+                                   cur_entry->stream_name_nbytes;
 
                /* Length including the null terminator and the padding */
                total_length = ((length_no_padding + 2) + 7) & ~7;
@@ -1166,22 +1200,16 @@ static int read_ads_entries(const u8 *p, struct wim_inode *inode,
                        goto out_free_ads_entries;
                }
 
-               if (cur_entry->stream_name_len) {
-                       cur_entry->stream_name = MALLOC(cur_entry->stream_name_len);
+               if (cur_entry->stream_name_nbytes) {
+                       cur_entry->stream_name = MALLOC((size_t)
+                                                       cur_entry->stream_name_nbytes + 2);
                        if (!cur_entry->stream_name) {
                                ret = WIMLIB_ERR_NOMEM;
                                goto out_free_ads_entries;
                        }
-                       get_bytes(p, cur_entry->stream_name_len,
-                                 (u8*)cur_entry->stream_name);
-
-                       ret = utf16_to_utf8(cur_entry->stream_name,
-                                           cur_entry->stream_name_len,
-                                           &cur_entry->stream_name_utf8,
-                                           &utf8_len);
-                       if (ret != 0)
-                               goto out_free_ads_entries;
-                       cur_entry->stream_name_utf8_len = utf8_len;
+                       get_bytes(p, cur_entry->stream_name_nbytes,
+                                 cur_entry->stream_name);
+                       cur_entry->stream_name[cur_entry->stream_name_nbytes / 2] = 0;
                }
                /* It's expected that the size of every ADS entry is a multiple
                 * of 8.  However, to be safe, I'm allowing the possibility of
@@ -1224,17 +1252,16 @@ out_free_ads_entries:
  * this was a special "end of directory" dentry and not a real dentry.  If
  * nonzero, this was a real dentry.
  */
-int read_dentry(const u8 metadata_resource[], u64 metadata_resource_len,
-               u64 offset, struct wim_dentry *dentry)
+int
+read_dentry(const u8 metadata_resource[], u64 metadata_resource_len,
+           u64 offset, struct wim_dentry *dentry)
 {
        const u8 *p;
        u64 calculated_size;
-       char *file_name = NULL;
-       char *file_name_utf8 = NULL;
-       char *short_name = NULL;
-       u16 short_name_len;
-       u16 file_name_len;
-       size_t file_name_utf8_len = 0;
+       utf16lechar *file_name = NULL;
+       utf16lechar *short_name = NULL;
+       u16 short_name_nbytes;
+       u16 file_name_nbytes;
        int ret;
        struct wim_inode *inode = NULL;
 
@@ -1321,8 +1348,8 @@ int read_dentry(const u8 metadata_resource[], u64 metadata_resource_len,
 
        p = get_u16(p, &inode->i_num_ads);
 
-       p = get_u16(p, &short_name_len);
-       p = get_u16(p, &file_name_len);
+       p = get_u16(p, &short_name_nbytes);
+       p = get_u16(p, &file_name_nbytes);
 
        /* We now know the length of the file name and short name.  Make sure
         * the length of the dentry is large enough to actually hold them.
@@ -1330,40 +1357,35 @@ int read_dentry(const u8 metadata_resource[], u64 metadata_resource_len,
         * The calculated length here is unaligned to allow for the possibility
         * that the dentry->length names an unaligned length, although this
         * would be unexpected. */
-       calculated_size = __dentry_correct_length_unaligned(file_name_len,
-                                                           short_name_len);
+       calculated_size = __dentry_correct_length_unaligned(file_name_nbytes,
+                                                           short_name_nbytes);
 
        if (dentry->length < calculated_size) {
                ERROR("Unexpected end of directory entry! (Expected "
                      "at least %"PRIu64" bytes, got %"PRIu64" bytes. "
-                     "short_name_len = %hu, file_name_len = %hu)",
+                     "short_name_nbytes = %hu, file_name_nbytes = %hu)",
                      calculated_size, dentry->length,
-                     short_name_len, file_name_len);
+                     short_name_nbytes, file_name_nbytes);
                ret = WIMLIB_ERR_INVALID_DENTRY;
                goto out_free_inode;
        }
 
        /* Read the filename if present.  Note: if the filename is empty, there
         * is no null terminator following it. */
-       if (file_name_len) {
-               file_name = MALLOC(file_name_len);
+       if (file_name_nbytes) {
+               file_name = MALLOC((size_t)file_name_nbytes + 2);
                if (!file_name) {
-                       ERROR("Failed to allocate %hu bytes for dentry file name",
-                             file_name_len);
+                       ERROR("Failed to allocate %zu bytes for dentry file name",
+                             (size_t)file_name_nbytes + 2);
                        ret = WIMLIB_ERR_NOMEM;
                        goto out_free_inode;
                }
-               p = get_bytes(p, file_name_len, file_name);
-
-               /* Convert filename to UTF-8. */
-               ret = utf16_to_utf8(file_name, file_name_len, &file_name_utf8,
-                                   &file_name_utf8_len);
-               if (ret != 0)
-                       goto out_free_file_name;
-               if (*(u16*)p)
-                       WARNING("Expected two zero bytes following the file name "
-                               "`%s', but found non-zero bytes", file_name_utf8);
-               p += 2;
+               p = get_bytes(p, (size_t)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 "
+                               "null-terminated!", file_name);
+               }
        }
 
        /* Align the calculated size */
@@ -1393,27 +1415,27 @@ int read_dentry(const u8 metadata_resource[], u64 metadata_resource_len,
                 *      u64 reserved1; (always 0)
                 *      u64 reserved2; (always 0)
                 * };*/
-               DEBUG("Dentry for file or directory `%s' has %"PRIu64" extra "
-                     "bytes of data",
-                     file_name_utf8, dentry->length - calculated_size);
+               /*DEBUG("Dentry for file or directory `%s' has %"PRIu64" extra "*/
+                     /*"bytes of data",*/
+                     /*file_name_utf8, dentry->length - calculated_size);*/
        }
 
        /* Read the short filename if present.  Note: if there is no short
         * filename, there is no null terminator following it. */
-       if (short_name_len) {
-               short_name = MALLOC(short_name_len);
+       if (short_name_nbytes) {
+               short_name = MALLOC((size_t)short_name_nbytes + 2);
                if (!short_name) {
-                       ERROR("Failed to allocate %hu bytes for short filename",
-                             short_name_len);
+                       ERROR("Failed to allocate %zu bytes for dentry short name",
+                             (size_t)short_name_nbytes + 2);
                        ret = WIMLIB_ERR_NOMEM;
-                       goto out_free_file_name_utf8;
+                       goto out_free_file_name;
+               }
+               p = get_bytes(p, (size_t)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 "
+                               "null-terminated!", file_name);
                }
-
-               p = get_bytes(p, short_name_len, short_name);
-               if (*(u16*)p)
-                       WARNING("Expected two zero bytes following the short name of "
-                               "`%s', but found non-zero bytes", file_name_utf8);
-               p += 2;
        }
 
        /*
@@ -1451,25 +1473,20 @@ int read_dentry(const u8 metadata_resource[], u64 metadata_resource_len,
                                goto out;
                }
                ERROR("Failed to read alternate data stream "
-                     "entries of `%s'", dentry->file_name_utf8);
+                     "entries of WIM dentry \"%W\"", file_name);
                goto out_free_short_name;
        }
 out:
-
        /* We've read all the data for this dentry.  Set the names and their
         * lengths, and we've done. */
-       dentry->d_inode            = inode;
-       dentry->file_name          = file_name;
-       dentry->file_name_utf8     = file_name_utf8;
-       dentry->short_name         = short_name;
-       dentry->file_name_len      = file_name_len;
-       dentry->file_name_utf8_len = file_name_utf8_len;
-       dentry->short_name_len     = short_name_len;
+       dentry->d_inode           = inode;
+       dentry->file_name         = file_name;
+       dentry->short_name        = short_name;
+       dentry->file_name_nbytes  = file_name_nbytes;
+       dentry->short_name_nbytes = short_name_nbytes;
        return 0;
 out_free_short_name:
        FREE(short_name);
-out_free_file_name_utf8:
-       FREE(file_name_utf8);
 out_free_file_name:
        FREE(file_name);
 out_free_inode:
@@ -1491,10 +1508,11 @@ out_free_inode:
  *             does not need to be the real root because this procedure is
  *             called recursively.
  *
- * @return:    Zero on success, nonzero on failure.
+ * Returns zero on success; nonzero on failure.
  */
-int read_dentry_tree(const u8 metadata_resource[], u64 metadata_resource_len,
-                    struct wim_dentry *dentry)
+int
+read_dentry_tree(const u8 metadata_resource[], u64 metadata_resource_len,
+                struct wim_dentry *dentry)
 {
        u64 cur_offset = dentry->subdir_offset;
        struct wim_dentry *child;
@@ -1563,7 +1581,8 @@ int read_dentry_tree(const u8 metadata_resource[], u64 metadata_resource_len,
  * @return:  Pointer to the byte after the last byte we wrote as part of the
  *             dentry.
  */
-static u8 *write_dentry(const struct wim_dentry *dentry, u8 *p)
+static u8 *
+write_dentry(const struct wim_dentry *dentry, u8 *p)
 {
        u8 *orig_p = p;
        const u8 *hash;
@@ -1600,15 +1619,15 @@ static u8 *write_dentry(const struct wim_dentry *dentry, u8 *p)
                p = put_u64(p, link_group_id);
        }
        p = put_u16(p, inode->i_num_ads);
-       p = put_u16(p, dentry->short_name_len);
-       p = put_u16(p, dentry->file_name_len);
-       if (dentry->file_name_len) {
-               p = put_bytes(p, dentry->file_name_len, (u8*)dentry->file_name);
-               p = put_u16(p, 0); /* filename padding, 2 bytes. */
+       p = put_u16(p, dentry->short_name_nbytes);
+       p = put_u16(p, dentry->file_name_nbytes);
+       if (dentry->file_name_nbytes) {
+               p = put_bytes(p, dentry->file_name_nbytes + 2,
+                             dentry->file_name);
        }
-       if (dentry->short_name) {
-               p = put_bytes(p, dentry->short_name_len, (u8*)dentry->short_name);
-               p = put_u16(p, 0); /* short name padding, 2 bytes */
+       if (dentry->short_name_nbytes) {
+               p = put_bytes(p, dentry->short_name_nbytes + 2,
+                             dentry->short_name);
        }
 
        /* Align to 8-byte boundary */
@@ -1623,11 +1642,11 @@ static u8 *write_dentry(const struct wim_dentry *dentry, u8 *p)
                p = put_u64(p, 0); /* Unused */
                hash = inode_stream_hash(inode, i + 1);
                p = put_bytes(p, SHA1_HASH_SIZE, hash);
-               p = put_u16(p, inode->i_ads_entries[i].stream_name_len);
-               if (inode->i_ads_entries[i].stream_name_len) {
-                       p = put_bytes(p, inode->i_ads_entries[i].stream_name_len,
-                                        (u8*)inode->i_ads_entries[i].stream_name);
-                       p = put_u16(p, 0);
+               p = put_u16(p, inode->i_ads_entries[i].stream_name_nbytes);
+               if (inode->i_ads_entries[i].stream_name_nbytes) {
+                       p = put_bytes(p,
+                                     inode->i_ads_entries[i].stream_name_nbytes + 2,
+                                     inode->i_ads_entries[i].stream_name);
                }
                p = put_zeroes(p, (8 - (p - orig_p) % 8) % 8);
        }
@@ -1635,16 +1654,19 @@ static u8 *write_dentry(const struct wim_dentry *dentry, u8 *p)
        return p;
 }
 
-static int write_dentry_cb(struct wim_dentry *dentry, void *_p)
+static int
+write_dentry_cb(struct wim_dentry *dentry, void *_p)
 {
        u8 **p = _p;
        *p = write_dentry(dentry, *p);
        return 0;
 }
 
-static u8 *write_dentry_tree_recursive(const struct wim_dentry *parent, u8 *p);
+static u8 *
+write_dentry_tree_recursive(const struct wim_dentry *parent, u8 *p);
 
-static int write_dentry_tree_recursive_cb(struct wim_dentry *dentry, void *_p)
+static int
+write_dentry_tree_recursive_cb(struct wim_dentry *dentry, void *_p)
 {
        u8 **p = _p;
        *p = write_dentry_tree_recursive(dentry, *p);
@@ -1653,7 +1675,8 @@ static int write_dentry_tree_recursive_cb(struct wim_dentry *dentry, void *_p)
 
 /* Recursive function that writes a dentry tree rooted at @parent, not including
  * @parent itself, which has already been written. */
-static u8 *write_dentry_tree_recursive(const struct wim_dentry *parent, u8 *p)
+static u8 *
+write_dentry_tree_recursive(const struct wim_dentry *parent, u8 *p)
 {
        /* Nothing to do if this dentry has no children. */
        if (parent->subdir_offset == 0)
@@ -1682,7 +1705,8 @@ static u8 *write_dentry_tree_recursive(const struct wim_dentry *parent, u8 *p)
  *
  * Returns pointer to the byte after the last byte we wrote.
  */
-u8 *write_dentry_tree(const struct wim_dentry *root, u8 *p)
+u8 *
+write_dentry_tree(const struct wim_dentry *root, u8 *p)
 {
        DEBUG("Writing dentry tree.");
        wimlib_assert(dentry_is_root(root));
index 7608732..dfbcafc 100644 (file)
@@ -74,18 +74,12 @@ struct wim_ads_entry {
                struct wim_lookup_table_entry *lte;
        };
 
-       /* Length of stream name (UTF-16).  This is in bytes, not characters,
-        * and does not include the terminating null character   */
-       u16 stream_name_len;
+       /* Length of UTF16-encoded stream name, in bytes, not including the
+        * terminating null character. */
+       u16 stream_name_nbytes;
 
-       /* Length of stream name (UTF-8) */
-       u16 stream_name_utf8_len;
-
-       /* Stream name (UTF-16) */
-       char *stream_name;
-
-       /* Stream name (UTF-8) */
-       char *stream_name_utf8;
+       /* Stream name (UTF-16LE) */
+       utf16lechar *stream_name;
 
 #ifdef WITH_FUSE
        /* Number to identify an alternate data stream even after it's possibly
@@ -95,13 +89,13 @@ struct wim_ads_entry {
 };
 
 
-static inline bool ads_entries_have_same_name(const struct wim_ads_entry *entry_1,
-                                             const struct wim_ads_entry *entry_2)
+static inline bool
+ads_entries_have_same_name(const struct wim_ads_entry *entry_1,
+                          const struct wim_ads_entry *entry_2)
 {
-       if (entry_1->stream_name_len != entry_2->stream_name_len)
-               return false;
-       return memcmp(entry_1->stream_name, entry_2->stream_name,
-                     entry_1->stream_name_len) == 0;
+       return entry_1->stream_name_nbytes == entry_2->stream_name_nbytes &&
+              memcmp(entry_1->stream_name, entry_2->stream_name,
+                     entry_1->stream_name_nbytes) == 0;
 }
 
 /*
@@ -133,46 +127,31 @@ static inline bool ads_entries_have_same_name(const struct wim_ads_entry *entry_
  * dentry_tree_fix_inodes() in hardlink.c).
  */
 struct wim_dentry {
-       /* Byte 0 */
-
        /* The inode for this dentry */
        struct wim_inode *d_inode;
 
-       /* Byte 8 */
-
        /* Red-black tree of sibling dentries */
        struct rb_node rb_node;
 
-       /* Byte 32 */
+       /* Length of UTF-16LE encoded short filename, in bytes, not including
+        * the terminating zero wide-character. */
+       u16 short_name_nbytes;
 
-       /* Length of short filename, in bytes, not including the terminating
-        * zero wide-character. */
-       u16 short_name_len;
+       /* Length of UTF-16LE encoded "long" file name, in bytes, not including
+        * the terminating null character. */
+       u16 file_name_nbytes;
 
-       /* Length of file name, in bytes, not including the terminating zero
-        * wide-character. */
-       u16 file_name_len;
-
-       /* Length of the filename converted into UTF-8, in bytes, not including
-        * the terminating zero byte. */
-       u16 file_name_utf8_len;
+       /* Length of full path name, in bytes, as a multibyte-encoded string */
+       u32 full_path_nbytes;
 
        u8 is_extracted : 1;
 
        /* Only used during NTFS capture */
        u8 is_win32_name : 1;
 
-       /* Byte 40 */
-
-       /* Pointer to the filename converted to UTF-8 (malloc()ed buffer). */
-       char *file_name_utf8;
-
-       /* Byte 48 */
-
+       /* Temporary list */
        struct list_head tmp_list;
 
-       /* Byte 64 */
-
        /* List of dentries in the inode (hard link set)  */
        struct list_head d_alias;
 
@@ -209,16 +188,14 @@ struct wim_dentry {
         * WIMStructs */
        u32 refcnt;
 
-       u32 full_path_utf8_len;
-
-       /* Pointer to the UTF-16 short filename (malloc()ed buffer) */
-       char *short_name;
+       /* Pointer to the UTF-16LE short filename (malloc()ed buffer) */
+       utf16lechar *short_name;
 
-       /* Pointer to the UTF-16 filename (malloc()ed buffer). */
-       char *file_name;
+       /* Pointer to the UTF-16LE filename (malloc()ed buffer). */
+       utf16lechar *file_name;
 
-       /* Full path (UTF-8) to this dentry (malloc()ed buffer). */
-       char *full_path_utf8;
+       /* Full path of this dentry */
+       mbchar *full_path;
 };
 
 #define rbnode_dentry(node) container_of(node, struct wim_dentry, rb_node)
@@ -294,7 +271,7 @@ struct wim_inode {
 
        struct list_head i_lte_inode_list;
 
-       char *i_extracted_file;
+       mbchar *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
@@ -326,80 +303,119 @@ struct wim_inode {
 #define inode_first_dentry(inode) \
                container_of(inode->i_dentry.next, struct wim_dentry, d_alias)
 
-static inline bool dentry_is_first_in_inode(const struct wim_dentry *dentry)
+static inline bool
+dentry_is_first_in_inode(const struct wim_dentry *dentry)
 {
        return inode_first_dentry(dentry->d_inode) == dentry;
 }
 
-extern u64 dentry_correct_total_length(const struct wim_dentry *dentry);
+extern u64
+dentry_correct_total_length(const struct wim_dentry *dentry);
 
-extern int for_dentry_in_tree(struct wim_dentry *root,
-                             int (*visitor)(struct wim_dentry*, void*),
-                             void *args);
+extern int
+for_dentry_in_tree(struct wim_dentry *root,
+                  int (*visitor)(struct wim_dentry*, void*),
+                  void *args);
 
-extern int for_dentry_in_rbtree(struct rb_node *node,
-                               int (*visitor)(struct wim_dentry *, void *),
-                               void *arg);
+extern int
+for_dentry_in_rbtree(struct rb_node *node,
+                    int (*visitor)(struct wim_dentry *, void *),
+                    void *arg);
 
-static inline int for_dentry_child(const struct wim_dentry *dentry,
-                                  int (*visitor)(struct wim_dentry *, void *),
-                                  void *arg)
+static inline int
+for_dentry_child(const struct wim_dentry *dentry,
+                int (*visitor)(struct wim_dentry *, void *),
+                void *arg)
 {
        return for_dentry_in_rbtree(dentry->d_inode->i_children.rb_node,
                                    visitor,
                                    arg);
 }
 
-extern int for_dentry_in_tree_depth(struct wim_dentry *root,
-                                   int (*visitor)(struct wim_dentry*, void*),
-                                   void *args);
+extern int
+for_dentry_in_tree_depth(struct wim_dentry *root,
+                        int (*visitor)(struct wim_dentry*, void*),
+                        void *args);
+
+extern int
+calculate_dentry_full_path(struct wim_dentry *dentry, void *ignore);
+
+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);
 
-extern int calculate_dentry_full_path(struct wim_dentry *dentry, void *ignore);
-extern void calculate_subdir_offsets(struct wim_dentry *dentry, u64 *subdir_offset_p);
-extern int set_dentry_name(struct wim_dentry *dentry, const char *new_name);
+extern struct wim_dentry *
+get_dentry(struct WIMStruct *w, const mbchar *path);
+
+extern struct wim_inode *
+wim_pathname_to_inode(struct WIMStruct *w, const mbchar *path);
 
-extern struct wim_dentry *get_dentry(struct WIMStruct *w, const char *path);
+extern struct wim_dentry *
+get_dentry_child_with_name(const struct wim_dentry *dentry,
+                          const mbchar *name);
 
-extern struct wim_inode *wim_pathname_to_inode(struct WIMStruct *w,
-                                              const char *path);
+extern struct wim_dentry *
+get_dentry_child_with_utf16le_name(const struct wim_dentry *dentry,
+                                  const utf16lechar *name);
 
 extern struct wim_dentry *
-get_dentry_child_with_name(const struct wim_dentry *dentry, const char *name);
+get_parent_dentry(struct WIMStruct *w, const mbchar *path);
+
+extern int
+print_dentry(struct wim_dentry *dentry, void *lookup_table);
+
+extern int
+print_dentry_full_path(struct wim_dentry *entry, void *ignore);
+
+extern struct
+wim_dentry *new_dentry(const mbchar *name);
+
+extern struct wim_dentry *
+new_dentry_with_inode(const mbchar *name);
+
+extern struct wim_dentry *
+new_dentry_with_timeless_inode(const mbchar *name);
+
+extern void
+free_inode(struct wim_inode *inode);
+
+extern void
+free_dentry(struct wim_dentry *dentry);
 
-extern struct wim_dentry *get_parent_dentry(struct WIMStruct *w,
-                                           const char *path);
+extern void
+put_dentry(struct wim_dentry *dentry);
 
-extern int print_dentry(struct wim_dentry *dentry, void *lookup_table);
-extern int print_dentry_full_path(struct wim_dentry *entry, void *ignore);
+extern void
+free_dentry_tree(struct wim_dentry *root,
+                struct wim_lookup_table *lookup_table);
 
-extern struct wim_dentry *new_dentry(const char *name);
-extern struct wim_dentry *new_dentry_with_inode(const char *name);
-extern struct wim_dentry *new_dentry_with_timeless_inode(const char *name);
+extern int
+increment_dentry_refcnt(struct wim_dentry *dentry, void *ignore);
 
-extern void free_inode(struct wim_inode *inode);
-extern void free_dentry(struct wim_dentry *dentry);
-extern void put_dentry(struct wim_dentry *dentry);
+extern void
+unlink_dentry(struct wim_dentry *dentry);
 
-extern void free_dentry_tree(struct wim_dentry *root,
-                            struct wim_lookup_table *lookup_table);
-extern int increment_dentry_refcnt(struct wim_dentry *dentry, void *ignore);
+extern bool
+dentry_add_child(struct wim_dentry * restrict parent,
+                struct wim_dentry * restrict child);
 
-extern void unlink_dentry(struct wim_dentry *dentry);
-extern bool 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,
+                   u16 *idx_ret);
 
-extern struct wim_ads_entry *inode_get_ads_entry(struct wim_inode *inode,
-                                                const char *stream_name,
-                                                u16 *idx_ret);
+extern struct wim_ads_entry *
+inode_add_ads(struct wim_inode *dentry, const mbchar *stream_name);
 
-extern struct wim_ads_entry *inode_add_ads(struct wim_inode *dentry,
-                                          const char *stream_name);
-extern int inode_add_ads_with_data(struct wim_inode *inode, const char *name,
-                                  const u8 *value, size_t size,
-                                  struct wim_lookup_table *lookup_table);
+extern int
+inode_add_ads_with_data(struct wim_inode *inode, const mbchar *name,
+                       const void *value, size_t size,
+                       struct wim_lookup_table *lookup_table);
 
-extern void inode_remove_ads(struct wim_inode *inode, u16 idx,
-                            struct wim_lookup_table *lookup_table);
+extern void
+inode_remove_ads(struct wim_inode *inode, u16 idx,
+                struct wim_lookup_table *lookup_table);
 
 #define WIMLIB_UNIX_DATA_TAG "$$__wimlib_UNIX_data"
 
@@ -418,72 +434,82 @@ struct wimlib_unix_data {
 
 #define NO_UNIX_DATA (-1)
 #define BAD_UNIX_DATA (-2)
-extern int inode_get_unix_data(const struct wim_inode *inode,
-                              struct wimlib_unix_data *unix_data,
-                              u16 *stream_idx_ret);
+extern int
+inode_get_unix_data(const struct wim_inode *inode,
+                   struct wimlib_unix_data *unix_data,
+                   u16 *stream_idx_ret);
 
 #define UNIX_DATA_UID    0x1
 #define UNIX_DATA_GID    0x2
 #define UNIX_DATA_MODE   0x4
 #define UNIX_DATA_ALL    (UNIX_DATA_UID | UNIX_DATA_GID | UNIX_DATA_MODE)
 #define UNIX_DATA_CREATE 0x8
-extern int inode_set_unix_data(struct wim_inode *inode,
-                              uid_t uid, gid_t gid, mode_t mode,
-                              struct wim_lookup_table *lookup_table,
-                              int which);
+extern int
+inode_set_unix_data(struct wim_inode *inode, uid_t uid, gid_t gid, mode_t mode,
+                   struct wim_lookup_table *lookup_table, int which);
 #endif
 
-extern int read_dentry(const u8 metadata_resource[], u64 metadata_resource_len,
-                      u64 offset, struct wim_dentry *dentry);
+extern int
+read_dentry(const u8 metadata_resource[], u64 metadata_resource_len,
+           u64 offset, struct wim_dentry *dentry);
 
 
-extern int read_dentry_tree(const u8 metadata_resource[],
-                           u64 metadata_resource_len,
-                           struct wim_dentry *dentry);
+extern int
+read_dentry_tree(const u8 metadata_resource[], u64 metadata_resource_len,
+                struct wim_dentry *dentry);
 
-extern u8 *write_dentry_tree(const struct wim_dentry *tree, u8 *p);
+extern u8 *
+write_dentry_tree(const struct wim_dentry *tree, u8 *p);
 
-static inline bool dentry_is_root(const struct wim_dentry *dentry)
+static inline bool
+dentry_is_root(const struct wim_dentry *dentry)
 {
        return dentry->parent == dentry;
 }
 
-static inline bool inode_is_directory(const struct wim_inode *inode)
+static inline bool
+inode_is_directory(const struct wim_inode *inode)
 {
        return (inode->i_attributes & FILE_ATTRIBUTE_DIRECTORY)
                && !(inode->i_attributes & FILE_ATTRIBUTE_REPARSE_POINT);
 }
 
-static inline bool dentry_is_directory(const struct wim_dentry *dentry)
+static inline bool
+dentry_is_directory(const struct wim_dentry *dentry)
 {
        return inode_is_directory(dentry->d_inode);
 }
 
 /* For our purposes, we consider "real" symlinks and "junction points" to both
  * be symlinks. */
-static inline bool inode_is_symlink(const struct wim_inode *inode)
+static inline bool
+inode_is_symlink(const struct wim_inode *inode)
 {
        return (inode->i_attributes & FILE_ATTRIBUTE_REPARSE_POINT)
                && ((inode->i_reparse_tag == WIM_IO_REPARSE_TAG_SYMLINK) ||
                     inode->i_reparse_tag == WIM_IO_REPARSE_TAG_MOUNT_POINT);
 }
 
-static inline bool inode_is_regular_file(const struct wim_inode *inode)
+static inline bool
+inode_is_regular_file(const struct wim_inode *inode)
 {
        return !inode_is_directory(inode) && !inode_is_symlink(inode);
 }
 
-static inline bool dentry_is_regular_file(const struct wim_dentry *dentry)
+static inline bool
+dentry_is_regular_file(const struct wim_dentry *dentry)
 {
        return inode_is_regular_file(dentry->d_inode);
 }
 
-static inline bool inode_has_children(const struct wim_inode *inode)
+static inline bool
+inode_has_children(const struct wim_inode *inode)
 {
        return inode->i_children.rb_node != NULL;
 }
 
-static inline bool dentry_has_children(const struct wim_dentry *dentry)
+static inline bool
+dentry_has_children(const struct wim_dentry *dentry)
 {
        return inode_has_children(dentry->d_inode);
 }
index bddb181..de04358 100644 (file)
@@ -1,5 +1,7 @@
 /*
- * encoding.c:  Convert UTF-8 to UTF-16LE strings and vice versa
+ * encoding.c:  Convert "multibyte" strings (the locale-default encoding---
+ * generally, UTF-8 or something like ISO-8859-1) to UTF-16LE strings, and vice
+ * versa.
  */
 
 /*
  */
 
 #include "config.h"
-#include "wimlib.h"
-#include "util.h"
-#include "endianness.h"
-
-#include <errno.h>
-
-#ifdef WITH_NTFS_3G
-#  include <ntfs-3g/volume.h>
-#  include <ntfs-3g/unistr.h>
-#elif defined(__WIN32__)
-#  include <wchar.h>
-#  include <stdlib.h>
-#else
-#  include <iconv.h>
-#endif
+#include "wimlib_internal.h"
+#include <pthread.h>
+#include "list.h"
 
-/*
- * NOTE:
- *
- * utf16_to_utf8_size() and utf8_to_utf16_size() were taken from
- * libntfs-3g/unistr.c in the NTFS-3g sources.  (Modified slightly to remove
- * unneeded functionality.)
- */
-#if !defined(WITH_NTFS_3G) && !defined(__WIN32__)
-/*
- * Return the amount of 8-bit elements in UTF-8 needed (without the terminating
- * null) to store a given UTF-16LE string.
- *
- * Return -1 with errno set if string has invalid byte sequence or too long.
- */
-static int utf16_to_utf8_size(const u16 *ins, const int ins_len)
-{
-       int i, ret = -1;
-       int count = 0;
-       bool surrog;
-
-       surrog = false;
-       for (i = 0; i < ins_len && ins[i]; i++) {
-               unsigned short c = le16_to_cpu(ins[i]);
-               if (surrog) {
-                       if ((c >= 0xdc00) && (c < 0xe000)) {
-                               surrog = false;
-                               count += 4;
-                       } else
-                               goto fail;
-               } else
-                       if (c < 0x80)
-                               count++;
-                       else if (c < 0x800)
-                               count += 2;
-                       else if (c < 0xd800)
-                               count += 3;
-                       else if (c < 0xdc00)
-                               surrog = true;
-#if NOREVBOM
-                       else if ((c >= 0xe000) && (c < 0xfffe))
-#else
-                       else if (c >= 0xe000)
-#endif
-                               count += 3;
-                       else
-                               goto fail;
-       }
-       if (surrog)
-               goto fail;
+#include <iconv.h>
+#include <stdlib.h>
 
-       ret = count;
-out:
-       return ret;
-fail:
-       errno = EILSEQ;
-       goto out;
+bool wimlib_mbs_is_utf8 = false;
+
+struct iconv_list_head {
+       const char *from_encoding;
+       const char *to_encoding;
+       struct list_head list;
+       pthread_mutex_t mutex;
+};
+
+struct iconv_node {
+       iconv_t cd;
+       struct list_head list;
+       struct iconv_list_head *head;
+};
+
+#define ICONV_LIST(name, from, to)                     \
+struct iconv_list_head name = {                                \
+       .from_encoding = from,                          \
+       .to_encoding = to,                              \
+       .list = LIST_HEAD_INIT(name.list),              \
+       .mutex = PTHREAD_MUTEX_INITIALIZER,             \
 }
 
-/*
- * Return the amount of 16-bit elements in UTF-16LE needed
- * (without the terminating null) to store given UTF-8 string.
- *
- * Return -1 with errno set if it's longer than PATH_MAX or string is invalid.
- *
- * Note: This does not check whether the input sequence is a valid utf8 string,
- *      and should be used only in context where such check is made!
- */
-static int utf8_to_utf16_size(const char *s)
+static ICONV_LIST(iconv_mbs_to_utf16le, "", "UTF-16LE");
+static ICONV_LIST(iconv_utf16le_to_mbs, "UTF-16LE", "");
+
+static iconv_t *
+get_iconv(struct iconv_list_head *head)
 {
-       unsigned int byte;
-       size_t count = 0;
-       while ((byte = *((const unsigned char *)s++))) {
-               count++;
-               if (byte >= 0xc0) {
-                       if (byte >= 0xF5) {
-                               errno = EILSEQ;
-                               return -1;
-                       }
-                       if (!*s)
-                               break;
-                       if (byte >= 0xC0)
-                               s++;
-                       if (!*s)
-                               break;
-                       if (byte >= 0xE0)
-                               s++;
-                       if (!*s)
-                               break;
-                       if (byte >= 0xF0) {
-                               s++;
-                               count++;
+       iconv_t cd;
+       struct iconv_node *i;
+
+       pthread_mutex_lock(&head->mutex);
+       if (list_empty(&head->list)) {
+               cd = iconv_open(head->to_encoding, head->from_encoding);
+               if (cd == (iconv_t)-1) {
+                       goto out_unlock;
+               } else {
+                       i = MALLOC(sizeof(struct iconv_node));
+                       if (!i) {
+                               iconv_close(cd);
+                               cd = (iconv_t)-1;
+                               goto out_unlock;
                        }
+                       i->head = head;
                }
+       } else {
+               i = container_of(head->list.next, struct iconv_node, list);
+               list_del(head->list.next);
        }
-       return count;
+       cd = i->cd;
+out_unlock:
+       pthread_mutex_unlock(&head->mutex);
+       return cd;
 }
 
-static iconv_t cd_utf8_to_utf16 = (iconv_t)(-1);
-static iconv_t cd_utf16_to_utf8 = (iconv_t)(-1);
+static void
+put_iconv(iconv_t *cd)
+{
+       struct iconv_node *i = container_of(cd, struct iconv_node, cd);
+       struct iconv_list_head *head = i->head;
+       
+       pthread_mutex_lock(&head->mutex);
+       list_add(&i->list, &head->list);
+       pthread_mutex_unlock(&head->mutex);
+}
 
-int iconv_global_init()
+int
+mbs_to_utf16le_nbytes(const mbchar *mbs, size_t mbs_nbytes,
+                     size_t *utf16le_nbytes_ret)
 {
-       if (cd_utf16_to_utf8 == (iconv_t)(-1)) {
-               cd_utf16_to_utf8 = iconv_open("UTF-8", "UTF-16LE");
-               if (cd_utf16_to_utf8 == (iconv_t)-1) {
-                       ERROR_WITH_ERRNO("Failed to get conversion descriptor "
-                                        "for converting UTF-16LE to UTF-8");
-                       if (errno == ENOMEM)
-                               return WIMLIB_ERR_NOMEM;
-                       else
-                               return WIMLIB_ERR_ICONV_NOT_AVAILABLE;
-               }
-       }
+       iconv_t *cd = get_iconv(&iconv_mbs_to_utf16le);
+       if (*cd == (iconv_t)-1)
+               return WIMLIB_ERR_ICONV_NOT_AVAILABLE;
 
-       if (cd_utf8_to_utf16 == (iconv_t)(-1)) {
-               cd_utf8_to_utf16 = iconv_open("UTF-16LE", "UTF-8");
-               if (cd_utf8_to_utf16 == (iconv_t)-1) {
-                       ERROR_WITH_ERRNO("Failed to get conversion descriptor "
-                                        "for converting UTF-8 to UTF-16LE");
-                       if (errno == ENOMEM)
-                               return WIMLIB_ERR_NOMEM;
-                       else
-                               return WIMLIB_ERR_ICONV_NOT_AVAILABLE;
-               }
+       /* Worst case length */
+       utf16lechar buf[mbs_nbytes * 2];
+       char *inbuf = (char*)mbs;
+       char *outbuf = (char*)buf;
+       size_t outbytesleft = sizeof(buf);
+       size_t inbytesleft = mbs_nbytes;
+       size_t len;
+       int ret;
+
+       len = iconv(*cd, &inbuf, &inbytesleft, &outbuf, &outbytesleft);
+       if (len == (size_t)-1) {
+               ret = WIMLIB_ERR_INVALID_MULTIBYTE_STRING;
+       } else {
+               *utf16le_nbytes_ret = sizeof(buf) - outbytesleft;
+               ret = 0;
        }
-       return 0;
+       put_iconv(cd);
+       return ret;
 }
 
-void iconv_global_cleanup()
-{
-       if (cd_utf8_to_utf16 != (iconv_t)(-1))
-               iconv_close(cd_utf8_to_utf16);
-       if (cd_utf16_to_utf8 != (iconv_t)(-1))
-               iconv_close(cd_utf16_to_utf8);
-}
-#endif /* !WITH_NTFS_3G && !__WIN32__ */
 
-/* Converts a string in the UTF-16LE encoding to a newly allocated string in the
- * UTF-8 encoding.
- *
- * If available, do so by calling a similar function from libntfs-3g.
- * Otherwise, use iconv() along with the helper function utf16_to_utf8_size().
- */
-int utf16_to_utf8(const char *utf16_str, size_t utf16_nbytes,
-                 char **utf8_str_ret, size_t *utf8_nbytes_ret)
+int
+utf16le_to_mbs_nbytes(const utf16lechar *utf16le_str, size_t utf16le_nbytes,
+                     size_t *mbs_nbytes_ret)
 {
+       iconv_t *cd = get_iconv(&iconv_utf16le_to_mbs);
+       if (*cd == (iconv_t)-1)
+               return WIMLIB_ERR_ICONV_NOT_AVAILABLE;
+
+       /* Worst case length */
+       mbchar buf[utf16le_nbytes / 2 * MB_CUR_MAX];
+       char *inbuf = (char*)utf16le_str;
+       char *outbuf = (char*)buf;
+       size_t outbytesleft = sizeof(buf);
+       size_t inbytesleft = utf16le_nbytes;
+       size_t len;
        int ret;
 
-       if (utf16_nbytes == 0) {
-               *utf8_str_ret = NULL;
-               *utf8_nbytes_ret = 0;
-               return 0;
+       len = iconv(*cd, &inbuf, &inbytesleft, &outbuf, &outbytesleft);
+       if (len == (size_t)-1) {
+               ERROR("Could not convert \"%W\" to encoding of current locale",
+                     utf16le_str);
+               /* EILSEQ is supposed to mean that the *input* is invalid, but
+                * it's also returned if any input characters are not
+                * representable in the output encoding.  (The actual behavior
+                * in this case is undefined for some reason...).  Assume it's
+                * the latter error case. */
+               ret = WIMLIB_ERR_UNICODE_STRING_NOT_REPRESENTABLE;
+       } else {
+               *mbs_nbytes_ret  = sizeof(buf) - outbytesleft;
+               ret = 0;
        }
+       put_iconv(cd);
+       return ret;
+}
 
-       if (utf16_nbytes & 1) {
-               ERROR("UTF-16LE string is invalid (odd number of bytes)!");
-               return WIMLIB_ERR_INVALID_UTF16_STRING;
-       }
-#ifdef WITH_NTFS_3G
-       char *outs = NULL;
-       int outs_len = ntfs_ucstombs((const ntfschar*)utf16_str,
-                                    utf16_nbytes / 2, &outs, 0);
-       if (outs_len >= 0) {
-               *utf8_str_ret = outs;
-               *utf8_nbytes_ret = outs_len;
-               ret = 0;
+int
+mbs_to_utf16le_buf(const mbchar *mbs, size_t mbs_nbytes,
+                  utf16lechar *utf16le_str)
+{
+       iconv_t *cd = get_iconv(&iconv_mbs_to_utf16le);
+       if (*cd == (iconv_t)-1)
+               return WIMLIB_ERR_ICONV_NOT_AVAILABLE;
+
+       char *inbuf = (char*)mbs;
+       size_t inbytesleft = mbs_nbytes;
+       char *outbuf = (char*)utf16le_str;
+       size_t outbytesleft = SIZE_MAX;
+       size_t len;
+       int ret;
+
+       len = iconv(*cd, &inbuf, &inbytesleft, &outbuf, &outbytesleft);
+       if (len == (size_t)-1) {
+               ret = WIMLIB_ERR_INVALID_MULTIBYTE_STRING;
        } else {
-               if (errno == ENOMEM)
-                       ret = WIMLIB_ERR_NOMEM;
-               else
-                       ret = WIMLIB_ERR_INVALID_UTF16_STRING;
+               ret = 0;
        }
-#elif defined(__WIN32__)
-       char *utf8_str;
-       size_t utf8_nbytes;
-       utf8_nbytes = wcstombs(NULL, (const wchar_t*)utf16_str, 0);
-       if (utf8_nbytes == (size_t)(-1)) {
+       put_iconv(cd);
+       return ret;
+}
+
+int
+utf16le_to_mbs_buf(const utf16lechar *utf16le_str, size_t utf16le_nbytes,
+                  mbchar *mbs)
+{
+       int ret;
+       iconv_t *cd = get_iconv(&iconv_utf16le_to_mbs);
+       if (*cd == (iconv_t)-1)
+               return WIMLIB_ERR_ICONV_NOT_AVAILABLE;
+
+       char *inbuf = (char*)utf16le_str;
+       size_t inbytesleft;
+       char *outbuf = (char*)mbs;
+       size_t outbytesleft = SIZE_MAX;
+       size_t len;
+
+       len = iconv(*cd, &inbuf, &inbytesleft, &outbuf, &outbytesleft);
+       if (len == (size_t)-1) {
                ret = WIMLIB_ERR_INVALID_UTF16_STRING;
        } else {
-               utf8_str = MALLOC(utf8_nbytes + 1);
-               if (!utf8_str) {
-                       ret = WIMLIB_ERR_NOMEM;
-               } else {
-                       wcstombs(utf8_str, (const wchar_t*)utf16_str, utf8_nbytes + 1);
-                       *utf8_str_ret = utf8_str;
-                       *utf8_nbytes_ret = utf8_nbytes;
-                       ret = 0;
-               }
+               ret = 0;
        }
-#else
-       ret = iconv_global_init();
-       if (ret != 0)
+       mbs[SIZE_MAX - inbytesleft] = '\0';
+       put_iconv(cd);
+       return ret;
+}
+
+int
+mbs_to_utf16le(const mbchar *mbs, size_t mbs_nbytes,
+              utf16lechar **utf16le_ret, size_t *utf16le_nbytes_ret)
+{
+       int ret;
+       utf16lechar *utf16le_str;
+       size_t utf16le_nbytes;
+
+       ret = mbs_to_utf16le_nbytes(mbs, mbs_nbytes,
+                                   &utf16le_nbytes);
+       if (ret)
                return ret;
 
-       ret = utf16_to_utf8_size((const u16*)utf16_str, utf16_nbytes / 2);
-       if (ret >= 0) {
-               size_t utf8_expected_nbytes;
-               char  *utf8_str;
-               size_t utf8_bytes_left;
-               size_t utf16_bytes_left;
-               size_t num_chars_converted;
-               char  *utf8_str_save;
-               const char *utf16_str_save;
-
-               utf8_expected_nbytes = ret;
-               utf8_str = MALLOC(utf8_expected_nbytes + 1);
-               if (utf8_str) {
-                       utf8_bytes_left = utf8_expected_nbytes;
-                       utf16_bytes_left = utf16_nbytes;
-                       utf8_str_save = utf8_str;
-                       utf16_str_save = utf16_str;
-                       num_chars_converted = iconv(cd_utf16_to_utf8,
-                                                   (char**)&utf16_str,
-                                                   &utf16_bytes_left,
-                                                   &utf8_str,
-                                                   &utf8_bytes_left);
-                       utf8_str = utf8_str_save;
-                       utf16_str = utf16_str_save;
-                       if (utf16_bytes_left == 0 &&
-                           utf8_bytes_left == 0 &&
-                           num_chars_converted != (size_t)(-1))
-                       {
-                               utf8_str[utf8_expected_nbytes] = '\0';
-                               *utf8_str_ret = utf8_str;
-                               *utf8_nbytes_ret = utf8_expected_nbytes;
-                               ret = 0;
-                       } else {
-                               FREE(utf8_str);
-                               ret = WIMLIB_ERR_INVALID_UTF16_STRING;
-                       }
-               } else
-                       ret = WIMLIB_ERR_NOMEM;
-       } else
-               ret = WIMLIB_ERR_INVALID_UTF16_STRING;
-#endif /* WITH_NTFS_3G */
-
-#ifdef ENABLE_ERROR_MESSAGES
-       if (ret != 0) {
-               ERROR_WITH_ERRNO("Error converting UTF-16LE string to UTF-8");
-               ERROR("The failing string was:");
-               print_string(utf16_str, utf16_nbytes);
-               putchar('\n');
+       utf16le_str = MALLOC(utf16le_nbytes + 1);
+       if (!utf16le_str)
+               return WIMLIB_ERR_NOMEM;
+
+       ret = mbs_to_utf16le_buf(mbs, mbs_nbytes, utf16le_str);
+       if (ret) {
+               FREE(utf16le_str);
+       } else {
+               *utf16le_ret = utf16le_str;
+               *utf16le_nbytes_ret = utf16le_nbytes;
        }
-#endif /* ENABLE_ERROR_MESSAGES */
        return ret;
 }
 
 
-/* Converts a string in the UTF-8 encoding to a newly allocated string in the
- * UTF-16 encoding.
- *
- * If available, do so by calling a similar function from libntfs-3g.
- * Otherwise, use iconv() along with the helper function utf8_to_utf16_size().
- */
-int utf8_to_utf16(const char *utf8_str, size_t utf8_nbytes,
-                 char **utf16_str_ret, size_t *utf16_nbytes_ret)
+int
+utf16le_to_mbs(const utf16lechar *utf16le_str, size_t utf16le_nbytes,
+              mbchar **mbs_ret, size_t *mbs_nbytes_ret)
 {
        int ret;
-       if (utf8_nbytes == 0) {
-               *utf16_str_ret = NULL;
-               *utf16_nbytes_ret = 0;
-               return 0;
-       }
-#ifdef WITH_NTFS_3G
-       char *outs = NULL;
-       int outs_nchars = ntfs_mbstoucs(utf8_str, (ntfschar**)&outs);
-       if (outs_nchars >= 0) {
-               *utf16_str_ret = outs;
-               *utf16_nbytes_ret = (size_t)outs_nchars * 2;
-               ret = 0;
-       } else {
-               if (errno == ENOMEM)
-                       ret = WIMLIB_ERR_NOMEM;
-               else
-                       ret = WIMLIB_ERR_INVALID_UTF8_STRING;
-       }
-#elif defined(__WIN32__)
+       mbchar *mbs;
+       size_t mbs_nbytes;
 
-       char *utf16_str;
-       size_t utf16_nchars;
-       utf16_nchars = mbstowcs(NULL, utf8_str, 0);
-       if (utf16_nchars == (size_t)(-1)) {
-               ret = WIMLIB_ERR_INVALID_UTF8_STRING;
-       } else {
-               utf16_str = MALLOC((utf16_nchars + 1) * sizeof(wchar_t));
-               if (!utf16_str) {
-                       ret = WIMLIB_ERR_NOMEM;
-               } else {
-                       mbstowcs((wchar_t*)utf16_str, utf8_str,
-                                utf16_nchars + 1);
-                       *utf16_str_ret = utf16_str;
-                       *utf16_nbytes_ret = utf16_nchars * sizeof(wchar_t);
-                       ret = 0;
-               }
-       }
-       
-#else
-       ret = iconv_global_init();
-       if (ret != 0)
+       ret = utf16le_to_mbs_nbytes(utf16le_str, utf16le_nbytes,
+                                   &mbs_nbytes);
+       if (ret)
                return ret;
-       ret = utf8_to_utf16_size(utf8_str);
-       if (ret >= 0) {
-               size_t utf16_expected_nbytes;
-               char  *utf16_str;
-               size_t utf16_bytes_left;
-               size_t utf8_bytes_left;
-               size_t num_chars_converted;
-               const char *utf8_str_save;
-               char  *utf16_str_save;
-
-               utf16_expected_nbytes = (size_t)ret * 2;
-               utf16_str = MALLOC(utf16_expected_nbytes + 2);
-               if (utf16_str) {
-                       utf16_bytes_left = utf16_expected_nbytes;
-                       utf8_bytes_left = utf8_nbytes;
-                       utf8_str_save = utf8_str;
-                       utf16_str_save = utf16_str;
-                       num_chars_converted = iconv(cd_utf8_to_utf16,
-                                                   (char**)&utf8_str,
-                                                   &utf8_bytes_left,
-                                                   &utf16_str,
-                                                   &utf16_bytes_left);
-                       utf8_str = utf8_str_save;
-                       utf16_str = utf16_str_save;
-                       if (utf16_bytes_left == 0 &&
-                           utf8_bytes_left == 0 &&
-                           num_chars_converted != (size_t)(-1))
-                       {
-                               utf16_str[utf16_expected_nbytes] = '\0';
-                               utf16_str[utf16_expected_nbytes + 1] = '\0';
-                               *utf16_str_ret = utf16_str;
-                               *utf16_nbytes_ret = utf16_expected_nbytes;
-                               ret = 0;
-                       } else {
-                               FREE(utf16_str);
-                               ret = WIMLIB_ERR_INVALID_UTF8_STRING;
-                       }
-               } else
-                       ret = WIMLIB_ERR_NOMEM;
-       } else
-               ret = WIMLIB_ERR_INVALID_UTF8_STRING;
-#endif /* WITH_NTFS_3G */
-
-#ifdef ENABLE_ERROR_MESSAGES
-       if (ret != 0) {
-               ERROR_WITH_ERRNO("Error converting UTF-8 string to UTF-16LE");
-               ERROR("The failing string was:");
-               print_string(utf8_str, utf8_nbytes);
-               putchar('\n');
-               ERROR("Length: %zu bytes", utf8_nbytes);
+
+       mbs = MALLOC(mbs_nbytes + 1);
+       if (!mbs)
+               return WIMLIB_ERR_NOMEM;
+
+       ret = utf16le_to_mbs_buf(utf16le_str, utf16le_nbytes, mbs);
+       if (ret) {
+               FREE(mbs);
+       } else {
+               *mbs_ret = mbs;
+               *mbs_nbytes_ret = mbs_nbytes;
        }
-#endif /* ENABLE_ERROR_MESSAGES */
        return ret;
 }
+
+bool
+utf8_str_contains_nonascii_chars(const utf8char *utf8_str)
+{
+       do {
+               if ((unsigned char)*utf8_str > 127)
+                       return false;
+       } while (*++utf8_str);
+       return true;
+}
index 19b87d4..199d20b 100644 (file)
 #endif
 
 #ifndef __WIN32__
-static int extract_regular_file_linked(struct wim_dentry *dentry,
-                                      const char *output_path,
-                                      struct apply_args *args,
-                                      struct wim_lookup_table_entry *lte)
+static int
+extract_regular_file_linked(struct wim_dentry *dentry,
+                           const mbchar *output_path,
+                           struct apply_args *args,
+                           struct wim_lookup_table_entry *lte)
 {
        /* This mode overrides the normal hard-link extraction and
         * instead either symlinks or hardlinks *all* identical files in
@@ -79,12 +80,12 @@ static int extract_regular_file_linked(struct wim_dentry *dentry,
                int num_path_components;
                int num_output_dir_path_components;
                size_t extracted_file_len;
-               char *p;
-               const char *p2;
+               mbchar *p;
+               const mbchar *p2;
                size_t i;
 
                num_path_components =
-                       get_num_path_components(dentry->full_path_utf8) - 1;
+                       get_num_path_components(dentry->full_path) - 1;
                num_output_dir_path_components =
                        get_num_path_components(args->target);
 
@@ -94,7 +95,7 @@ static int extract_regular_file_linked(struct wim_dentry *dentry,
                }
                extracted_file_len = strlen(lte->extracted_file);
 
-               char buf[extracted_file_len + 3 * num_path_components + 1];
+               mbchar buf[extracted_file_len + 3 * num_path_components + 1];
                p = &buf[0];
 
                for (i = 0; i < num_path_components; i++) {
@@ -109,8 +110,7 @@ static int extract_regular_file_linked(struct wim_dentry *dentry,
                        p2 = path_next_part(p2, NULL);
                strcpy(p, p2);
                if (symlink(buf, output_path) != 0) {
-                       ERROR_WITH_ERRNO("Failed to symlink `%s' to "
-                                        "`%s'",
+                       ERROR_WITH_ERRNO("Failed to symlink `%s' to `%s'",
                                         buf, lte->extracted_file);
                        return WIMLIB_ERR_LINK;
                }
@@ -118,8 +118,9 @@ static int extract_regular_file_linked(struct wim_dentry *dentry,
        return 0;
 }
 
-static int symlink_apply_unix_data(const char *link,
-                                  const struct wimlib_unix_data *unix_data)
+static int
+symlink_apply_unix_data(const mbchar *link,
+                       const struct wimlib_unix_data *unix_data)
 {
        if (lchown(link, unix_data->uid, unix_data->gid)) {
                if (errno == EPERM) {
@@ -133,7 +134,8 @@ static int symlink_apply_unix_data(const char *link,
        return 0;
 }
 
-static int fd_apply_unix_data(int fd, const struct wimlib_unix_data *unix_data)
+static int
+fd_apply_unix_data(int fd, const struct wimlib_unix_data *unix_data)
 {
        if (fchown(fd, unix_data->uid, unix_data->gid)) {
                if (errno == EPERM) {
@@ -157,8 +159,8 @@ static int fd_apply_unix_data(int fd, const struct wimlib_unix_data *unix_data)
        return 0;
 }
 
-static int dir_apply_unix_data(const char *dir,
-                              const struct wimlib_unix_data *unix_data)
+static int
+dir_apply_unix_data(const mbchar *dir, const struct wimlib_unix_data *unix_data)
 {
        int dfd = open(dir, O_RDONLY);
        int ret;
@@ -175,10 +177,11 @@ static int dir_apply_unix_data(const char *dir,
        return ret;
 }
 
-static int extract_regular_file_unlinked(struct wim_dentry *dentry,
-                                        struct apply_args *args,
-                                        const char *output_path,
-                                        struct wim_lookup_table_entry *lte)
+static int
+extract_regular_file_unlinked(struct wim_dentry *dentry,
+                             struct apply_args *args,
+                             const mbchar *output_path,
+                             struct wim_lookup_table_entry *lte)
 {
        /* Normal mode of extraction.  Regular files and hard links are
         * extracted in the way that they appear in the WIM. */
@@ -265,9 +268,10 @@ out:
        return ret;
 }
 
-static int extract_regular_file(struct wim_dentry *dentry,
-                               struct apply_args *args,
-                               const char *output_path)
+static int
+extract_regular_file(struct wim_dentry *dentry,
+                    struct apply_args *args,
+                    const mbchar *output_path)
 {
        struct wim_lookup_table_entry *lte;
        const struct wim_inode *inode = dentry->d_inode;
@@ -288,18 +292,19 @@ static int extract_regular_file(struct wim_dentry *dentry,
        return extract_regular_file_unlinked(dentry, args, output_path, lte);
 }
 
-static int extract_symlink(struct wim_dentry *dentry,
-                          struct apply_args *args,
-                          const char *output_path)
+static int
+extract_symlink(struct wim_dentry *dentry,
+               struct apply_args *args,
+               const mbchar *output_path)
 {
-       char target[4096];
+       mbchar target[4096];
        ssize_t ret = inode_readlink(dentry->d_inode, target,
                                     sizeof(target), args->w, 0);
        struct wim_lookup_table_entry *lte;
 
        if (ret <= 0) {
                ERROR("Could not read the symbolic link from dentry `%s'",
-                     dentry->full_path_utf8);
+                     dentry->full_path);
                return WIMLIB_ERR_INVALID_DENTRY;
        }
        ret = symlink(target, output_path);
@@ -328,8 +333,9 @@ static int extract_symlink(struct wim_dentry *dentry,
 
 #endif /* !__WIN32__ */
 
-static int extract_directory(struct wim_dentry *dentry,
-                            const char *output_path, bool is_root)
+static int
+extract_directory(struct wim_dentry *dentry,
+                 const mbchar *output_path, bool is_root)
 {
        int ret;
        struct stat stbuf;
@@ -350,10 +356,10 @@ static int extract_directory(struct wim_dentry *dentry,
                        return WIMLIB_ERR_STAT;
                }
        }
-       if (mkdir(output_path, S_IRWXU | S_IRGRP | S_IXGRP |
-                              S_IROTH | S_IXOTH) != 0) {
-               ERROR_WITH_ERRNO("Cannot create directory `%s'",
-                                output_path);
+
+       if (mkdir(output_path, S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH))
+       {
+               ERROR_WITH_ERRNO("Cannot create directory `%s'", output_path);
                return WIMLIB_ERR_MKDIR;
        }
 dir_exists:
@@ -374,7 +380,7 @@ dir_exists:
 }
 
 #ifndef __WIN32__
-static int unix_do_apply_dentry(const char *output_path,
+static int unix_do_apply_dentry(const mbchar *output_path,
                                size_t output_path_len,
                                struct wim_dentry *dentry,
                                struct apply_args *args)
@@ -391,10 +397,11 @@ static int unix_do_apply_dentry(const char *output_path,
                return extract_regular_file(dentry, args, output_path);
 }
 
-static int unix_do_apply_dentry_timestamps(const char *output_path,
-                                          size_t output_path_len,
-                                          const struct wim_dentry *dentry,
-                                          struct apply_args *args)
+static int
+unix_do_apply_dentry_timestamps(const mbchar *output_path,
+                               size_t output_path_len,
+                               const struct wim_dentry *dentry,
+                               struct apply_args *args)
 {
        int ret;
        const struct wim_inode *inode = dentry->d_inode;
@@ -452,21 +459,22 @@ static int unix_do_apply_dentry_timestamps(const char *output_path,
 #endif /* !__WIN32__ */
 
 /* Extracts a file, directory, or symbolic link from the WIM archive. */
-static int apply_dentry_normal(struct wim_dentry *dentry, void *arg)
+static int
+apply_dentry_normal(struct wim_dentry *dentry, void *arg)
 {
        struct apply_args *args = arg;
        size_t len;
-       char *output_path;
+       mbchar *output_path;
 
        len = strlen(args->target);
        if (dentry_is_root(dentry)) {
-               output_path = (char*)args->target;
+               output_path = (mbchar*)args->target;
        } else {
-               output_path = alloca(len + dentry->full_path_utf8_len + 1);
+               output_path = alloca(len + dentry->full_path_nbytes + 1);
                memcpy(output_path, args->target, len);
-               memcpy(output_path + len, dentry->full_path_utf8, dentry->full_path_utf8_len);
-               output_path[len + dentry->full_path_utf8_len] = '\0';
-               len += dentry->full_path_utf8_len;
+               memcpy(output_path + len, dentry->full_path, dentry->full_path_nbytes);
+               output_path[len + dentry->full_path_nbytes] = '\0';
+               len += dentry->full_path_nbytes;
        }
 #ifdef __WIN32__
        return win32_do_apply_dentry(output_path, len, dentry, args);
@@ -477,22 +485,24 @@ static int apply_dentry_normal(struct wim_dentry *dentry, void *arg)
 
 
 /* Apply timestamps to an extracted file or directory */
-static int apply_dentry_timestamps_normal(struct wim_dentry *dentry, void *arg)
+static int
+apply_dentry_timestamps_normal(struct wim_dentry *dentry, void *arg)
 {
        struct apply_args *args = arg;
        size_t len;
-       char *output_path;
+       mbchar *output_path;
 
        len = strlen(args->target);
        if (dentry_is_root(dentry)) {
-               output_path = (char*)args->target;
+               output_path = (mbchar*)args->target;
        } else {
-               output_path = alloca(len + dentry->full_path_utf8_len + 1);
+               output_path = alloca(len + dentry->full_path_nbytes + 1);
                memcpy(output_path, args->target, len);
-               memcpy(output_path + len, dentry->full_path_utf8, dentry->full_path_utf8_len);
-               output_path[len + dentry->full_path_utf8_len] = '\0';
-               len += dentry->full_path_utf8_len;
+               memcpy(output_path + len, dentry->full_path, dentry->full_path_nbytes);
+               output_path[len + dentry->full_path_nbytes] = '\0';
+               len += dentry->full_path_nbytes;
        }
+
 #ifdef __WIN32__
        return win32_do_apply_dentry_timestamps(output_path, len, dentry, args);
 #else
@@ -502,7 +512,8 @@ static int apply_dentry_timestamps_normal(struct wim_dentry *dentry, void *arg)
 
 /* Extract a dentry if it hasn't already been extracted, and either the dentry
  * has no streams or WIMLIB_EXTRACT_FLAG_NO_STREAMS is not specified. */
-static int maybe_apply_dentry(struct wim_dentry *dentry, void *arg)
+static int
+maybe_apply_dentry(struct wim_dentry *dentry, void *arg)
 {
        struct apply_args *args = arg;
        int ret;
@@ -516,7 +527,7 @@ static int maybe_apply_dentry(struct wim_dentry *dentry, void *arg)
 
        if ((args->extract_flags & WIMLIB_EXTRACT_FLAG_VERBOSE) &&
             args->progress_func) {
-               args->progress.extract.cur_path = dentry->full_path_utf8;
+               args->progress.extract.cur_path = dentry->full_path;
                args->progress_func(WIMLIB_PROGRESS_MSG_EXTRACT_DENTRY,
                                    &args->progress);
        }
@@ -526,7 +537,8 @@ static int maybe_apply_dentry(struct wim_dentry *dentry, void *arg)
        return ret;
 }
 
-static int cmp_streams_by_wim_position(const void *p1, const void *p2)
+static int
+cmp_streams_by_wim_position(const void *p1, const void *p2)
 {
        const struct wim_lookup_table_entry *lte1, *lte2;
        lte1 = *(const struct wim_lookup_table_entry**)p1;
@@ -539,7 +551,8 @@ static int cmp_streams_by_wim_position(const void *p1, const void *p2)
                return 0;
 }
 
-static int sort_stream_list_by_wim_position(struct list_head *stream_list)
+static int
+sort_stream_list_by_wim_position(struct list_head *stream_list)
 {
        struct list_head *cur;
        size_t num_streams;
@@ -572,9 +585,10 @@ static int sort_stream_list_by_wim_position(struct list_head *stream_list)
        return 0;
 }
 
-static void calculate_bytes_to_extract(struct list_head *stream_list,
-                                      int extract_flags,
-                                      union wimlib_progress_info *progress)
+static void
+calculate_bytes_to_extract(struct list_head *stream_list,
+                          int extract_flags,
+                          union wimlib_progress_info *progress)
 {
        struct wim_lookup_table_entry *lte;
        u64 total_bytes = 0;
@@ -603,8 +617,9 @@ static void calculate_bytes_to_extract(struct list_head *stream_list,
        progress->extract.completed_bytes = 0;
 }
 
-static void maybe_add_stream_for_extraction(struct wim_lookup_table_entry *lte,
-                                           struct list_head *stream_list)
+static void
+maybe_add_stream_for_extraction(struct wim_lookup_table_entry *lte,
+                               struct list_head *stream_list)
 {
        if (++lte->out_refcnt == 1) {
                INIT_LIST_HEAD(&lte->inode_list);
@@ -612,9 +627,10 @@ static void maybe_add_stream_for_extraction(struct wim_lookup_table_entry *lte,
        }
 }
 
-static void inode_find_streams_for_extraction(struct wim_inode *inode,
-                                             struct list_head *stream_list,
-                                             int extract_flags)
+static void
+inode_find_streams_for_extraction(struct wim_inode *inode,
+                                 struct list_head *stream_list,
+                                 int extract_flags)
 {
        struct wim_lookup_table_entry *lte;
        bool inode_added = false;
@@ -628,7 +644,7 @@ static void inode_find_streams_for_extraction(struct wim_inode *inode,
 #ifdef WITH_NTFS_3G
        if (extract_flags & WIMLIB_EXTRACT_FLAG_NTFS) {
                for (unsigned i = 0; i < inode->i_num_ads; i++) {
-                       if (inode->i_ads_entries[i].stream_name_len != 0) {
+                       if (inode->i_ads_entries[i].stream_name_nbytes != 0) {
                                lte = inode->i_ads_entries[i].lte;
                                if (lte) {
                                        maybe_add_stream_for_extraction(lte,
@@ -645,10 +661,11 @@ static void inode_find_streams_for_extraction(struct wim_inode *inode,
 #endif
 }
 
-static void find_streams_for_extraction(struct hlist_head *inode_list,
-                                       struct list_head *stream_list,
-                                       struct wim_lookup_table *lookup_table,
-                                       int extract_flags)
+static void
+find_streams_for_extraction(struct hlist_head *inode_list,
+                           struct list_head *stream_list,
+                           struct wim_lookup_table *lookup_table,
+                           int extract_flags)
 {
        struct wim_inode *inode;
        struct hlist_node *cur;
@@ -683,10 +700,11 @@ static const struct apply_operations ntfs_apply_operations = {
 };
 #endif
 
-static int apply_stream_list(struct list_head *stream_list,
-                            struct apply_args *args,
-                            const struct apply_operations *ops,
-                            wimlib_progress_func_t progress_func)
+static int
+apply_stream_list(struct list_head *stream_list,
+                 struct apply_args *args,
+                 const struct apply_operations *ops,
+                 wimlib_progress_func_t progress_func)
 {
        uint64_t bytes_per_progress = args->progress.extract.total_bytes / 100;
        uint64_t next_progress = bytes_per_progress;
@@ -738,9 +756,10 @@ static int apply_stream_list(struct list_head *stream_list,
 
 /* Extracts the image @image from the WIM @w to the directory or NTFS volume
  * @target. */
-static int extract_single_image(WIMStruct *w, int image,
-                               const char *target, int extract_flags,
-                               wimlib_progress_func_t progress_func)
+static int
+extract_single_image(WIMStruct *w, int image,
+                    const mbchar *target, int extract_flags,
+                    wimlib_progress_func_t progress_func)
 {
        int ret;
        struct list_head stream_list;
@@ -862,16 +881,17 @@ out:
 
 /* 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 char *target,
-                             int extract_flags,
-                             wimlib_progress_func_t progress_func)
+static int
+extract_all_images(WIMStruct *w, const mbchar *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);
-       char buf[output_path_len + 1 + image_name_max_len + 1];
+       mbchar buf[output_path_len + 1 + image_name_max_len + 1];
        int ret;
        int image;
-       const char *image_name;
+       const utf8char *image_name;
 
        ret = extract_directory(NULL, target, true);
        if (ret != 0)
@@ -881,10 +901,15 @@ static int extract_all_images(WIMStruct *w, const char *target,
        buf[output_path_len] = '/';
        for (image = 1; image <= w->hdr.image_count; image++) {
                image_name = wimlib_get_image_name(w, image);
-               if (image_name && *image_name) {
+               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);
                } else {
-                       /* Image name is empty. Use image number instead */
+                       /* 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);
                }
                ret = extract_single_image(w, image, buf, extract_flags,
index 45217fd..da91ac4 100644 (file)
@@ -72,12 +72,8 @@ struct wim_inode_table {
        struct hlist_head extra_inodes;
 };
 
-static inline void destroy_inode_table(struct wim_inode_table *table)
-{
-       FREE(table->array);
-}
-
-static int init_inode_table(struct wim_inode_table *table, size_t capacity)
+static int
+init_inode_table(struct wim_inode_table *table, size_t capacity)
 {
        table->array = CALLOC(capacity, sizeof(table->array[0]));
        if (!table->array) {
@@ -90,7 +86,14 @@ static int init_inode_table(struct wim_inode_table *table, size_t capacity)
        return 0;
 }
 
-static inline size_t inode_link_count(const struct wim_inode *inode)
+static inline void
+destroy_inode_table(struct wim_inode_table *table)
+{
+       FREE(table->array);
+}
+
+static inline size_t
+inode_link_count(const struct wim_inode *inode)
 {
        const struct list_head *cur;
        size_t size = 0;
@@ -102,9 +105,10 @@ static inline size_t inode_link_count(const struct wim_inode *inode)
 /* Insert a dentry into the inode table based on the inode number of the
  * attached inode (which came from the hard link group ID field of the on-disk
  * WIM dentry) */
-static int inode_table_insert(struct wim_dentry *dentry, void *__table)
+static int
+inode_table_insert(struct wim_dentry *dentry, void *_table)
 {
-       struct wim_inode_table *table = __table;
+       struct wim_inode_table *table = _table;
        struct wim_inode *d_inode = dentry->d_inode;
 
        if (d_inode->i_ino == 0) {
@@ -146,25 +150,30 @@ static int inode_table_insert(struct wim_dentry *dentry, void *__table)
        return 0;
 }
 
-static void print_inode_dentries(const struct wim_inode *inode)
+#ifdef ENABLE_ERROR_MESSAGES
+static void
+print_inode_dentries(const struct wim_inode *inode)
 {
        struct wim_dentry *dentry;
        inode_for_each_dentry(dentry, inode)
-               printf("`%s'\n", dentry->full_path_utf8);
+               printf("`%s'\n", dentry->full_path);
 }
+#endif
 
-static void inconsistent_inode(const struct wim_inode *inode)
+static void
+inconsistent_inode(const struct wim_inode *inode)
 {
+#ifdef ENABLE_ERROR_MESSAGES
        ERROR("An inconsistent hard link group that cannot be corrected has "
              "been detected");
        ERROR("The dentries are located at the following paths:");
-#ifdef ENABLE_ERROR_MESSAGES
        print_inode_dentries(inode);
 #endif
 }
 
-static bool ref_inodes_consistent(const struct wim_inode * restrict ref_inode_1,
-                                 const struct wim_inode * restrict ref_inode_2)
+static bool
+ref_inodes_consistent(const struct wim_inode * restrict ref_inode_1,
+                     const struct wim_inode * restrict ref_inode_2)
 {
        wimlib_assert(ref_inode_1 != ref_inode_2);
 
@@ -187,8 +196,9 @@ static bool ref_inodes_consistent(const struct wim_inode * restrict ref_inode_1,
        return true;
 }
 
-static bool inodes_consistent(const struct wim_inode * restrict ref_inode,
-                             const struct wim_inode * restrict inode)
+static bool
+inodes_consistent(const struct wim_inode * restrict ref_inode,
+                 const struct wim_inode * restrict inode)
 {
        wimlib_assert(ref_inode != inode);
 
@@ -212,7 +222,8 @@ static bool inodes_consistent(const struct wim_inode * restrict ref_inode,
 }
 
 /* Fix up a "true" inode and check for inconsistencies */
-static int fix_true_inode(struct wim_inode *inode, struct hlist_head *inode_list)
+static int
+fix_true_inode(struct wim_inode *inode, struct hlist_head *inode_list)
 {
        struct wim_dentry *dentry;
        struct wim_dentry *ref_dentry = NULL;
@@ -274,8 +285,8 @@ static int fix_true_inode(struct wim_inode *inode, struct hlist_head *inode_list
  * wim_inode's.  There will be just one `struct wim_inode' for each hard link
  * group remaining.
  */
-static int fix_nominal_inode(struct wim_inode *inode,
-                            struct hlist_head *inode_list)
+static int
+fix_nominal_inode(struct wim_inode *inode, struct hlist_head *inode_list)
 {
        struct wim_dentry *dentry;
        struct hlist_node *cur, *tmp;
@@ -393,8 +404,8 @@ next_dentry_2:
        return 0;
 }
 
-static int fix_inodes(struct wim_inode_table *table,
-                     struct hlist_head *inode_list)
+static int
+fix_inodes(struct wim_inode_table *table, struct hlist_head *inode_list)
 {
        struct wim_inode *inode;
        struct hlist_node *cur, *tmp;
@@ -440,7 +451,8 @@ static int fix_inodes(struct wim_inode_table *table,
  * failure.  On success, the list of "true" inodes, linked by the i_hlist field,
  * is returned in the hlist @inode_list.
  */
-int dentry_tree_fix_inodes(struct wim_dentry *root, struct hlist_head *inode_list)
+int
+dentry_tree_fix_inodes(struct wim_dentry *root, struct hlist_head *inode_list)
 {
        struct wim_inode_table inode_tab;
        int ret;
@@ -460,7 +472,8 @@ int dentry_tree_fix_inodes(struct wim_dentry *root, struct hlist_head *inode_lis
 
 /* Assign inode numbers to a list of inodes and return the next available
  * number. */
-u64 assign_inode_numbers(struct hlist_head *inode_list)
+u64
+assign_inode_numbers(struct hlist_head *inode_list)
 {
        DEBUG("Assigning inode numbers");
        struct wim_inode *inode;
index ab13e5e..d9301c2 100644 (file)
@@ -572,18 +572,20 @@ __lookup_resource(const struct wim_lookup_table *table, const u8 hash[])
  *
  * This is only for pre-resolved inodes.
  */
-int lookup_resource(WIMStruct *w, const char *path,
-                   int lookup_flags,
-                   struct wim_dentry **dentry_ret,
-                   struct wim_lookup_table_entry **lte_ret,
-                   u16 *stream_idx_ret)
+int
+lookup_resource(WIMStruct *w,
+               const mbchar *path,
+               int lookup_flags,
+               struct wim_dentry **dentry_ret,
+               struct wim_lookup_table_entry **lte_ret,
+               u16 *stream_idx_ret)
 {
        struct wim_dentry *dentry;
        struct wim_lookup_table_entry *lte;
        u16 stream_idx;
-       const char *stream_name = NULL;
+       const mbchar *stream_name = NULL;
        struct wim_inode *inode;
-       char *p = NULL;
+       mbchar *p = NULL;
 
        if (lookup_flags & LOOKUP_FLAG_ADS_OK) {
                stream_name = path_stream_name(path);
index ca41821..699e16e 100644 (file)
@@ -32,8 +32,8 @@ struct wim_lookup_table {
 
 #ifdef WITH_NTFS_3G
 struct ntfs_location {
-       char *path_utf8;
-       char *stream_name_utf16;
+       utf8char *path_utf8;
+       utf16lechar *stream_name_utf16;
        u16 stream_name_utf16_num_chars;
        struct _ntfs_volume **ntfs_vol_p;
        bool is_reparse_point;
@@ -150,15 +150,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.  */
-               char *extracted_file;
+               mbchar *extracted_file;
        };
 
        /* Pointers to somewhere where the stream is actually located.  See the
         * comments for the @resource_location field above. */
        union {
                WIMStruct *wim;
-               char *file_on_disk;
-               char *staging_file_name;
+               mbchar *file_on_disk;
+               mbchar *staging_file_name;
                u8 *attached_buffer;
        #ifdef WITH_NTFS_3G
                struct ntfs_location *ntfs_loc;
@@ -290,7 +290,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 char *path,
+lookup_resource(WIMStruct *w, const mbchar *path,
                int lookup_flags, struct wim_dentry **dentry_ret,
                struct wim_lookup_table_entry **lte_ret, u16 *stream_idx_ret);
 
@@ -398,13 +398,13 @@ inode_stream_hash(const struct wim_inode *inode, unsigned stream_idx)
 }
 
 static inline u16
-inode_stream_name_len(const struct wim_inode *inode, unsigned stream_idx)
+inode_stream_name_nbytes(const struct wim_inode *inode, unsigned stream_idx)
 {
        wimlib_assert(stream_idx <= inode->i_num_ads);
        if (stream_idx == 0)
                return 0;
        else
-               return inode->i_ads_entries[stream_idx - 1].stream_name_len;
+               return inode->i_ads_entries[stream_idx - 1].stream_name_nbytes;
 }
 
 static inline struct wim_lookup_table_entry *
@@ -412,7 +412,7 @@ inode_unnamed_lte_resolved(const struct wim_inode *inode)
 {
        wimlib_assert(inode->i_resolved);
        for (unsigned i = 0; i <= inode->i_num_ads; i++) {
-               if (inode_stream_name_len(inode, i) == 0 &&
+               if (inode_stream_name_nbytes(inode, i) == 0 &&
                    !is_zero_hash(inode_stream_hash_resolved(inode, i)))
                {
                        return inode_stream_lte_resolved(inode, i);
@@ -427,7 +427,7 @@ inode_unnamed_lte_unresolved(const struct wim_inode *inode,
 {
        wimlib_assert(!inode->i_resolved);
        for (unsigned i = 0; i <= inode->i_num_ads; i++) {
-               if (inode_stream_name_len(inode, i) == 0 &&
+               if (inode_stream_name_nbytes(inode, i) == 0 &&
                    !is_zero_hash(inode_stream_hash_unresolved(inode, i)))
                {
                        return inode_stream_lte_unresolved(inode, i, table);
index d968876..2f09ce7 100644 (file)
@@ -78,7 +78,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. */
-       char *staging_dir_name;
+       mbchar *staging_dir_name;
        size_t staging_dir_name_len;
 
        /* Flags passed to wimlib_mount(). */
@@ -106,8 +106,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 */
-       char *unmount_to_daemon_mq_name;
-       char *daemon_to_unmount_mq_name;
+       mbchar *unmount_to_daemon_mq_name;
+       mbchar *daemon_to_unmount_mq_name;
        mqd_t unmount_to_daemon_mq;
        mqd_t daemon_to_unmount_mq;
 
@@ -118,7 +118,8 @@ struct wimfs_context {
        bool have_status;
 };
 
-static void init_wimfs_context(struct wimfs_context *ctx)
+static void
+init_wimfs_context(struct wimfs_context *ctx)
 {
        memset(ctx, 0, sizeof(*ctx));
        ctx->unmount_to_daemon_mq = (mqd_t)-1;
@@ -128,28 +129,33 @@ static void init_wimfs_context(struct wimfs_context *ctx)
 
 #define WIMFS_CTX(fuse_ctx) ((struct wimfs_context*)(fuse_ctx)->private_data)
 
-static inline struct wimfs_context *wimfs_get_context()
+static inline struct wimfs_context *
+wimfs_get_context()
 {
        return WIMFS_CTX(fuse_get_context());
 }
 
-static inline WIMStruct *wimfs_get_WIMStruct()
+static inline WIMStruct *
+wimfs_get_WIMStruct()
 {
        return wimfs_get_context()->wim;
 }
 
-static inline bool wimfs_ctx_readonly(const struct wimfs_context *ctx)
+static inline bool
+wimfs_ctx_readonly(const struct wimfs_context *ctx)
 {
        return (ctx->mount_flags & WIMLIB_MOUNT_FLAG_READWRITE) == 0;
 }
 
-static inline int get_lookup_flags(const struct wimfs_context *ctx)
+static inline int
+get_lookup_flags(const struct wimfs_context *ctx)
 {
        return ctx->default_lookup_flags;
 }
 
 /* Returns nonzero if write permission is requested on the file open flags */
-static inline int flags_writable(int open_flags)
+static inline int
+flags_writable(int open_flags)
 {
        return open_flags & (O_RDWR | O_WRONLY);
 }
@@ -165,11 +171,12 @@ static inline int flags_writable(int open_flags)
  *
  * Return 0 iff successful or error code if unsuccessful.
  */
-static int alloc_wimfs_fd(struct wim_inode *inode,
-                         u32 stream_id,
-                         struct wim_lookup_table_entry *lte,
-                         struct wimfs_fd **fd_ret,
-                         bool readonly)
+static int
+alloc_wimfs_fd(struct wim_inode *inode,
+              u32 stream_id,
+              struct wim_lookup_table_entry *lte,
+              struct wimfs_fd **fd_ret,
+              bool readonly)
 {
        static const u16 fds_per_alloc = 8;
        static const u16 max_fds = 0xffff;
@@ -232,7 +239,8 @@ out:
        return ret;
 }
 
-static void inode_put_fd(struct wim_inode *inode, struct wimfs_fd *fd)
+static void
+inode_put_fd(struct wim_inode *inode, struct wimfs_fd *fd)
 {
        wimlib_assert(inode != NULL);
 
@@ -253,7 +261,8 @@ static void inode_put_fd(struct wim_inode *inode, struct wimfs_fd *fd)
        }
 }
 
-static int lte_put_fd(struct wim_lookup_table_entry *lte, struct wimfs_fd *fd)
+static int
+lte_put_fd(struct wim_lookup_table_entry *lte, struct wimfs_fd *fd)
 {
        wimlib_assert(fd->f_lte == lte);
 
@@ -275,7 +284,8 @@ static int lte_put_fd(struct wim_lookup_table_entry *lte, struct wimfs_fd *fd)
 }
 
 /* Close a file descriptor. */
-static int close_wimfs_fd(struct wimfs_fd *fd)
+static int
+close_wimfs_fd(struct wimfs_fd *fd)
 {
        int ret;
        DEBUG("Closing fd (ino = %#"PRIx64", opened = %u, allocated = %u)",
@@ -294,13 +304,13 @@ static int 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 char *path,
-                        mode_t mode, int attributes,
-                        struct wim_dentry **dentry_ret)
+static int
+create_dentry(struct fuse_context *fuse_ctx, const mbchar *path,
+             mode_t mode, int attributes, struct wim_dentry **dentry_ret)
 {
        struct wim_dentry *parent;
        struct wim_dentry *new;
-       const char *basename;
+       const mbchar *basename;
        struct wimfs_context *wimfs_ctx = WIMFS_CTX(fuse_ctx);
 
        parent = get_parent_dentry(wimfs_ctx->wim, path);
@@ -353,8 +363,9 @@ static int create_dentry(struct fuse_context *fuse_ctx,const char *path,
  * descriptors and no references remaining, it is freed, and the corresponding
  * staging file is unlinked.
  */
-static void remove_dentry(struct wim_dentry *dentry,
-                         struct wim_lookup_table *lookup_table)
+static void
+remove_dentry(struct wim_dentry *dentry,
+             struct wim_lookup_table *lookup_table)
 {
        struct wim_inode *inode = dentry->d_inode;
        struct wim_lookup_table_entry *lte;
@@ -369,7 +380,8 @@ static void remove_dentry(struct wim_dentry *dentry,
        put_dentry(dentry);
 }
 
-static mode_t inode_default_unix_mode(const struct wim_inode *inode)
+static mode_t
+inode_default_unix_mode(const struct wim_inode *inode)
 {
        if (inode_is_symlink(inode))
                return S_IFLNK | 0777;
@@ -384,9 +396,10 @@ static mode_t inode_default_unix_mode(const struct wim_inode *inode)
  * The lookup table entry tells us which stream in the inode we are statting.
  * For a named data stream, everything returned is the same as the unnamed data
  * stream except possibly the size and block count. */
-static int inode_to_stbuf(const struct wim_inode *inode,
-                         const struct wim_lookup_table_entry *lte,
-                         struct stat *stbuf)
+static int
+inode_to_stbuf(const struct wim_inode *inode,
+              const struct wim_lookup_table_entry *lte,
+              struct stat *stbuf)
 {
        const struct wimfs_context *ctx = wimfs_get_context();
 
@@ -433,7 +446,8 @@ static int inode_to_stbuf(const struct wim_inode *inode,
        return 0;
 }
 
-static void touch_inode(struct wim_inode *inode)
+static void
+touch_inode(struct wim_inode *inode)
 {
        u64 now = get_wim_timestamp();
        inode->i_last_access_time = now;
@@ -452,10 +466,11 @@ static void touch_inode(struct wim_inode *inode)
  * On success, returns the file descriptor for the staging file, opened for
  * writing.  On failure, returns -1 and sets errno.
  */
-static int create_staging_file(char **name_ret, struct wimfs_context *ctx)
+static int
+create_staging_file(mbchar **name_ret, struct wimfs_context *ctx)
 {
        size_t name_len;
-       char *name;
+       mbchar *name;
        struct stat stbuf;
        int fd;
        int errno_save;
@@ -519,11 +534,12 @@ static int create_staging_file(char **name_ret, struct wimfs_context *ctx)
  *
  * Returns 0 on success or a negative error code on failure.
  */
-static int extract_resource_to_staging_dir(struct wim_inode *inode,
-                                          u32 stream_id,
-                                          struct wim_lookup_table_entry **lte,
-                                          off_t size,
-                                          struct wimfs_context *ctx)
+static int
+extract_resource_to_staging_dir(struct wim_inode *inode,
+                               u32 stream_id,
+                               struct wim_lookup_table_entry **lte,
+                               off_t size,
+                               struct wimfs_context *ctx)
 {
        char *staging_file_name;
        int ret;
@@ -677,17 +693,18 @@ out_delete_staging_file:
  * Creates a randomly named staging directory and saves its name in the
  * filesystem context structure.
  */
-static int make_staging_dir(struct wimfs_context *ctx, const char *user_prefix)
+static int
+make_staging_dir(struct wimfs_context *ctx, const mbchar *user_prefix)
 {
        static const size_t random_suffix_len = 10;
-       static const char *common_suffix = ".staging";
+       static const mbchar *common_suffix = ".staging";
        static const size_t common_suffix_len = 8;
 
-       char *staging_dir_name = NULL;
+       mbchar *staging_dir_name = NULL;
        size_t staging_dir_name_len;
        size_t prefix_len;
-       const char *wim_basename;
-       char *real_user_prefix = NULL;
+       const mbchar *wim_basename;
+       mbchar *real_user_prefix = NULL;
        int ret;
 
        if (user_prefix) {
@@ -742,8 +759,9 @@ out:
        return ret;
 }
 
-static int remove_file_or_directory(const char *fpath, const struct stat *sb,
-                                   int typeflag, struct FTW *ftwbuf)
+static int
+remove_file_or_directory(const mbchar *fpath, const struct stat *sb,
+                        int typeflag, struct FTW *ftwbuf)
 {
        if (remove(fpath) == 0)
                return 0;
@@ -756,7 +774,8 @@ static int remove_file_or_directory(const char *fpath, const struct stat *sb,
 /*
  * Deletes the staging directory and all the files contained in it.
  */
-static int delete_staging_dir(struct wimfs_context *ctx)
+static int
+delete_staging_dir(struct wimfs_context *ctx)
 {
        int ret;
        ret = nftw(ctx->staging_dir_name, remove_file_or_directory,
@@ -766,9 +785,10 @@ static int delete_staging_dir(struct wimfs_context *ctx)
        return ret;
 }
 
-static void inode_update_lte_ptr(struct wim_inode *inode,
-                                struct wim_lookup_table_entry *old_lte,
-                                struct wim_lookup_table_entry *new_lte)
+static void
+inode_update_lte_ptr(struct wim_inode *inode,
+                    struct wim_lookup_table_entry *old_lte,
+                    struct wim_lookup_table_entry *new_lte)
 {
        if (inode->i_lte == old_lte) {
                inode->i_lte = new_lte;
@@ -782,8 +802,9 @@ static void inode_update_lte_ptr(struct wim_inode *inode,
        }
 }
 
-static int update_lte_of_staging_file(struct wim_lookup_table_entry *lte,
-                                     struct wim_lookup_table *table)
+static int
+update_lte_of_staging_file(struct wim_lookup_table_entry *lte,
+                          struct wim_lookup_table *table)
 {
        struct wim_lookup_table_entry *duplicate_lte;
        int ret;
@@ -822,7 +843,8 @@ static int update_lte_of_staging_file(struct wim_lookup_table_entry *lte,
        return 0;
 }
 
-static int inode_close_fds(struct wim_inode *inode)
+static int
+inode_close_fds(struct wim_inode *inode)
 {
        u16 num_opened_fds = inode->i_num_opened_fds;
        for (u16 i = 0, j = 0; j < num_opened_fds; i++) {
@@ -839,8 +861,9 @@ static int inode_close_fds(struct wim_inode *inode)
 }
 
 /* Overwrites the WIM file, with changes saved. */
-static int rebuild_wim(struct wimfs_context *ctx, int write_flags,
-                      wimlib_progress_func_t progress_func)
+static int
+rebuild_wim(struct wimfs_context *ctx, int write_flags,
+           wimlib_progress_func_t progress_func)
 {
        int ret;
        struct wim_lookup_table_entry *lte, *tmp;
@@ -867,10 +890,9 @@ static int rebuild_wim(struct wimfs_context *ctx, int write_flags,
        return ret;
 }
 
-
-
 /* Simple function that returns the concatenation of 2 strings. */
-static char *strcat_dup(const char *s1, const char *s2, size_t max_len)
+static char *
+strcat_dup(const char *s1, const char *s2, size_t max_len)
 {
        size_t len = strlen(s1) + strlen(s2);
        if (len > max_len)
@@ -882,13 +904,13 @@ static char *strcat_dup(const char *s1, const char *s2, size_t max_len)
        return p;
 }
 
-static int set_message_queue_names(struct wimfs_context *ctx,
-                                  const char *mount_dir)
+static int
+set_message_queue_names(struct wimfs_context *ctx, const mbchar *mount_dir)
 {
-       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;
+       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;
        int ret;
 
        dir_path = realpath(mount_dir, NULL);
@@ -927,7 +949,8 @@ out_free_dir_path:
        return ret;
 }
 
-static void free_message_queue_names(struct wimfs_context *ctx)
+static void
+free_message_queue_names(struct wimfs_context *ctx)
 {
        FREE(ctx->unmount_to_daemon_mq_name);
        FREE(ctx->daemon_to_unmount_mq_name);
@@ -944,7 +967,8 @@ static void free_message_queue_names(struct wimfs_context *ctx)
  * @daemon specifies whether the calling process is the filesystem daemon or the
  * unmount process.
  */
-static int open_message_queues(struct wimfs_context *ctx, bool daemon)
+static int
+open_message_queues(struct wimfs_context *ctx, bool daemon)
 {
        int unmount_to_daemon_mq_flags = O_WRONLY | O_CREAT;
        int daemon_to_unmount_mq_flags = O_RDONLY | O_CREAT;
@@ -991,7 +1015,8 @@ out:
 /* Try to determine the maximum message size of a message queue.  The return
  * value is the maximum message size, or a guess of 8192 bytes if it cannot be
  * determined. */
-static long mq_get_msgsize(mqd_t mq)
+static long
+mq_get_msgsize(mqd_t mq)
 {
        static const char *msgsize_max_file = "/proc/sys/fs/mqueue/msgsize_max";
        FILE *fp;
@@ -1020,8 +1045,9 @@ static long mq_get_msgsize(mqd_t mq)
        return msgsize;
 }
 
-static int get_mailbox(mqd_t mq, long needed_msgsize, long *msgsize_ret,
-                      void **mailbox_ret)
+static int
+get_mailbox(mqd_t mq, long needed_msgsize, long *msgsize_ret,
+           void **mailbox_ret)
 {
        long msgsize;
        char *mailbox;
@@ -1044,14 +1070,16 @@ static int get_mailbox(mqd_t mq, long needed_msgsize, long *msgsize_ret,
        return 0;
 }
 
-static void unlink_message_queues(struct wimfs_context *ctx)
+static void
+unlink_message_queues(struct wimfs_context *ctx)
 {
        mq_unlink(ctx->unmount_to_daemon_mq_name);
        mq_unlink(ctx->daemon_to_unmount_mq_name);
 }
 
 /* Closes the message queues, which are allocated in static variables */
-static void close_message_queues(struct wimfs_context *ctx)
+static void
+close_message_queues(struct wimfs_context *ctx)
 {
        DEBUG("Closing message queues");
        mq_close(ctx->unmount_to_daemon_mq);
@@ -1116,8 +1144,8 @@ struct daemon_msg_handler_context {
        struct wimfs_context *wimfs_ctx;
 };
 
-static int send_unmount_request_msg(mqd_t mq, int unmount_flags,
-                                   u8 want_progress_messages)
+static int
+send_unmount_request_msg(mqd_t mq, int unmount_flags, u8 want_progress_messages)
 {
        DEBUG("Sending unmount request msg");
        struct msg_unmount_request msg = {
@@ -1138,7 +1166,8 @@ static int send_unmount_request_msg(mqd_t mq, int unmount_flags,
        return 0;
 }
 
-static int send_daemon_info_msg(mqd_t mq, pid_t pid, int mount_flags)
+static int
+send_daemon_info_msg(mqd_t mq, pid_t pid, int mount_flags)
 {
        DEBUG("Sending daemon info msg (pid = %d, mount_flags=%x)",
              pid, mount_flags);
@@ -1160,7 +1189,8 @@ static int send_daemon_info_msg(mqd_t mq, pid_t pid, int mount_flags)
        return 0;
 }
 
-static void send_unmount_finished_msg(mqd_t mq, int status)
+static void
+send_unmount_finished_msg(mqd_t mq, int status)
 {
        DEBUG("Sending unmount finished msg");
        struct msg_unmount_finished msg = {
@@ -1176,8 +1206,9 @@ static void send_unmount_finished_msg(mqd_t mq, int status)
                ERROR_WITH_ERRNO("Failed to send status to unmount process");
 }
 
-static int unmount_progress_func(enum wimlib_progress_msg msg,
-                                const union wimlib_progress_info *info)
+static int
+unmount_progress_func(enum wimlib_progress_msg msg,
+                     const union wimlib_progress_info *info)
 {
        if (msg == WIMLIB_PROGRESS_MSG_WRITE_STREAMS) {
                struct msg_write_streams_progress msg = {
@@ -1199,7 +1230,8 @@ static int unmount_progress_func(enum wimlib_progress_msg msg,
        return 0;
 }
 
-static int msg_unmount_request_handler(const void *_msg, void *_handler_ctx)
+static int
+msg_unmount_request_handler(const void *_msg, void *_handler_ctx)
 {
        const struct msg_unmount_request *msg = _msg;
        struct daemon_msg_handler_context *handler_ctx = _handler_ctx;
@@ -1261,7 +1293,8 @@ out:
        return MSG_BREAK_LOOP;
 }
 
-static int msg_daemon_info_handler(const void *_msg, void *_handler_ctx)
+static int
+msg_daemon_info_handler(const void *_msg, void *_handler_ctx)
 {
        const struct msg_daemon_info *msg = _msg;
        struct unmount_msg_handler_context *handler_ctx = _handler_ctx;
@@ -1278,8 +1311,8 @@ static int msg_daemon_info_handler(const void *_msg, void *_handler_ctx)
        return 0;
 }
 
-static int msg_write_streams_progress_handler(const void *_msg,
-                                             void *_handler_ctx)
+static int
+msg_write_streams_progress_handler(const void *_msg, void *_handler_ctx)
 {
        const struct msg_write_streams_progress *msg = _msg;
        struct unmount_msg_handler_context *handler_ctx = _handler_ctx;
@@ -1293,7 +1326,8 @@ static int msg_write_streams_progress_handler(const void *_msg,
        return 0;
 }
 
-static int msg_unmount_finished_handler(const void *_msg, void *_handler_ctx)
+static int
+msg_unmount_finished_handler(const void *_msg, void *_handler_ctx)
 {
        const struct msg_unmount_finished *msg = _msg;
        struct unmount_msg_handler_context *handler_ctx = _handler_ctx;
@@ -1306,7 +1340,8 @@ static int msg_unmount_finished_handler(const void *_msg, void *_handler_ctx)
        return MSG_BREAK_LOOP;
 }
 
-static int unmount_timed_out_cb(void *_handler_ctx)
+static int
+unmount_timed_out_cb(void *_handler_ctx)
 {
        struct unmount_msg_handler_context *handler_ctx = _handler_ctx;
 
@@ -1329,7 +1364,8 @@ out_crashed:
        return WIMLIB_ERR_FILESYSTEM_DAEMON_CRASHED;
 }
 
-static int daemon_timed_out_cb(void *_handler_ctx)
+static int
+daemon_timed_out_cb(void *_handler_ctx)
 {
        ERROR("Timed out waiting for unmount request! "
              "Changes to the mounted WIM will not be committed.");
@@ -1359,10 +1395,11 @@ static const struct msg_handler_callbacks daemon_msg_handler_callbacks = {
        },
 };
 
-static int receive_message(mqd_t mq,
-                          struct msg_handler_context_hdr *handler_ctx,
-                          const msg_handler_t msg_handlers[],
-                          long mailbox_size, void *mailbox)
+static int
+receive_message(mqd_t mq,
+               struct msg_handler_context_hdr *handler_ctx,
+               const msg_handler_t msg_handlers[],
+               long mailbox_size, void *mailbox)
 {
        struct timeval now;
        struct timespec timeout;
@@ -1404,9 +1441,10 @@ static int receive_message(mqd_t mq,
        return ret;
 }
 
-static int message_loop(mqd_t mq,
-                       const struct msg_handler_callbacks *callbacks,
-                       struct msg_handler_context_hdr *handler_ctx)
+static int
+message_loop(mqd_t mq,
+            const struct msg_handler_callbacks *callbacks,
+            struct msg_handler_context_hdr *handler_ctx)
 {
        static const size_t MAX_MSG_SIZE = 512;
        long msgsize;
@@ -1454,7 +1492,8 @@ static int message_loop(mqd_t mq,
  *  not.  However, after that, the unmount process must wait for the filesystem
  *  daemon to finish writing the WIM file.
  */
-static int execute_fusermount(const char *dir)
+static int
+execute_fusermount(const mbchar *dir)
 {
        pid_t pid;
        int ret;
@@ -1531,7 +1570,8 @@ static int wimfs_access(const char *path, int mask)
 }
 #endif
 
-static int wimfs_chmod(const char *path, mode_t mask)
+static int
+wimfs_chmod(const mbchar *path, mode_t mask)
 {
        struct wim_dentry *dentry;
        struct wimfs_context *ctx = wimfs_get_context();
@@ -1551,7 +1591,8 @@ static int wimfs_chmod(const char *path, mode_t mask)
        return ret ? -ENOMEM : 0;
 }
 
-static int wimfs_chown(const char *path, uid_t uid, gid_t gid)
+static int
+wimfs_chown(const mbchar *path, uid_t uid, gid_t gid)
 {
        struct wim_dentry *dentry;
        struct wimfs_context *ctx = wimfs_get_context();
@@ -1573,7 +1614,8 @@ static int wimfs_chown(const char *path, uid_t uid, gid_t gid)
 }
 
 /* Called when the filesystem is unmounted. */
-static void wimfs_destroy(void *p)
+static void
+wimfs_destroy(void *p)
 {
        struct wimfs_context *wimfs_ctx = wimfs_get_context();
        if (open_message_queues(wimfs_ctx, true) == 0) {
@@ -1600,15 +1642,16 @@ static int wimfs_fallocate(const char *path, int mode,
 
 #endif
 
-static int wimfs_fgetattr(const char *path, struct stat *stbuf,
-                         struct fuse_file_info *fi)
+static int
+wimfs_fgetattr(const mbchar *path, struct stat *stbuf,
+              struct fuse_file_info *fi)
 {
        struct wimfs_fd *fd = (struct wimfs_fd*)(uintptr_t)fi->fh;
        return inode_to_stbuf(fd->f_inode, fd->f_lte, stbuf);
 }
 
-static int wimfs_ftruncate(const char *path, off_t size,
-                          struct fuse_file_info *fi)
+static int
+wimfs_ftruncate(const mbchar *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);
@@ -1622,7 +1665,8 @@ static int wimfs_ftruncate(const char *path, off_t size,
 /*
  * Fills in a `struct stat' that corresponds to a file or directory in the WIM.
  */
-static int wimfs_getattr(const char *path, struct stat *stbuf)
+static int
+wimfs_getattr(const mbchar *path, struct stat *stbuf)
 {
        struct wim_dentry *dentry;
        struct wim_lookup_table_entry *lte;
@@ -1639,8 +1683,9 @@ static int wimfs_getattr(const char *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 char *path, const char *name, char *value,
-                         size_t size)
+static int
+wimfs_getxattr(const mbchar *path, const mbchar *name, char *value,
+              size_t size)
 {
        int ret;
        struct wim_inode *inode;
@@ -1683,10 +1728,11 @@ static int wimfs_getxattr(const char *path, const char *name, char *value,
 #endif
 
 /* Create a hard link */
-static int wimfs_link(const char *to, const char *from)
+static int
+wimfs_link(const mbchar *to, const mbchar *from)
 {
        struct wim_dentry *from_dentry, *from_dentry_parent;
-       const char *link_name;
+       const mbchar *link_name;
        struct wim_inode *inode;
        struct wim_lookup_table_entry *lte;
        WIMStruct *w = wimfs_get_WIMStruct();
@@ -1727,13 +1773,15 @@ static int wimfs_link(const char *to, const char *from)
 }
 
 #ifdef ENABLE_XATTR
-static int wimfs_listxattr(const char *path, char *list, size_t size)
+static int
+wimfs_listxattr(const mbchar *path, mbchar *list, size_t size)
 {
        size_t needed_size;
        struct wim_inode *inode;
        struct wimfs_context *ctx = wimfs_get_context();
        u16 i;
-       char *p;
+       mbchar *p;
+       bool size_only = (size == 0);
 
        if (!(ctx->mount_flags & WIMLIB_MOUNT_FLAG_STREAM_INTERFACE_XATTR))
                return -ENOTSUP;
@@ -1744,38 +1792,53 @@ static int wimfs_listxattr(const char *path, char *list, size_t size)
        if (!inode)
                return -errno;
 
-       if (size == 0) {
-               needed_size = 0;
-               for (i = 0; i < inode->i_num_ads; i++)
-                       needed_size += inode->i_ads_entries[i].stream_name_utf8_len + 6;
-               return needed_size;
-       } else {
-               p = list;
-               for (i = 0; i < inode->i_num_ads; i++) {
-                       needed_size = inode->i_ads_entries[i].stream_name_utf8_len + 6;
-                       if (needed_size > size)
+       p = list;
+       for (i = 0; i < inode->i_num_ads; i++) {
+               mbchar *stream_name_mbs;
+               size_t stream_name_mbs_nbytes;
+               int ret;
+
+               ret = utf16le_to_mbs(inode->i_ads_entries[i].stream_name,
+                                    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;
+               }
+
+               needed_size = stream_name_mbs_nbytes + 6;
+               if (!size_only) {
+                       if (needed_size > size) {
+                               FREE(stream_name_mbs);
                                return -ERANGE;
-                       p += sprintf(p, "user.%s",
-                                    inode->i_ads_entries[i].stream_name_utf8) + 1;
+                       }
+                       sprintf(p, "user.%s", stream_name_mbs);
                        size -= needed_size;
                }
-               return p - list;
+               p += needed_size;
+               FREE(stream_name_mbs);
        }
+       return p - list;
 }
 #endif
 
 
 /* Create a directory in the WIM image. */
-static int wimfs_mkdir(const char *path, mode_t mode)
+static int
+wimfs_mkdir(const mbchar *path, mode_t mode)
 {
        return create_dentry(fuse_get_context(), path, mode | S_IFDIR,
                             FILE_ATTRIBUTE_DIRECTORY, NULL);
 }
 
 /* Create a regular file or alternate data stream in the WIM image. */
-static int wimfs_mknod(const char *path, mode_t mode, dev_t rdev)
+static int
+wimfs_mknod(const mbchar *path, mode_t mode, dev_t rdev)
 {
-       const char *stream_name;
+       const mbchar *stream_name;
        struct fuse_context *fuse_ctx = fuse_get_context();
        struct wimfs_context *wimfs_ctx = WIMFS_CTX(fuse_ctx);
 
@@ -1788,7 +1851,7 @@ static int wimfs_mknod(const char *path, mode_t mode, dev_t rdev)
                struct wim_ads_entry *new_entry;
                struct wim_inode *inode;
 
-               char *p = (char*)stream_name - 1;
+               mbchar *p = (mbchar*)stream_name - 1;
                wimlib_assert(*p == ':');
                *p = '\0';
 
@@ -1811,9 +1874,9 @@ static int wimfs_mknod(const char *path, mode_t mode, dev_t rdev)
        }
 }
 
-
 /* Open a file.  */
-static int wimfs_open(const char *path, struct fuse_file_info *fi)
+static int
+wimfs_open(const mbchar *path, struct fuse_file_info *fi)
 {
        struct wim_dentry *dentry;
        struct wim_lookup_table_entry *lte;
@@ -1870,7 +1933,8 @@ static int wimfs_open(const char *path, struct fuse_file_info *fi)
 }
 
 /* Opens a directory. */
-static int wimfs_opendir(const char *path, struct fuse_file_info *fi)
+static int
+wimfs_opendir(const mbchar *path, struct fuse_file_info *fi)
 {
        struct wim_inode *inode;
        int ret;
@@ -1892,8 +1956,9 @@ static int wimfs_opendir(const char *path, struct fuse_file_info *fi)
 /*
  * Read data from a file in the WIM or in the staging directory.
  */
-static int wimfs_read(const char *path, char *buf, size_t size,
-                     off_t offset, struct fuse_file_info *fi)
+static int
+wimfs_read(const mbchar *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;
        ssize_t ret;
@@ -1924,7 +1989,7 @@ static int wimfs_read(const char *path, char *buf, size_t size,
                if (offset > res_size)
                        return -EOVERFLOW;
                size = min(size, res_size - offset);
-               if (read_wim_resource(fd->f_lte, (u8*)buf,
+               if (read_wim_resource(fd->f_lte, buf,
                                      size, offset,
                                      WIMLIB_RESOURCE_FLAG_MULTITHREADED) != 0)
                        return -EIO;
@@ -1937,17 +2002,35 @@ struct fill_params {
        fuse_fill_dir_t filler;
 };
 
-static int dentry_fuse_fill(struct wim_dentry *dentry, void *arg)
+static int
+dentry_fuse_fill(struct wim_dentry *dentry, void *arg)
 {
        struct fill_params *fill_params = arg;
-       return fill_params->filler(fill_params->buf, dentry->file_name_utf8,
-                                  NULL, 0);
+
+       mbchar *file_name_mbs;
+       size_t file_name_mbs_nbytes;
+       int ret;
+
+       ret = utf16le_to_mbs(dentry->file_name,
+                            dentry->file_name_nbytes,
+                            &file_name_mbs,
+                            &file_name_mbs_nbytes);
+       if (ret) {
+               if (ret == WIMLIB_ERR_NOMEM)
+                       return -ENOMEM;
+               else
+                       return -EILSEQ;
+       }
+       ret = fill_params->filler(fill_params->buf, file_name_mbs, NULL, 0);
+       FREE(file_name_mbs);
+       return ret;
 }
 
 /* Fills in the entries of the directory specified by @path using the
  * FUSE-provided function @filler.  */
-static int wimfs_readdir(const char *path, void *buf, fuse_fill_dir_t filler,
-                        off_t offset, struct fuse_file_info *fi)
+static int
+wimfs_readdir(const mbchar *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;
        struct wim_inode *inode;
@@ -1970,7 +2053,8 @@ static int wimfs_readdir(const char *path, void *buf, fuse_fill_dir_t filler,
 }
 
 
-static int wimfs_readlink(const char *path, char *buf, size_t buf_len)
+static int
+wimfs_readlink(const mbchar *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);
@@ -1988,14 +2072,16 @@ static int wimfs_readlink(const char *path, char *buf, size_t buf_len)
 }
 
 /* Close a file. */
-static int wimfs_release(const char *path, struct fuse_file_info *fi)
+static int
+wimfs_release(const mbchar *path, struct fuse_file_info *fi)
 {
        struct wimfs_fd *fd = (struct wimfs_fd*)(uintptr_t)fi->fh;
        return close_wimfs_fd(fd);
 }
 
 /* Close a directory */
-static int wimfs_releasedir(const char *path, struct fuse_file_info *fi)
+static int
+wimfs_releasedir(const mbchar *path, struct fuse_file_info *fi)
 {
        struct wimfs_fd *fd = (struct wimfs_fd*)(uintptr_t)fi->fh;
        return close_wimfs_fd(fd);
@@ -2003,7 +2089,8 @@ static int wimfs_releasedir(const char *path, struct fuse_file_info *fi)
 
 #ifdef ENABLE_XATTR
 /* Remove an alternate data stream through the XATTR interface */
-static int wimfs_removexattr(const char *path, const char *name)
+static int
+wimfs_removexattr(const char *path, const mbchar *name)
 {
        struct wim_inode *inode;
        struct wim_ads_entry *ads_entry;
@@ -2030,7 +2117,8 @@ static int wimfs_removexattr(const char *path, const char *name)
 #endif
 
 /* Renames a file or directory.  See rename (3) */
-static int wimfs_rename(const char *from, const char *to)
+static int
+wimfs_rename(const mbchar *from, const mbchar *to)
 {
        struct wim_dentry *src;
        struct wim_dentry *dst;
@@ -2087,7 +2175,8 @@ static int wimfs_rename(const char *from, const char *to)
 }
 
 /* Remove a directory */
-static int wimfs_rmdir(const char *path)
+static int
+wimfs_rmdir(const mbchar *path)
 {
        struct wim_dentry *dentry;
        WIMStruct *w = wimfs_get_WIMStruct();
@@ -2108,8 +2197,9 @@ static int wimfs_rmdir(const char *path)
 
 #ifdef ENABLE_XATTR
 /* Write an alternate data stream through the XATTR interface */
-static int wimfs_setxattr(const char *path, const char *name,
-                         const char *value, size_t size, int flags)
+static int
+wimfs_setxattr(const mbchar *path, const mbchar *name,
+              const char *value, size_t size, int flags)
 {
        struct wim_ads_entry *existing_ads_entry;
        struct wim_inode *inode;
@@ -2137,7 +2227,7 @@ static int wimfs_setxattr(const char *path, const char *name,
                        return -ENOATTR;
        }
 
-       ret = inode_add_ads_with_data(inode, name, (const u8*)value,
+       ret = inode_add_ads_with_data(inode, name, value,
                                      size, ctx->wim->lookup_table);
        if (ret == 0) {
                if (existing_ads_entry)
@@ -2149,7 +2239,8 @@ static int wimfs_setxattr(const char *path, const char *name,
 }
 #endif
 
-static int wimfs_symlink(const char *to, const char *from)
+static int
+wimfs_symlink(const mbchar *to, const mbchar *from)
 {
        struct fuse_context *fuse_ctx = fuse_get_context();
        struct wimfs_context *wimfs_ctx = WIMFS_CTX(fuse_ctx);
@@ -2172,7 +2263,8 @@ static int wimfs_symlink(const char *to, const char *from)
 
 
 /* Reduce the size of a file */
-static int wimfs_truncate(const char *path, off_t size)
+static int
+wimfs_truncate(const mbchar *path, off_t size)
 {
        struct wim_dentry *dentry;
        struct wim_lookup_table_entry *lte;
@@ -2211,7 +2303,8 @@ static int wimfs_truncate(const char *path, off_t size)
 }
 
 /* Unlink a non-directory or alternate data stream */
-static int wimfs_unlink(const char *path)
+static int
+wimfs_unlink(const mbchar *path)
 {
        struct wim_dentry *dentry;
        struct wim_lookup_table_entry *lte;
@@ -2239,7 +2332,8 @@ static int wimfs_unlink(const char *path)
  *
  * Note that alternate data streams do not have their own timestamps.
  */
-static int wimfs_utimens(const char *path, const struct timespec tv[2])
+static int
+wimfs_utimens(const mbchar *path, const struct timespec tv[2])
 {
        struct wim_dentry *dentry;
        struct wim_inode *inode;
@@ -2264,8 +2358,9 @@ static int wimfs_utimens(const char *path, const struct timespec tv[2])
        }
        return 0;
 }
-#else
-static int wimfs_utime(const char *path, struct utimbuf *times)
+#else /* HAVE_UTIMENSAT */
+static int
+wimfs_utime(const mbchar *path, struct utimbuf *times)
 {
        struct wim_dentry *dentry;
        struct wim_inode *inode;
@@ -2280,13 +2375,14 @@ static int wimfs_utime(const char *path, struct utimbuf *times)
        inode->i_last_access_time = unix_timestamp_to_wim(times->actime);
        return 0;
 }
-#endif
+#endif /* !HAVE_UTIMENSAT */
 
 /* Writes to a file in the WIM filesystem.
  * 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 char *path, const char *buf, size_t size,
-                      off_t offset, struct fuse_file_info *fi)
+static int
+wimfs_write(const mbchar *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;
        int ret;
@@ -2375,15 +2471,16 @@ static struct fuse_operations wimfs_operations = {
 
 
 /* Mounts an image from a WIM file. */
-WIMLIBAPI int wimlib_mount_image(WIMStruct *wim, int image, const char *dir,
-                                int mount_flags, WIMStruct **additional_swms,
-                                unsigned num_additional_swms,
-                                const char *staging_dir)
+WIMLIBAPI int
+wimlib_mount_image(WIMStruct *wim, int image, const mbchar *dir,
+                  int mount_flags, WIMStruct **additional_swms,
+                  unsigned num_additional_swms,
+                  const mbchar *staging_dir)
 {
        int argc;
        char *argv[16];
        int ret;
-       char *dir_copy;
+       mbchar *dir_copy;
        struct wim_lookup_table *joined_tab, *wim_tab_save;
        struct wim_image_metadata *imd;
        struct wimfs_context ctx;
@@ -2589,8 +2686,9 @@ out:
  * Unmounts the WIM file that was previously mounted on @dir by using
  * wimlib_mount_image().
  */
-WIMLIBAPI int wimlib_unmount_image(const char *dir, int unmount_flags,
-                                  wimlib_progress_func_t progress_func)
+WIMLIBAPI int
+wimlib_unmount_image(const mbchar *dir, int unmount_flags,
+                    wimlib_progress_func_t progress_func)
 {
        int ret;
        struct wimfs_context wimfs_ctx;
@@ -2639,7 +2737,8 @@ out:
 #else /* WITH_FUSE */
 
 
-static inline int mount_unsupported_error()
+static int
+mount_unsupported_error()
 {
 #if defined(__WIN32__)
        ERROR("Sorry-- Mounting WIM images is not supported on Windows!");
@@ -2650,18 +2749,20 @@ static inline int mount_unsupported_error()
        return WIMLIB_ERR_UNSUPPORTED;
 }
 
-WIMLIBAPI int wimlib_unmount_image(const char *dir, int unmount_flags,
-                                  wimlib_progress_func_t progress_func)
+WIMLIBAPI int
+wimlib_unmount_image(const mbchar *dir, int unmount_flags,
+                    wimlib_progress_func_t progress_func)
 {
        return mount_unsupported_error();
 }
 
-WIMLIBAPI int wimlib_mount_image(WIMStruct *wim_p, int image, const char *dir,
-                                int mount_flags, WIMStruct **additional_swms,
-                                unsigned num_additional_swms,
-                                const char *staging_dir)
+WIMLIBAPI int
+wimlib_mount_image(WIMStruct *wim, int image, const mbchar *dir,
+                  int mount_flags, WIMStruct **additional_swms,
+                  unsigned num_additional_swms,
+                  const mbchar *staging_dir)
 {
        return mount_unsupported_error();
 }
 
-#endif /* WITH_FUSE */
+#endif /* !WITH_FUSE */
index db9c635..0bffb3a 100644 (file)
  *
  * Returns zero on success, nonzero on failure.
  */
-static int read_compressed_resource(FILE *fp, u64 resource_compressed_size,
-                                   u64 resource_uncompressed_size,
-                                   u64 resource_offset, int resource_ctype,
-                                   u64 len, u64 offset, u8  contents_ret[])
+static int
+read_compressed_resource(FILE *fp, u64 resource_compressed_size,
+                        u64 resource_uncompressed_size,
+                        u64 resource_offset, int resource_ctype,
+                        u64 len, u64 offset, void *contents_ret)
 {
 
        DEBUG2("comp size = %"PRIu64", uncomp size = %"PRIu64", "
@@ -211,7 +212,7 @@ static int read_compressed_resource(FILE *fp, u64 resource_compressed_size,
 
        /* Pointer to current position in the output buffer for uncompressed
         * data. */
-       u8 *out_p = (u8*)contents_ret;
+       u8 *out_p = contents_ret;
 
        /* Buffer for compressed data.  While most compressed chunks will have a
         * size much less than WIM_CHUNK_SIZE, WIM_CHUNK_SIZE - 1 is the maximum
@@ -353,8 +354,8 @@ err:
 /*
  * Reads uncompressed data from an open file stream.
  */
-int read_uncompressed_resource(FILE *fp, u64 offset, u64 len,
-                              u8 contents_ret[])
+int
+read_uncompressed_resource(FILE *fp, u64 offset, u64 len, void *contents_ret)
 {
        if (fseeko(fp, offset, SEEK_SET) != 0) {
                ERROR("Failed to seek to byte %"PRIu64" of input file "
@@ -378,7 +379,8 @@ int read_uncompressed_resource(FILE *fp, u64 offset, u64 len,
 /* Reads the contents of a struct resource_entry, as represented in the on-disk
  * format, from the memory pointed to by @p, and fills in the fields of @entry.
  * A pointer to the byte after the memory read at @p is returned. */
-const u8 *get_resource_entry(const u8 *p, struct resource_entry *entry)
+const u8 *
+get_resource_entry(const u8 *p, struct resource_entry *entry)
 {
        u64 size;
        u8 flags;
@@ -408,7 +410,8 @@ const u8 *get_resource_entry(const u8 *p, struct resource_entry *entry)
 /* Copies the struct resource_entry @entry to the memory pointed to by @p in the
  * on-disk format.  A pointer to the byte after the memory written at @p is
  * returned. */
-u8 *put_resource_entry(u8 *p, const struct resource_entry *entry)
+u8 *
+put_resource_entry(u8 *p, const struct resource_entry *entry)
 {
        p = put_u56(p, entry->size);
        p = put_u8(p, entry->flags);
@@ -418,7 +421,8 @@ u8 *put_resource_entry(u8 *p, const struct resource_entry *entry)
 }
 
 #ifdef WITH_FUSE
-static FILE *wim_get_fp(WIMStruct *w)
+static FILE *
+wim_get_fp(WIMStruct *w)
 {
        pthread_mutex_lock(&w->fp_tab_mutex);
        FILE *fp;
@@ -441,7 +445,8 @@ out:
        return fp;
 }
 
-static int wim_release_fp(WIMStruct *w, FILE *fp)
+static int
+wim_release_fp(WIMStruct *w, FILE *fp)
 {
        int ret = 0;
        FILE **fp_tab;
@@ -468,7 +473,7 @@ out:
        pthread_mutex_unlock(&w->fp_tab_mutex);
        return ret;
 }
-#endif
+#endif /* !WITH_FUSE */
 
 /*
  * Reads some data from the resource corresponding to a WIM lookup table entry.
@@ -480,8 +485,9 @@ out:
  *
  * Returns zero on success, nonzero on failure.
  */
-int read_wim_resource(const struct wim_lookup_table_entry *lte, u8 buf[],
-                     size_t size, u64 offset, int flags)
+int
+read_wim_resource(const struct wim_lookup_table_entry *lte, void *buf,
+                 size_t size, u64 offset, int flags)
 {
        int ctype;
        int ret = 0;
@@ -607,8 +613,9 @@ int read_wim_resource(const struct wim_lookup_table_entry *lte, u8 buf[],
  *
  * Returns 0 on success; nonzero on failure.
  */
-int read_full_wim_resource(const struct wim_lookup_table_entry *lte, u8 buf[],
-                          int flags)
+int
+read_full_wim_resource(const struct wim_lookup_table_entry *lte,
+                      void *buf, int flags)
 {
        return read_wim_resource(lte, buf, wim_resource_size(lte), 0, flags);
 }
@@ -619,10 +626,11 @@ int read_full_wim_resource(const struct wim_lookup_table_entry *lte, u8 buf[],
  *
  * @extract_chunk is a function that is called to extract each chunk of the
  * resource. */
-int extract_wim_resource(const struct wim_lookup_table_entry *lte,
-                        u64 size,
-                        extract_chunk_func_t extract_chunk,
-                        void *extract_chunk_arg)
+int
+extract_wim_resource(const struct wim_lookup_table_entry *lte,
+                    u64 size,
+                    extract_chunk_func_t extract_chunk,
+                    void *extract_chunk_arg)
 {
        u64 bytes_remaining = size;
        u8 buf[min(WIM_CHUNK_SIZE, bytes_remaining)];
@@ -667,9 +675,10 @@ int extract_wim_resource(const struct wim_lookup_table_entry *lte,
  * and on short writes.
  *
  * Returns short count and set errno on failure. */
-static ssize_t full_write(int fd, const void *buf, size_t n)
+static ssize_t
+full_write(int fd, const void *buf, size_t n)
 {
-       const char *p = buf;
+       const void *p = buf;
        ssize_t ret;
        ssize_t total = 0;
 
@@ -687,7 +696,8 @@ static ssize_t full_write(int fd, const void *buf, size_t n)
        return total;
 }
 
-int extract_wim_chunk_to_fd(const u8 *buf, size_t len, u64 offset, void *arg)
+int
+extract_wim_chunk_to_fd(const void *buf, size_t len, u64 offset, void *arg)
 {
        int fd = *(int*)arg;
        ssize_t ret = full_write(fd, buf, len);
@@ -709,7 +719,8 @@ int extract_wim_chunk_to_fd(const u8 *buf, size_t len, u64 offset, void *arg)
  *
  * (This function is confusing and should be refactored somehow.)
  */
-int copy_resource(struct wim_lookup_table_entry *lte, void *wim)
+int
+copy_resource(struct wim_lookup_table_entry *lte, void *wim)
 {
        WIMStruct *w = wim;
        int ret;
index 2e60aa5..ae71c5d 100644 (file)
@@ -255,7 +255,8 @@ typedef struct {
  * entries anyway; however this ensures that that the security descriptors pass
  * the validation in libntfs-3g.
  */
-static void empty_sacl_fixup(u8 *descr, u64 *size_p)
+static void
+empty_sacl_fixup(u8 *descr, u64 *size_p)
 {
        if (*size_p >= sizeof(SecurityDescriptor)) {
                SecurityDescriptor *sd = (SecurityDescriptor*)descr;
@@ -281,8 +282,9 @@ static void empty_sacl_fixup(u8 *descr, u64 *size_p)
  * Note: There is no `offset' argument because the security data is located at
  * the beginning of the metadata resource.
  */
-int read_security_data(const u8 metadata_resource[], u64 metadata_resource_len,
-                      struct wim_security_data **sd_p)
+int
+read_security_data(const u8 metadata_resource[], u64 metadata_resource_len,
+                  struct wim_security_data **sd_p)
 {
        struct wim_security_data *sd;
        const u8 *p;
@@ -431,7 +433,8 @@ out_free_sd:
 /*
  * Writes security data to an in-memory buffer.
  */
-u8 *write_security_data(const struct wim_security_data *sd, u8 *p)
+u8 *
+write_security_data(const struct wim_security_data *sd, u8 *p)
 {
        DEBUG("Writing security data (total_length = %"PRIu32", num_entries "
              "= %"PRIu32")", sd->total_length, sd->num_entries);
@@ -455,7 +458,8 @@ u8 *write_security_data(const struct wim_security_data *sd, u8 *p)
        return p;
 }
 
-static void print_acl(const u8 *p, const char *type)
+static void
+print_acl(const u8 *p, const char *type)
 {
        const ACL *acl = (const ACL*)p;
        u8 revision = acl->revision;
@@ -481,7 +485,8 @@ static void print_acl(const u8 *p, const char *type)
        putchar('\n');
 }
 
-static void print_sid(const u8 *p, const char *type)
+static void
+print_sid(const u8 *p, const char *type)
 {
        const SID *sid = (const SID*)p;
        printf("    [%s SID]\n", type);
@@ -497,7 +502,8 @@ static void print_sid(const u8 *p, const char *type)
        putchar('\n');
 }
 
-static void print_security_descriptor(const u8 *p, u64 size)
+static void
+print_security_descriptor(const u8 *p, u64 size)
 {
        const SecurityDescriptor *sd = (const SecurityDescriptor*)p;
        u8 revision      = sd->revision;
@@ -526,7 +532,8 @@ static void print_security_descriptor(const u8 *p, u64 size)
 /*
  * Prints the security data for a WIM file.
  */
-void print_security_data(const struct wim_security_data *sd)
+void
+print_security_data(const struct wim_security_data *sd)
 {
        wimlib_assert(sd != NULL);
 
@@ -543,7 +550,8 @@ void print_security_data(const struct wim_security_data *sd)
        putchar('\n');
 }
 
-void free_security_data(struct wim_security_data *sd)
+void
+free_security_data(struct wim_security_data *sd)
 {
        if (sd) {
                wimlib_assert(sd->refcnt != 0);
@@ -569,7 +577,8 @@ struct sd_node {
        struct rb_node rb_node;
 };
 
-static void free_sd_tree(struct rb_node *node)
+static void
+free_sd_tree(struct rb_node *node)
 {
        if (node) {
                free_sd_tree(node->rb_left);
@@ -579,13 +588,15 @@ static void free_sd_tree(struct rb_node *node)
 }
 
 /* Frees a security descriptor index set. */
-void destroy_sd_set(struct sd_set *sd_set)
+void
+destroy_sd_set(struct sd_set *sd_set)
 {
        free_sd_tree(sd_set->rb_root.rb_node);
 }
 
 /* Inserts a a new node into the security descriptor index tree. */
-static void insert_sd_node(struct sd_set *set, struct sd_node *new)
+static void
+insert_sd_node(struct sd_set *set, struct sd_node *new)
 {
        struct rb_root *root = &set->rb_root;
        struct rb_node **p = &(root->rb_node);
@@ -609,7 +620,8 @@ static void insert_sd_node(struct sd_set *set, struct sd_node *new)
 
 /* Returns the index of the security descriptor having a SHA1 message digest of
  * @hash.  If not found, return -1. */
-int lookup_sd(struct sd_set *set, const u8 hash[SHA1_HASH_SIZE])
+int
+lookup_sd(struct sd_set *set, const u8 hash[SHA1_HASH_SIZE])
 {
        struct rb_node *node = set->rb_root.rb_node;
 
@@ -633,8 +645,8 @@ int lookup_sd(struct sd_set *set, const u8 hash[SHA1_HASH_SIZE])
  * the security ID for it.  If a new security descriptor cannot be allocated,
  * return -1.
  */
-int sd_set_add_sd(struct sd_set *sd_set, const char descriptor[],
-                 size_t size)
+int
+sd_set_add_sd(struct sd_set *sd_set, const char descriptor[], size_t size)
 {
        u8 hash[SHA1_HASH_SIZE];
        int security_id;
index 5fb506e..ca1ad0e 100644 (file)
@@ -224,7 +224,8 @@ static int 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 char *filename, u8 md[SHA1_HASH_SIZE])
+int
+sha1sum(const mbchar *filename, u8 md[SHA1_HASH_SIZE])
 {
        FILE *fp;
        int ret;
index 8573c54..5238a92 100644 (file)
 
 extern const u8 zero_hash[SHA1_HASH_SIZE];
 
-static inline void copy_hash(u8 dest[SHA1_HASH_SIZE],
-                            const u8 src[SHA1_HASH_SIZE])
+static inline void
+copy_hash(u8 dest[SHA1_HASH_SIZE], const u8 src[SHA1_HASH_SIZE])
 {
        memcpy(dest, src, SHA1_HASH_SIZE);
 }
 
-static inline void random_hash(u8 hash[SHA1_HASH_SIZE])
+static inline void
+random_hash(u8 hash[SHA1_HASH_SIZE])
 {
        randomize_byte_array(hash, SHA1_HASH_SIZE);
 }
 
-static inline bool hashes_equal(const u8 h1[SHA1_HASH_SIZE],
-                               const u8 h2[SHA1_HASH_SIZE])
+static inline bool
+hashes_equal(const u8 h1[SHA1_HASH_SIZE], const u8 h2[SHA1_HASH_SIZE])
 {
        return memcmp(h1, h2, SHA1_HASH_SIZE) == 0;
 }
-static inline int hashes_cmp(const u8 h1[SHA1_HASH_SIZE],
+
+static inline int
+hashes_cmp(const u8 h1[SHA1_HASH_SIZE],
                             const u8 h2[SHA1_HASH_SIZE])
 {
        return memcmp(h1, h2, SHA1_HASH_SIZE);
 }
 
-/* Prints a hash code field. */
-static inline void print_hash(const u8 hash[SHA1_HASH_SIZE])
+static inline void
+print_hash(const u8 hash[SHA1_HASH_SIZE])
 {
        print_byte_field(hash, SHA1_HASH_SIZE);
 }
 
-static inline bool is_zero_hash(const u8 hash[SHA1_HASH_SIZE])
+static inline bool
+is_zero_hash(const u8 hash[SHA1_HASH_SIZE])
 {
        if (hash)
                for (u8 i = 0; i < SHA1_HASH_SIZE / 4; i++)
@@ -48,7 +52,8 @@ static inline bool is_zero_hash(const u8 hash[SHA1_HASH_SIZE])
        return true;
 }
 
-static inline void zero_out_hash(u8 hash[SHA1_HASH_SIZE])
+static inline void
+zero_out_hash(u8 hash[SHA1_HASH_SIZE])
 {
        memset(hash, 0, SHA1_HASH_SIZE);
 }
@@ -65,20 +70,26 @@ static inline void zero_out_hash(u8 hash[SHA1_HASH_SIZE])
 #else /* WITH_LIBCRYPTO */
 
 typedef struct {
-    u32 state[5];
-    u32 count[2];
-    u8  buffer[64];
+       u32 state[5];
+       u32 count[2];
+       u8 buffer[64];
 } SHA_CTX;
 
-extern void sha1_buffer(const u8 buffer[], size_t len, u8 hash[SHA1_HASH_SIZE]);
-extern void sha1_init(SHA_CTX *ctx);
-extern void sha1_update(SHA_CTX *ctx, const u8 data[], size_t len);
-extern void sha1_final(u8 hash[SHA1_HASH_SIZE], SHA_CTX *ctx);
+extern void
+sha1_buffer(const u8 buffer[], size_t len, u8 hash[SHA1_HASH_SIZE]);
 
-#endif /* !WITH_LIBCRYPTO */
+extern void
+sha1_init(SHA_CTX *ctx);
 
-extern int sha1sum(const char *filename, u8 hash[SHA1_HASH_SIZE]);
+extern void
+sha1_update(SHA_CTX *ctx, const u8 data[], size_t len);
 
+extern void
+sha1_final(u8 hash[SHA1_HASH_SIZE], SHA_CTX *ctx);
+
+#endif /* !WITH_LIBCRYPTO */
 
+extern int
+sha1sum(const mbchar *filename, u8 hash[SHA1_HASH_SIZE]);
 
 #endif /* _WIMLIB_SHA1_H */
index f6a66c2..5c8417c 100644 (file)
  * dentry, and we already know the reparse tag length from the lookup table
  * entry resource length.
  */
-static ssize_t get_symlink_name(const u8 *resource, size_t resource_len,
-                               char *buf, size_t buf_len,
-                               u32 reparse_tag)
+static ssize_t
+get_symlink_name(const void *resource, size_t resource_len,
+                void *buf, size_t buf_len,
+                u32 reparse_tag)
 {
        const u8 *p = resource;
        u16 substitute_name_offset;
@@ -128,8 +129,9 @@ out:
        return ret;
 }
 
-static int make_symlink_reparse_data_buf(const char *symlink_target,
-                                        size_t *len_ret, void **buf_ret)
+static int
+make_symlink_reparse_data_buf(const mbchar *symlink_target,
+                             size_t *len_ret, void **buf_ret)
 {
        size_t utf8_len = strlen(symlink_target);
        char *name_utf16;
@@ -171,8 +173,9 @@ static int make_symlink_reparse_data_buf(const char *symlink_target,
  * WIM_IO_REPARSE_TAG_SYMLINK), or it may be a junction point (reparse tag
  * WIM_IO_REPARSE_TAG_MOUNT_POINT).
  */
-ssize_t inode_readlink(const struct wim_inode *inode, char *buf, size_t buf_len,
-                      const WIMStruct *w, int read_resource_flags)
+ssize_t
+inode_readlink(const struct wim_inode *inode, mbchar *buf, size_t buf_len,
+              const WIMStruct *w, int read_resource_flags)
 {
        const struct wim_lookup_table_entry *lte;
        int ret;
@@ -205,9 +208,11 @@ ssize_t inode_readlink(const struct wim_inode *inode, char *buf, size_t buf_len,
  *
  * On failure @dentry and @lookup_table are not modified.
  */
-int inode_set_symlink(struct wim_inode *inode, const char *target,
-                     struct wim_lookup_table *lookup_table,
-                     struct wim_lookup_table_entry **lte_ret)
+int
+inode_set_symlink(struct wim_inode *inode,
+                 const mbchar *target,
+                 struct wim_lookup_table *lookup_table,
+                 struct wim_lookup_table_entry **lte_ret)
 
 {
        int ret;
index df813bb..626fba4 100644 (file)
@@ -39,6 +39,7 @@
 #include <ctype.h>
 #include <errno.h>
 #include <stdlib.h>
+#include <stdarg.h>
 
 #include <unistd.h> /* for getpid() */
 
 #  define strerror_r(errnum, buf, bufsize) strerror_s(buf, bufsize, errnum)
 #endif
 
+static size_t utf16le_strlen(const utf16lechar *s)
+{
+       const utf16lechar *p = s;
+       while (p)
+               p++;
+       return (p - s) / sizeof(utf16lechar);
+}
+
+/* Handle %W for UTF16-LE printing and %U for UTF-8 printing.
+ *
+ * WARNING: this is not yet done properly--- it's assumed that if the format
+ * string contains %W and/or %U, then it contains no other format specifiers.
+ */
+static int
+wimlib_vfprintf(FILE *fp, const char *format, va_list va)
+{
+       const char *p;
+
+       for (p = format; *p; p++)
+               if (*p == '%' && ((*p + 1) == 'W' || *(p + 1) == 'U'))
+                       goto special;
+       return vfprintf(fp, format, va);
+special:
+       ;
+       int n = 0;
+       for (p = format; *p; p++) {
+               if (*p == '%' && ((*p + 1) == 'W' || *(p + 1) == 'U')) {
+                       int ret;
+                       mbchar *mbs;
+                       size_t mbs_len;
+
+                       if (*(p + 1) == 'W') {
+                               utf16lechar *ucs = va_arg(va, utf16lechar*);
+                               size_t ucs_nbytes = utf16le_strlen(ucs);
+                               ret = utf16le_to_mbs(ucs, ucs_nbytes,
+                                                    &mbs, &mbs_len);
+                       } else {
+                               utf8char *ucs = va_arg(va, utf8char*);
+                               size_t ucs_nbytes = strlen(ucs);
+                               ret = utf8_to_mbs(ucs, ucs_nbytes,
+                                                 &mbs, &mbs_len);
+                       }
+                       if (ret) {
+                               ret = fprintf(fp, "???");
+                       } else {
+                               ret = fprintf(fp, "%s", mbs);
+                               FREE(mbs);
+                       }
+                       if (ret < 0)
+                               return -1;
+                       else
+                               n += ret;
+               } else {
+                       if (putc(*p, fp) == EOF)
+                               return -1;
+                       n++;
+               }
+       }
+       return n;
+}
+
+int
+wimlib_printf(const char *format, ...)
+{
+       int ret;
+       va_list va;
+
+       va_start(va, format);
+       ret = wimlib_vfprintf(stdout, format, va);
+       va_end(va);
+       return ret;
+}
+
+int
+wimlib_fprintf(FILE *fp, const char *format, ...)
+{
+       int ret;
+       va_list va;
+
+       va_start(va, format);
+       ret = wimlib_vfprintf(fp, format, va);
+       va_end(va);
+       return ret;
+}
+
 /* True if wimlib is to print an informational message when an error occurs.
  * This can be turned off by calling wimlib_set_print_errors(false). */
 #ifdef ENABLE_ERROR_MESSAGES
 #include <stdarg.h>
 static bool wimlib_print_errors = false;
 
-static void wimlib_vmsg(const char *tag, const char *format,
-                       va_list va, bool perror)
+static void
+wimlib_vmsg(const char *tag, const char *format,
+           va_list va, bool perror)
 {
        if (wimlib_print_errors) {
                int errno_save = errno;
                fflush(stdout);
                fputs(tag, stderr);
-               vfprintf(stderr, format, va);
+               wimlib_vfprintf(stderr, format, va);
                if (perror && errno_save != 0) {
                        char buf[50];
                        int res;
@@ -76,7 +163,8 @@ static void wimlib_vmsg(const char *tag, const char *format,
        }
 }
 
-void wimlib_error(const char *format, ...)
+void
+wimlib_error(const char *format, ...)
 {
        va_list va;
 
@@ -85,7 +173,8 @@ void wimlib_error(const char *format, ...)
        va_end(va);
 }
 
-void wimlib_error_with_errno(const char *format, ...)
+void
+wimlib_error_with_errno(const char *format, ...)
 {
        va_list va;
 
@@ -94,7 +183,8 @@ void wimlib_error_with_errno(const char *format, ...)
        va_end(va);
 }
 
-void wimlib_warning(const char *format, ...)
+void
+wimlib_warning(const char *format, ...)
 {
        va_list va;
 
@@ -103,7 +193,8 @@ void wimlib_warning(const char *format, ...)
        va_end(va);
 }
 
-void wimlib_warning_with_errno(const char *format, ...)
+void
+wimlib_warning_with_errno(const char *format, ...)
 {
        va_list va;
 
@@ -114,7 +205,8 @@ void wimlib_warning_with_errno(const char *format, ...)
 
 #endif
 
-WIMLIBAPI int wimlib_set_print_errors(bool show_error_messages)
+WIMLIBAPI int
+wimlib_set_print_errors(bool show_error_messages)
 {
 #ifdef ENABLE_ERROR_MESSAGES
        wimlib_print_errors = show_error_messages;
@@ -127,7 +219,7 @@ WIMLIBAPI int wimlib_set_print_errors(bool show_error_messages)
 #endif
 }
 
-static const char *error_strings[] = {
+static const mbchar *error_strings[] = {
        [WIMLIB_ERR_SUCCESS]
                = "Success",
        [WIMLIB_ERR_ALREADY_LOCKED]
@@ -175,6 +267,8 @@ static const char *error_strings[] = {
                = "The WIM's integrity table is invalid",
        [WIMLIB_ERR_INVALID_LOOKUP_TABLE_ENTRY]
                = "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",
        [WIMLIB_ERR_INVALID_OVERLAY]
                = "Conflicting files in overlay when creating a WIM image",
        [WIMLIB_ERR_INVALID_PARAM]
@@ -239,6 +333,8 @@ static const char *error_strings[] = {
                = "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",
+       [WIMLIB_ERR_UNICODE_STRING_NOT_REPRESENTABLE]
+               = "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",
        [WIMLIB_ERR_UNSUPPORTED]
@@ -249,7 +345,8 @@ static const char *error_strings[] = {
                = "The XML data of the WIM is invalid",
 };
 
-WIMLIBAPI const char *wimlib_get_error_string(enum wimlib_error_code code)
+WIMLIBAPI const mbchar *
+wimlib_get_error_string(enum wimlib_error_code code)
 {
        if (code < WIMLIB_ERR_SUCCESS || code > WIMLIB_ERR_XML)
                return NULL;
@@ -264,7 +361,8 @@ void *(*wimlib_malloc_func) (size_t)             = malloc;
 void  (*wimlib_free_func)   (void *)        = free;
 void *(*wimlib_realloc_func)(void *, size_t) = realloc;
 
-void *wimlib_calloc(size_t nmemb, size_t size)
+void *
+wimlib_calloc(size_t nmemb, size_t size)
 {
        size_t total_size = nmemb * size;
        void *p = MALLOC(total_size);
@@ -273,7 +371,8 @@ void *wimlib_calloc(size_t nmemb, size_t size)
        return p;
 }
 
-char *wimlib_strdup(const char *str)
+char *
+wimlib_strdup(const char *str)
 {
        size_t size;
        char *p;
@@ -285,14 +384,16 @@ char *wimlib_strdup(const char *str)
        return p;
 }
 
-extern void xml_set_memory_allocator(void *(*malloc_func)(size_t),
-                                  void (*free_func)(void *),
-                                  void *(*realloc_func)(void *, size_t));
+extern void
+xml_set_memory_allocator(void *(*malloc_func)(size_t),
+                        void (*free_func)(void *),
+                        void *(*realloc_func)(void *, size_t));
 #endif
 
-WIMLIBAPI int wimlib_set_memory_allocator(void *(*malloc_func)(size_t),
-                                          void (*free_func)(void *),
-                                          void *(*realloc_func)(void *, size_t))
+WIMLIBAPI int
+wimlib_set_memory_allocator(void *(*malloc_func)(size_t),
+                           void (*free_func)(void *),
+                           void *(*realloc_func)(void *, size_t))
 {
 #ifdef ENABLE_CUSTOM_MEMORY_ALLOCATOR
        wimlib_malloc_func  = malloc_func  ? malloc_func  : malloc;
@@ -312,14 +413,16 @@ WIMLIBAPI int wimlib_set_memory_allocator(void *(*malloc_func)(size_t),
 
 static bool seeded = false;
 
-static void seed_random()
+static void
+seed_random()
 {
        srand(time(NULL) * getpid());
        seeded = true;
 }
 
 /* Fills @n bytes pointed to by @p with random alphanumeric characters. */
-void randomize_char_array_with_alnum(char p[], size_t n)
+void
+randomize_char_array_with_alnum(char p[], size_t n)
 {
        if (!seeded)
                seed_random();
@@ -335,7 +438,8 @@ void randomize_char_array_with_alnum(char p[], size_t n)
 }
 
 /* Fills @n bytes pointer to by @p with random numbers. */
-void randomize_byte_array(u8 *p, size_t n)
+void
+randomize_byte_array(u8 *p, size_t n)
 {
        if (!seeded)
                seed_random();
@@ -345,7 +449,8 @@ void 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)
+void
+to_parent_name(char buf[], size_t len)
 {
        ssize_t i = (ssize_t)len - 1;
        while (i >= 0 && buf[i] == '/')
@@ -359,7 +464,8 @@ void to_parent_name(char buf[], size_t len)
 
 /* Like the basename() function, but does not modify @path; it just returns a
  * pointer to it. */
-const char *path_basename(const char *path)
+const char *
+path_basename(const char *path)
 {
        const char *p = path;
        while (*p)
@@ -385,7 +491,8 @@ const char *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 char *
+path_stream_name(const char *path)
 {
        const char *base = path_basename(path);
        const char *stream_name = strchr(base, ':');
@@ -406,7 +513,8 @@ const char *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 char *
+path_next_part(const char *path, size_t *first_part_len_ret)
 {
        size_t i;
        const char *next_part;
@@ -423,7 +531,8 @@ const char *path_next_part(const char *path, size_t *first_part_len_ret)
 }
 
 /* Returns the number of components of @path.  */
-int get_num_path_components(const char *path)
+int
+get_num_path_components(const char *path)
 {
        int num_components = 0;
        while (*path) {
@@ -442,7 +551,8 @@ int get_num_path_components(const char *path)
  * Prints a string.  Printable characters are printed as-is, while unprintable
  * characters are printed as their octal escape codes.
  */
-void print_string(const void *string, size_t len)
+void
+print_string(const void *string, size_t len)
 {
        const u8 *p = string;
 
@@ -455,14 +565,16 @@ void print_string(const void *string, size_t len)
        }
 }
 
-u64 get_wim_timestamp()
+u64
+get_wim_timestamp()
 {
        struct timeval tv;
        gettimeofday(&tv, NULL);
        return timeval_to_wim_timestamp(tv);
 }
 
-void wim_timestamp_to_str(u64 timestamp, char *buf, size_t len)
+void
+wim_timestamp_to_str(u64 timestamp, char *buf, size_t len)
 {
        struct tm tm;
        time_t t = wim_timestamp_to_unix(timestamp);
index c51fc71..71590ff 100644 (file)
@@ -49,6 +49,24 @@ 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 characters have
+ * the same representation, 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;
+
 #ifndef min
 #define min(a, b) ({ typeof(a) __a = (a); typeof(b) __b = (b); \
                                        (__a < __b) ? __a : __b; })
@@ -95,14 +113,17 @@ dummy_printf(const char *format, ...)
 }
 
 #ifdef ENABLE_ERROR_MESSAGES
-extern void wimlib_error(const char *format, ...)
-               FORMAT(printf, 1, 2) COLD;
-extern void wimlib_error_with_errno(const char *format, ...)
-               FORMAT(printf, 1, 2) COLD;
-extern void wimlib_warning(const char *format, ...)
-               FORMAT(printf, 1, 2) COLD;
-extern void wimlib_warning_with_errno(const char *format, ...)
-               FORMAT(printf, 1, 2) COLD;
+extern void
+wimlib_error(const char *format, ...) FORMAT(printf, 1, 2) COLD;
+
+extern void
+wimlib_error_with_errno(const char *format, ...) FORMAT(printf, 1, 2) COLD;
+
+extern void
+wimlib_warning(const char *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
@@ -119,7 +140,7 @@ extern void wimlib_warning_with_errno(const char *format, ...)
 #      define DEBUG(format, ...)                                       \
        ({                                                              \
                int __errno_save = errno;                               \
-               fprintf(stdout, "[%s %d] %s(): " format,                \
+               wimlib_fprintf(stdout, "[%s %d] %s(): " format,         \
                        __FILE__, __LINE__, __func__, ## __VA_ARGS__);  \
                putchar('\n');                                          \
                fflush(stdout);                                         \
@@ -173,51 +194,40 @@ extern char *wimlib_strdup(const char *str);
 #endif /* ENABLE_CUSTOM_MEMORY_ALLOCATOR */
 
 
-/* encoding.c */
-
-#if defined(WITH_NTFS_3G) || defined(__WIN32__)
-static inline int iconv_global_init()
-{
-       return 0;
-}
-
-static inline void iconv_global_cleanup() { }
-#else
-extern int iconv_global_init();
-extern void iconv_global_cleanup();
-#endif
-
-extern int utf16_to_utf8(const char *utf16_str, size_t utf16_nbytes,
-                        char **utf8_str_ret, size_t *utf8_nbytes_ret);
-
-extern int utf8_to_utf16(const char *utf8_str, size_t utf8_nbytes,
-                        char **utf16_str_ret, size_t *utf16_nbytes_ret);
-
 /* util.c */
-extern void randomize_byte_array(u8 *p, size_t n);
+extern void
+randomize_byte_array(u8 *p, size_t n);
 
-extern void randomize_char_array_with_alnum(char p[], size_t n);
+extern void
+randomize_char_array_with_alnum(char p[], size_t n);
 
-extern const char *path_next_part(const char *path,
-                                 size_t *first_part_len_ret);
+extern const char *
+path_next_part(const char *path, size_t *first_part_len_ret);
 
-extern const char *path_basename(const char *path);
+extern const char *
+path_basename(const char *path);
 
-extern const char *path_stream_name(const char *path);
+extern const char *
+path_stream_name(const char *path);
 
-extern void to_parent_name(char buf[], size_t len);
+extern void
+to_parent_name(char buf[], size_t len);
 
-extern void print_string(const void *string, size_t len);
+extern void
+print_string(const void *string, size_t len);
 
-extern int get_num_path_components(const char *path);
+extern int
+get_num_path_components(const char *path);
 
-static inline void print_byte_field(const u8 field[], size_t len)
+static inline void
+print_byte_field(const u8 field[], size_t len)
 {
        while (len--)
                printf("%02hhx", *field++);
 }
 
-static inline u32 bsr32(u32 n)
+static inline u32
+bsr32(u32 n)
 {
 #if defined(__x86__) || defined(__x86_64__)
        asm("bsrl %0, %0;"
@@ -232,4 +242,10 @@ static inline u32 bsr32(u32 n)
 #endif
 }
 
+extern int
+wimlib_fprintf(FILE *fp, const char *format, ...) FORMAT(printf, 2, 3);
+
+extern int
+wimlib_printf(const char *format, ...) FORMAT(printf, 1, 2);
+
 #endif /* _WIMLIB_UTIL_H */
index 60b2b57..6df2c71 100644 (file)
--- a/src/wim.c
+++ b/src/wim.c
@@ -27,6 +27,7 @@
 
 #include <errno.h>
 #include <fcntl.h>
+#include <langinfo.h>
 #include <limits.h>
 #include <stdarg.h>
 #include <stdlib.h>
@@ -645,11 +646,16 @@ WIMLIBAPI void wimlib_free(WIMStruct *w)
        DEBUG("Freed WIMStruct");
 }
 
+bool wimlib_mbs_is_utf8;
+
 /* Get global memory allocations out of the way.  Not strictly necessary in
  * single-threaded programs like 'imagex'. */
 WIMLIBAPI int wimlib_global_init()
 {
+       char *encoding;
+
        libxml_global_init();
+       wimlib_mbs_is_utf8 = (strcmp(nl_langinfo(CODESET), "UTF-8") == 0);
        return iconv_global_init();
 }
 
index 6abb6e5..f875afb 100644 (file)
  */
 typedef struct WIMStruct WIMStruct;
 
+typedef char wimlib_mbchar;
+typedef char wimlib_utf8char;
+
 /**
  * Specifies the compression type of a WIM file.
  */
@@ -406,12 +409,12 @@ union wimlib_progress_info {
         * ::WIMLIB_PROGRESS_MSG_SCAN_END. */
        struct wimlib_progress_info_scan {
                /** Directory or NTFS volume that is being scanned. */
-               const char *source;
+               const wimlib_mbchar *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 char *cur_path;
+               const wimlib_mbchar *cur_path;
 
                /** True iff @a cur_path is being excluded from the image
                 * capture due to the capture configuration file. */
@@ -420,7 +423,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 char *wim_target_path;
+               const wimlib_mbchar *wim_target_path;
        } scan;
 
        /** Valid on messages ::WIMLIB_PROGRESS_MSG_EXTRACT_IMAGE_BEGIN,
@@ -436,18 +439,18 @@ union wimlib_progress_info {
                int extract_flags;
 
                /** Full path to the WIM file being extracted. */
-               const char *wimfile_name;
+               const wimlib_mbchar *wimfile_name;
 
                /** Name of the image being extracted. */
-               const char *image_name;
+               const wimlib_utf8char *image_name;
 
                /** Directory or NTFS volume to which the image is being
                 * extracted. */
-               const char *target;
+               const wimlib_mbchar *target;
 
                /** Current dentry being extracted.  (Valid only if message is
                 * ::WIMLIB_PROGRESS_MSG_EXTRACT_DENTRY.) */
-               const char *cur_path;
+               const wimlib_mbchar *cur_path;
 
                /** Number of bytes of uncompressed data that will be extracted.
                 * Takes into account hard links (they are not counted for each
@@ -469,11 +472,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 char *from;
+               const wimlib_mbchar *from;
 
                /** Name of the original WIM file to which the temporary file is
                 * being renamed. */
-               const char *to;
+               const wimlib_mbchar *to;
        } rename;
 
        /** Valid on messages ::WIMLIB_PROGRESS_MSG_VERIFY_INTEGRITY and
@@ -501,7 +504,7 @@ union wimlib_progress_info {
 
                /** Filename of the WIM (only valid if the message is
                 * ::WIMLIB_PROGRESS_MSG_VERIFY_INTEGRITY). */
-               const char *filename;
+               const wimlib_mbchar *filename;
        } integrity;
 
        /** Valid on messages ::WIMLIB_PROGRESS_MSG_JOIN_STREAMS. */
@@ -543,7 +546,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 char *part_name;
+               const wimlib_mbchar *part_name;
        } split;
 };
 
@@ -564,12 +567,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. */
-       char *fs_source_path;
+       wimlib_mbchar *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. */
-       char *wim_target_path;
+       wimlib_mbchar *wim_target_path;
 
        /** Reserved; set to 0. */
        long reserved;
@@ -793,6 +796,8 @@ enum wimlib_error_code {
        WIMLIB_ERR_WRITE,
        WIMLIB_ERR_XML,
        WIMLIB_ERR_INVALID_OVERLAY,
+       WIMLIB_ERR_INVALID_MULTIBYTE_STRING,
+       WIMLIB_ERR_UNICODE_STRING_NOT_REPRESENTABLE,
 };
 
 
@@ -885,10 +890,12 @@ enum wimlib_error_code {
  *     ::WIMLIB_ADD_IMAGE_FLAG_NTFS was specified in @a add_image_flags, but
  *     wimlib was configured with the @c --without-ntfs-3g flag.
  */
-extern int wimlib_add_image(WIMStruct *wim, const char *source,
-                           const char *name, const char *config,
-                           size_t config_len, int add_image_flags,
-                           wimlib_progress_func_t progress_func);
+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_progress_func_t progress_func);
 
 /** This function is equivalent to wimlib_add_image() except it allows for
  * multiple sources to be combined into a single WIM image.  This is done by
@@ -912,14 +919,15 @@ extern int wimlib_add_image(WIMStruct *wim, const char *source,
  * (In this respect, there is no advantage to using
  * wimlib_add_image_multisource() instead of wimlib_add_image() when requesting
  * NTFS mode.) */
-extern int wimlib_add_image_multisource(WIMStruct *w,
-                                       struct wimlib_capture_source *sources,
-                                       size_t num_sources,
-                                       const char *name,
-                                       const char *config_str,
-                                       size_t config_len,
-                                       int add_image_flags,
-                                       wimlib_progress_func_t progress_func);
+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,
+                            size_t config_len,
+                            int add_image_flags,
+                            wimlib_progress_func_t progress_func);
 
 /**
  * Creates a ::WIMStruct for a new WIM file.
@@ -943,7 +951,8 @@ extern int wimlib_add_image_multisource(WIMStruct *w,
  * @retval ::WIMLIB_ERR_NOMEM
  *     Failed to allocate needed memory.
  */
-extern int wimlib_create_new_wim(int ctype, WIMStruct **wim_ret);
+extern int
+wimlib_create_new_wim(int ctype, WIMStruct **wim_ret);
 
 /**
  * Deletes an image, or all images, from a WIM file.
@@ -986,7 +995,8 @@ extern int wimlib_create_new_wim(int ctype, WIMStruct **wim_ret);
  *     @a wim is part of a split WIM.  Deleting an image from a split WIM is
  *     unsupported.
  */
-extern int wimlib_delete_image(WIMStruct *wim, int image);
+extern int
+wimlib_delete_image(WIMStruct *wim, int image);
 
 /**
  * Exports an image, or all the images, from a WIM file, into another WIM file.
@@ -1095,12 +1105,15 @@ extern int wimlib_delete_image(WIMStruct *wim, int image);
  *     @a dest_wim is part of a split WIM.  Exporting an image to a split WIM
  *     is unsupported.
  */
-extern int wimlib_export_image(WIMStruct *src_wim, int src_image,
-                              WIMStruct *dest_wim, const char *dest_name,
-                              const char *dest_description, int export_flags,
-                              WIMStruct **additional_swms,
-                              unsigned num_additional_swms,
-                              wimlib_progress_func_t progress_func);
+extern int
+wimlib_export_image(WIMStruct *src_wim, int src_image,
+                   WIMStruct *dest_wim,
+                   const wimlib_utf8char *dest_name,
+                   const wimlib_utf8char *dest_description,
+                   int export_flags,
+                   WIMStruct **additional_swms,
+                   unsigned num_additional_swms,
+                   wimlib_progress_func_t progress_func);
 
 /**
  * Extracts an image, or all images, from a standalone or split WIM file to a
@@ -1224,11 +1237,13 @@ extern int wimlib_export_image(WIMStruct *src_wim, int src_image,
  *     Failed to write a file being extracted (only if
  *     ::WIMLIB_EXTRACT_FLAG_NTFS was not specified in @a extract_flags).
  */
-extern int wimlib_extract_image(WIMStruct *wim, int image,
-                               const char *target, int extract_flags,
-                               WIMStruct **additional_swms,
-                               unsigned num_additional_swms,
-                               wimlib_progress_func_t progress_func);
+extern int
+wimlib_extract_image(WIMStruct *wim, int image,
+                    const wimlib_mbchar *target,
+                    int extract_flags,
+                    WIMStruct **additional_swms,
+                    unsigned num_additional_swms,
+                    wimlib_progress_func_t progress_func);
 
 /**
  * Extracts the XML data of a WIM file to a file stream.  Every WIM file
@@ -1246,7 +1261,8 @@ extern int wimlib_extract_image(WIMStruct *wim, int image,
  * @retval ::WIMLIB_ERR_INVALID_PARAM
  *     @a wim is not a ::WIMStruct that was created by wimlib_open_wim().
  */
-extern int wimlib_extract_xml_data(WIMStruct *wim, FILE *fp);
+extern int
+wimlib_extract_xml_data(WIMStruct *wim, FILE *fp);
 
 /**
  * Frees all memory allocated for a WIMStruct and closes all files associated
@@ -1257,7 +1273,8 @@ extern int wimlib_extract_xml_data(WIMStruct *wim, FILE *fp);
  *
  * @return This function has no return value.
  */
-extern void wimlib_free(WIMStruct *wim);
+extern void
+wimlib_free(WIMStruct *wim);
 
 /**
  * Returns the index of the bootable image of the WIM.
@@ -1269,7 +1286,8 @@ extern void wimlib_free(WIMStruct *wim);
  *     0 if no image is marked as bootable, or the number of the image marked
  *     as bootable (numbered starting at 1).
  */
-extern int wimlib_get_boot_idx(const WIMStruct *wim);
+extern int
+wimlib_get_boot_idx(const WIMStruct *wim);
 
 /**
  * Returns the compression type used in the WIM.
@@ -1281,7 +1299,8 @@ extern int wimlib_get_boot_idx(const WIMStruct *wim);
  *     ::WIMLIB_COMPRESSION_TYPE_NONE, ::WIMLIB_COMPRESSION_TYPE_LZX, or
  *     ::WIMLIB_COMPRESSION_TYPE_XPRESS.
  */
-extern int wimlib_get_compression_type(const WIMStruct *wim);
+extern int
+wimlib_get_compression_type(const WIMStruct *wim);
 
 /**
  * Converts a ::wimlib_compression_type value into a string.
@@ -1294,7 +1313,8 @@ extern int wimlib_get_compression_type(const WIMStruct *wim);
  *     A statically allocated string: "None", "LZX", "XPRESS", or "Invalid",
  *     respectively.
  */
-extern const char *wimlib_get_compression_type_string(int ctype);
+extern const wimlib_mbchar *
+wimlib_get_compression_type_string(int ctype);
 
 /**
  * Converts an error code into a string describing it.
@@ -1306,7 +1326,8 @@ extern const char *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 char *wimlib_get_error_string(enum wimlib_error_code code);
+extern const wimlib_mbchar *
+wimlib_get_error_string(enum wimlib_error_code code);
 
 /**
  * Returns the description of the specified image.
@@ -1324,7 +1345,8 @@ extern const char *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 char *wimlib_get_image_description(const WIMStruct *wim, int image);
+extern const wimlib_utf8char *
+wimlib_get_image_description(const WIMStruct *wim, int image);
 
 /**
  * Returns the name of the specified image.
@@ -1345,7 +1367,8 @@ extern const char *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 char *wimlib_get_image_name(const WIMStruct *wim, int image);
+extern const wimlib_utf8char *
+wimlib_get_image_name(const WIMStruct *wim, int image);
 
 
 /**
@@ -1358,7 +1381,8 @@ extern const char *wimlib_get_image_name(const WIMStruct *wim, int image);
  * @return
  *     The number of images contained in the WIM file.
  */
-extern int wimlib_get_num_images(const WIMStruct *wim);
+extern int
+wimlib_get_num_images(const WIMStruct *wim);
 
 /**
  * Returns the part number of a WIM in a split WIM and the total number of parts
@@ -1373,7 +1397,8 @@ extern int wimlib_get_num_images(const WIMStruct *wim);
  * @return
  *     The part number of the WIM (1 for non-split WIMs)
  */
-extern int wimlib_get_part_number(const WIMStruct *wim, int *total_parts_ret);
+extern int
+wimlib_get_part_number(const WIMStruct *wim, int *total_parts_ret);
 
 /**
  * Since wimlib 1.2.6:  Initialization function for wimlib.  This is not
@@ -1394,14 +1419,16 @@ extern int wimlib_get_part_number(const WIMStruct *wim, int *total_parts_ret);
  * indicates that further calls into wimlib will probably fail when they try to
  * repeat the same initializations.
  */
-extern int wimlib_global_init();
+extern int
+wimlib_global_init();
 
 /**
  * Since wimlib 1.2.6:  Cleanup function for wimlib.  This is not re-entrant.
  * You are not required to call this function, but it will release any global
  * memory allocated by the library.
  */
-extern void wimlib_global_cleanup();
+extern void
+wimlib_global_cleanup();
 
 /**
  * Returns true if the WIM has an integrity table.
@@ -1414,8 +1441,8 @@ extern void wimlib_global_cleanup();
  *     wimlib_open_wim(), @c false will be returned, even if wimlib_write() has
  *     been called on @a wim with ::WIMLIB_WRITE_FLAG_CHECK_INTEGRITY set.
  */
-extern bool wimlib_has_integrity_table(const WIMStruct *wim);
-
+extern bool
+wimlib_has_integrity_table(const WIMStruct *wim);
 
 /**
  * Determines if an image name is already used by some image in the WIM.
@@ -1430,7 +1457,8 @@ extern bool wimlib_has_integrity_table(const WIMStruct *wim);
  *     if there is no image named @a name in @a wim.  If @a name is @c NULL or
  *     the empty string, @c false is returned.
  */
-extern bool wimlib_image_name_in_use(const WIMStruct *wim, const char *name);
+extern bool
+wimlib_image_name_in_use(const WIMStruct *wim, const wimlib_utf8char *name);
 
 /**
  * Joins a split WIM into a stand-alone one-part WIM.
@@ -1469,10 +1497,13 @@ extern bool wimlib_image_name_in_use(const WIMStruct *wim, const char *name);
  * Note: wimlib_export_image() can provide similar functionality to
  * wimlib_join(), since it is possible to export all images from a split WIM.
  */
-extern int wimlib_join(const char * const *swms, unsigned num_swms,
-                      const char *output_path, int swm_open_flags,
-                      int wim_write_flags,
-                      wimlib_progress_func_t progress_func);
+extern int
+wimlib_join(const wimlib_mbchar * const *swms,
+           unsigned num_swms,
+           const wimlib_mbchar *output_path,
+           int swm_open_flags,
+           int wim_write_flags,
+           wimlib_progress_func_t progress_func);
 
 /**
  * Mounts an image in a WIM file on a directory read-only or read-write.
@@ -1572,10 +1603,11 @@ extern int wimlib_join(const char * const *swms, unsigned num_swms,
  *     The WIM is a split WIM and a read-write mount was requested.  We only
  *     support mounting a split WIM read-only.
  */
-extern int wimlib_mount_image(WIMStruct *wim, int image, const char *dir,
-                             int mount_flags, WIMStruct **additional_swms,
-                             unsigned num_additional_swms,
-                             const char *staging_dir);
+extern int
+wimlib_mount_image(WIMStruct *wim, int image, const wimlib_mbchar *dir,
+                  int mount_flags, WIMStruct **additional_swms,
+                  unsigned num_additional_swms,
+                  const wimlib_mbchar *staging_dir);
 
 /**
  * Opens a WIM file and creates a ::WIMStruct for it.
@@ -1655,9 +1687,9 @@ extern int wimlib_mount_image(WIMStruct *wim, int image, const char *dir,
  * @retval ::WIMLIB_ERR_XML
  *     The XML data for @a wim_file is invalid.
  */
-extern int wimlib_open_wim(const char *wim_file, int open_flags,
-                          WIMStruct **wim_ret,
-                          wimlib_progress_func_t progress_func);
+extern int
+wimlib_open_wim(const wimlib_mbchar *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.
@@ -1730,9 +1762,9 @@ extern int wimlib_open_wim(const char *wim_file, int open_flags,
  *     accessed, so this limits the functions that can be called on @a wim
  *     before calling wimlib_free().
  */
-extern int wimlib_overwrite(WIMStruct *wim, int write_flags,
-                           unsigned num_threads,
-                           wimlib_progress_func_t progress_func);
+extern int
+wimlib_overwrite(WIMStruct *wim, int write_flags, unsigned num_threads,
+                wimlib_progress_func_t progress_func);
 
 /**
  * Prints information about one image, or all images, contained in a WIM.
@@ -1748,7 +1780,8 @@ extern int wimlib_overwrite(WIMStruct *wim, int write_flags,
  * printing the information.  If @a image is invalid, an error message is
  * printed.
  */
-extern void wimlib_print_available_images(const WIMStruct *wim, int image);
+extern void
+wimlib_print_available_images(const WIMStruct *wim, int image);
 
 /**
  * Prints the full paths to all files contained in an image, or all images, in a
@@ -1783,7 +1816,8 @@ extern void wimlib_print_available_images(const WIMStruct *wim, int image);
  *     @a wim was not a standalone WIM and was not the first part of a split
  *     WIM.
  */
-extern int wimlib_print_files(WIMStruct *wim, int image);
+extern int
+wimlib_print_files(WIMStruct *wim, int image);
 
 /**
  * Prints detailed information from the header of a WIM file.
@@ -1795,7 +1829,8 @@ extern int wimlib_print_files(WIMStruct *wim, int image);
  * @return This function has no return value.
  *
  */
-extern void wimlib_print_header(const WIMStruct *wim);
+extern void
+wimlib_print_header(const WIMStruct *wim);
 
 /**
  * Prints the lookup table of a WIM file.  The lookup table maps SHA1 message
@@ -1809,7 +1844,8 @@ extern void wimlib_print_header(const WIMStruct *wim);
  *
  * @return This function has no return value.
  */
-extern void wimlib_print_lookup_table(WIMStruct *wim);
+extern void
+wimlib_print_lookup_table(WIMStruct *wim);
 
 /**
  * Prints the metadata of the specified image in a WIM file.  The metadata
@@ -1845,7 +1881,8 @@ extern void wimlib_print_lookup_table(WIMStruct *wim);
  *     @a wim was not a standalone WIM and was not the first part of a split
  *     WIM.
  */
-extern int wimlib_print_metadata(WIMStruct *wim, int image);
+extern int
+wimlib_print_metadata(WIMStruct *wim, int image);
 
 /**
  * Prints some basic information about a WIM file.  All information printed by
@@ -1858,7 +1895,8 @@ extern int wimlib_print_metadata(WIMStruct *wim, int image);
  *
  * @return This function has no return value.
  */
-extern void wimlib_print_wim_information(const WIMStruct *wim);
+extern void
+wimlib_print_wim_information(const WIMStruct *wim);
 
 /**
  * Translates a string specifying the name or number of an image in the WIM into
@@ -1886,7 +1924,9 @@ extern void wimlib_print_wim_information(const WIMStruct *wim);
  *     the empty string, ::WIMLIB_NO_IMAGE is returned, even if one or more
  *     images in @a wim has no name.
  */
-extern int wimlib_resolve_image(WIMStruct *wim, const char *image_name_or_num);
+extern int
+wimlib_resolve_image(WIMStruct *wim,
+                    const wimlib_utf8char *image_name_or_num);
 
 /**
  * Sets which image in the WIM is marked as bootable.
@@ -1904,7 +1944,8 @@ extern int wimlib_resolve_image(WIMStruct *wim, const char *image_name_or_num);
  *     @a wim is part of a split WIM.  We do not support changing the boot
  *     index of a split WIM.
  */
-extern int wimlib_set_boot_idx(WIMStruct *wim, int boot_idx);
+extern int
+wimlib_set_boot_idx(WIMStruct *wim, int boot_idx);
 
 /**
  * Changes the description of an image in the WIM.
@@ -1926,8 +1967,9 @@ extern int wimlib_set_boot_idx(WIMStruct *wim, int boot_idx);
  *     Failed to allocate the memory needed to duplicate the @a description
  *     string.
  */
-extern int wimlib_set_image_descripton(WIMStruct *wim, int image,
-                                      const char *description);
+extern int
+wimlib_set_image_descripton(WIMStruct *wim, int image,
+                           const wimlib_utf8char *description);
 
 /**
  * Changes what is written in the \<FLAGS\> element in the WIM XML data
@@ -1949,7 +1991,8 @@ extern int wimlib_set_image_descripton(WIMStruct *wim, int image,
  * @retval ::WIMLIB_ERR_NOMEM
  *     Failed to allocate the memory needed to duplicate the @a flags string.
  */
-extern int wimlib_set_image_flags(WIMStruct *wim, int image, const char *flags);
+extern int wimlib_set_image_flags(WIMStruct *wim, int image,
+                                 const wimlib_utf8char *flags);
 
 /**
  * Changes the name of an image in the WIM.
@@ -1973,7 +2016,8 @@ extern int wimlib_set_image_flags(WIMStruct *wim, int image, const char *flags);
  * @retval ::WIMLIB_ERR_NOMEM
  *     Failed to allocate the memory needed to duplicate the @a name string.
  */
-extern int wimlib_set_image_name(WIMStruct *wim, int image, const char *name);
+extern int wimlib_set_image_name(WIMStruct *wim, int image,
+                                const wimlib_utf8char *name);
 
 /**
  * Set the functions that wimlib uses to allocate and free memory.
@@ -2003,9 +2047,10 @@ extern int wimlib_set_image_name(WIMStruct *wim, int image, const char *name);
  *     wimlib was compiled with the @c --without-custom-memory-allocator flag,
  *     so custom memory allocators are unsupported.
  */
-int wimlib_set_memory_allocator(void *(*malloc_func)(size_t),
-                                void (*free_func)(void *),
-                                void *(*realloc_func)(void *, size_t));
+extern int
+wimlib_set_memory_allocator(void *(*malloc_func)(size_t),
+                           void (*free_func)(void *),
+                           void *(*realloc_func)(void *, size_t));
 
 /**
  * Sets whether wimlib is to print error messages to @c stderr when a function
@@ -2027,7 +2072,8 @@ int wimlib_set_memory_allocator(void *(*malloc_func)(size_t),
  *     --without-error-messages option.   Therefore, error messages cannot be
  *     shown.
  */
-extern int wimlib_set_print_errors(bool show_messages);
+extern int
+wimlib_set_print_errors(bool show_messages);
 
 /**
  * Splits a WIM into multiple parts.
@@ -2063,9 +2109,10 @@ extern int wimlib_set_print_errors(bool show_messages);
  * when they are copied from the joined WIM to the split WIM parts, nor are
  * compressed resources re-compressed.
  */
-extern int wimlib_split(WIMStruct *wim, const char *swm_name,
-                       size_t part_size, int write_flags,
-                       wimlib_progress_func_t progress_func);
+extern int
+wimlib_split(WIMStruct *wim, const wimlib_mbchar *swm_name,
+            size_t part_size, int write_flags,
+            wimlib_progress_func_t progress_func);
 
 /**
  * Unmounts a WIM image that was mounted using wimlib_mount_image().
@@ -2124,8 +2171,9 @@ extern int wimlib_split(WIMStruct *wim, const char *swm_name,
  *     WIM file, or the filesystem daemon was unable to flush changes that had
  *     been made to files in the staging directory.
  */
-extern int wimlib_unmount_image(const char *dir, int unmount_flags,
-                               wimlib_progress_func_t progress_func);
+extern int
+wimlib_unmount_image(const wimlib_mbchar *dir, int unmount_flags,
+                    wimlib_progress_func_t progress_func);
 
 /**
  * Writes a standalone WIM to a file.
@@ -2195,8 +2243,9 @@ extern int wimlib_unmount_image(const char *dir, int unmount_flags,
  *     An error occurred when trying to write data to the new WIM file at @a
  *     path.
  */
-extern int wimlib_write(WIMStruct *wim, const char *path, int image,
-                       int write_flags, unsigned num_threads,
-                       wimlib_progress_func_t progress_func);
+extern int
+wimlib_write(WIMStruct *wim, const wimlib_mbchar *path, int image,
+            int write_flags, unsigned num_threads,
+            wimlib_progress_func_t progress_func);
 
 #endif /* _WIMLIB_H */
index 554d3cc..580960f 100644 (file)
@@ -281,13 +281,13 @@ struct WIMStruct {
        FILE *out_fp;
 
        /* The name of the WIM file (if any) that has been opened. */
-       char *filename;
+       mbchar *filename;
 
        /* The lookup table for the WIM file. */
        struct wim_lookup_table *lookup_table;
 
-       /* Pointer to the XML data read from the WIM file. */
-       u8 *xml_data;
+       /* Pointer to the XML data read from the WIM file (UTF16LE-encoded). */
+       utf16lechar *xml_data;
 
        /* Information retrieved from the XML data, arranged in an orderly
         * manner. */
@@ -321,7 +321,8 @@ struct WIMStruct {
 
 /* Inline utility functions for WIMStructs. */
 
-static inline struct wim_dentry *wim_root_dentry(WIMStruct *w)
+static inline struct wim_dentry *
+wim_root_dentry(WIMStruct *w)
 {
        return w->image_metadata[w->current_image - 1].root_dentry;
 }
@@ -344,7 +345,8 @@ wim_get_current_image_metadata(WIMStruct *w)
 }
 
 /* Nonzero if a struct resource_entry indicates a compressed resource. */
-static inline int resource_is_compressed(const struct resource_entry *entry)
+static inline int
+resource_is_compressed(const struct resource_entry *entry)
 {
        return (entry->flags & WIM_RESHDR_FLAG_COMPRESSED);
 }
@@ -352,7 +354,7 @@ static inline int resource_is_compressed(const struct resource_entry *entry)
 /* add_image.c */
 
 struct pattern_list {
-       const char **pats;
+       const mbchar **pats;
        size_t num_pats;
        size_t num_allocated_pats;
 };
@@ -362,15 +364,66 @@ struct capture_config {
        struct pattern_list exclusion_exception;
        struct pattern_list compression_exclusion_list;
        struct pattern_list alignment_list;
-       char *config_str;
-       char *prefix;
+       mbchar *config_str;
+       mbchar *prefix;
        size_t prefix_len;
 };
-extern bool exclude_path(const char *path,
-                        const struct capture_config *config,
-                        bool exclude_prefix);
-extern int add_new_dentry_tree(WIMStruct *dest_wim, struct wim_dentry *root,
-                              struct wim_security_data *sd);
+extern bool
+exclude_path(const mbchar *path, const struct capture_config *config,
+            bool exclude_prefix);
+
+extern int
+add_new_dentry_tree(WIMStruct *dest_wim, struct wim_dentry *root,
+                   struct wim_security_data *sd);
+
+/* encoding.c */
+
+#if defined(WITH_NTFS_3G) || defined(__WIN32__)
+
+static inline int
+iconv_global_init()
+{
+       return 0;
+}
+
+static inline void
+iconv_global_cleanup() { }
+#else
+extern int
+iconv_global_init();
+
+extern void
+iconv_global_cleanup();
+#endif
+
+extern bool wimlib_mbs_is_utf8;
+
+extern bool
+utf8_str_contains_nonascii_chars(const utf8char *utf8_str);
+
+extern int
+mbs_to_utf16le_nbytes(const mbchar *mbs, size_t mbs_nbytes,
+                     size_t *utf16le_nbytes_ret);
+
+extern int
+utf16le_to_mbs_nbytes(const utf16lechar *utf16le_str,
+                     size_t utf16le_nbytes, size_t *mbs_nbytes_ret);
+
+extern int
+mbs_to_utf16le_buf(const mbchar *mbs, size_t mbs_nbytes,
+                  utf16lechar *utf16le_str);
+
+extern int
+utf16le_to_mbs_buf(const utf16lechar *utf16le_str, size_t utf16le_nbytes,
+                  mbchar *mbs);
+
+extern int
+mbs_to_utf16le(const mbchar *mbs, size_t mbs_nbytes,
+              utf16lechar **utf16le_str_ret, size_t *utf16le_nbytes_ret);
+
+extern int
+utf16le_to_mbs(const utf16lechar *utf16le_str, size_t utf16le_nbytes,
+              mbchar **mbs_ret, size_t *mbs_nbytes_ret);
 
 /* extract_image.c */
 
@@ -381,15 +434,22 @@ extern int add_new_dentry_tree(WIMStruct *dest_wim, struct wim_dentry *root,
 
 /* hardlink.c */
 
-extern u64 assign_inode_numbers(struct hlist_head *inode_list);
+extern u64
+assign_inode_numbers(struct hlist_head *inode_list);
 
-extern int dentry_tree_fix_inodes(struct wim_dentry *root,
-                                 struct hlist_head *inode_list);
+extern int
+dentry_tree_fix_inodes(struct wim_dentry *root, struct hlist_head *inode_list);
 
 /* header.c */
-extern int read_header(FILE *fp, struct wim_header *hdr, int split_ok);
-extern int write_header(const struct wim_header *hdr, FILE *out);
-extern int init_header(struct wim_header *hdr, int ctype);
+
+extern int
+read_header(FILE *fp, struct wim_header *hdr, int split_ok);
+
+extern int
+write_header(const struct wim_header *hdr, FILE *out);
+
+extern int
+init_header(struct wim_header *hdr, int ctype);
 
 /* integrity.c */
 
@@ -397,33 +457,36 @@ extern int init_header(struct wim_header *hdr, int ctype);
 #define WIM_INTEGRITY_NOT_OK -1
 #define WIM_INTEGRITY_NONEXISTENT -2
 
-extern int write_integrity_table(FILE *out,
-                                struct resource_entry *integrity_res_entry,
-                                off_t new_lookup_table_end,
-                                off_t old_lookup_table_end,
-                                wimlib_progress_func_t progress_func);
+extern int
+write_integrity_table(FILE *out, struct resource_entry *integrity_res_entry,
+                     off_t new_lookup_table_end,
+                     off_t old_lookup_table_end,
+                     wimlib_progress_func_t progress_func);
 
-extern int check_wim_integrity(WIMStruct *w,
-                              wimlib_progress_func_t progress_func);
+extern int
+check_wim_integrity(WIMStruct *w, wimlib_progress_func_t progress_func);
 
 /* join.c */
 
-extern int new_joined_lookup_table(WIMStruct *w,
-                                  WIMStruct **additional_swms,
-                                  unsigned num_additional_swms,
-                                  struct wim_lookup_table **table_ret);
+extern int
+new_joined_lookup_table(WIMStruct *w, WIMStruct **additional_swms,
+                       unsigned num_additional_swms,
+                       struct wim_lookup_table **table_ret);
 
 /* metadata_resource.c */
 
-extern int read_metadata_resource(WIMStruct *w,
+extern int
+read_metadata_resource(WIMStruct *w,
                                  struct wim_image_metadata *image_metadata);
-extern int write_metadata_resource(WIMStruct *w);
+
+extern int
+write_metadata_resource(WIMStruct *w);
 
 /* ntfs-apply.c */
 
 struct apply_args {
        WIMStruct *w;
-       const char *target;
+       const mbchar *target;
        int extract_flags;
        unsigned num_utime_warnings;
        struct list_head *stream_list;
@@ -435,18 +498,22 @@ struct apply_args {
        int (*apply_dentry)(struct wim_dentry *, void *);
 };
 
-extern int apply_dentry_ntfs(struct wim_dentry *dentry, void *arg);
-extern int apply_dentry_timestamps_ntfs(struct wim_dentry *dentry, void *arg);
+extern int
+apply_dentry_ntfs(struct wim_dentry *dentry, void *arg);
+
+extern int
+apply_dentry_timestamps_ntfs(struct wim_dentry *dentry, void *arg);
 
 /* ntfs-capture.c */
-extern int build_dentry_tree_ntfs(struct wim_dentry **root_p,
-                                 const char *device,
-                                 struct wim_lookup_table *lookup_table,
-                                 struct wim_security_data *sd,
-                                 const struct capture_config *config,
-                                 int add_image_flags,
-                                 wimlib_progress_func_t progress_func,
-                                 void *extra_arg);
+extern int
+build_dentry_tree_ntfs(struct wim_dentry **root_p,
+                      const mbchar *device,
+                      struct wim_lookup_table *lookup_table,
+                      struct wim_security_data *sd,
+                      const struct capture_config *config,
+                      int add_image_flags,
+                      wimlib_progress_func_t progress_func,
+                      void *extra_arg);
 
 /* resource.c */
 
@@ -454,31 +521,38 @@ extern int build_dentry_tree_ntfs(struct wim_dentry **root_p,
 #define WIMLIB_RESOURCE_FLAG_MULTITHREADED     0x2
 #define WIMLIB_RESOURCE_FLAG_RECOMPRESS                0x4
 
-extern const u8 *get_resource_entry(const u8 *p, struct resource_entry *entry);
-extern u8 *put_resource_entry(u8 *p, const struct resource_entry *entry);
+extern const u8 *
+get_resource_entry(const u8 *p, struct resource_entry *entry);
+
+extern u8 *
+put_resource_entry(u8 *p, const struct resource_entry *entry);
 
-extern int read_uncompressed_resource(FILE *fp, u64 offset, u64 size, u8 buf[]);
+extern int
+read_uncompressed_resource(FILE *fp, u64 offset, u64 size, void *buf);
 
-extern int read_wim_resource(const struct wim_lookup_table_entry *lte, u8 buf[],
-                            size_t size, u64 offset, int flags);
+extern int
+read_wim_resource(const struct wim_lookup_table_entry *lte, void *buf,
+                 size_t size, u64 offset, int flags);
 
-extern int read_full_wim_resource(const struct wim_lookup_table_entry *lte,
-                                 u8 buf[], int flags);
+extern int
+read_full_wim_resource(const struct wim_lookup_table_entry *lte,
+                      void *buf, int flags);
 
-extern int write_wim_resource(struct wim_lookup_table_entry *lte,
-                             FILE *out_fp, int out_ctype,
-                             struct resource_entry *out_res_entry,
-                             int flags);
+extern int
+write_wim_resource(struct wim_lookup_table_entry *lte, FILE *out_fp,
+                  int out_ctype, struct resource_entry *out_res_entry,
+                  int flags);
 
 
-typedef int (*extract_chunk_func_t)(const u8 *, size_t, u64, void *);
+typedef int (*extract_chunk_func_t)(const void *, size_t, u64, void *);
 
-extern int extract_wim_chunk_to_fd(const u8 *buf, size_t len,
-                                  u64 offset, void *arg);
+extern int
+extract_wim_chunk_to_fd(const void *buf, size_t len, u64 offset, void *arg);
 
-extern int extract_wim_resource(const struct wim_lookup_table_entry *lte,
-                               u64 size, extract_chunk_func_t extract_chunk,
-                               void *extract_chunk_arg);
+extern int
+extract_wim_resource(const struct wim_lookup_table_entry *lte,
+                    u64 size, extract_chunk_func_t extract_chunk,
+                    void *extract_chunk_arg);
 
 /*
  * Extracts the first @size bytes of the WIM resource specified by @lte to the
@@ -495,38 +569,59 @@ extract_wim_resource_to_fd(const struct wim_lookup_table_entry *lte,
 }
 
 
-extern int write_dentry_resources(struct wim_dentry *dentry, void *wim_p);
-extern int copy_resource(struct wim_lookup_table_entry *lte, void *w);
+extern int
+write_dentry_resources(struct wim_dentry *dentry, void *wim_p);
+
+extern int
+copy_resource(struct wim_lookup_table_entry *lte, void *w);
 
 
 /* security.c */
-extern int read_security_data(const u8 metadata_resource[],
-                             u64 metadata_resource_len,
-                             struct wim_security_data **sd_p);
-extern void print_security_data(const struct wim_security_data *sd);
-extern u8 *write_security_data(const struct wim_security_data *sd, u8 *p);
-extern void free_security_data(struct wim_security_data *sd);
+extern int
+read_security_data(const u8 metadata_resource[],
+                  u64 metadata_resource_len, struct wim_security_data **sd_p);
+extern void
+print_security_data(const struct wim_security_data *sd);
+
+extern u8 *
+write_security_data(const struct wim_security_data *sd, u8 *p);
+
+extern void
+free_security_data(struct wim_security_data *sd);
 
 /* symlink.c */
-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 char *target,
-                            struct wim_lookup_table *lookup_table,
-                            struct wim_lookup_table_entry **lte_ret);
+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,
+                 struct wim_lookup_table *lookup_table,
+                 struct wim_lookup_table_entry **lte_ret);
 
 /* verify.c */
-extern int verify_dentry(struct wim_dentry *dentry, void *wim);
-extern int wim_run_full_verifications(WIMStruct *w);
-extern int verify_swm_set(WIMStruct *w,
-                         WIMStruct **additional_swms,
-                         unsigned num_additional_swms);
+
+extern int
+verify_dentry(struct wim_dentry *dentry, void *wim);
+
+extern int
+wim_run_full_verifications(WIMStruct *w);
+
+extern int
+verify_swm_set(WIMStruct *w,
+              WIMStruct **additional_swms, unsigned num_additional_swms);
 
 /* wim.c */
-extern int select_wim_image(WIMStruct *w, int image);
-extern int for_image(WIMStruct *w, int image, int (*visitor)(WIMStruct *));
-extern void destroy_image_metadata(struct wim_image_metadata *imd,
-                                  struct wim_lookup_table *lt);
+
+extern int
+select_wim_image(WIMStruct *w, int image);
+
+extern int
+for_image(WIMStruct *w, int image, int (*visitor)(WIMStruct *));
+
+extern void
+destroy_image_metadata(struct wim_image_metadata *imd,
+                      struct wim_lookup_table *lt);
 
 /* write.c */
 
@@ -540,16 +635,22 @@ extern void destroy_image_metadata(struct wim_image_metadata *imd,
 #define WIMLIB_ADD_IMAGE_FLAG_SOURCE    0x40000000
 
 
-extern int begin_write(WIMStruct *w, const char *path, int write_flags);
-extern void close_wim_writable(WIMStruct *w);
+extern int
+begin_write(WIMStruct *w, const mbchar *path, int write_flags);
 
-extern int finish_write(WIMStruct *w, int image, int write_flags,
-                       wimlib_progress_func_t progress_func);
+extern void
+close_wim_writable(WIMStruct *w);
+
+extern int
+finish_write(WIMStruct *w, int image, int write_flags,
+            wimlib_progress_func_t progress_func);
 
 #if defined(HAVE_SYS_FILE_H) && defined(HAVE_FLOCK)
-extern int lock_wim(WIMStruct *w, FILE *fp);
+extern int
+lock_wim(WIMStruct *w, FILE *fp);
 #else
-static inline int lock_wim(WIMStruct *w, FILE *fp)
+static inline int
+lock_wim(WIMStruct *w, FILE *fp)
 {
        return 0;
 }
index 16bdf79..97d0b44 100644 (file)
@@ -77,7 +77,7 @@ void *win32_open_file_readonly(const void *path)
 }
 
 int win32_read_file(const char *filename,
-                   void *handle, u64 offset, size_t size, u8 *buf)
+                   void *handle, u64 offset, size_t size, void *buf)
 {
        HANDLE h = handle;
        DWORD err;
@@ -1205,7 +1205,8 @@ unsigned 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. */
-char *realpath(const char *path, char *resolved_path)
+mbchar *
+realpath(const mbchar *path, mbchar *resolved_path)
 {
        DWORD ret;
        wimlib_assert(resolved_path == NULL);
index 5f4ff56..18513be 100644 (file)
@@ -11,7 +11,7 @@ extern void win32_release_restore_privileges();
 extern void win32_acquire_restore_privileges();
 
 extern int win32_build_dentry_tree(struct wim_dentry **root_ret,
-                                  const char *root_disk_path,
+                                  const mbchar *root_disk_path,
                                   struct wim_lookup_table *lookup_table,
                                   struct wim_security_data *sd,
                                   const struct capture_config *config,
@@ -19,8 +19,8 @@ extern int win32_build_dentry_tree(struct wim_dentry **root_ret,
                                   wimlib_progress_func_t progress_func,
                                   void *extra_arg);
 
-extern int win32_read_file(const char *filename, void *handle, u64 offset,
-                          size_t size, u8 *buf);
+extern int win32_read_file(const mbchar *filename, void *handle, u64 offset,
+                          size_t size, void *buf);
 extern void *win32_open_file_readonly(const void *path_utf16);
 extern void win32_close_file(void *handle);
 
@@ -32,14 +32,14 @@ extern void win32_error(u32 err);
 
 #define FNM_PATHNAME 0x1
 #define FNM_NOMATCH 1
-extern int fnmatch(const char *pattern, const char *string, int flags);
+extern int fnmatch(const mbchar *pattern, const mbchar *string, int flags);
 
-extern int win32_do_apply_dentry(const char *output_path,
+extern int win32_do_apply_dentry(const mbchar *output_path,
                                 size_t output_path_len,
                                 struct wim_dentry *dentry,
                                 struct apply_args *args);
 
-extern int win32_do_apply_dentry_timestamps(const char *output_path,
+extern int win32_do_apply_dentry_timestamps(const mbchar *output_path,
                                            size_t output_path_len,
                                            const struct wim_dentry *dentry,
                                            const struct apply_args *args);
@@ -48,7 +48,7 @@ extern int fsync(int fd);
 
 extern unsigned win32_get_number_of_processors();
 
-extern char *realpath(const char *path, char *resolved_path);
+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.  */
index 2ac8cea..6515ee9 100644 (file)
--- a/src/xml.c
+++ b/src/xml.c
@@ -48,19 +48,19 @@ struct windows_version {
 };
 
 struct windows_info {
-       u64    arch;
-       char  *product_name;
-       char  *edition_id;
-       char  *installation_type;
-       char  *hal;
-       char  *product_type;
-       char  *product_suite;
-       char **languages;
-       char  *default_language;
-       size_t num_languages;
-       char  *system_root;
-       bool   windows_version_exists;
-       struct windows_version windows_version;
+       u64        arch;
+       utf8char  *product_name;
+       utf8char  *edition_id;
+       utf8char  *installation_type;
+       utf8char  *hal;
+       utf8char  *product_type;
+       utf8char  *product_suite;
+       utf8char **languages;
+       utf8char  *default_language;
+       size_t     num_languages;
+       utf8char  *system_root;
+       bool       windows_version_exists;
+       struct     windows_version windows_version;
 };
 
 struct image_info {
@@ -73,12 +73,12 @@ struct image_info {
        u64 creation_time;
        u64 last_modification_time;
        struct windows_info windows_info;
-       char *name;
-       char *description;
-       char *display_name;
-       char *display_description;
+       utf8char *name;
+       utf8char *description;
+       utf8char *display_name;
+       utf8char *display_description;
        union {
-               char *flags;
+               utf8char *flags;
                struct wim_lookup_table *lookup_table;
        };
 };
@@ -86,9 +86,9 @@ struct image_info {
 
 /* Returns a statically allocated string that is a string representation of the
  * architecture number. */
-static const char *get_arch(int arch)
+static const char *
+get_arch(int arch)
 {
-       static char buf[20];
        switch (arch) {
        case 0:
                return "x86";
@@ -98,8 +98,7 @@ static const char *get_arch(int arch)
                return "x86_64";
        /* XXX Are there other arch values? */
        default:
-               snprintf(buf, sizeof(buf), "%d (unknown)", arch);
-               return buf;
+               return NULL;
        }
 }
 
@@ -109,17 +108,20 @@ static const char *get_arch(int arch)
        for (child = parent->children; child != NULL; child = child->next)
 
 /* Utility functions for xmlNodes */
-static inline bool node_is_element(xmlNode *node)
+static inline bool
+node_is_element(xmlNode *node)
 {
        return node->type == XML_ELEMENT_NODE;
 }
 
-static inline bool node_is_text(xmlNode *node)
+static inline bool
+node_is_text(xmlNode *node)
 {
        return node->type == XML_TEXT_NODE;
 }
 
-static inline bool node_name_is(xmlNode *node, const char *name)
+static inline bool
+node_name_is(xmlNode *node, const utf8char *name)
 {
        /* For now, both upper case and lower case element names are accepted. */
        return strcasecmp((const char *)node->name, name) == 0;
@@ -128,7 +130,8 @@ static inline bool node_name_is(xmlNode *node, const char *name)
 /* Finds the text node that is a child of an element node and returns its
  * content converted to a 64-bit unsigned integer.  Returns 0 if no text node is
  * found. */
-static u64 node_get_u64(const xmlNode *u64_node)
+static u64
+node_get_u64(const xmlNode *u64_node)
 {
        xmlNode *child;
        for_node_child(u64_node, child)
@@ -138,7 +141,8 @@ static u64 node_get_u64(const xmlNode *u64_node)
 }
 
 /* Like node_get_u64(), but expects a number in base 16. */
-static u64 node_get_hex_u64(const xmlNode *u64_node)
+static u64
+node_get_hex_u64(const xmlNode *u64_node)
 {
        xmlNode *child;
        for_node_child(u64_node, child)
@@ -147,7 +151,8 @@ static u64 node_get_hex_u64(const xmlNode *u64_node)
        return 0;
 }
 
-static int node_get_string(const xmlNode *string_node, char **str)
+static int
+node_get_string(const xmlNode *string_node, utf8char **str)
 {
        xmlNode *child;
        char *p = NULL;
@@ -166,7 +171,8 @@ static int node_get_string(const xmlNode *string_node, char **str)
 
 /* Returns the timestamp from a time node.  It has child elements <HIGHPART> and
  * <LOWPART> that are then used to construct a 64-bit timestamp. */
-static u64 node_get_timestamp(const xmlNode *time_node)
+static u64
+node_get_timestamp(const xmlNode *time_node)
 {
        u32 high_part = 0;
        u32 low_part = 0;
@@ -183,7 +189,8 @@ static u64 node_get_timestamp(const xmlNode *time_node)
 }
 
 /* Used to sort an array of struct image_infos by their image indices. */
-static int sort_by_index(const void *p1, const void *p2)
+static int
+sort_by_index(const void *p1, const void *p2)
 {
        int index_1 = ((const struct image_info*)p1)->index;
        int index_2 = ((const struct image_info*)p2)->index;
@@ -197,7 +204,8 @@ static int sort_by_index(const void *p1, const void *p2)
 
 
 /* Frees memory allocated inside a struct windows_info structure. */
-static void destroy_windows_info(struct windows_info *windows_info)
+static void
+destroy_windows_info(struct windows_info *windows_info)
 {
        FREE(windows_info->product_name);
        FREE(windows_info->edition_id);
@@ -213,7 +221,8 @@ static void destroy_windows_info(struct windows_info *windows_info)
 }
 
 /* Frees memory allocated inside a struct image_info structure. */
-static void destroy_image_info(struct image_info *image_info)
+static void
+destroy_image_info(struct image_info *image_info)
 {
        FREE(image_info->name);
        FREE(image_info->description);
@@ -224,7 +233,8 @@ static void destroy_image_info(struct image_info *image_info)
        memset(image_info, 0, sizeof(struct image_info));
 }
 
-void free_wim_info(struct wim_info *info)
+void
+free_wim_info(struct wim_info *info)
 {
        if (info) {
                if (info->images) {
@@ -238,8 +248,9 @@ void free_wim_info(struct wim_info *info)
 
 /* Reads the information from a <VERSION> element inside the <WINDOWS> element.
  * */
-static void xml_read_windows_version(const xmlNode *version_node,
-                                    struct windows_version* windows_version)
+static void
+xml_read_windows_version(const xmlNode *version_node,
+                        struct windows_version* windows_version)
 {
        xmlNode *child;
        for_node_child(version_node, child) {
@@ -260,14 +271,15 @@ static void xml_read_windows_version(const xmlNode *version_node,
 
 /* Reads the information from a <LANGUAGE> element inside a <WINDOWS> element.
  * */
-static int xml_read_languages(const xmlNode *languages_node,
-                             char ***languages_ret,
-                             size_t *num_languages_ret,
-                             char **default_language_ret)
+static int
+xml_read_languages(const xmlNode *languages_node,
+                  utf8char ***languages_ret,
+                  size_t *num_languages_ret,
+                  utf8char **default_language_ret)
 {
        xmlNode *child;
        size_t num_languages = 0;
-       char **languages;
+       utf8char **languages;
        int ret;
 
        for_node_child(languages_node, child)
@@ -296,8 +308,9 @@ static int xml_read_languages(const xmlNode *languages_node,
 }
 
 /* Reads the information from a <WINDOWS> element inside an <IMAGE> element. */
-static int xml_read_windows_info(const xmlNode *windows_node,
-                                struct windows_info *windows_info)
+static int
+xml_read_windows_info(const xmlNode *windows_node,
+                     struct windows_info *windows_info)
 {
        xmlNode *child;
        int ret = 0;
@@ -343,8 +356,8 @@ static int xml_read_windows_info(const xmlNode *windows_node,
 }
 
 /* Reads the information from an <IMAGE> element. */
-static int xml_read_image_info(xmlNode *image_node,
-                              struct image_info *image_info)
+static int
+xml_read_image_info(xmlNode *image_node, struct image_info *image_info)
 {
        xmlNode *child;
        xmlChar *index_prop;
@@ -394,7 +407,7 @@ static int xml_read_image_info(xmlNode *image_node,
                        return ret;
        }
        if (!image_info->name) {
-               char *empty_name;
+               utf8char *empty_name;
                WARNING("Image with index %d has no name", image_info->index);
                empty_name = MALLOC(1);
                if (!empty_name)
@@ -407,8 +420,8 @@ static int xml_read_image_info(xmlNode *image_node,
 
 /* Reads the information from a <WIM> element, which should be the root element
  * of the XML tree. */
-static int xml_read_wim_info(const xmlNode *wim_node,
-                            struct wim_info **wim_info_ret)
+static int
+xml_read_wim_info(const xmlNode *wim_node, struct wim_info **wim_info_ret)
 {
        struct wim_info *wim_info;
        xmlNode *child;
@@ -477,49 +490,54 @@ err:
        return ret;
 }
 
-/* Prints the information contained in a `struct windows_info'. */
-static void print_windows_info(const struct windows_info *windows_info)
+/* Prints the information contained in a `struct windows_info'. 
+ *
+ * Warning: any strings printed here are in UTF-8 encoding.  If the locale
+ * character encoding is not UTF-8, the printed strings may be garbled. */
+static void
+print_windows_info(const struct windows_info *windows_info)
 {
        const struct windows_version *windows_version;
 
-       printf("Architecture:           %s\n", get_arch(windows_info->arch));
+       wimlib_printf("Architecture:           %s\n",
+                     get_arch(windows_info->arch) ?: "unknown");
 
        if (windows_info->product_name)
-               printf("Product Name:           %s\n",
-                      windows_info->product_name);
+               wimlib_printf("Product Name:           %U\n",
+                             windows_info->product_name);
 
        if (windows_info->edition_id)
-               printf("Edition ID:             %s\n",
-                      windows_info->edition_id);
+               wimlib_printf("Edition ID:             %U\n",
+                             windows_info->edition_id);
 
        if (windows_info->installation_type)
-               printf("Installation Type:      %s\n",
-                      windows_info->installation_type);
+               wimlib_printf("Installation Type:      %U\n",
+                             windows_info->installation_type);
 
        if (windows_info->hal)
-               printf("HAL:                    %s\n",
-                      windows_info->hal);
+               wimlib_printf("HAL:                    %U\n",
+                             windows_info->hal);
 
        if (windows_info->product_type)
-               printf("Product Type:           %s\n",
-                      windows_info->product_type);
+               wimlib_printf("Product Type:           %U\n",
+                             windows_info->product_type);
 
        if (windows_info->product_suite)
-               printf("Product Suite:          %s\n",
-                      windows_info->product_suite);
+               wimlib_printf("Product Suite:          %U\n",
+                             windows_info->product_suite);
 
        printf("Languages:              ");
        for (size_t i = 0; i < windows_info->num_languages; i++) {
-               fputs(windows_info->languages[i], stdout);
+               wimlib_printf("%U", windows_info->languages[i]);
                putchar(' ');
        }
        putchar('\n');
        if (windows_info->default_language)
-               printf("Default Language:       %s\n",
+               wimlib_printf("Default Language:       %U\n",
                       windows_info->default_language);
        if (windows_info->system_root)
-               printf("System Root:            %s\n",
-                      windows_info->system_root);
+               wimlib_printf("System Root:            %U\n",
+                             windows_info->system_root);
        if (windows_info->windows_version_exists) {
                windows_version = &windows_info->windows_version;
                printf("Major Version:          %"PRIu64"\n",
@@ -539,8 +557,9 @@ static void print_windows_info(const struct windows_info *windows_info)
 /* Writes the information contained in a `struct windows_version' to the XML
  * document being written.  This is the <VERSION> element inside the <WINDOWS>
  * element. */
-static int xml_write_windows_version(xmlTextWriter *writer,
-                                    const struct windows_version *version)
+static int
+xml_write_windows_version(xmlTextWriter *writer,
+                         const struct windows_version *version)
 {
        int rc;
        rc = xmlTextWriterStartElement(writer, "VERSION");
@@ -577,8 +596,9 @@ static int xml_write_windows_version(xmlTextWriter *writer,
 
 /* Writes the information contained in a `struct windows_info' to the XML
  * document being written. This is the <WINDOWS> element. */
-static int xml_write_windows_info(xmlTextWriter *writer,
-                                 const struct windows_info *windows_info)
+static int
+xml_write_windows_info(xmlTextWriter *writer,
+                      const struct windows_info *windows_info)
 {
        int rc;
        rc = xmlTextWriterStartElement(writer, "WINDOWS");
@@ -670,8 +690,8 @@ static int xml_write_windows_info(xmlTextWriter *writer,
 }
 
 /* Writes a time element to the XML document being constructed in memory. */
-static int xml_write_time(xmlTextWriter *writer, const char *element_name,
-                         u64 time)
+static int
+xml_write_time(xmlTextWriter *writer, const utf8char *element_name, u64 time)
 {
        int rc;
        rc = xmlTextWriterStartElement(writer, element_name);
@@ -695,8 +715,8 @@ static int xml_write_time(xmlTextWriter *writer, const char *element_name,
 }
 
 /* Writes an <IMAGE> element to the XML document. */
-static int xml_write_image_info(xmlTextWriter *writer,
-                               const struct image_info *image_info)
+static int
+xml_write_image_info(xmlTextWriter *writer, const struct image_info *image_info)
 {
        int rc;
        rc = xmlTextWriterStartElement(writer, "IMAGE");
@@ -783,7 +803,8 @@ static int xml_write_image_info(xmlTextWriter *writer,
 
 /* Makes space for another image in the XML information and return a pointer to
  * it.*/
-static struct image_info *add_image_info_struct(struct wim_info *wim_info)
+static struct image_info *
+add_image_info_struct(struct wim_info *wim_info)
 {
        struct image_info *images;
 
@@ -798,8 +819,8 @@ static struct image_info *add_image_info_struct(struct wim_info *wim_info)
        return &images[wim_info->num_images - 1];
 }
 
-static int clone_windows_info(const struct windows_info *old,
-                             struct windows_info *new)
+static int
+clone_windows_info(const struct windows_info *old, struct windows_info *new)
 {
        if (old->product_name && !(new->product_name = STRDUP(old->product_name)))
                return WIMLIB_ERR_NOMEM;
@@ -816,7 +837,7 @@ static int clone_windows_info(const struct windows_info *old,
                return WIMLIB_ERR_NOMEM;
 
        if (old->languages) {
-               new->languages = CALLOC(old->num_languages, sizeof(char*));
+               new->languages = CALLOC(old->num_languages, sizeof(new->languages[0]));
                if (!new->languages)
                        return WIMLIB_ERR_NOMEM;
                new->num_languages = old->num_languages;
@@ -841,7 +862,8 @@ static int clone_windows_info(const struct windows_info *old,
        return 0;
 }
 
-static int clone_image_info(const struct image_info *old, struct image_info *new)
+static int
+clone_image_info(const struct image_info *old, struct image_info *new)
 {
        new->dir_count              = old->dir_count;
        new->file_count             = old->file_count;
@@ -886,11 +908,12 @@ static int clone_image_info(const struct image_info *old, struct image_info *new
  * On failure, WIMLIB_ERR_NOMEM is returned and no changes are made.  Otherwise,
  * 0 is returned and the WIM information at *new_wim_info_p is modified.
  */
-int xml_export_image(const struct wim_info *old_wim_info,
-                    int image,
-                    struct wim_info **new_wim_info_p,
-                    const char *dest_image_name,
-                    const char *dest_image_description)
+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)
 {
        struct wim_info *new_wim_info;
        struct image_info *image_info;
@@ -942,7 +965,8 @@ err:
 }
 
 /* Removes an image from the XML information. */
-void xml_delete_image(struct wim_info **wim_info_p, int image)
+void
+xml_delete_image(struct wim_info **wim_info_p, int image)
 {
        struct wim_info *wim_info;
 
@@ -965,7 +989,8 @@ void xml_delete_image(struct wim_info **wim_info_p, int image)
        }
 }
 
-size_t xml_get_max_image_name_len(const WIMStruct *w)
+size_t
+xml_get_max_image_name_len(const WIMStruct *w)
 {
        size_t max_len = 0;
        if (w->wim_info) {
@@ -980,15 +1005,17 @@ size_t xml_get_max_image_name_len(const WIMStruct *w)
 }
 
 #ifdef ENABLE_CUSTOM_MEMORY_ALLOCATOR
-void xml_set_memory_allocator(void *(*malloc_func)(size_t),
-                                  void (*free_func)(void *),
-                                  void *(*realloc_func)(void *, size_t))
+void
+xml_set_memory_allocator(void *(*malloc_func)(size_t),
+                        void (*free_func)(void *),
+                        void *(*realloc_func)(void *, size_t))
 {
        xmlMemSetup(free_func, malloc_func, realloc_func, STRDUP);
 }
 #endif
 
-static int calculate_dentry_statistics(struct wim_dentry *dentry, void *arg)
+static int
+calculate_dentry_statistics(struct wim_dentry *dentry, void *arg)
 {
        struct image_info *info = arg;
        struct wim_lookup_table *lookup_table = info->lookup_table;
@@ -1066,10 +1093,11 @@ static int calculate_dentry_statistics(struct wim_dentry *dentry, void *arg)
  * Please note there is no official documentation for exactly how this is done.
  * But, see calculate_dentry_statistics().
  */
-void xml_update_image_info(WIMStruct *w, int image)
+void
+xml_update_image_info(WIMStruct *w, int image)
 {
        struct image_info *image_info;
-       char *flags_save;
+       utf8char *flags_save;
 
        DEBUG("Updating the image info for image %d", image);
 
@@ -1090,7 +1118,8 @@ void xml_update_image_info(WIMStruct *w, int image)
 }
 
 /* Adds an image to the XML information. */
-int xml_add_image(WIMStruct *w, const char *name)
+int
+xml_add_image(WIMStruct *w, const utf8char *name)
 {
        struct wim_info *wim_info;
        struct image_info *image_info;
@@ -1131,7 +1160,8 @@ out_free_wim_info:
 
 /* Prints information about the specified image from struct wim_info structure.
  * */
-void print_image_info(const struct wim_info *wim_info, int image)
+void
+print_image_info(const struct wim_info *wim_info, int image)
 {
        const struct image_info *image_info;
        const char *desc;
@@ -1142,7 +1172,7 @@ void print_image_info(const struct wim_info *wim_info, int image)
        image_info = &wim_info->images[image - 1];
 
        printf("Index:                  %d\n", image_info->index);
-       printf("Name:                   %s\n", image_info->name);
+       wimlib_printf("Name:                   %U\n", image_info->name);
 
        /* Always print the Description: part even if there is no
         * description. */
@@ -1150,15 +1180,15 @@ void print_image_info(const struct wim_info *wim_info, int image)
                desc = image_info->description;
        else
                desc = "";
-       printf("Description:            %s\n", desc);
+       wimlib_printf("Description:            %U\n", desc);
 
        if (image_info->display_name)
-               printf("Display Name:           %s\n",
-                      image_info->display_name);
+               wimlib_printf("Display Name:           %U\n",
+                             image_info->display_name);
 
        if (image_info->display_description)
-               printf("Display Description:    %s\n",
-                      image_info->display_description);
+               wimlib_printf("Display Description:    %U\n",
+                             image_info->display_description);
 
        printf("Directory Count:        %"PRIu64"\n", image_info->dir_count);
        printf("File Count:             %"PRIu64"\n", image_info->file_count);
@@ -1177,23 +1207,28 @@ void print_image_info(const struct wim_info *wim_info, int image)
        putchar('\n');
 }
 
-void libxml_global_init()
+void
+libxml_global_init()
 {
        xmlInitParser();
+       xmlInitCharEncodingHandlers();
 }
 
-void libxml_global_cleanup()
+void
+libxml_global_cleanup()
 {
        xmlCleanupParser();
+       xmlCleanupCharEncodingHandlers();
 }
 
 /*
  * Reads the XML data from a WIM file.
  */
-int read_xml_data(FILE *fp, const struct resource_entry *res_entry,
-                 u8 **xml_data_ret, struct wim_info **info_ret)
+int
+read_xml_data(FILE *fp, const struct resource_entry *res_entry,
+             utf16lechar **xml_data_ret, struct wim_info **info_ret)
 {
-       u8 *xml_data;
+       utf16lechar *xml_data;
        xmlDoc *doc;
        xmlNode *root;
        int ret;
@@ -1213,7 +1248,7 @@ int read_xml_data(FILE *fp, const struct resource_entry *res_entry,
                goto out;
        }
 
-       xml_data = MALLOC(res_entry->size + 2);
+       xml_data = MALLOC(res_entry->size + 3);
        if (!xml_data) {
                ret = WIMLIB_ERR_NOMEM;
                goto out;
@@ -1225,8 +1260,9 @@ int read_xml_data(FILE *fp, const struct resource_entry *res_entry,
                goto out_free_xml_data;
 
        /* Null-terminate just in case */
-       xml_data[res_entry->size] = 0;
-       xml_data[res_entry->size + 1] = 0;
+       ((u8*)xml_data)[res_entry->size] = 0;
+       ((u8*)xml_data)[res_entry->size + 1] = 0;
+       ((u8*)xml_data)[res_entry->size + 2] = 0;
 
        DEBUG("Parsing XML using libxml2 to create XML tree");
 
@@ -1283,8 +1319,9 @@ out:
  * element in the XML data.  If zero, TOTALBYTES is given the default value of
  * the offset of the XML data.
  */
-int write_xml_data(const struct wim_info *wim_info, int image, FILE *out,
-                  u64 total_bytes, struct resource_entry *out_res_entry)
+int
+write_xml_data(const struct wim_info *wim_info, int image, FILE *out,
+              u64 total_bytes, struct resource_entry *out_res_entry)
 {
        xmlCharEncodingHandler *encoding_handler;
        xmlOutputBuffer *out_buffer;
@@ -1324,21 +1361,19 @@ int write_xml_data(const struct wim_info *wim_info, int image, FILE *out,
        if (total_bytes == 0)
                total_bytes = start_offset;
 
-       xmlInitCharEncodingHandlers();
-
        /* The encoding of the XML data must be UTF-16LE. */
        encoding_handler = xmlGetCharEncodingHandler(XML_CHAR_ENCODING_UTF16LE);
        if (!encoding_handler) {
                ERROR("Failed to get XML character encoding handler for UTF-16LE");
                ret = WIMLIB_ERR_LIBXML_UTF16_HANDLER_NOT_AVAILABLE;
-               goto out_cleanup_char_encoding_handlers;
+               goto out;
        }
 
        out_buffer = xmlOutputBufferCreateFile(out, encoding_handler);
        if (!out_buffer) {
                ERROR("Failed to allocate xmlOutputBuffer");
                ret = WIMLIB_ERR_NOMEM;
-               goto out_cleanup_char_encoding_handlers;
+               goto out;
        }
 
        writer = xmlNewTextWriter(out_buffer);
@@ -1403,8 +1438,6 @@ out_free_text_writer:
 out_output_buffer_close:
        if (out_buffer != NULL)
                xmlOutputBufferClose(out_buffer);
-out_cleanup_char_encoding_handlers:
-       xmlCleanupCharEncodingHandlers();
 out:
        if (ret == 0)
                DEBUG("Successfully wrote XML data");
@@ -1412,7 +1445,8 @@ out:
 }
 
 /* Returns the name of the specified image. */
-WIMLIBAPI const char *wimlib_get_image_name(const WIMStruct *w, int image)
+WIMLIBAPI const utf8char *
+wimlib_get_image_name(const WIMStruct *w, int image)
 {
        if (image < 1 || image > w->hdr.image_count)
                return NULL;
@@ -1420,8 +1454,8 @@ WIMLIBAPI const char *wimlib_get_image_name(const WIMStruct *w, int image)
 }
 
 /* Returns the description of the specified image. */
-WIMLIBAPI const char *wimlib_get_image_description(const WIMStruct *w,
-                                                  int image)
+WIMLIBAPI const utf8char *
+wimlib_get_image_description(const WIMStruct *w, int image)
 {
        if (image < 1 || image > w->hdr.image_count)
                return NULL;
@@ -1429,7 +1463,8 @@ WIMLIBAPI const char *wimlib_get_image_description(const WIMStruct *w,
 }
 
 /* Determines if an image name is already used by some image in the WIM. */
-WIMLIBAPI bool wimlib_image_name_in_use(const WIMStruct *w, const char *name)
+WIMLIBAPI bool
+wimlib_image_name_in_use(const WIMStruct *w, const utf8char *name)
 {
        if (!name || !*name)
                return false;
@@ -1440,12 +1475,15 @@ WIMLIBAPI bool wimlib_image_name_in_use(const WIMStruct *w, const char *name)
 }
 
 /* Extracts the raw XML data to a file stream. */
-WIMLIBAPI int wimlib_extract_xml_data(WIMStruct *w, FILE *fp)
+WIMLIBAPI int
+wimlib_extract_xml_data(WIMStruct *w, FILE *fp)
 {
+       size_t bytes_written;
+
        if (!w->xml_data)
                return WIMLIB_ERR_INVALID_PARAM;
-       if (fwrite(w->xml_data, 1, w->hdr.xml_res_entry.size, fp) !=
-                       w->hdr.xml_res_entry.size) {
+       bytes_written = fwrite(w->xml_data, 1, w->hdr.xml_res_entry.size, fp);
+       if (bytes_written != w->hdr.xml_res_entry.size) {
                ERROR_WITH_ERRNO("Failed to extract XML data");
                return WIMLIB_ERR_WRITE;
        }
@@ -1453,9 +1491,10 @@ WIMLIBAPI int wimlib_extract_xml_data(WIMStruct *w, FILE *fp)
 }
 
 /* Sets the name of an image in the WIM. */
-WIMLIBAPI int wimlib_set_image_name(WIMStruct *w, int image, const char *name)
+WIMLIBAPI int
+wimlib_set_image_name(WIMStruct *w, int image, const utf8char *name)
 {
-       char *p;
+       utf8char *p;
        int i;
 
        DEBUG("Setting the name of image %d to %s", image, name);
@@ -1474,8 +1513,8 @@ WIMLIBAPI int wimlib_set_image_name(WIMStruct *w, int image, const char *name)
                if (i == image)
                        continue;
                if (strcmp(w->wim_info->images[i - 1].name, name) == 0) {
-                       ERROR("The name `%s' is already used for image %d",
-                             name, i);
+                       ERROR("The name `%U' is already in use in the WIM!",
+                             name);
                        return WIMLIB_ERR_IMAGE_NAME_COLLISION;
                }
        }
@@ -1490,10 +1529,11 @@ WIMLIBAPI int wimlib_set_image_name(WIMStruct *w, int image, const char *name)
 }
 
 /* Sets the description of an image in the WIM. */
-WIMLIBAPI int wimlib_set_image_descripton(WIMStruct *w, int image,
-                                         const char *description)
+WIMLIBAPI int
+wimlib_set_image_descripton(WIMStruct *w, int image,
+                           const utf8char *description)
 {
-       char *p;
+       utf8char *p;
 
        if (image < 1 || image > w->hdr.image_count) {
                ERROR("%d is not a valid image", image);
@@ -1512,8 +1552,8 @@ WIMLIBAPI int wimlib_set_image_descripton(WIMStruct *w, int image,
 }
 
 /* Set the <FLAGS> element of a WIM image */
-WIMLIBAPI int wimlib_set_image_flags(WIMStruct *w, int image,
-                                    const char *flags)
+WIMLIBAPI int
+wimlib_set_image_flags(WIMStruct *w, int image, const utf8char *flags)
 {
        char *p;
 
index 54993cb..6356613 100644 (file)
--- a/src/xml.h
+++ b/src/xml.h
@@ -13,38 +13,53 @@ struct wim_info {
 };
 
 /* xml.c */
-extern int xml_export_image(const struct wim_info *old_wim_info, int image,
-                           struct wim_info **new_wim_info_p,
-                           const char *dest_image_name,
-                           const char *dest_image_description);
+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);
 
-extern size_t xml_get_max_image_name_len(const WIMStruct *w);
+extern size_t
+xml_get_max_image_name_len(const WIMStruct *w);
 
-extern void xml_update_image_info(WIMStruct *w, int image);
+extern void
+xml_update_image_info(WIMStruct *w, int image);
 
-extern void xml_delete_image(struct wim_info **wim_info_p, int image);
+extern void
+xml_delete_image(struct wim_info **wim_info_p, int image);
 
-extern int xml_add_image(WIMStruct *w, const char *name);
+extern int
+xml_add_image(WIMStruct *w, const utf8char *name);
 
-extern void free_wim_info(struct wim_info *info);
+extern void
+free_wim_info(struct wim_info *info);
 
-extern void print_image_info(const struct wim_info *wim_info, int image);
+extern void
+print_image_info(const struct wim_info *wim_info, int image);
 
-extern int read_xml_data(FILE *fp, const struct resource_entry *res,
-                        u8 **xml_data_ret, struct wim_info **info_ret);
+extern int
+read_xml_data(FILE *fp, const struct resource_entry *res,
+             utf16lechar **xml_data_ret,
+             struct wim_info **info_ret);
 
-extern int write_xml_data(const struct wim_info *wim_info, int image, FILE *out,
-                         u64 total_bytes, struct resource_entry *out_res_entry);
+extern int
+write_xml_data(const struct wim_info *wim_info, int image, FILE *out,
+              u64 total_bytes, struct resource_entry *out_res_entry);
 
-extern void libxml_global_init();
-extern void libxml_global_cleanup();
+extern void
+libxml_global_init();
 
-static inline u64 wim_info_get_total_bytes(const struct wim_info *info)
+extern void
+libxml_global_cleanup();
+
+static inline u64
+wim_info_get_total_bytes(const struct wim_info *info)
 {
        return info->total_bytes;
 }
 
-static inline unsigned wim_info_get_num_images(const struct wim_info *info)
+static inline unsigned
+wim_info_get_num_images(const struct wim_info *info)
 {
        return info->num_images;
 }