#include <ctype.h>
#include <errno.h>
#include <stdlib.h>
-#include <string.h>
+
+#if TCHAR_IS_UTF16LE
+# include <wchar.h>
+#else
+# include <string.h>
+#endif
+
#include <unistd.h>
#ifdef HAVE_ALLOCA_H
#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
*/
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,
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;
/* 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] = '/';
* 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,
#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"
"*.mp3\n"
"*.zip\n"
"*.cab\n"
-"\\WINDOWS\\inf\\*.pnf\n";
+"\\WINDOWS\\inf\\*.pnf\n"
+);
#else
-"";
+T("");
#endif
static void
}
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));
* `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);
}
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:
}
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
#endif
) == 0)
{
- DEBUG("`%s' matches the pattern \"%s\"",
+ DEBUG("\"%"TS"\" matches the pattern \"%"TS"\"",
string, pat);
return true;
}
* 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);
/* 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++;
}
}
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
/* 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
{
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;
}
/* 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;
}
*/
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 */
/* 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;
}
/* 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) {
* 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.
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 *,
}
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;
}
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)
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) {
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;
}
}
if (root_dentry == NULL) {
- ret = new_filler_directory("" , &root_dentry);
+ ret = new_filler_directory(T(""), &root_dentry);
if (ret)
goto out_free_dentry_tree;
}
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)
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,
#include "wimlib_internal.h"
#include <errno.h>
+#ifdef TCHAR_IS_UTF16LE
+# include <wchar.h>
+#endif
+
/* Calculates the unaligned length, in bytes, of an on-disk WIM dentry that has
* a file name and short name that take the specified numbers of bytes. This
* excludes any alternate data stream entries that may follow the dentry. */
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,
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;
/* 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 {
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++;
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,
p = pp;
parent_dentry = cur_dentry;
}
- FREE(path_utf16le);
if (cur_dentry == NULL) {
if (dentry_is_directory(parent_dentry))
errno = ENOENT;
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);
/* 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);
}
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;
}
* 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
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) {
} 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);
}
/* 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;
*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;
}
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);
}
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);
}
* 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 {
break;
}
} while (++i != inode->i_num_ads);
+ #if !TCHAR_IS_UTF16LE
FREE(stream_name_utf16le);
+ #endif
return result;
}
}
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;
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);
}
* 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)
{
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)
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;
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)
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);
}
}
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);
}
}
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:
* 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;
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)
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
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,
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);
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);
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 *
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);
#include <iconv.h>
#include <pthread.h>
#include <stdlib.h>
+#include <string.h>
-bool wimlib_mbs_is_utf8 = true;
+bool wimlib_mbs_is_utf8 = !TCHAR_IS_UTF16LE;
/* List of iconv_t conversion descriptors for a specific character conversion.
* The idea is that it is not thread-safe to have just one conversion
#define DEFINE_CHAR_CONVERSION_FUNCTIONS(varname1, longname1, chartype1,\
varname2, longname2, chartype2,\
+ earlyreturn, \
worst_case_len_expr, \
err_return, \
err_msg) \
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) \
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 "
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)
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)
{
} while (*++utf8_str);
return false;
}
+#endif
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,
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;
}
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;
}
# include <alloca.h>
#endif
+#if TCHAR_IS_UTF16LE
+# include <wchar.h>
+#endif
+
#ifndef __WIN32__
static int
extract_regular_file_linked(struct wim_dentry *dentry,
- const mbchar *output_path,
+ const char *output_path,
struct apply_args *args,
struct wim_lookup_table_entry *lte)
{
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 =
}
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++) {
}
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;
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
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;
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;
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:
}
#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)
}
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)
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);
{
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
* @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;
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;
/* 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;
}
}
+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);
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,
* 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)
* 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;
}
* 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)
{
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;
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,
*/
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,
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;
#ifdef WITH_NTFS_3G
struct ntfs_location {
- mbchar *path;
+ tchar *path;
utf16lechar *stream_name;
u16 stream_name_nchars;
struct _ntfs_volume **ntfs_vol_p;
* 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;
__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);
#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"
* 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(). */
* 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;
* 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;
* 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;
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;
* 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) {
}
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)
}
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);
* daemon to finish writing the WIM file.
*/
static int
-execute_fusermount(const mbchar *dir)
+execute_fusermount(const char *dir)
{
pid_t pid;
int ret;
#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();
}
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();
#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;
}
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);
* 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;
#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;
/* 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();
#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))
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;
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) {
/* 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);
/* 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);
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';
/* 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;
/* 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;
* 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;
{
struct fill_params *fill_params = arg;
- mbchar *file_name_mbs;
+ char *file_name_mbs;
size_t file_name_mbs_nbytes;
int ret;
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;
/* 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;
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);
/* 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);
/* 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);
#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;
/* 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;
/* Remove a directory */
static int
-wimfs_rmdir(const mbchar *path)
+wimfs_rmdir(const char *path)
{
struct wim_dentry *dentry;
WIMStruct *w = wimfs_get_WIMStruct();
#ifdef ENABLE_XATTR
/* Write an alternate data stream through the XATTR interface */
static int
-wimfs_setxattr(const 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;
#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);
/* 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;
/* 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;
* 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;
}
#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;
* 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;
/* 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;
/*
* 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"
* 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;
}
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();
}
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;
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;
}
#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:
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;
}
/* 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;
#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 */
#include "xml.h"
#include "buffer_io.h"
+#if TCHAR_IS_UTF16LE
+# include <wchar.h>
+#endif
+
struct split_args {
WIMStruct *w;
- mbchar *swm_base_name;
+ tchar *swm_base_name;
size_t swm_base_name_len;
- const mbchar *swm_suffix;
+ const tchar *swm_suffix;
struct list_head lte_list;
int cur_part_number;
int write_flags;
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;
/* 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;
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;
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;
* 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;
}
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;
/* 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.
* 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;
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;
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);
}
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;
* 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;
*/
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)
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
#include <unistd.h> /* for getpid() */
-/* Windoze compatibility */
-#ifdef __WIN32__
-# define strerror_r(errnum, buf, bufsize) strerror_s(buf, bufsize, errnum)
-#endif
-
size_t
utf16le_strlen(const utf16lechar *s)
{
* 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,
&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)
}
}
return n;
+#endif
}
int
-wimlib_printf(const char *format, ...)
+wimlib_printf(const tchar *format, ...)
{
int ret;
va_list va;
}
int
-wimlib_fprintf(FILE *fp, const char *format, ...)
+wimlib_fprintf(FILE *fp, const tchar *format, ...)
{
int ret;
va_list va;
#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
#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
}
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);
#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))
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 *),
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();
/* 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--;
/* 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;
* 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
* 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;
}
}
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);
}
# 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
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);
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); \
#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__)
#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__)
extern void (*wimlib_free_func)(void *);
extern void *(*wimlib_realloc_func)(void *, size_t);
extern void *wimlib_calloc(size_t nmemb, size_t size);
+#ifdef __WIN32__
+extern wchar_t *wimlib_wcsdup(const wchar_t *str);
+#endif
extern char *wimlib_strdup(const char *str);
# define MALLOC wimlib_malloc_func
# define FREE wimlib_free_func
# define REALLOC wimlib_realloc_func
# define CALLOC wimlib_calloc
# define STRDUP wimlib_strdup
+# define WSTRDUP wimlib_wcsdup
#else /* ENABLE_CUSTOM_MEMORY_ALLOCATOR */
# include <stdlib.h>
# include <string.h>
# define REALLOC realloc
# define CALLOC calloc
# define STRDUP strdup
+# define WSTRDUP wcsdup
#endif /* !ENABLE_CUSTOM_MEMORY_ALLOCATOR */
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);
print_byte_field(const u8 field[], size_t len)
{
while (len--)
- printf("%02hhx", *field++);
+ tprintf(T("%02hhx"), *field++);
}
static inline u32
}
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)
;
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");
}
}
* 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)
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
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);
}
* 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;
}
/* 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;
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)");
xml_num_images = wim_info_get_num_images(w->wim_info);
if (xml_num_images != w->hdr.image_count) {
- ERROR("In the file `%s', there are %u <IMAGE> elements "
+ ERROR("In the file `%"TS"', there are %u <IMAGE> elements "
"in the XML data,", in_wim_path, xml_num_images);
ERROR("but %u images in the WIM! There must be exactly one "
"<IMAGE> element per image.", w->hdr.image_count);
return WIMLIB_ERR_IMAGE_COUNT;
}
- DEBUG("Done beginning read of WIM file `%s'.", in_wim_path);
+ DEBUG("Done beginning read of WIM file `%"TS"'.", in_wim_path);
return 0;
}
* 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)
{
*/
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.
* ::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. */
/** 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,
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
/** 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
/** 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. */
/** 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;
};
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;
* 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.
*
* 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
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);
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,
*/
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,
* 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);
/**
* 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);
/**
* 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);
/**
* 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);
* 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.
* 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);
* 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.
* 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.
*/
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.
*/
extern int
wimlib_set_image_descripton(WIMStruct *wim, int image,
- const wimlib_utf8char *description);
+ const wimlib_tchar *description);
/**
* Changes what is written in the \<FLAGS\> element in the WIM XML data
* 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.
* 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.
* 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);
/**
* 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);
/**
* 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 */
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;
/* add_image.c */
struct pattern_list {
- const mbchar **pats;
+ const tchar **pats;
size_t num_pats;
size_t num_allocated_pats;
};
struct pattern_list exclusion_exception;
struct pattern_list compression_exclusion_list;
struct pattern_list alignment_list;
- 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
struct apply_args {
WIMStruct *w;
- const mbchar *target;
+ const tchar *target;
int extract_flags;
unsigned num_utime_warnings;
struct list_head *stream_list;
/* 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,
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 */
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);
/* 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;
/* 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);
}
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;
}
/* 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;
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);
+}
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,
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
#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);
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
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();
# define INVALID_HANDLE_VALUE ((HANDLE)(-1))
#endif
+#if TCHAR_IS_UTF16LE
+# include <wchar.h>
+#endif
+
static int
fflush_and_ftruncate(FILE *fp, off_t size)
{
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;
}
}
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;
}
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;
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;
}
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);
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;
}
#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;
}
}
/* 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,
/* 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)
{
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;
}
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
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;
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
#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;
}
/* 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;
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;
}
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;
};
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;
};
};
/* 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;
{
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);
}
}
+const struct xml_string_spec {
+ const char *name;
+ size_t offset;
+};
+
+#define ELEM(STRING_NAME, MEMBER_NAME) \
+ {STRING_NAME, offsetof(struct image_info, MEMBER_NAME)}
+static const struct xml_string_spec image_info_xml_string_specs[] =
+ ELEM("NAME", name),
+ ELEM("DESCRIPTION", description),
+ ELEM("DISPLAYNAME", display_name),
+ ELEM("DISPLAYDESCRIPTION", display_description),
+ ELEM("FLAGS", flags),
+};
+#undef ELEM
+
+#define ELEM(STRING_NAME, MEMBER_NAME) \
+ {STRING_NAME, offsetof(struct windows_info, MEMBER_NAME)}
+static const struct xml_string_spec windows_info_xml_string_specs[] = {
+ ELEM("PRODUCTNAME", product_name),
+ ELEM("EDITIONID", edition_id),
+ ELEM("INSTALLATIONTYPE", installation_type),
+ ELEM("HAL", hal),
+ ELEM("PRODUCTTYPE", product_type),
+ ELEM("PRODUCTSUITE", product_suite),
+ ELEM("DEFAULT", default_language),
+ ELEM("SYSTEMROOT", system_root),
+};
+
+static int
+xml_write_string(xmlTextWriter *writer, const char *name,
+ const tchar *tstr)
+{
+ if (tstr) {
+ const utf8char *utf8_str;
+ int rc = tstr_to_utf8_simple(tstr, &utf8_str);
+ if (rc)
+ return rc;
+ rc = xmlTextWriterWriteElement(writer, name, utf8_str);
+ FREE(utf8_str);
+ if (rc < 0)
+ return rc;
+ }
+ return 0;
+}
+
+static int
+xml_write_strings_from_specs(xmlTextWriter *writer, const void *struct_with_strings,
+ const struct xml_string_spec *specs, size_t num_specs)
+{
+ for (size_t i = 0; i < num_specs; i++) {
+ int rc = xml_write_string(writer, specs[i].name,
+ *(const tchar * const *)
+ (struct_with_strings + specs[i].offset));
+ if (rc)
+ return rc;
+ }
+ return 0;
+}
+
+
/* Writes the information contained in a `struct windows_version' to the XML
* document being written. This is the <VERSION> element inside the <WINDOWS>
return rc;
}
- if (image_info->name) {
- rc = xmlTextWriterWriteElement(writer, "NAME",
- image_info->name);
- if (rc < 0)
- return rc;
- }
-
- if (image_info->description) {
- rc = xmlTextWriterWriteElement(writer, "DESCRIPTION",
- image_info->description);
- if (rc < 0)
- return rc;
- }
- if (image_info->display_name) {
- rc = xmlTextWriterWriteElement(writer, "DISPLAYNAME",
- image_info->display_name);
- if (rc < 0)
- return rc;
- }
- if (image_info->display_description) {
- rc = xmlTextWriterWriteElement(writer, "DISPLAYDESCRIPTION",
- image_info->display_description);
- if (rc < 0)
- return rc;
- }
-
- if (image_info->flags) {
- rc = xmlTextWriterWriteElement(writer, "FLAGS",
- image_info->flags);
- if (rc < 0)
- return rc;
- }
+ rc = xml_write_strings_from_specs(writer, image_info,
+ image_info_xml_string_specs,
+ ARRAY_LEN(image_info_xml_string_specs));
+ if (rc)
+ return rc;
- return xmlTextWriterEndElement(writer); /* </IMAGE> */
+ rc = xmlTextWriterEndElement(writer); /* </IMAGE> */
+ if (rc < 0)
+ return rc;
+ return 0;
}
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;
DEBUG("Writing %d <IMAGE> elements", last - first + 1);
for (int i = first; i <= last; i++) {
ret = xml_write_image_info(writer, &wim_info->images[i - 1]);
- CHECK_RET;
+ if (ret) {
+ CHECK_RET;
+ goto out_free_text_writer;
+ }
}
}
}
/* 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)
}
/* 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)
return false;
}
+
/* Extracts the raw XML data to a file stream. */
WIMLIBAPI int
wimlib_extract_xml_data(WIMStruct *w, FILE *fp)
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);
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);