* 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;
* 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;
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;
/* 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] = '/';
* 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,
#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. */
"";
#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);
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) {
/* 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;
*eol = '\0';
/* Translate backslash to forward slash */
- for (char *pp = p; pp != eol; pp++)
+ for (mbchar *pp = p; pp != eol; pp++)
if (*pp == '\\')
*pp = '/';
}
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;
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++) {
* 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
/* 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)
}
#ifdef __WIN32__
-static void zap_backslashes(char *s)
+static void
+zap_backslashes(char *s)
{
while (*s) {
if (*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\"}",
}
}
-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);
*
* 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) {
/* 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);
/* 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;
}
/* 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;
}
}
* 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 */
/* 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 {
}
}
-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;
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)
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;
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;
}
/*
* 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;
/* 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;
}
* 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++)
/* 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));
/* 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;
}
}
-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) {
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) {
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;
* @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;
}
}
-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);
/* 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;
}
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);
}
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");
*
* 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;
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);
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)
{
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);
* @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));
}
/* 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)
* 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;
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;
}
/* 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;
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)
}
#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;
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;
* 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;
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;
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
* 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;
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.
* 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 */
* 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;
}
/*
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:
* 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;
* @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;
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 */
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);
}
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);
/* 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)
*
* 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));
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
};
-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;
}
/*
* 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;
* 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)
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
#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"
#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);
}
/*
- * 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;
+}
#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
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);
}
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++) {
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;
}
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) {
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) {
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;
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. */
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;
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);
#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;
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:
}
#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)
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;
#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);
/* 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
/* 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;
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);
}
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;
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;
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;
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(<e->inode_list);
}
}
-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;
#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,
#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;
};
#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;
/* 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;
/* 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)
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,
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) {
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;
/* 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) {
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);
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);
}
/* 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;
* 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;
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;
* 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;
/* 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;
*
* 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);
#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;
* 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;
__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);
}
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 *
{
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);
{
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);
* 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(). */
* 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;
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;
#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);
}
*
* 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;
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);
}
}
-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);
}
/* 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)",
*
* 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);
* 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;
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;
* 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();
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;
* 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;
*
* 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;
* 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) {
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;
/*
* 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,
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;
}
}
-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;
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++) {
}
/* 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;
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)
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);
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);
* @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;
/* 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;
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;
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);
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 = {
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);
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 = {
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 = {
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;
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;
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;
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;
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;
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.");
},
};
-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;
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;
* 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;
}
#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();
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();
}
/* 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) {
#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);
/*
* 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;
#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;
#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();
}
#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;
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);
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';
}
}
-
/* 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;
}
/* 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;
/*
* 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;
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;
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;
}
-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);
}
/* 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);
#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;
#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;
}
/* 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();
#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;
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)
}
#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);
/* 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;
}
/* 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;
*
* 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;
}
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;
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;
/* 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;
* 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;
#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!");
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 */
*
* 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", "
/* 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
/*
* 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 "
/* 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;
/* 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);
}
#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;
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;
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.
*
* 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;
*
* 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);
}
*
* @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)];
* 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;
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);
*
* (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;
* 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;
* 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;
/*
* 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);
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;
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);
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;
/*
* 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);
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);
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);
}
/* 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);
/* 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;
* 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;
/* 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;
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++)
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);
}
#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 */
* 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;
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;
* 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;
*
* 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;
#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;
}
}
-void wimlib_error(const char *format, ...)
+void
+wimlib_error(const char *format, ...)
{
va_list va;
va_end(va);
}
-void wimlib_error_with_errno(const char *format, ...)
+void
+wimlib_error_with_errno(const char *format, ...)
{
va_list va;
va_end(va);
}
-void wimlib_warning(const char *format, ...)
+void
+wimlib_warning(const char *format, ...)
{
va_list va;
va_end(va);
}
-void wimlib_warning_with_errno(const char *format, ...)
+void
+wimlib_warning_with_errno(const char *format, ...)
{
va_list va;
#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;
#endif
}
-static const char *error_strings[] = {
+static const mbchar *error_strings[] = {
[WIMLIB_ERR_SUCCESS]
= "Success",
[WIMLIB_ERR_ALREADY_LOCKED]
= "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]
= "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]
= "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;
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);
return p;
}
-char *wimlib_strdup(const char *str)
+char *
+wimlib_strdup(const char *str)
{
size_t size;
char *p;
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;
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();
}
/* 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();
/* 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] == '/')
/* 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)
* 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, ':');
* 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;
}
/* 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) {
* 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;
}
}
-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);
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; })
}
#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
# 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); \
#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;"
#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 */
#include <errno.h>
#include <fcntl.h>
+#include <langinfo.h>
#include <limits.h>
#include <stdarg.h>
#include <stdlib.h>
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();
}
*/
typedef struct WIMStruct WIMStruct;
+typedef char wimlib_mbchar;
+typedef char wimlib_utf8char;
+
/**
* Specifies the compression type of a WIM file.
*/
* ::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. */
/** 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,
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
/** 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
/** 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. */
/** 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;
};
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;
WIMLIB_ERR_WRITE,
WIMLIB_ERR_XML,
WIMLIB_ERR_INVALID_OVERLAY,
+ WIMLIB_ERR_INVALID_MULTIBYTE_STRING,
+ WIMLIB_ERR_UNICODE_STRING_NOT_REPRESENTABLE,
};
* ::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
* (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.
* @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.
* @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.
* @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
* 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
* @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
*
* @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.
* 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.
* ::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.
* 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.
* 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.
* 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.
* 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);
/**
* @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
* @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
* 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.
* 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.
* 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.
* 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.
* 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.
* @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.
* 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.
* 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
* @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.
* @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
*
* @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
* @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
*
* @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
* 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.
* @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.
* 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
* @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.
* @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.
* 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
* --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.
* 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().
* 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.
* 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 */
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. */
/* 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;
}
}
/* 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);
}
/* add_image.c */
struct pattern_list {
- const char **pats;
+ const mbchar **pats;
size_t num_pats;
size_t num_allocated_pats;
};
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 */
/* 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 */
#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;
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 */
#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
}
-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 */
#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;
}
}
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;
/* 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);
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,
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);
#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);
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. */
};
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 {
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;
};
};
/* 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";
return "x86_64";
/* XXX Are there other arch values? */
default:
- snprintf(buf, sizeof(buf), "%d (unknown)", arch);
- return buf;
+ return NULL;
}
}
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;
/* 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)
}
/* 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)
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;
/* 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;
}
/* 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;
/* 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);
}
/* 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);
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) {
/* 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) {
/* 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)
}
/* 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;
}
/* 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;
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)
/* 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;
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",
/* 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");
/* 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");
}
/* 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);
}
/* 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");
/* 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;
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;
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;
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;
* 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;
}
/* 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;
}
}
-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) {
}
#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;
* 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);
}
/* 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;
/* 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;
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. */
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);
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;
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;
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");
* 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;
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);
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");
}
/* 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;
}
/* 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;
}
/* 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;
}
/* 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;
}
}
/* 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);
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;
}
}
}
/* 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);
}
/* 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;
};
/* 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;
}