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