goto out;
}
- root = new_dentry_with_timeless_inode(path_basename(root_disk_path));
- if (!root) {
- if (errno == EILSEQ)
- ret = WIMLIB_ERR_INVALID_UTF8_STRING;
- else if (errno == ENOMEM)
- ret = WIMLIB_ERR_NOMEM;
- else
- ret = WIMLIB_ERR_ICONV_NOT_AVAILABLE;
+ ret = new_dentry_with_timeless_inode(path_basename(root_disk_path),
+ &root);
+ if (ret)
goto out;
- }
inode = root->d_inode;
/* Creates a new directory to place in the WIM image. This is to create parent
* directories that are not part of any target as needed. */
-static struct wim_dentry *
-new_filler_directory(const mbchar *name)
+static int
+new_filler_directory(const mbchar *name, struct wim_dentry **dentry_ret)
{
+ int ret;
struct wim_dentry *dentry;
+
DEBUG("Creating filler directory \"%s\"", name);
- dentry = new_dentry_with_inode(name);
- if (dentry) {
+ ret = new_dentry_with_inode(name, &dentry);
+ if (ret == 0) {
/* Leave the inode number as 0 for now. The final inode number
* will be assigned later by assign_inode_numbers(). */
dentry->d_inode->i_resolved = 1;
dentry->d_inode->i_attributes = FILE_ATTRIBUTE_DIRECTORY;
}
- return dentry;
+ return ret;
}
/* Transfers the children of @branch to @target. It is an error if @target is
{
char *slash;
struct wim_dentry *dentry, *parent, *target;
+ int ret;
DEBUG("Attaching branch \"%W\" => \"%s\"",
branch->file_name, target_path);
/* Adding a non-root branch. Create root if it hasn't been created
* already. */
if (!*root_p) {
- *root_p = new_filler_directory("");
- if (!*root_p)
- return WIMLIB_ERR_NOMEM;
+ ret = new_filler_directory("", root_p);
+ if (ret)
+ return ret;
}
/* Walk the path to the branch, creating filler directories as needed.
*slash = '\0';
dentry = get_dentry_child_with_name(parent, target_path);
if (!dentry) {
- dentry = new_filler_directory(target_path);
- if (!dentry)
- return WIMLIB_ERR_NOMEM;
+ ret = new_filler_directory(target_path, &dentry);
+ if (ret)
+ return ret;
dentry_add_child(parent, dentry);
}
parent = dentry;
/* If the target path already existed, overlay the branch onto it.
* Otherwise, set the branch as the target path. */
- target = get_dentry_child_with_utf16le_name(parent, branch->file_name);
+ target = get_dentry_child_with_utf16le_name(parent, branch->file_name,
+ branch->file_name_nbytes);
if (target) {
return do_overlay(target, branch);
} else {
}
if (wimlib_image_name_in_use(w, name)) {
- ERROR("There is already an image named \"%s\" in `%s'",
- name, w->filename);
+ ERROR("There is already an image named \"%U\" in the WIM!",
+ name);
return WIMLIB_ERR_IMAGE_NAME_COLLISION;
}
DEBUG("Building dentry tree.");
if (num_sources == 0) {
- root_dentry = new_filler_directory("");
- if (!root_dentry) {
- ret = WIMLIB_ERR_NOMEM;
+ ret = new_filler_directory("", &root_dentry);
+ if (ret)
goto out_free_security_data;
- }
} else {
size_t i;
* the output location, with the size indicated in the function name, in little
* endian format. A pointer to the input location directly following the bytes
* read is returned. */
-static inline const u8 *get_u8(const u8 *p, u8 *res)
+static inline const void *
+get_u8(const void *p, u8 *res)
{
- *res = *p;
+ *res = *(const u8*)p;
return p + 1;
}
-
-static inline const u8 *get_u16(const u8 *p, u16 *res)
+static inline const void *
+get_u16(const void *p, u16 *res)
{
- *res = le16_to_cpu(*(u16*)p);
+ *res = le16_to_cpu(*(const u16*)p);
return p + 2;
}
-static inline const u8 *get_u32(const u8 *p, u32 *res)
+static inline const void *
+get_u32(const void *p, u32 *res)
{
- *res = le32_to_cpu(*(u32*)p);
+ *res = le32_to_cpu(*(const u32*)p);
return p + 4;
}
-static inline const u8 *get_u56(const u8 *p, u64 *res)
+static inline const void *
+get_u56(const void *p, u64 *res)
{
- *res = le64_to_cpu(*(u64*)p) & 0x00ffffffffffffff;
+ *res = le64_to_cpu(*(const u64*)p) & 0x00ffffffffffffff;
return p + 7;
}
-static inline const u8 *get_u64(const u8 *p, u64 *res)
+static inline const void *
+get_u64(const void *p, u64 *res)
{
- *res = le64_to_cpu(*(u64*)p);
+ *res = le64_to_cpu(*(const u64*)p);
return p + 8;
}
* location in little-endian format as the data type indicated in the function
* name, and a pointer to the output location directory following the bytes
* written is returned. */
-static inline u8 *put_u8(u8 *res, u8 val)
+static inline void *
+put_u8(void *res, u8 val)
{
- *res = val;
+ *(u8*)res = val;
return res + 1;
}
-static inline u8 *put_u16(u8 *res, u16 val)
+static inline void *
+put_u16(void *res, u16 val)
{
*(uint16_t*)res = cpu_to_le16(val);
return res + 2;
}
-static inline u8 *put_u32(u8 *res, u32 val)
+static inline void *
+put_u32(void *res, u32 val)
{
*(uint32_t*)res = cpu_to_le32(val);
return res + 4;
}
-static inline u8 *put_u56(u8 *res, u64 val)
+static inline void *
+put_u56(void *res, u64 val)
{
const u8 *__p = (const u8*)&val;
#ifdef WORDS_BIGENDIAN
return res + 7;
}
-static inline u8 *put_u64(u8 *res, u64 val)
+static inline void *
+put_u64(void *res, u64 val)
{
*(u64*)res = cpu_to_le64(val);
return res + 8;
}
-static inline const u8 *get_bytes(const u8 *p, size_t num_bytes, void *res)
+static inline const void *
+get_bytes(const void *p, size_t num_bytes, void *res)
{
memcpy(res, p, num_bytes);
return p + num_bytes;
}
-static inline u8 *put_zeroes(u8 *p, size_t num_bytes)
+static inline void *
+put_zeroes(void *p, size_t num_bytes)
{
return (u8*)memset(p, 0, num_bytes) + num_bytes;
}
-static inline u8 *put_bytes(u8 *p, size_t num_bytes, const void *input)
+static inline void *
+put_bytes(void *p, size_t num_bytes, const void *input)
{
return (u8*)memcpy(p, input, num_bytes) + num_bytes;
}
ret = mbs_to_utf16le(name, strlen(name), &name_utf16le,
&name_utf16le_nbytes);
- if (name_utf16le_nbytes > 0xffff) {
- FREE(name_utf16le);
- ERROR("Multibyte string \"%s\" is too long!", name);
- ret = WIMLIB_ERR_INVALID_UTF8_STRING;
- }
if (ret == 0) {
- FREE(*name_utf16le_ret);
- *name_utf16le_ret = name_utf16le;
- *name_utf16le_nbytes_ret = name_utf16le_nbytes;
+ if (name_utf16le_nbytes > 0xffff) {
+ FREE(name_utf16le);
+ ERROR("Multibyte string \"%s\" is too long!", name);
+ ret = WIMLIB_ERR_INVALID_UTF8_STRING;
+ } else {
+ FREE(*name_utf16le_ret);
+ *name_utf16le_ret = name_utf16le;
+ *name_utf16le_nbytes_ret = name_utf16le_nbytes;
+ }
}
return ret;
}
&dentry->file_name_nbytes);
if (ret == 0) {
/* Clear the short name and recalculate the dentry length */
- if (dentry->short_name_nbytes) {
+ if (dentry_has_short_name(dentry)) {
FREE(dentry->short_name);
dentry->short_name = NULL;
dentry->short_name_nbytes = 0;
char *parent_full_path;
u32 parent_full_path_nbytes;
const struct wim_dentry *parent;
- char *name_mbs;
size_t name_mbs_nbytes;
int ret;
}
static int
-dentry_compare_names(const struct wim_dentry *d1, const struct wim_dentry *d2)
+compare_utf16le_names(const utf16lechar *name1, size_t nbytes1,
+ const utf16lechar *name2, size_t nbytes2)
{
- int result = memcmp(d1->file_name, d2->file_name,
- min(d1->file_name_nbytes, d2->file_name_nbytes));
+ int result = memcmp(name1, name2, min(nbytes1, nbytes2));
if (result)
return result;
else
- return d1->file_name_nbytes - d2->file_name_nbytes;
+ return (int)nbytes1 - (int)nbytes2;
+}
+
+static int
+dentry_compare_names(const struct wim_dentry *d1, const struct wim_dentry *d2)
+{
+ return compare_utf16le_names(d1->file_name, d1->file_name_nbytes,
+ d2->file_name, d2->file_name_nbytes);
}
struct wim_dentry *
get_dentry_child_with_utf16le_name(const struct wim_dentry *dentry,
- const utf16lechar *name)
+ const utf16lechar *name,
+ size_t name_nbytes)
{
struct rb_node *node = dentry->d_inode->i_children.rb_node;
+ struct wim_dentry *child;
while (node) {
- struct wim_dentry *child = rbnode_dentry(node);
- int result = dentry_compare_names(dentry, child);
+ child = rbnode_dentry(node);
+ int result = compare_utf16le_names(name, name_nbytes,
+ child->file_name,
+ child->file_name_nbytes);
if (result < 0)
node = node->rb_left;
else if (result > 0)
child = NULL;
} else {
child = get_dentry_child_with_utf16le_name(dentry,
- utf16le_name);
+ utf16le_name,
+ utf16le_name_nbytes);
FREE(utf16le_name);
}
return child;
int ret;
struct wim_dentry *cur_dentry, *parent_dentry;
utf16lechar *p, *pp;
- utf16lechar save;
ret = mbs_to_utf16le(path, strlen(path), &path_utf16le,
&path_utf16le_nbytes);
- if (ret) {
- errno = ENOMEM;
+ if (ret)
return NULL;
- }
parent_dentry = wim_root_dentry(w);
p = path_utf16le;
while (1) {
- while (*p == '/')
+ while (*p == cpu_to_le16('/'))
p++;
cur_dentry = parent_dentry;
if (*p == '\0')
break;
pp = p;
- while (*pp != '/' && *pp != '\0')
+ while (*pp != cpu_to_le16('/') && *pp != '\0')
pp++;
- save = *pp;
- *pp = '\0';
- cur_dentry = get_dentry_child_with_utf16le_name(parent_dentry, p);
+ cur_dentry = get_dentry_child_with_utf16le_name(parent_dentry, p,
+ (void*)pp - (void*)p);
if (cur_dentry == NULL)
break;
- *pp = save;
p = pp;
+ parent_dentry = cur_dentry;
}
FREE(path_utf16le);
if (cur_dentry == NULL) {
/* 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)
+struct wim_dentry *
+get_parent_dentry(WIMStruct *w, const mbchar *path)
{
size_t path_len = strlen(path);
mbchar buf[path_len + 1];
}
/* Prints the full path of a dentry. */
-int print_dentry_full_path(struct wim_dentry *dentry, void *ignore)
+int
+print_dentry_full_path(struct wim_dentry *dentry, void *ignore)
{
if (dentry->full_path)
puts(dentry->full_path);
/* Prints a directory entry. @lookup_table is a pointer to the lookup table, if
* available. If the dentry is unresolved and the lookup table is NULL, the
* lookup table entries will not be printed. Otherwise, they will be. */
-int print_dentry(struct wim_dentry *dentry, void *lookup_table)
+int
+print_dentry(struct wim_dentry *dentry, void *lookup_table)
{
const u8 *hash;
struct wim_lookup_table_entry *lte;
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);
- wimlib_printf("Filename = \"%W\"\n", dentry->file_name);
- wimlib_printf("Short Name \"%W\"\n", dentry->short_name);
- printf("Full Path = \"%s\"\n", dentry->full_path);
+ if (dentry_has_long_name(dentry))
+ wimlib_printf("Filename = \"%W\"\n", dentry->file_name);
+ if (dentry_has_short_name(dentry))
+ wimlib_printf("Short Name \"%W\"\n", dentry->short_name);
+ if (dentry->full_path)
+ printf("Full Path = \"%s\"\n", dentry->full_path);
lte = inode_stream_lte(dentry->d_inode, 0, lookup_table);
if (lte) {
}
/* Initializations done on every `struct wim_dentry'. */
-static void dentry_common_init(struct wim_dentry *dentry)
+static void
+dentry_common_init(struct wim_dentry *dentry)
{
memset(dentry, 0, sizeof(struct wim_dentry));
dentry->refcnt = 1;
}
-static struct wim_inode *new_timeless_inode()
+static struct wim_inode *
+new_timeless_inode()
{
struct wim_inode *inode = CALLOC(1, sizeof(struct wim_inode));
if (inode) {
return inode;
}
-static struct wim_inode *new_inode()
+static struct wim_inode *
+new_inode()
{
struct wim_inode *inode = new_timeless_inode();
if (inode) {
return inode;
}
-/*
- * Creates an unlinked directory entry.
- *
- * @name: The UTF-8 filename of the new dentry.
- *
- * Returns a pointer to the new dentry, or NULL if out of memory.
- */
-struct wim_dentry *new_dentry(const mbchar *name)
+/* Creates an unlinked directory entry. */
+int new_dentry(const mbchar *name, struct wim_dentry **dentry_ret)
{
struct wim_dentry *dentry;
+ int ret;
dentry = MALLOC(sizeof(struct wim_dentry));
if (!dentry)
- goto err;
+ return WIMLIB_ERR_NOMEM;
dentry_common_init(dentry);
- if (set_dentry_name(dentry, name) != 0)
- goto err;
-
- dentry->parent = dentry;
-
- return dentry;
-err:
- FREE(dentry);
- ERROR_WITH_ERRNO("Failed to create new dentry with name \"%s\"", name);
- return NULL;
+ ret = set_dentry_name(dentry, name);
+ if (ret == 0) {
+ dentry->parent = dentry;
+ *dentry_ret = dentry;
+ } else {
+ FREE(dentry);
+ ERROR("Failed to set name on new dentry with name \"%s\"", name);
+ }
+ return ret;
}
-static struct wim_dentry *
-__new_dentry_with_inode(const mbchar *name, bool timeless)
+static int
+__new_dentry_with_inode(const mbchar *name, struct wim_dentry **dentry_ret,
+ bool timeless)
{
struct wim_dentry *dentry;
- dentry = new_dentry(name);
- if (dentry) {
- if (timeless)
- dentry->d_inode = new_timeless_inode();
- else
- dentry->d_inode = new_inode();
- if (dentry->d_inode) {
- inode_add_dentry(dentry, dentry->d_inode);
- } else {
- free_dentry(dentry);
- dentry = NULL;
- }
+ int ret;
+
+ ret = new_dentry(name, &dentry);
+ if (ret)
+ return ret;
+
+ if (timeless)
+ dentry->d_inode = new_timeless_inode();
+ else
+ dentry->d_inode = new_inode();
+ if (!dentry->d_inode) {
+ free_dentry(dentry);
+ return WIMLIB_ERR_NOMEM;
}
- return dentry;
+
+ inode_add_dentry(dentry, dentry->d_inode);
+ *dentry_ret = dentry;
+ return 0;
}
-struct wim_dentry *
-new_dentry_with_timeless_inode(const mbchar *name)
+int
+new_dentry_with_timeless_inode(const mbchar *name, struct wim_dentry **dentry_ret)
{
- return __new_dentry_with_inode(name, true);
+ return __new_dentry_with_inode(name, dentry_ret, true);
}
-struct wim_dentry *
-new_dentry_with_inode(const mbchar *name)
+int
+new_dentry_with_inode(const mbchar *name, struct wim_dentry **dentry_ret)
{
- return __new_dentry_with_inode(name, false);
+ return __new_dentry_with_inode(name, dentry_ret, false);
}
static int
-init_ads_entry(struct wim_ads_entry *ads_entry, const mbchar *name)
+init_ads_entry(struct wim_ads_entry *ads_entry, const void *name,
+ size_t name_nbytes, bool is_utf16le)
{
int ret = 0;
memset(ads_entry, 0, sizeof(*ads_entry));
- if (name && *name) {
- ret = get_utf16le_name(name, &ads_entry->stream_name,
- &ads_entry->stream_name_nbytes);
+
+ if (is_utf16le) {
+ utf16lechar *p = MALLOC(name_nbytes + sizeof(utf16lechar));
+ if (!p)
+ return WIMLIB_ERR_NOMEM;
+ memcpy(p, name, name_nbytes);
+ p[name_nbytes / 2] = 0;
+ ads_entry->stream_name = p;
+ ads_entry->stream_name_nbytes = name_nbytes;
+ } else {
+ if (name && *(const char*)name) {
+ ret = get_utf16le_name(name, &ads_entry->stream_name,
+ &ads_entry->stream_name_nbytes);
+ }
}
return ret;
}
}
}
-/*
- * Add an alternate stream entry to a WIM inode and return a pointer to it, or
- * NULL if memory could not be allocated.
- */
-struct wim_ads_entry *
-inode_add_ads(struct wim_inode *inode, const char *stream_name)
+static struct wim_ads_entry *
+do_inode_add_ads(struct wim_inode *inode, const void *stream_name,
+ size_t stream_name_nbytes, bool is_utf16le)
{
u16 num_ads;
struct wim_ads_entry *ads_entries;
inode->i_ads_entries = ads_entries;
new_entry = &inode->i_ads_entries[num_ads - 1];
- if (init_ads_entry(new_entry, stream_name) != 0)
+ if (init_ads_entry(new_entry, stream_name, stream_name_nbytes, is_utf16le))
return NULL;
#ifdef WITH_FUSE
new_entry->stream_id = inode->i_next_stream_id++;
return new_entry;
}
+struct wim_ads_entry *
+inode_add_ads_utf16le(struct wim_inode *inode,
+ const utf16lechar *stream_name,
+ size_t stream_name_nbytes)
+{
+ return do_inode_add_ads(inode, stream_name, stream_name_nbytes, true);
+}
+
+/*
+ * Add an alternate stream entry to a WIM inode and return a pointer to it, or
+ * NULL if memory could not be allocated.
+ */
+struct wim_ads_entry *
+inode_add_ads(struct wim_inode *inode, const char *stream_name)
+{
+ return do_inode_add_ads(inode, stream_name, strlen(stream_name), false);
+}
+
int
inode_add_ads_with_data(struct wim_inode *inode, const mbchar *name,
const void *value, size_t size,
u64 length;
u64 length_no_padding;
u64 total_length;
- size_t utf8_len;
const u8 *p_save = p;
cur_entry = &ads_entries[i];
p = get_u64(p, &length);
p += 8; /* Skip the reserved field */
- p = get_bytes(p, SHA1_HASH_SIZE, (u8*)cur_entry->hash);
+ p = get_bytes(p, SHA1_HASH_SIZE, cur_entry->hash);
p = get_u16(p, &cur_entry->stream_name_nbytes);
cur_entry->stream_name = NULL;
}
if (cur_entry->stream_name_nbytes) {
- cur_entry->stream_name = MALLOC((size_t)
- cur_entry->stream_name_nbytes + 2);
+ cur_entry->stream_name = MALLOC(cur_entry->stream_name_nbytes + 2);
if (!cur_entry->stream_name) {
ret = WIMLIB_ERR_NOMEM;
goto out_free_ads_entries;
/* Read the filename if present. Note: if the filename is empty, there
* is no null terminator following it. */
if (file_name_nbytes) {
- file_name = MALLOC((size_t)file_name_nbytes + 2);
+ file_name = MALLOC(file_name_nbytes + 2);
if (!file_name) {
- ERROR("Failed to allocate %zu bytes for dentry file name",
- (size_t)file_name_nbytes + 2);
+ ERROR("Failed to allocate %d bytes for dentry file name",
+ file_name_nbytes + 2);
ret = WIMLIB_ERR_NOMEM;
goto out_free_inode;
}
- p = get_bytes(p, (size_t)file_name_nbytes + 2, file_name);
+ 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 "
/* Read the short filename if present. Note: if there is no short
* filename, there is no null terminator following it. */
if (short_name_nbytes) {
- short_name = MALLOC((size_t)short_name_nbytes + 2);
+ short_name = MALLOC(short_name_nbytes + 2);
if (!short_name) {
- ERROR("Failed to allocate %zu bytes for dentry short name",
- (size_t)short_name_nbytes + 2);
+ ERROR("Failed to allocate %d bytes for dentry short name",
+ short_name_nbytes + 2);
ret = WIMLIB_ERR_NOMEM;
goto out_free_file_name;
}
- p = get_bytes(p, (size_t)short_name_nbytes + 2, short_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 "
p = put_u16(p, inode->i_num_ads);
p = put_u16(p, dentry->short_name_nbytes);
p = put_u16(p, dentry->file_name_nbytes);
- if (dentry->file_name_nbytes) {
+ if (dentry_has_long_name(dentry)) {
p = put_bytes(p, dentry->file_name_nbytes + 2,
dentry->file_name);
}
- if (dentry->short_name_nbytes) {
+ if (dentry_has_short_name(dentry)) {
p = put_bytes(p, dentry->short_name_nbytes + 2,
dentry->short_name);
}
extern struct wim_dentry *
get_dentry_child_with_utf16le_name(const struct wim_dentry *dentry,
- const utf16lechar *name);
+ const utf16lechar *name,
+ size_t name_nbytes);
extern struct wim_dentry *
get_parent_dentry(struct WIMStruct *w, const mbchar *path);
extern int
print_dentry_full_path(struct wim_dentry *entry, void *ignore);
-extern struct
-wim_dentry *new_dentry(const mbchar *name);
+extern int
+new_dentry(const mbchar *name, struct wim_dentry **dentry_ret);
-extern struct wim_dentry *
-new_dentry_with_inode(const mbchar *name);
+extern int
+new_dentry_with_inode(const mbchar *name, struct wim_dentry **dentry_ret);
-extern struct wim_dentry *
-new_dentry_with_timeless_inode(const mbchar *name);
+extern int
+new_dentry_with_timeless_inode(const mbchar *name, struct wim_dentry **dentry_ret);
extern void
free_inode(struct wim_inode *inode);
inode_get_ads_entry(struct wim_inode *inode, const mbchar *stream_name,
u16 *idx_ret);
+extern struct wim_ads_entry *
+inode_add_ads_utf16le(struct wim_inode *inode,
+ const utf16lechar *stream_name,
+ size_t stream_name_nbytes);
+
extern struct wim_ads_entry *
inode_add_ads(struct wim_inode *dentry, const mbchar *stream_name);
inode_remove_ads(struct wim_inode *inode, u16 idx,
struct wim_lookup_table *lookup_table);
+
#define WIMLIB_UNIX_DATA_TAG "$$__wimlib_UNIX_data"
+#define WIMLIB_UNIX_DATA_TAG_NBYTES (sizeof(WIMLIB_UNIX_DATA_TAG) - 1)
-#define WIMLIB_UNIX_DATA_TAG_LEN (sizeof(WIMLIB_UNIX_DATA_TAG) - 1)
+#define WIMLIB_UNIX_DATA_TAG_UTF16LE "$\0$\0_\0_\0w\0i\0m\0l\0i\0b\0_\0U\0N\0I\0X\0_\0d\0a\0t\0a\0"
+#define WIMLIB_UNIX_DATA_TAG_UTF16LE_NBYTES (sizeof(WIMLIB_UNIX_DATA_TAG_UTF16LE) - 1)
/* Format for special alternate data stream entries to store UNIX data for files
* and directories (see: WIMLIB_ADD_IMAGE_FLAG_UNIX_DATA) */
return inode_has_children(dentry->d_inode);
}
+static inline bool
+dentry_has_short_name(const struct wim_dentry *dentry)
+{
+ return dentry->short_name_nbytes != 0;
+}
+
+static inline bool
+dentry_has_long_name(const struct wim_dentry *dentry)
+{
+ return dentry->file_name_nbytes != 0;
+}
+
#endif
.mutex = PTHREAD_MUTEX_INITIALIZER, \
}
-static ICONV_LIST(iconv_mbs_to_utf16le, "", "UTF-16LE");
-static ICONV_LIST(iconv_utf16le_to_mbs, "UTF-16LE", "");
-
static iconv_t *
get_iconv(struct iconv_list_head *head)
{
iconv_t cd;
+ iconv_t *cd_p;
struct iconv_node *i;
pthread_mutex_lock(&head->mutex);
if (list_empty(&head->list)) {
cd = iconv_open(head->to_encoding, head->from_encoding);
if (cd == (iconv_t)-1) {
- goto out_unlock;
+ ERROR_WITH_ERRNO("Failed to open iconv from %s to %s",
+ head->from_encoding, head->to_encoding);
+ cd_p = NULL;
} else {
i = MALLOC(sizeof(struct iconv_node));
- if (!i) {
+ if (i) {
+ i->head = head;
+ i->cd = cd;
+ cd_p = &i->cd;
+ } else {
iconv_close(cd);
- cd = (iconv_t)-1;
- goto out_unlock;
+ cd_p = NULL;
}
- i->head = head;
}
} else {
i = container_of(head->list.next, struct iconv_node, list);
list_del(head->list.next);
+ cd_p = &i->cd;
}
- cd = i->cd;
-out_unlock:
pthread_mutex_unlock(&head->mutex);
- return cd;
+ return cd_p;
}
static void
put_iconv(iconv_t *cd)
{
+ int errno_save = errno;
struct iconv_node *i = container_of(cd, struct iconv_node, cd);
struct iconv_list_head *head = i->head;
pthread_mutex_lock(&head->mutex);
list_add(&i->list, &head->list);
pthread_mutex_unlock(&head->mutex);
+ errno = errno_save;
}
-int
-mbs_to_utf16le_nbytes(const mbchar *mbs, size_t mbs_nbytes,
- size_t *utf16le_nbytes_ret)
-{
- iconv_t *cd = get_iconv(&iconv_mbs_to_utf16le);
- if (*cd == (iconv_t)-1)
- return WIMLIB_ERR_ICONV_NOT_AVAILABLE;
-
- /* Worst case length */
- utf16lechar buf[mbs_nbytes * 2];
- char *inbuf = (char*)mbs;
- char *outbuf = (char*)buf;
- size_t outbytesleft = sizeof(buf);
- size_t inbytesleft = mbs_nbytes;
- size_t len;
- int ret;
-
- len = iconv(*cd, &inbuf, &inbytesleft, &outbuf, &outbytesleft);
- if (len == (size_t)-1) {
- ret = WIMLIB_ERR_INVALID_MULTIBYTE_STRING;
- } else {
- *utf16le_nbytes_ret = sizeof(buf) - outbytesleft;
- ret = 0;
- }
- put_iconv(cd);
- return ret;
+#define DEFINE_CHAR_CONVERSION_FUNCTIONS(varname1, longname1, chartype1,\
+ varname2, longname2, chartype2,\
+ worst_case_len_expr, \
+ err_return, \
+ err_msg) \
+static ICONV_LIST(iconv_##varname1##_to_##varname2, \
+ longname1, longname2); \
+ \
+int \
+varname1##_to_##varname2##_nbytes(const chartype1 *in, size_t in_nbytes,\
+ size_t *out_nbytes_ret) \
+{ \
+ iconv_t *cd = get_iconv(&iconv_##varname1##_to_##varname2); \
+ if (cd == NULL) \
+ return WIMLIB_ERR_ICONV_NOT_AVAILABLE; \
+ \
+ /* Worst case length */ \
+ chartype2 buf[worst_case_len_expr]; \
+ char *inbuf = (char*)in; \
+ size_t inbytesleft = in_nbytes; \
+ char *outbuf = (char*)buf; \
+ size_t outbytesleft = sizeof(buf); \
+ size_t len; \
+ int ret; \
+ \
+ len = iconv(*cd, &inbuf, &inbytesleft, &outbuf, &outbytesleft); \
+ if (len == (size_t)-1) { \
+ err_msg; \
+ ret = err_return; \
+ } else { \
+ *out_nbytes_ret = sizeof(buf) - outbytesleft; \
+ ret = 0; \
+ } \
+ put_iconv(cd); \
+ return ret; \
+} \
+ \
+int \
+varname1##_to_##varname2##_buf(const chartype1 *in, size_t in_nbytes, \
+ chartype2 *out) \
+{ \
+ iconv_t *cd = get_iconv(&iconv_##varname1##_to_##varname2); \
+ if (cd == NULL) \
+ return WIMLIB_ERR_ICONV_NOT_AVAILABLE; \
+ \
+ char *inbuf = (char*)in; \
+ size_t inbytesleft = in_nbytes; \
+ char *outbuf = (char*)out; \
+ const size_t LARGE_NUMBER = 1000000000; \
+ size_t outbytesleft = LARGE_NUMBER; \
+ size_t len; \
+ int ret; \
+ \
+ len = iconv(*cd, &inbuf, &inbytesleft, &outbuf, &outbytesleft); \
+ if (len == (size_t)-1) { \
+ err_msg; \
+ ret = err_return; \
+ } else { \
+ out[(LARGE_NUMBER-outbytesleft)/sizeof(chartype2)] = 0; \
+ ret = 0; \
+ } \
+ put_iconv(cd); \
+ return ret; \
+} \
+ \
+int \
+varname1##_to_##varname2(const chartype1 *in, size_t in_nbytes, \
+ chartype2 **out_ret, \
+ size_t *out_nbytes_ret) \
+{ \
+ int ret; \
+ chartype2 *out; \
+ size_t out_nbytes; \
+ \
+ ret = varname1##_to_##varname2##_nbytes(in, in_nbytes, \
+ &out_nbytes); \
+ if (ret) \
+ return ret; \
+ \
+ out = MALLOC(out_nbytes + sizeof(chartype2)); \
+ if (!out) \
+ return WIMLIB_ERR_NOMEM; \
+ \
+ ret = varname1##_to_##varname2##_buf(in, in_nbytes, out); \
+ if (ret) { \
+ int errno_save = errno; \
+ FREE(out); \
+ errno = errno_save; \
+ } else { \
+ *out_ret = out; \
+ *out_nbytes_ret = out_nbytes; \
+ } \
+ return ret; \
}
+DEFINE_CHAR_CONVERSION_FUNCTIONS(utf16le, "UTF-16LE", utf16lechar,
+ mbs, "", mbchar,
+ in_nbytes / 2 * MB_CUR_MAX,
+ WIMLIB_ERR_UNICODE_STRING_NOT_REPRESENTABLE,
+ ERROR_WITH_ERRNO("Failed to convert UTF-16LE "
+ "string %U to multibyte string", in))
-int
-utf16le_to_mbs_nbytes(const utf16lechar *utf16le_str, size_t utf16le_nbytes,
- size_t *mbs_nbytes_ret)
-{
- iconv_t *cd = get_iconv(&iconv_utf16le_to_mbs);
- if (*cd == (iconv_t)-1)
- return WIMLIB_ERR_ICONV_NOT_AVAILABLE;
+DEFINE_CHAR_CONVERSION_FUNCTIONS(mbs, "", mbchar,
+ utf16le, "UTF-16LE", utf16lechar,
+ in_nbytes * 2,
+ WIMLIB_ERR_INVALID_MULTIBYTE_STRING,
+ ERROR_WITH_ERRNO("Failed to convert multibyte "
+ "string %s to UTF-16LE string", in))
- /* Worst case length */
- mbchar buf[utf16le_nbytes / 2 * MB_CUR_MAX];
- char *inbuf = (char*)utf16le_str;
- char *outbuf = (char*)buf;
- size_t outbytesleft = sizeof(buf);
- size_t inbytesleft = utf16le_nbytes;
- size_t len;
- int ret;
+DEFINE_CHAR_CONVERSION_FUNCTIONS(utf8, "UTF-8", utf8char,
+ mbs, "", mbchar,
+ in_nbytes,
+ WIMLIB_ERR_INVALID_UTF8_STRING,
+ ERROR_WITH_ERRNO("Failed to convert UTF-8 "
+ "string %U to multibyte string", in))
- len = iconv(*cd, &inbuf, &inbytesleft, &outbuf, &outbytesleft);
- if (len == (size_t)-1) {
- ERROR("Could not convert \"%W\" to encoding of current locale",
- utf16le_str);
- /* EILSEQ is supposed to mean that the *input* is invalid, but
- * it's also returned if any input characters are not
- * representable in the output encoding. (The actual behavior
- * in this case is undefined for some reason...). Assume it's
- * the latter error case. */
- ret = WIMLIB_ERR_UNICODE_STRING_NOT_REPRESENTABLE;
- } else {
- *mbs_nbytes_ret = sizeof(buf) - outbytesleft;
- ret = 0;
- }
- put_iconv(cd);
- return ret;
-}
-
-int
-mbs_to_utf16le_buf(const mbchar *mbs, size_t mbs_nbytes,
- utf16lechar *utf16le_str)
-{
- iconv_t *cd = get_iconv(&iconv_mbs_to_utf16le);
- if (*cd == (iconv_t)-1)
- return WIMLIB_ERR_ICONV_NOT_AVAILABLE;
-
- char *inbuf = (char*)mbs;
- size_t inbytesleft = mbs_nbytes;
- char *outbuf = (char*)utf16le_str;
- size_t outbytesleft = SIZE_MAX;
- size_t len;
- int ret;
-
- len = iconv(*cd, &inbuf, &inbytesleft, &outbuf, &outbytesleft);
- if (len == (size_t)-1) {
- ret = WIMLIB_ERR_INVALID_MULTIBYTE_STRING;
- } else {
- ret = 0;
- }
- put_iconv(cd);
- return ret;
-}
-int
-utf16le_to_mbs_buf(const utf16lechar *utf16le_str, size_t utf16le_nbytes,
- mbchar *mbs)
+static void
+iconv_cleanup(struct iconv_list_head *head)
{
- int ret;
- iconv_t *cd = get_iconv(&iconv_utf16le_to_mbs);
- if (*cd == (iconv_t)-1)
- return WIMLIB_ERR_ICONV_NOT_AVAILABLE;
-
- char *inbuf = (char*)utf16le_str;
- size_t inbytesleft;
- char *outbuf = (char*)mbs;
- size_t outbytesleft = SIZE_MAX;
- size_t len;
-
- len = iconv(*cd, &inbuf, &inbytesleft, &outbuf, &outbytesleft);
- if (len == (size_t)-1) {
- ret = WIMLIB_ERR_INVALID_UTF16_STRING;
- } else {
- ret = 0;
+ pthread_mutex_destroy(&head->mutex);
+ while (!list_empty(&head->list)) {
+ struct iconv_node *i;
+
+ i = container_of(head->list.next, struct iconv_node, list);
+ list_del(&i->list);
+ iconv_close(i->cd);
+ FREE(i);
}
- mbs[SIZE_MAX - inbytesleft] = '\0';
- put_iconv(cd);
- return ret;
}
-int
-mbs_to_utf16le(const mbchar *mbs, size_t mbs_nbytes,
- utf16lechar **utf16le_ret, size_t *utf16le_nbytes_ret)
+void
+iconv_global_cleanup()
{
- int ret;
- utf16lechar *utf16le_str;
- size_t utf16le_nbytes;
-
- ret = mbs_to_utf16le_nbytes(mbs, mbs_nbytes,
- &utf16le_nbytes);
- if (ret)
- return ret;
-
- utf16le_str = MALLOC(utf16le_nbytes + 1);
- if (!utf16le_str)
- return WIMLIB_ERR_NOMEM;
-
- ret = mbs_to_utf16le_buf(mbs, mbs_nbytes, utf16le_str);
- if (ret) {
- FREE(utf16le_str);
- } else {
- *utf16le_ret = utf16le_str;
- *utf16le_nbytes_ret = utf16le_nbytes;
- }
- return ret;
+ iconv_cleanup(&iconv_utf16le_to_mbs);
+ iconv_cleanup(&iconv_mbs_to_utf16le);
+ iconv_cleanup(&iconv_utf8_to_mbs);
}
-int
-utf16le_to_mbs(const utf16lechar *utf16le_str, size_t utf16le_nbytes,
- mbchar **mbs_ret, size_t *mbs_nbytes_ret)
-{
- int ret;
- mbchar *mbs;
- size_t mbs_nbytes;
-
- ret = utf16le_to_mbs_nbytes(utf16le_str, utf16le_nbytes,
- &mbs_nbytes);
- if (ret)
- return ret;
-
- mbs = MALLOC(mbs_nbytes + 1);
- if (!mbs)
- return WIMLIB_ERR_NOMEM;
-
- ret = utf16le_to_mbs_buf(utf16le_str, utf16le_nbytes, mbs);
- if (ret) {
- FREE(mbs);
- } else {
- *mbs_ret = mbs;
- *mbs_nbytes_ret = mbs_nbytes;
- }
- return ret;
-}
bool
utf8_str_contains_nonascii_chars(const utf8char *utf8_str)
if (!loc)
goto out_free;
memcpy(loc, old->ntfs_loc, sizeof(*loc));
- loc->path_utf8 = NULL;
- loc->stream_name_utf16 = NULL;
+ loc->path = NULL;
+ loc->stream_name = NULL;
new->ntfs_loc = loc;
- loc->path_utf8 = STRDUP(old->ntfs_loc->path_utf8);
- if (!loc->path_utf8)
+ loc->path = STRDUP(old->ntfs_loc->path);
+ if (!loc->path)
goto out_free;
- loc->stream_name_utf16 = MALLOC(loc->stream_name_utf16_num_chars * 2);
- if (!loc->stream_name_utf16)
+ loc->stream_name = MALLOC((loc->stream_name_nchars + 1) * 2);
+ if (!loc->stream_name)
goto out_free;
- memcpy(loc->stream_name_utf16,
- old->ntfs_loc->stream_name_utf16,
- loc->stream_name_utf16_num_chars * 2);
+ memcpy(loc->stream_name,
+ old->ntfs_loc->stream_name,
+ (loc->stream_name_nchars + 1) * 2);
}
break;
#endif
#ifdef WITH_NTFS_3G
case RESOURCE_IN_NTFS_VOLUME:
if (lte->ntfs_loc) {
- FREE(lte->ntfs_loc->path_utf8);
- FREE(lte->ntfs_loc->stream_name_utf16);
+ FREE(lte->ntfs_loc->path);
+ FREE(lte->ntfs_loc->stream_name);
FREE(lte->ntfs_loc);
}
break;
if (lookup_flags & LOOKUP_FLAG_ADS_OK) {
stream_name = path_stream_name(path);
if (stream_name) {
- p = (char*)stream_name - 1;
+ p = (mbchar*)stream_name - 1;
*p = '\0';
}
}
if (p)
*p = ':';
if (!dentry)
- return -ENOENT;
+ return -errno;
inode = dentry->d_inode;
#ifdef WITH_NTFS_3G
struct ntfs_location {
- utf8char *path_utf8;
- utf16lechar *stream_name_utf16;
- u16 stream_name_utf16_num_chars;
+ mbchar *path;
+ utf16lechar *stream_name;
+ u16 stream_name_nchars;
struct _ntfs_volume **ntfs_vol_p;
bool is_reparse_point;
};
struct wim_dentry *new;
const mbchar *basename;
struct wimfs_context *wimfs_ctx = WIMFS_CTX(fuse_ctx);
+ int ret;
parent = get_parent_dentry(wimfs_ctx->wim, path);
if (!parent)
if (get_dentry_child_with_name(parent, basename))
return -EEXIST;
- new = new_dentry_with_inode(basename);
- if (!new)
- return -errno;
+ ret = new_dentry_with_inode(basename, &new);
+ if (ret)
+ return -ENOMEM;
new->d_inode->i_resolved = 1;
new->d_inode->i_ino = wimfs_ctx->next_ino++;
struct wim_lookup_table_entry *lte;
WIMStruct *w = wimfs_get_WIMStruct();
u16 i;
+ int ret;
inode = wim_pathname_to_inode(w, to);
if (!inode)
link_name = path_basename(from);
if (get_dentry_child_with_name(from_dentry_parent, link_name))
return -EEXIST;
- from_dentry = new_dentry(link_name);
- if (!from_dentry)
- return -errno;
+
+ ret = new_dentry(link_name, &from_dentry);
+ if (ret)
+ return -ENOMEM;
inode_add_dentry(from_dentry, inode);
from_dentry->d_inode = inode;
{
struct wimfs_fd *fd = (struct wimfs_fd*)(uintptr_t)fi->fh;
int ret;
- u64 now;
if (!fd)
return -EBADF;
#include <ntfs-3g/reparse.h>
#include <ntfs-3g/xattrs.h>
#include <string.h>
+#include <locale.h>
-static int extract_wim_chunk_to_ntfs_attr(const u8 *buf, size_t len,
+static int extract_wim_chunk_to_ntfs_attr(const void *buf, size_t len,
u64 offset, void *arg)
{
ntfs_attr *na = arg;
int ret = 0;
unsigned stream_idx = 0;
ntfschar *stream_name = AT_UNNAMED;
- u32 stream_name_len = 0;
- const char *stream_name_utf8;
+ u32 stream_name_nbytes = 0;
const struct wim_inode *inode = dentry->d_inode;
struct wim_lookup_table_entry *lte;
DEBUG("Writing %u NTFS data stream%s for `%s'",
inode->i_num_ads + 1,
(inode->i_num_ads == 0 ? "" : "s"),
- dentry->full_path_utf8);
+ dentry->full_path);
lte = inode->i_lte;
while (1) {
- if (stream_name_len) {
-
+ if (stream_name_nbytes) {
/* Skip special UNIX data entries (see documentation for
* WIMLIB_ADD_IMAGE_FLAG_UNIX_DATA) */
- if (stream_name_len == WIMLIB_UNIX_DATA_TAG_LEN
- && !memcmp(stream_name_utf8,
- WIMLIB_UNIX_DATA_TAG,
- WIMLIB_UNIX_DATA_TAG_LEN))
+ if (stream_name_nbytes == WIMLIB_UNIX_DATA_TAG_UTF16LE_NBYTES
+ && !memcmp(stream_name,
+ WIMLIB_UNIX_DATA_TAG_UTF16LE,
+ WIMLIB_UNIX_DATA_TAG_UTF16LE_NBYTES))
goto cont;
/* Create an empty named stream. */
ret = ntfs_attr_add(ni, AT_DATA, stream_name,
- stream_name_len, NULL, 0);
+ stream_name_nbytes / 2, NULL, 0);
if (ret != 0) {
- ERROR_WITH_ERRNO("Failed to create name data "
+ ERROR_WITH_ERRNO("Failed to create named data "
"stream for extracted file "
"`%s'",
- dentry->full_path_utf8);
+ dentry->full_path);
ret = WIMLIB_ERR_NTFS_3G;
break;
if (lte) {
ntfs_attr *na;
- na = ntfs_attr_open(ni, AT_DATA, stream_name, stream_name_len);
+ na = ntfs_attr_open(ni, AT_DATA, stream_name,
+ stream_name_nbytes / 2);
if (!na) {
ERROR_WITH_ERRNO("Failed to open a data stream of "
"extracted file `%s'",
- dentry->full_path_utf8);
+ dentry->full_path);
ret = WIMLIB_ERR_NTFS_3G;
break;
}
break;
/* Get the name and lookup table entry for the next stream. */
- stream_name = (ntfschar*)inode->i_ads_entries[stream_idx].stream_name;
- stream_name_utf8 = inode->i_ads_entries[stream_idx].stream_name_utf8;
- stream_name_len = inode->i_ads_entries[stream_idx].stream_name_len / 2;
+ stream_name = inode->i_ads_entries[stream_idx].stream_name;
+ stream_name_nbytes = inode->i_ads_entries[stream_idx].stream_name_nbytes;
lte = inode->i_ads_entries[stream_idx].lte;
stream_idx++;
}
/* Open the NTFS inode that corresponds to the parent of a WIM dentry. Returns
* the opened inode, or NULL on failure. */
-static ntfs_inode *dentry_open_parent_ni(const struct wim_dentry *dentry,
- ntfs_volume *vol)
+static ntfs_inode *
+dentry_open_parent_ni(const struct wim_dentry *dentry, ntfs_volume *vol)
{
- char *p;
- const char *dir_name;
+ mbchar *p;
+ const mbchar *dir_name;
ntfs_inode *dir_ni;
- char orig;
+ mbchar orig;
- p = dentry->full_path_utf8 + dentry->full_path_utf8_len;
+ p = dentry->full_path + dentry->full_path_nbytes;
do {
p--;
} while (*p != '/');
orig = *p;
*p = '\0';
- dir_name = dentry->full_path_utf8;
+ dir_name = dentry->full_path;
dir_ni = ntfs_pathname_to_inode(vol, NULL, dir_name);
if (!dir_ni) {
ERROR_WITH_ERRNO("Could not find NTFS inode for `%s'",
* directory specified by @dir_ni, and it is made to point to the previously
* extracted file located at @inode->i_extracted_file.
*
- * Or, in other words, this adds a new name @from_dentry->full_path_utf8 to an
+ * Or, in other words, this adds a new name @from_dentry->full_path to an
* existing NTFS inode which already has a name @inode->i_extracted_file.
*
* The new name is made in the POSIX namespace (this is the behavior of
*
* Return 0 on success, nonzero on failure. dir_ni is closed either way.
*/
-static int apply_ntfs_hardlink(const struct wim_dentry *from_dentry,
- const struct wim_inode *inode,
- ntfs_inode *dir_ni)
+static int
+apply_ntfs_hardlink(const struct wim_dentry *from_dentry,
+ const struct wim_inode *inode,
+ ntfs_inode *dir_ni)
{
int ret;
ntfs_inode *to_ni;
}
DEBUG("Extracting NTFS hard link `%s' => `%s'",
- from_dentry->full_path_utf8, inode->i_extracted_file);
+ from_dentry->full_path, inode->i_extracted_file);
to_ni = ntfs_pathname_to_inode(vol, NULL, inode->i_extracted_file);
if (!to_ni) {
}
ret = ntfs_link(to_ni, dir_ni,
- (ntfschar*)from_dentry->file_name,
- from_dentry->file_name_len / 2);
+ from_dentry->file_name,
+ from_dentry->file_name_nbytes / 2);
ret |= ntfs_inode_close(dir_ni);
ret |= ntfs_inode_close(to_ni);
if (ret) {
ERROR_WITH_ERRNO("Could not create hard link `%s' => `%s'",
- from_dentry->full_path_utf8,
+ from_dentry->full_path,
inode->i_extracted_file);
ret = WIMLIB_ERR_NTFS_3G;
}
inode = dentry->d_inode;
DEBUG("Setting NTFS file attributes on `%s' to %#"PRIx32,
- dentry->full_path_utf8, inode->i_attributes);
+ dentry->full_path, inode->i_attributes);
attributes_le32 = cpu_to_le32(inode->i_attributes);
memset(&ctx, 0, sizeof(ctx));
sizeof(u32), 0);
if (ret != 0) {
ERROR("Failed to set NTFS file attributes on `%s'",
- dentry->full_path_utf8);
+ dentry->full_path);
return WIMLIB_ERR_NTFS_3G;
}
if (inode->i_security_id != -1) {
wimlib_assert(inode->i_security_id < sd->num_entries);
desc = (const char *)sd->descriptors[inode->i_security_id];
DEBUG("Applying security descriptor %d to `%s'",
- inode->i_security_id, dentry->full_path_utf8);
+ inode->i_security_id, dentry->full_path);
ret = ntfs_xattr_system_setxattr(&ctx, XATTR_NTFS_ACL,
ni, dir_ni, desc,
if (ret != 0) {
ERROR_WITH_ERRNO("Failed to set security data on `%s'",
- dentry->full_path_utf8);
+ dentry->full_path);
return WIMLIB_ERR_NTFS_3G;
}
}
lte = inode_unnamed_lte_resolved(dentry->d_inode);
- DEBUG("Applying reparse data to `%s'", dentry->full_path_utf8);
+ DEBUG("Applying reparse data to `%s'", dentry->full_path);
if (!lte) {
ERROR("Could not find reparse data for `%s'",
- dentry->full_path_utf8);
+ dentry->full_path);
return WIMLIB_ERR_INVALID_DENTRY;
}
if (wim_resource_size(lte) >= 0xffff) {
ERROR("Reparse data of `%s' is too long (%"PRIu64" bytes)",
- dentry->full_path_utf8, wim_resource_size(lte));
+ dentry->full_path, wim_resource_size(lte));
return WIMLIB_ERR_INVALID_DENTRY;
}
wim_resource_size(lte) + 8, 0);
if (ret != 0) {
ERROR_WITH_ERRNO("Failed to set NTFS reparse data on `%s'",
- dentry->full_path_utf8);
+ dentry->full_path);
return WIMLIB_ERR_NTFS_3G;
}
progress_info->extract.completed_bytes += wim_resource_size(lte);
*
* @return: 0 on success; nonzero on failure.
*/
-static int do_apply_dentry_ntfs(struct wim_dentry *dentry, ntfs_inode *dir_ni,
- struct apply_args *args)
+static int
+do_apply_dentry_ntfs(struct wim_dentry *dentry, ntfs_inode *dir_ni,
+ struct apply_args *args)
{
int ret = 0;
mode_t type;
* extracted yet, so go ahead and extract the
* first one. */
FREE(inode->i_extracted_file);
- inode->i_extracted_file = STRDUP(dentry->full_path_utf8);
+ inode->i_extracted_file = STRDUP(dentry->full_path);
if (!inode->i_extracted_file) {
ret = WIMLIB_ERR_NOMEM;
goto out_close_dir_ni;
* Note: For symbolic links that are not directory junctions, S_IFREG is
* passed here, since the reparse data and file attributes are set
* later. */
- ni = ntfs_create(dir_ni, 0, (ntfschar*)dentry->file_name,
- dentry->file_name_len / 2, type);
+ ni = ntfs_create(dir_ni, 0, dentry->file_name,
+ dentry->file_name_nbytes / 2, type);
if (!ni) {
ERROR_WITH_ERRNO("Could not create NTFS inode for `%s'",
- dentry->full_path_utf8);
+ dentry->full_path);
ret = WIMLIB_ERR_NTFS_3G;
goto out_close_dir_ni;
}
goto out_close_dir_ni;
}
-
ret = apply_file_attributes_and_security_data(ni, dir_ni, dentry,
args->w);
if (ret != 0)
}
/* Set DOS (short) name if given */
- if (dentry->short_name_len != 0) {
- char *short_name_utf8;
- size_t short_name_utf8_len;
- ret = utf16_to_utf8(dentry->short_name,
- dentry->short_name_len,
- &short_name_utf8,
- &short_name_utf8_len);
+ if (dentry_has_short_name(dentry)) {
+ mbchar *short_name_mbs;
+ size_t short_name_mbs_nbytes;
+ ret = utf16le_to_mbs(dentry->short_name,
+ dentry->short_name_nbytes,
+ &short_name_mbs,
+ &short_name_mbs_nbytes);
if (ret != 0)
goto out_close_dir_ni;
DEBUG("Setting short (DOS) name of `%s' to %s",
- dentry->full_path_utf8, short_name_utf8);
+ dentry->full_path, short_name_mbs);
- ret = ntfs_set_ntfs_dos_name(ni, dir_ni, short_name_utf8,
- short_name_utf8_len, 0);
- FREE(short_name_utf8);
+ ret = ntfs_set_ntfs_dos_name(ni, dir_ni, short_name_mbs,
+ short_name_mbs_nbytes, 0);
+ FREE(short_name_mbs);
if (ret != 0) {
ERROR_WITH_ERRNO("Could not set DOS (short) name for `%s'",
- dentry->full_path_utf8);
+ dentry->full_path);
ret = WIMLIB_ERR_NTFS_3G;
}
/* inodes have been closed by ntfs_set_ntfs_dos_name(). */
if (ret == 0)
ret = WIMLIB_ERR_NTFS_3G;
ERROR_WITH_ERRNO("Failed to close inode for `%s'",
- dentry->full_path_utf8);
+ dentry->full_path);
}
}
if (ntfs_inode_close(dir_ni)) {
if (ret == 0)
ret = WIMLIB_ERR_NTFS_3G;
ERROR_WITH_ERRNO("Failed to close inode of directory "
- "containing `%s'", dentry->full_path_utf8);
+ "containing `%s'", dentry->full_path);
}
}
out:
return ret;
}
-static int apply_root_dentry_ntfs(const struct wim_dentry *dentry,
- ntfs_volume *vol, const WIMStruct *w)
+static int
+apply_root_dentry_ntfs(const struct wim_dentry *dentry,
+ ntfs_volume *vol, const WIMStruct *w)
{
ntfs_inode *ni;
int ret = 0;
}
/* Applies a WIM dentry to the NTFS volume */
-int apply_dentry_ntfs(struct wim_dentry *dentry, void *arg)
+int
+apply_dentry_ntfs(struct wim_dentry *dentry, void *arg)
{
struct apply_args *args = arg;
ntfs_volume *vol = args->vol;
* file. So, this implies that the correct ordering of function calls
* to extract a NTFS file are:
*
- * if (file has a DOS name) {
+ if (file has a DOS name) {
* - Call ntfs_create() to create long name associated with
* the DOS name (this initially creates a POSIX name)
* - Call ntfs_set_ntfs_dos_name() to associate a DOS name
again:
orig_dentry = NULL;
if (!dentry->d_inode->i_dos_name_extracted &&
- dentry->short_name_len == 0)
+ !dentry_has_short_name(dentry))
{
inode_for_each_dentry(other, dentry->d_inode) {
- if (other->short_name_len != 0) {
+ if (dentry_has_short_name(other)) {
orig_dentry = dentry;
dentry = other;
break;
/* Transfers the 100-nanosecond precision timestamps from a WIM dentry to a NTFS
* inode */
-int apply_dentry_timestamps_ntfs(struct wim_dentry *dentry, void *arg)
+int
+apply_dentry_timestamps_ntfs(struct wim_dentry *dentry, void *arg)
{
struct apply_args *args = arg;
ntfs_volume *vol = args->vol;
ntfs_inode *ni;
int ret;
- DEBUG("Setting timestamps on `%s'", dentry->full_path_utf8);
+ DEBUG("Setting timestamps on `%s'", dentry->full_path);
- ni = ntfs_pathname_to_inode(vol, NULL, dentry->full_path_utf8);
+ ni = ntfs_pathname_to_inode(vol, NULL, dentry->full_path);
if (!ni) {
ERROR_WITH_ERRNO("Could not find NTFS inode for `%s'",
- dentry->full_path_utf8);
+ dentry->full_path);
return WIMLIB_ERR_NTFS_3G;
}
ret = ntfs_inode_set_times(ni, (const char*)buf, 3 * sizeof(u64), 0);
if (ret != 0) {
ERROR_WITH_ERRNO("Failed to set NTFS timestamps on `%s'",
- dentry->full_path_utf8);
+ dentry->full_path);
ret = WIMLIB_ERR_NTFS_3G;
}
if (ret == 0)
ret = WIMLIB_ERR_NTFS_3G;
ERROR_WITH_ERRNO("Failed to close NTFS inode for `%s'",
- dentry->full_path_utf8);
+ dentry->full_path);
}
return ret;
}
+
+void
+libntfs3g_global_init()
+{
+ ntfs_set_char_encoding(setlocale(LC_ALL, ""));
+}
#include <alloca.h>
#endif
-static inline ntfschar *attr_record_name(ATTR_RECORD *ar)
+static inline ntfschar *
+attr_record_name(ATTR_RECORD *ar)
{
return (ntfschar*)((u8*)ar + le16_to_cpu(ar->name_offset));
}
*
* Return 0 on success or nonzero on error.
*/
-static int ntfs_attr_sha1sum(ntfs_inode *ni, ATTR_RECORD *ar,
- u8 md[SHA1_HASH_SIZE],
- bool is_reparse_point,
- u32 *reparse_tag_ret)
+static int
+ntfs_attr_sha1sum(ntfs_inode *ni, ATTR_RECORD *ar,
+ u8 md[SHA1_HASH_SIZE],
+ bool is_reparse_point,
+ u32 *reparse_tag_ret)
{
s64 pos = 0;
s64 bytes_remaining;
/* Load the streams from a file or reparse point in the NTFS volume into the WIM
* lookup table */
-static int capture_ntfs_streams(struct wim_dentry *dentry, ntfs_inode *ni,
- char path[], size_t path_len,
- struct wim_lookup_table *lookup_table,
- ntfs_volume **ntfs_vol_p,
- ATTR_TYPES type)
+static int
+capture_ntfs_streams(struct wim_dentry *dentry,
+ ntfs_inode *ni,
+ mbchar *path,
+ size_t path_len,
+ struct wim_lookup_table *lookup_table,
+ ntfs_volume **ntfs_vol_p,
+ ATTR_TYPES type)
{
ntfs_attr_search_ctx *actx;
u8 attr_hash[SHA1_HASH_SIZE];
while (!ntfs_attr_lookup(type, NULL, 0,
CASE_SENSITIVE, 0, NULL, 0, actx))
{
- char *stream_name_utf8;
u32 reparse_tag;
u64 data_size = ntfs_get_attribute_value_length(actx->attr);
u64 name_length = actx->attr->name_length;
-
if (data_size == 0) {
if (errno != 0) {
ERROR_WITH_ERRNO("Failed to get size of attribute of "
if (!ntfs_loc)
goto out_put_actx;
ntfs_loc->ntfs_vol_p = ntfs_vol_p;
- ntfs_loc->path_utf8 = MALLOC(path_len + 1);
- if (!ntfs_loc->path_utf8)
+ ntfs_loc->path = MALLOC(path_len + 1);
+ if (!ntfs_loc->path)
goto out_free_ntfs_loc;
- memcpy(ntfs_loc->path_utf8, path, path_len + 1);
+ memcpy(ntfs_loc->path, path, path_len + 1);
if (name_length) {
- ntfs_loc->stream_name_utf16 = MALLOC(name_length * 2);
- if (!ntfs_loc->stream_name_utf16)
+ ntfs_loc->stream_name = MALLOC(name_length * 2);
+ if (!ntfs_loc->stream_name)
goto out_free_ntfs_loc;
- memcpy(ntfs_loc->stream_name_utf16,
+ memcpy(ntfs_loc->stream_name,
attr_record_name(actx->attr),
actx->attr->name_length * 2);
- ntfs_loc->stream_name_utf16_num_chars = name_length;
+ ntfs_loc->stream_name_nchars = name_length;
}
lte = new_lookup_table_entry();
lte->resource_entry.size = data_size;
}
ntfs_loc = NULL;
- DEBUG("Add resource for `%s' (size = %"PRIu64")",
- dentry->file_name_utf8,
- lte->resource_entry.original_size);
copy_hash(lte->hash, attr_hash);
lookup_table_insert(lookup_table, lte);
}
if (name_length == 0) {
/* Unnamed data stream. Put the reference to it in the
* dentry's inode. */
- #if 0
- if (dentry->d_inode->i_lte) {
- ERROR("Found two un-named data streams for "
- "`%s'", path);
- ret = WIMLIB_ERR_NTFS_3G;
- goto out_free_lte;
- }
- dentry->d_inode->i_lte = lte;
- #else
if (dentry->d_inode->i_lte) {
WARNING("Found two un-named data streams for "
"`%s'", path);
} else {
dentry->d_inode->i_lte = lte;
}
- #endif
} else {
/* Named data stream. Put the reference to it in the
* alternate data stream entries */
struct wim_ads_entry *new_ads_entry;
- size_t stream_name_utf8_len;
- ret = utf16_to_utf8((const char*)attr_record_name(actx->attr),
- name_length * 2,
- &stream_name_utf8,
- &stream_name_utf8_len);
- if (ret != 0)
- goto out_free_lte;
- new_ads_entry = inode_add_ads(dentry->d_inode, stream_name_utf8);
- FREE(stream_name_utf8);
+ new_ads_entry = inode_add_ads_utf16le(dentry->d_inode,
+ attr_record_name(actx->attr),
+ name_length * 2);
if (!new_ads_entry)
goto out_free_lte;
-
- wimlib_assert(new_ads_entry->stream_name_len == name_length * 2);
-
+ wimlib_assert(new_ads_entry->stream_name_nbytes == name_length * 2);
new_ads_entry->lte = lte;
}
}
free_lookup_table_entry(lte);
out_free_ntfs_loc:
if (ntfs_loc) {
- FREE(ntfs_loc->path_utf8);
- FREE(ntfs_loc->stream_name_utf16);
+ FREE(ntfs_loc->path);
+ FREE(ntfs_loc->stream_name);
FREE(ntfs_loc);
}
out_put_actx:
struct dos_name_node {
struct rb_node rb_node;
char dos_name[24];
- int name_len_bytes;
+ int name_nbytes;
u64 ntfs_ino;
};
/* Inserts a new DOS name into the map */
-static int insert_dos_name(struct dos_name_map *map,
- const ntfschar *dos_name, int name_len,
- u64 ntfs_ino)
+static int
+insert_dos_name(struct dos_name_map *map, const ntfschar *dos_name,
+ size_t name_nbytes, u64 ntfs_ino)
{
struct dos_name_node *new_node;
struct rb_node **p;
struct rb_root *root;
struct rb_node *rb_parent;
- DEBUG("DOS name_len = %d", name_len);
+ DEBUG("DOS name_len = %zu", name_nbytes);
new_node = MALLOC(sizeof(struct dos_name_node));
if (!new_node)
return -1;
/* DOS names are supposed to be 12 characters max (that's 24 bytes,
* assuming 2-byte ntfs characters) */
- wimlib_assert(name_len * sizeof(ntfschar) <= sizeof(new_node->dos_name));
+ wimlib_assert(name_nbytes <= sizeof(new_node->dos_name));
/* Initialize the DOS name, DOS name length, and NTFS inode number of
* the red-black tree node */
- memcpy(new_node->dos_name, dos_name, name_len * sizeof(ntfschar));
- new_node->name_len_bytes = name_len * sizeof(ntfschar);
+ memcpy(new_node->dos_name, dos_name, name_nbytes);
+ new_node->name_nbytes = name_nbytes;
new_node->ntfs_ino = ntfs_ino;
/* Insert the red-black tree node */
return NULL;
}
-static int set_dentry_dos_name(struct wim_dentry *dentry, void *arg)
+static int
+set_dentry_dos_name(struct wim_dentry *dentry, void *arg)
{
const struct dos_name_map *map = arg;
const struct dos_name_node *node;
if (dentry->is_win32_name) {
node = lookup_dos_name(map, dentry->d_inode->i_ino);
if (node) {
- dentry->short_name = MALLOC(node->name_len_bytes);
+ dentry->short_name = MALLOC(node->name_nbytes + 2);
if (!dentry->short_name)
return WIMLIB_ERR_NOMEM;
memcpy(dentry->short_name, node->dos_name,
- node->name_len_bytes);
- dentry->short_name_len = node->name_len_bytes;
+ node->name_nbytes);
+ dentry->short_name[node->name_nbytes / 2] = 0;
+ dentry->short_name_nbytes = node->name_nbytes;
DEBUG("Assigned DOS name to ino %"PRIu64,
dentry->d_inode->i_ino);
} else {
return 0;
}
-static void free_dos_name_tree(struct rb_node *node) {
+static void
+free_dos_name_tree(struct rb_node *node) {
if (node) {
free_dos_name_tree(node->rb_left);
free_dos_name_tree(node->rb_right);
}
}
-static void destroy_dos_name_map(struct dos_name_map *map)
+static void
+destroy_dos_name_map(struct dos_name_map *map)
{
free_dos_name_tree(map->rb_root.rb_node);
}
struct readdir_ctx {
struct wim_dentry *parent;
ntfs_inode *dir_ni;
- char *path;
+ mbchar *path;
size_t path_len;
struct wim_lookup_table *lookup_table;
struct sd_set *sd_set;
int add_image_flags,
wimlib_progress_func_t progress_func);
-static int wim_ntfs_capture_filldir(void *dirent, const ntfschar *name,
- const int name_len, const int name_type,
- const s64 pos, const MFT_REF mref,
- const unsigned dt_type)
+static int
+wim_ntfs_capture_filldir(void *dirent, const ntfschar *name,
+ const int name_nchars, const int name_type,
+ const s64 pos, const MFT_REF mref,
+ const unsigned dt_type)
{
struct readdir_ctx *ctx;
- size_t utf8_name_len;
- char *utf8_name;
+ size_t mbs_name_nbytes;
+ char *mbs_name;
struct wim_dentry *child;
int ret;
size_t path_len;
+ size_t name_nbytes = name_nchars * sizeof(ntfschar);
ctx = dirent;
if (name_type & FILE_NAME_DOS) {
/* If this is the entry for a DOS name, store it for later. */
ret = insert_dos_name(ctx->dos_name_map, name,
- name_len, mref & MFT_REF_MASK_CPU);
+ name_nbytes, mref & MFT_REF_MASK_CPU);
/* Return now if an error occurred or if this is just a DOS name
* and not a Win32+DOS name. */
if (ret != 0 || name_type == FILE_NAME_DOS)
return ret;
}
- ret = utf16_to_utf8((const char*)name, name_len * 2,
- &utf8_name, &utf8_name_len);
+ ret = utf16le_to_mbs(name, name_nbytes,
+ &mbs_name, &mbs_name_nbytes);
if (ret != 0)
return -1;
- if (utf8_name[0] == '.' &&
- (utf8_name[1] == '\0' ||
- (utf8_name[1] == '.' && utf8_name[2] == '\0'))) {
+ if (mbs_name[0] == '.' &&
+ (mbs_name[1] == '\0' ||
+ (mbs_name[1] == '.' && mbs_name[2] == '\0'))) {
/* . or .. entries
*
* note: name_type is POSIX for these, so DOS names will not
* have been inserted for them. */
ret = 0;
- goto out_free_utf8_name;
+ goto out_free_mbs_name;
}
/* Open the inode for this directory entry and recursively capture the
ntfs_inode *ni = ntfs_inode_open(ctx->dir_ni->vol, mref);
if (!ni) {
ERROR_WITH_ERRNO("Failed to open NTFS inode");
- goto out_free_utf8_name;
+ goto out_free_mbs_name;
}
path_len = ctx->path_len;
if (path_len != 1)
ctx->path[path_len++] = '/';
- memcpy(ctx->path + path_len, utf8_name, utf8_name_len + 1);
- path_len += utf8_name_len;
+ memcpy(ctx->path + path_len, mbs_name, mbs_name_nbytes + 1);
+ path_len += mbs_name_nbytes;
child = NULL;
ret = build_dentry_tree_ntfs_recursive(&child, ctx->dir_ni,
ni, ctx->path, path_len, name_type,
if (child)
dentry_add_child(ctx->parent, child);
ntfs_inode_close(ni);
-out_free_utf8_name:
- FREE(utf8_name);
+out_free_mbs_name:
+ FREE(mbs_name);
return ret;
}
* At the same time, update the WIM lookup table with lookup table entries for
* the NTFS streams, and build an array of security descriptors.
*/
-static int build_dentry_tree_ntfs_recursive(struct wim_dentry **root_p,
- ntfs_inode *dir_ni,
- ntfs_inode *ni,
- char path[],
- size_t path_len,
- int name_type,
- struct wim_lookup_table *lookup_table,
- struct sd_set *sd_set,
- const struct capture_config *config,
- ntfs_volume **ntfs_vol_p,
- int add_image_flags,
- wimlib_progress_func_t progress_func)
+static int
+build_dentry_tree_ntfs_recursive(struct wim_dentry **root_p,
+ ntfs_inode *dir_ni,
+ ntfs_inode *ni,
+ mbchar *path,
+ size_t path_len,
+ int name_type,
+ struct wim_lookup_table *lookup_table,
+ struct sd_set *sd_set,
+ const struct capture_config *config,
+ ntfs_volume **ntfs_vol_p,
+ int add_image_flags,
+ wimlib_progress_func_t progress_func)
{
u32 attributes;
int ret;
}
/* Create the new WIM dentry */
- root = new_dentry_with_timeless_inode(path_basename(path));
- if (!root) {
- if (errno == EILSEQ)
- return WIMLIB_ERR_INVALID_UTF8_STRING;
- else if (errno == ENOMEM)
- return WIMLIB_ERR_NOMEM;
- else
- return WIMLIB_ERR_ICONV_NOT_AVAILABLE;
- }
+ ret = new_dentry_with_timeless_inode(path_basename(path), &root);
+ if (ret)
+ return ret;
+
*root_p = root;
if (name_type & FILE_NAME_WIN32) /* Win32 or Win32+DOS name */
return ret;
}
-int build_dentry_tree_ntfs(struct wim_dentry **root_p,
- const char *device,
- struct wim_lookup_table *lookup_table,
- struct wim_security_data *sd,
- const struct capture_config *config,
- int add_image_flags,
- wimlib_progress_func_t progress_func,
- void *extra_arg)
+int
+build_dentry_tree_ntfs(struct wim_dentry **root_p,
+ const mbchar *device,
+ struct wim_lookup_table *lookup_table,
+ struct wim_security_data *sd,
+ const struct capture_config *config,
+ int add_image_flags,
+ wimlib_progress_func_t progress_func,
+ void *extra_arg)
{
ntfs_volume *vol;
ntfs_inode *root_ni;
goto out;
}
- /* Currently we assume that all the UTF-8 paths fit into this length and
- * there is no check for overflow. */
- char *path = MALLOC(32768);
+ /* Currently we assume that all the paths fit into this length and there
+ * is no check for overflow. */
+ mbchar *path = MALLOC(32768);
if (!path) {
ERROR("Could not allocate memory for NTFS pathname");
ret = WIMLIB_ERR_NOMEM;
if (ntfs_attr_pread(lte->attr, offset, size, buf) != size) {
ERROR_WITH_ERRNO("Error reading NTFS attribute "
"at `%s'",
- lte->ntfs_loc->path_utf8);
+ lte->ntfs_loc->path);
ret = WIMLIB_ERR_NTFS_3G;
}
break;
* entry resource length.
*/
static ssize_t
-get_symlink_name(const void *resource, size_t resource_len,
- void *buf, size_t buf_len,
- u32 reparse_tag)
+get_symlink_name(const void *resource, size_t resource_len, mbchar *buf,
+ size_t buf_len, u32 reparse_tag)
{
const u8 *p = resource;
u16 substitute_name_offset;
u16 substitute_name_len;
u16 print_name_offset;
u16 print_name_len;
- char *link_target;
+ mbchar *link_target;
size_t link_target_len;
ssize_t ret;
unsigned header_size;
- char *translated_target;
+ mbchar *translated_target;
bool is_absolute;
u32 flags;
if (header_size + substitute_name_offset + substitute_name_len > resource_len)
return -EIO;
- ret = utf16_to_utf8((const char *)p + substitute_name_offset,
+ 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)
make_symlink_reparse_data_buf(const mbchar *symlink_target,
size_t *len_ret, void **buf_ret)
{
- size_t utf8_len = strlen(symlink_target);
- char *name_utf16;
- size_t utf16_len;
+ utf16lechar *name_utf16le;
+ size_t name_utf16le_nbytes;
int ret;
- ret = utf8_to_utf16(symlink_target, utf8_len,
- &name_utf16, &utf16_len);
+ ret = mbs_to_utf16le(symlink_target, strlen(symlink_target),
+ &name_utf16le, &name_utf16le_nbytes);
if (ret != 0)
return ret;
- for (size_t i = 0; i < utf16_len / 2; i++)
- if (((u16*)name_utf16)[i] == cpu_to_le16('/'))
- ((u16*)name_utf16)[i] = cpu_to_le16('\\');
- size_t len = 12 + utf16_len * 2;
+ for (size_t i = 0; i < name_utf16le_nbytes / 2; i++)
+ if (name_utf16le[i] == cpu_to_le16('/'))
+ name_utf16le[i] = cpu_to_le16('\\');
+
+ size_t len = 12 + name_utf16le_nbytes * 2;
void *buf = MALLOC(len);
if (buf) {
u8 *p = buf;
- p = put_u16(p, utf16_len); /* Substitute name offset */
- p = put_u16(p, utf16_len); /* Substitute name length */
+ p = put_u16(p, name_utf16le_nbytes); /* Substitute name offset */
+ p = put_u16(p, name_utf16le_nbytes); /* Substitute name length */
p = put_u16(p, 0); /* Print name offset */
- p = put_u16(p, utf16_len); /* Print name length */
+ p = put_u16(p, name_utf16le_nbytes); /* Print name length */
p = put_u32(p, 1); /* flags: 0 iff *full* target, including drive letter??? */
- p = put_bytes(p, utf16_len, (const u8*)name_utf16);
- p = put_bytes(p, utf16_len, (const u8*)name_utf16);
+ p = put_bytes(p, name_utf16le_nbytes, name_utf16le);
+ p = put_bytes(p, name_utf16le_nbytes, name_utf16le);
*len_ret = len;
*buf_ret = buf;
ret = 0;
} else {
ret = WIMLIB_ERR_NOMEM;
}
- FREE(name_utf16);
+ FREE(name_utf16le);
return ret;
}
static size_t utf16le_strlen(const utf16lechar *s)
{
const utf16lechar *p = s;
- while (p)
+ while (*p)
p++;
return (p - s) / sizeof(utf16lechar);
}
const char *p;
for (p = format; *p; p++)
- if (*p == '%' && ((*p + 1) == 'W' || *(p + 1) == 'U'))
+ if (*p == '%' && (*(p + 1) == 'W' || *(p + 1) == 'U'))
goto special;
return vfprintf(fp, format, va);
special:
;
int n = 0;
for (p = format; *p; p++) {
- if (*p == '%' && ((*p + 1) == 'W' || *(p + 1) == 'U')) {
+ if (*p == '%' && (*(p + 1) == 'W' || *(p + 1) == 'U')) {
int ret;
mbchar *mbs;
- size_t mbs_len;
+ size_t mbs_nbytes;
if (*(p + 1) == 'W') {
utf16lechar *ucs = va_arg(va, utf16lechar*);
size_t ucs_nbytes = utf16le_strlen(ucs);
ret = utf16le_to_mbs(ucs, ucs_nbytes,
- &mbs, &mbs_len);
+ &mbs, &mbs_nbytes);
} else {
utf8char *ucs = va_arg(va, utf8char*);
size_t ucs_nbytes = strlen(ucs);
ret = utf8_to_mbs(ucs, ucs_nbytes,
- &mbs, &mbs_len);
+ &mbs, &mbs_nbytes);
}
if (ret) {
- ret = fprintf(fp, "???");
+ ret = fprintf(fp, "???CONVERSION FAILURE???");
} else {
ret = fprintf(fp, "%s", mbs);
FREE(mbs);
return -1;
else
n += ret;
+ p++;
} else {
if (putc(*p, fp) == EOF)
return -1;
WIMLIBAPI const mbchar *
wimlib_get_error_string(enum wimlib_error_code code)
{
- if (code < WIMLIB_ERR_SUCCESS || code > WIMLIB_ERR_XML)
+ if (code < 0 || code >= ARRAY_LEN(error_strings))
return NULL;
else
return error_strings[code];
/* A pointer to 'utf16lechar' indicates a UTF-16LE encoded string */
typedef u16 utf16lechar;
+/* encoding.c */
+extern void
+iconv_global_cleanup();
+
+extern bool wimlib_mbs_is_utf8;
+
+#define DECLARE_CHAR_CONVERSION_FUNCTIONS(varname1, varname2, \
+ chartype1, chartype2) \
+ \
+extern int \
+varname1##_to_##varname2##_nbytes(const chartype1 *in, size_t in_nbytes,\
+ size_t *out_nbytes_ret); \
+ \
+extern int \
+varname1##_to_##varname2##_buf(const chartype1 *in, size_t in_nbytes, \
+ chartype2 *out); \
+ \
+extern int \
+varname1##_to_##varname2(const chartype1 *in, size_t in_nbytes, \
+ chartype2 **out_ret, \
+ size_t *out_nbytes_ret); \
+
+/* multi-byte string to UTF16-LE string */
+DECLARE_CHAR_CONVERSION_FUNCTIONS(mbs, utf16le, mbchar, utf16lechar);
+
+/* UTF16-LE string to multi-byte string */
+DECLARE_CHAR_CONVERSION_FUNCTIONS(utf16le, mbs, utf16lechar, mbchar);
+
+/* UTF-8 string to multi-byte string */
+DECLARE_CHAR_CONVERSION_FUNCTIONS(utf8, mbs, utf8char, mbchar);
+
+extern bool
+utf8_str_contains_nonascii_chars(const utf8char *utf8_str);
+
#ifndef min
#define min(a, b) ({ typeof(a) __a = (a); typeof(b) __b = (b); \
(__a < __b) ? __a : __b; })
* image's security descriptors table. */
if (inode->i_security_id < -1) {
ERROR("Dentry `%s' has an invalid security ID (%d)",
- first_dentry->full_path_utf8, inode->i_security_id);
+ first_dentry->full_path, inode->i_security_id);
goto out;
}
if (inode->i_security_id >= sd->num_entries) {
ERROR("Dentry `%s' has an invalid security ID (%d) "
"(there are only %u entries in the security table)",
- first_dentry->full_path_utf8, inode->i_security_id,
- sd->num_entries);
+ first_dentry->full_path, inode->i_security_id,
+ sd->num_entries);
goto out;
}
lte = __lookup_resource(table, hash);
if (!lte && !is_zero_hash(hash)) {
ERROR("Could not find lookup table entry for stream "
- "%u of dentry `%s'", i, first_dentry->full_path_utf8);
+ "%u of dentry `%s'", i, first_dentry->full_path);
goto out;
}
if (lte)
for (unsigned i = 0; i <= inode->i_num_ads; i++) {
const u8 *hash;
hash = inode_stream_hash_unresolved(inode, i);
- if (inode_stream_name_len(inode, i) == 0 && !is_zero_hash(hash))
+ if (inode_stream_name_nbytes(inode, i) == 0 && !is_zero_hash(hash))
num_unnamed_streams++;
}
if (num_unnamed_streams > 1) {
ERROR("Dentry `%s' has multiple (%u) un-named streams",
- first_dentry->full_path_utf8, num_unnamed_streams);
+ first_dentry->full_path, num_unnamed_streams);
goto out;
}
* Source: NTFS-3g authors. */
const struct wim_dentry *dentry_with_dos_name = NULL;
inode_for_each_dentry(dentry, inode) {
- if (dentry->short_name_len) {
+ if (dentry_has_short_name(dentry)) {
if (dentry_with_dos_name) {
ERROR("Hard-linked file has a DOS name at "
"both `%s' and `%s'",
- dentry_with_dos_name->full_path_utf8,
- dentry->full_path_utf8);
+ dentry_with_dos_name->full_path,
+ dentry->full_path);
goto out;
}
dentry_with_dos_name = dentry;
/* Directories with multiple links have not been tested. XXX */
if (inode->i_nlink > 1 && inode->i_attributes & FILE_ATTRIBUTE_DIRECTORY) {
ERROR("Hard-linked directory `%s' is unsupported",
- first_dentry->full_path_utf8);
+ first_dentry->full_path);
goto out;
}
* into a single WIM dentry, even if they are stored separately on NTFS.
* (This seems to be the case...) */
if (dentry_is_root(dentry)) {
- if (dentry->file_name_len || dentry->short_name_len) {
- ERROR("The root dentry is named `%s', but it must "
- "be unnamed", dentry->file_name_utf8);
+ if (dentry_has_long_name(dentry) || dentry_has_short_name(dentry)) {
+ ERROR("The root dentry has a nonempty name!");
return WIMLIB_ERR_INVALID_DENTRY;
}
} else {
- if (!dentry->file_name_len) {
- ERROR("Dentry `%s' has no long name",
- dentry->full_path_utf8);
+ if (!dentry_has_long_name(dentry)) {
+ ERROR("Dentry `%s' has no long name!",
+ dentry->full_path);
return WIMLIB_ERR_INVALID_DENTRY;
}
}
#include "wimlib_internal.h"
#include "xml.h"
-static int image_print_metadata(WIMStruct *w)
+static int
+image_print_metadata(WIMStruct *w)
{
DEBUG("Printing metadata for image %d", w->current_image);
print_security_data(wim_security_data(w));
}
-static int image_print_files(WIMStruct *w)
+static int
+image_print_files(WIMStruct *w)
{
return for_dentry_in_tree(wim_root_dentry(w), print_dentry_full_path,
NULL);
}
-static WIMStruct *new_wim_struct()
+static WIMStruct *
+new_wim_struct()
{
WIMStruct *w = CALLOC(1, sizeof(WIMStruct));
#ifdef WITH_FUSE
* current image in turn. If @image is a certain image, @visitor is called on
* the WIM only once, with that image selected.
*/
-int for_image(WIMStruct *w, int image, int (*visitor)(WIMStruct *))
+int
+for_image(WIMStruct *w, int image, int (*visitor)(WIMStruct *))
{
int ret;
int start;
return 0;
}
-static int sort_image_metadata_by_position(const void *p1, const void *p2)
+static int
+sort_image_metadata_by_position(const void *p1, const void *p2)
{
const struct wim_image_metadata *imd1 = p1;
const struct wim_image_metadata *imd2 = p2;
* If @lte points to a metadata resource, append it to the list of metadata
* resources in the WIMStruct. Otherwise, do nothing.
*/
-static int append_metadata_resource_entry(struct wim_lookup_table_entry *lte,
- void *wim_p)
+static int
+append_metadata_resource_entry(struct wim_lookup_table_entry *lte, void *wim_p)
{
WIMStruct *w = wim_p;
int ret = 0;
}
/* Returns the compression type given in the flags of a WIM header. */
-static int wim_hdr_flags_compression_type(int wim_hdr_flags)
+static int
+wim_hdr_flags_compression_type(int wim_hdr_flags)
{
if (wim_hdr_flags & WIM_HDR_FLAG_COMPRESSION) {
if (wim_hdr_flags & WIM_HDR_FLAG_COMPRESS_LZX)
/*
* Creates a WIMStruct for a new WIM file.
*/
-WIMLIBAPI int wimlib_create_new_wim(int ctype, WIMStruct **w_ret)
+WIMLIBAPI int
+wimlib_create_new_wim(int ctype, WIMStruct **w_ret)
{
WIMStruct *w;
struct wim_lookup_table *table;
return ret;
}
-WIMLIBAPI int wimlib_get_num_images(const WIMStruct *w)
+WIMLIBAPI int
+wimlib_get_num_images(const WIMStruct *w)
{
return w->hdr.image_count;
}
-int select_wim_image(WIMStruct *w, int image)
+int
+select_wim_image(WIMStruct *w, int image)
{
struct wim_image_metadata *imd;
int ret;
/* Returns the compression type of the WIM file. */
-WIMLIBAPI int wimlib_get_compression_type(const WIMStruct *w)
+WIMLIBAPI int
+wimlib_get_compression_type(const WIMStruct *w)
{
return wim_hdr_flags_compression_type(w->hdr.flags);
}
-WIMLIBAPI const char *wimlib_get_compression_type_string(int ctype)
+WIMLIBAPI const char *
+wimlib_get_compression_type_string(int ctype)
{
switch (ctype) {
case WIMLIB_COMPRESSION_TYPE_NONE:
* the number of the image, or the name of the image. The images are numbered
* starting at 1.
*/
-WIMLIBAPI int wimlib_resolve_image(WIMStruct *w, const char *image_name_or_num)
+WIMLIBAPI int
+wimlib_resolve_image(WIMStruct *w, const utf8char *image_name_or_num)
{
char *p;
int image;
/* Prints some basic information about a WIM file. */
-WIMLIBAPI void wimlib_print_wim_information(const WIMStruct *w)
+WIMLIBAPI void
+wimlib_print_wim_information(const WIMStruct *w)
{
const struct wim_header *hdr;
putchar('\n');
}
-WIMLIBAPI bool wimlib_has_integrity_table(const WIMStruct *w)
+WIMLIBAPI bool
+wimlib_has_integrity_table(const WIMStruct *w)
{
return w->hdr.integrity.size != 0;
}
-WIMLIBAPI void wimlib_print_available_images(const WIMStruct *w, int image)
+WIMLIBAPI void
+wimlib_print_available_images(const WIMStruct *w, int image)
{
int first;
int last;
/* Prints the metadata for the specified image, which may be WIMLIB_ALL_IMAGES, but
* not WIMLIB_NO_IMAGE. */
-WIMLIBAPI int wimlib_print_metadata(WIMStruct *w, int image)
+WIMLIBAPI int
+wimlib_print_metadata(WIMStruct *w, int image)
{
if (w->hdr.part_number != 1) {
ERROR("Cannot show the metadata from part %hu of a %hu-part split WIM!",
return for_image(w, image, image_print_metadata);
}
-WIMLIBAPI int wimlib_print_files(WIMStruct *w, int image)
+WIMLIBAPI int
+wimlib_print_files(WIMStruct *w, int image)
{
if (w->hdr.part_number != 1) {
ERROR("Cannot list the files from part %hu of a %hu-part split WIM!",
}
/* Sets the index of the bootable image. */
-WIMLIBAPI int wimlib_set_boot_idx(WIMStruct *w, int boot_idx)
+WIMLIBAPI int
+wimlib_set_boot_idx(WIMStruct *w, int boot_idx)
{
if (w->hdr.total_parts != 1) {
ERROR("Cannot modify the boot index of a split WIM!");
return 0;
}
-WIMLIBAPI int wimlib_get_part_number(const WIMStruct *w, int *total_parts_ret)
+WIMLIBAPI int
+wimlib_get_part_number(const WIMStruct *w, int *total_parts_ret)
{
if (total_parts_ret)
*total_parts_ret = w->hdr.total_parts;
}
-WIMLIBAPI int wimlib_get_boot_idx(const WIMStruct *w)
+WIMLIBAPI int
+wimlib_get_boot_idx(const WIMStruct *w)
{
return w->hdr.boot_idx;
}
* Begins the reading of a WIM file; opens the file and reads its header and
* lookup table, and optionally checks the integrity.
*/
-static int begin_read(WIMStruct *w, const char *in_wim_path, int open_flags,
- wimlib_progress_func_t progress_func)
+static int
+begin_read(WIMStruct *w, const mbchar *in_wim_path, int open_flags,
+ wimlib_progress_func_t progress_func)
{
int ret;
int xml_num_images;
return 0;
}
-
/*
* Opens a WIM file and creates a WIMStruct for it.
*/
-WIMLIBAPI int wimlib_open_wim(const char *wim_file, int open_flags,
- WIMStruct **w_ret,
- wimlib_progress_func_t progress_func)
+WIMLIBAPI int
+wimlib_open_wim(const mbchar *wim_file, int open_flags,
+ WIMStruct **w_ret,
+ wimlib_progress_func_t progress_func)
{
WIMStruct *w;
int ret;
return ret;
}
-void destroy_image_metadata(struct wim_image_metadata *imd,
- struct wim_lookup_table *table)
+void
+destroy_image_metadata(struct wim_image_metadata *imd,
+ struct wim_lookup_table *table)
{
free_dentry_tree(imd->root_dentry, table);
free_security_data(imd->security_data);
/* Frees the memory for the WIMStruct, including all internal memory; also
* closes all files associated with the WIMStruct. */
-WIMLIBAPI void wimlib_free(WIMStruct *w)
+WIMLIBAPI void
+wimlib_free(WIMStruct *w)
{
DEBUG("Freeing WIMStruct");
/* Get global memory allocations out of the way. Not strictly necessary in
* single-threaded programs like 'imagex'. */
-WIMLIBAPI int wimlib_global_init()
+WIMLIBAPI int
+wimlib_global_init()
{
- char *encoding;
-
libxml_global_init();
+#ifdef WITH_NTFS_3G
+ libntfs3g_global_init();
+#endif
wimlib_mbs_is_utf8 = (strcmp(nl_langinfo(CODESET), "UTF-8") == 0);
- return iconv_global_init();
+ return 0;
}
/* Free global memory allocations. Not strictly necessary if the process using
* wimlib is just about to exit (as is the case for 'imagex'). */
-WIMLIBAPI void wimlib_global_cleanup()
+WIMLIBAPI void
+wimlib_global_cleanup()
{
libxml_global_cleanup();
iconv_global_cleanup();
add_new_dentry_tree(WIMStruct *dest_wim, struct wim_dentry *root,
struct wim_security_data *sd);
-/* encoding.c */
-
-#if defined(WITH_NTFS_3G) || defined(__WIN32__)
-
-static inline int
-iconv_global_init()
-{
- return 0;
-}
-
-static inline void
-iconv_global_cleanup() { }
-#else
-extern int
-iconv_global_init();
-
-extern void
-iconv_global_cleanup();
-#endif
-
-extern bool wimlib_mbs_is_utf8;
-
-extern bool
-utf8_str_contains_nonascii_chars(const utf8char *utf8_str);
-
-extern int
-mbs_to_utf16le_nbytes(const mbchar *mbs, size_t mbs_nbytes,
- size_t *utf16le_nbytes_ret);
-
-extern int
-utf16le_to_mbs_nbytes(const utf16lechar *utf16le_str,
- size_t utf16le_nbytes, size_t *mbs_nbytes_ret);
-
-extern int
-mbs_to_utf16le_buf(const mbchar *mbs, size_t mbs_nbytes,
- utf16lechar *utf16le_str);
-
-extern int
-utf16le_to_mbs_buf(const utf16lechar *utf16le_str, size_t utf16le_nbytes,
- mbchar *mbs);
-
-extern int
-mbs_to_utf16le(const mbchar *mbs, size_t mbs_nbytes,
- utf16lechar **utf16le_str_ret, size_t *utf16le_nbytes_ret);
-
-extern int
-utf16le_to_mbs(const utf16lechar *utf16le_str, size_t utf16le_nbytes,
- mbchar **mbs_ret, size_t *mbs_nbytes_ret);
/* extract_image.c */
extern int
apply_dentry_timestamps_ntfs(struct wim_dentry *dentry, void *arg);
+extern void
+libntfs3g_global_init();
+
/* ntfs-capture.c */
extern int
build_dentry_tree_ntfs(struct wim_dentry **root_p,
#include <limits.h>
-static int fflush_and_ftruncate(FILE *fp, off_t size)
+static int
+fflush_and_ftruncate(FILE *fp, off_t size)
{
int ret;
*/
typedef int (*compress_func_t)(const void *, unsigned, void *, unsigned *);
-compress_func_t get_compress_func(int out_ctype)
+compress_func_t
+get_compress_func(int out_ctype)
{
if (out_ctype == WIMLIB_COMPRESSION_TYPE_LZX)
return lzx_compress;
*
* Returns 0 on success; nonzero on failure.
*/
-static int write_wim_resource_chunk(const u8 chunk[], unsigned chunk_size,
- FILE *out_fp, compress_func_t compress,
- struct chunk_table *chunk_tab)
+static int
+write_wim_resource_chunk(const u8 chunk[], unsigned chunk_size,
+ FILE *out_fp, compress_func_t compress,
+ struct chunk_table *chunk_tab)
{
const u8 *out_chunk;
unsigned out_chunk_size;
/* Prepare for multiple reads to a resource by caching a FILE * or NTFS
* attribute pointer in the lookup table entry. */
-static int prepare_resource_for_read(struct wim_lookup_table_entry *lte
+static int
+prepare_resource_for_read(struct wim_lookup_table_entry *lte
- #ifdef WITH_NTFS_3G
- , ntfs_inode **ni_ret
- #endif
- )
+ #ifdef WITH_NTFS_3G
+ , ntfs_inode **ni_ret
+ #endif
+ )
{
switch (lte->resource_location) {
case RESOURCE_IN_FILE_ON_DISK:
struct ntfs_location *loc = lte->ntfs_loc;
ntfs_inode *ni;
wimlib_assert(loc);
- ni = ntfs_pathname_to_inode(*loc->ntfs_vol_p, NULL, loc->path_utf8);
+ ni = ntfs_pathname_to_inode(*loc->ntfs_vol_p, NULL, loc->path);
if (!ni) {
ERROR_WITH_ERRNO("Failed to open inode `%s' in NTFS "
- "volume", loc->path_utf8);
+ "volume", loc->path);
return WIMLIB_ERR_NTFS_3G;
}
lte->attr = ntfs_attr_open(ni,
loc->is_reparse_point ? AT_REPARSE_POINT : AT_DATA,
- (ntfschar*)loc->stream_name_utf16,
- loc->stream_name_utf16_num_chars);
+ loc->stream_name,
+ loc->stream_name_nchars);
if (!lte->attr) {
ERROR_WITH_ERRNO("Failed to open attribute of `%s' in "
- "NTFS volume", loc->path_utf8);
+ "NTFS volume", loc->path);
ntfs_inode_close(ni);
return WIMLIB_ERR_NTFS_3G;
}
/* Undo prepare_resource_for_read() by closing the cached FILE * or NTFS
* attribute. */
-static void end_wim_resource_read(struct wim_lookup_table_entry *lte
- #ifdef WITH_NTFS_3G
- , ntfs_inode *ni
- #endif
- )
+static void
+end_wim_resource_read(struct wim_lookup_table_entry *lte
+ #ifdef WITH_NTFS_3G
+ , ntfs_inode *ni
+ #endif
+ )
{
if (lte->resource_location == RESOURCE_IN_FILE_ON_DISK
&& lte->file_on_disk_fp)
*
* Returns 0 on success; nonzero on failure.
*/
-int write_wim_resource(struct wim_lookup_table_entry *lte,
- FILE *out_fp, int out_ctype,
- struct resource_entry *out_res_entry,
- int flags)
+int
+write_wim_resource(struct wim_lookup_table_entry *lte,
+ FILE *out_fp, int out_ctype,
+ struct resource_entry *out_res_entry,
+ int flags)
{
u64 bytes_remaining;
u64 original_size;
pthread_cond_t space_avail_cond;
};
-static int shared_queue_init(struct shared_queue *q, unsigned size)
+static int
+shared_queue_init(struct shared_queue *q, unsigned size)
{
wimlib_assert(size != 0);
q->array = CALLOC(sizeof(q->array[0]), size);
return 0;
}
-static void shared_queue_destroy(struct shared_queue *q)
+static void
+shared_queue_destroy(struct shared_queue *q)
{
FREE(q->array);
pthread_mutex_destroy(&q->lock);
pthread_cond_destroy(&q->space_avail_cond);
}
-static void shared_queue_put(struct shared_queue *q, void *obj)
+static void
+shared_queue_put(struct shared_queue *q, void *obj)
{
pthread_mutex_lock(&q->lock);
while (q->filled_slots == q->size)
pthread_mutex_unlock(&q->lock);
}
-static void *shared_queue_get(struct shared_queue *q)
+static void *
+shared_queue_get(struct shared_queue *q)
{
void *obj;
u64 begin_chunk;
};
-static void compress_chunks(struct message *msg, compress_func_t compress)
+static void
+compress_chunks(struct message *msg, compress_func_t compress)
{
for (unsigned i = 0; i < msg->num_chunks; i++) {
DEBUG2("compress chunk %u of %u", i, msg->num_chunks);
* res_to_compress_queue, compress them, and put them in the
* compressed_res_queue. A NULL pointer indicates that the thread should stop.
* */
-static void *compressor_thread_proc(void *arg)
+static void *
+compressor_thread_proc(void *arg)
{
struct compressor_thread_params *params = arg;
struct shared_queue *res_to_compress_queue = params->res_to_compress_queue;
DEBUG("Compressor thread terminating");
return NULL;
}
-#endif
+#endif /* ENABLE_MULTITHREADED_COMPRESSION */
-static int do_write_stream_list(struct list_head *my_resources,
- FILE *out_fp,
- int out_ctype,
- wimlib_progress_func_t progress_func,
- union wimlib_progress_info *progress,
- int write_resource_flags)
+static int
+do_write_stream_list(struct list_head *my_resources,
+ FILE *out_fp,
+ int out_ctype,
+ wimlib_progress_func_t progress_func,
+ union wimlib_progress_info *progress,
+ int write_resource_flags)
{
int ret;
struct wim_lookup_table_entry *lte, *tmp;
return 0;
}
-static int write_stream_list_serial(struct list_head *stream_list,
- FILE *out_fp,
- int out_ctype,
- int write_flags,
- wimlib_progress_func_t progress_func,
- union wimlib_progress_info *progress)
+static int
+write_stream_list_serial(struct list_head *stream_list,
+ FILE *out_fp,
+ int out_ctype,
+ int write_flags,
+ wimlib_progress_func_t progress_func,
+ union wimlib_progress_info *progress)
{
int write_resource_flags;
}
#ifdef ENABLE_MULTITHREADED_COMPRESSION
-static int write_wim_chunks(struct message *msg, FILE *out_fp,
- struct chunk_table *chunk_tab)
+static int
+write_wim_chunks(struct message *msg, FILE *out_fp,
+ struct chunk_table *chunk_tab)
{
for (unsigned i = 0; i < msg->num_chunks; i++) {
unsigned chunk_csize = msg->compressed_chunk_sizes[i];
* res_to_compress_queue, and it is passed back through the
* compressed_res_queue.
*/
-static int main_writer_thread_proc(struct list_head *stream_list,
- FILE *out_fp,
- int out_ctype,
- struct shared_queue *res_to_compress_queue,
- struct shared_queue *compressed_res_queue,
- size_t num_messages,
- int write_flags,
- wimlib_progress_func_t progress_func,
- union wimlib_progress_info *progress)
+static int
+main_writer_thread_proc(struct list_head *stream_list,
+ FILE *out_fp,
+ int out_ctype,
+ struct shared_queue *res_to_compress_queue,
+ struct shared_queue *compressed_res_queue,
+ size_t num_messages,
+ int write_flags,
+ wimlib_progress_func_t progress_func,
+ union wimlib_progress_info *progress)
{
int ret;
struct chunk_table *cur_chunk_tab = NULL;
return ret;
}
-static long get_default_num_threads()
+static long
+get_default_num_threads()
{
#ifdef __WIN32__
return win32_get_number_of_processors();
#endif
}
-static int write_stream_list_parallel(struct list_head *stream_list,
- FILE *out_fp,
- int out_ctype,
- int write_flags,
- unsigned num_threads,
- wimlib_progress_func_t progress_func,
- union wimlib_progress_info *progress)
+static int
+write_stream_list_parallel(struct list_head *stream_list,
+ FILE *out_fp,
+ int out_ctype,
+ int write_flags,
+ unsigned num_threads,
+ wimlib_progress_func_t progress_func,
+ union wimlib_progress_info *progress)
{
int ret;
struct shared_queue res_to_compress_queue;
* Write a list of streams to a WIM (@out_fp) using the compression type
* @out_ctype and up to @num_threads compressor threads.
*/
-static int write_stream_list(struct list_head *stream_list, FILE *out_fp,
- int out_ctype, int write_flags,
- unsigned num_threads,
- wimlib_progress_func_t progress_func)
+static int
+write_stream_list(struct list_head *stream_list, FILE *out_fp,
+ int out_ctype, int write_flags,
+ unsigned num_threads,
+ wimlib_progress_func_t progress_func)
{
struct wim_lookup_table_entry *lte;
size_t num_streams = 0;
struct list_head *stream_list;
};
-static int lte_overwrite_prepare(struct wim_lookup_table_entry *lte, void *arg)
+static int
+lte_overwrite_prepare(struct wim_lookup_table_entry *lte, void *arg)
{
struct lte_overwrite_prepare_args *args = arg;
return 0;
}
-static int wim_find_new_streams(WIMStruct *wim, off_t end_offset,
- struct list_head *stream_list)
+static int
+wim_find_new_streams(WIMStruct *wim, off_t end_offset,
+ struct list_head *stream_list)
{
struct lte_overwrite_prepare_args args = {
.wim = wim,
lte_overwrite_prepare, &args);
}
-static int inode_find_streams_to_write(struct wim_inode *inode,
- struct wim_lookup_table *table,
- struct list_head *stream_list)
+static int
+inode_find_streams_to_write(struct wim_inode *inode,
+ struct wim_lookup_table *table,
+ struct list_head *stream_list)
{
struct wim_lookup_table_entry *lte;
for (unsigned i = 0; i <= inode->i_num_ads; i++) {
return 0;
}
-static int image_find_streams_to_write(WIMStruct *w)
+static int
+image_find_streams_to_write(WIMStruct *w)
{
struct wim_inode *inode;
struct hlist_node *cur;
return 0;
}
-static int write_wim_streams(WIMStruct *w, int image, int write_flags,
+static int
+write_wim_streams(WIMStruct *w, int image, int write_flags,
unsigned num_threads,
wimlib_progress_func_t progress_func)
{
* fsync() the output file before closing it.
*
*/
-int finish_write(WIMStruct *w, int image, int write_flags,
- wimlib_progress_func_t progress_func)
+int
+finish_write(WIMStruct *w, int image, int write_flags,
+ wimlib_progress_func_t progress_func)
{
int ret;
struct wim_header hdr;
}
#if defined(HAVE_SYS_FILE_H) && defined(HAVE_FLOCK)
-int lock_wim(WIMStruct *w, FILE *fp)
+int
+lock_wim(WIMStruct *w, FILE *fp)
{
int ret = 0;
if (fp && !w->wim_locked) {
}
#endif
-static int open_wim_writable(WIMStruct *w, const char *path,
- bool trunc, bool readable)
+static int
+open_wim_writable(WIMStruct *w, const mbchar *path,
+ bool trunc, bool readable)
{
const char *mode;
if (trunc)
}
-void close_wim_writable(WIMStruct *w)
+void
+close_wim_writable(WIMStruct *w)
{
if (w->out_fp) {
if (fclose(w->out_fp) != 0) {
}
/* Open file stream and write dummy header for WIM. */
-int begin_write(WIMStruct *w, const char *path, int write_flags)
+int
+begin_write(WIMStruct *w, const mbchar *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 char *path,
- int image, int write_flags, unsigned num_threads,
- wimlib_progress_func_t progress_func)
+WIMLIBAPI int
+wimlib_write(WIMStruct *w, const mbchar *path,
+ int image, int write_flags, unsigned num_threads,
+ wimlib_progress_func_t progress_func)
{
int ret;
return ret;
}
-static bool any_images_modified(WIMStruct *w)
+static bool
+any_images_modified(WIMStruct *w)
{
for (int i = 0; i < w->hdr.image_count; i++)
if (w->image_metadata[i].modified)
* table, xml data, and integrity table were. (These usually only take up a
* small amount of space compared to the streams, however.)
*/
-static int overwrite_wim_inplace(WIMStruct *w, int write_flags,
- unsigned num_threads,
- wimlib_progress_func_t progress_func)
+static int
+overwrite_wim_inplace(WIMStruct *w, int write_flags,
+ unsigned num_threads,
+ wimlib_progress_func_t progress_func)
{
int ret;
struct list_head stream_list;
return ret;
}
-static int overwrite_wim_via_tmpfile(WIMStruct *w, int write_flags,
- unsigned num_threads,
- wimlib_progress_func_t progress_func)
+static int
+overwrite_wim_via_tmpfile(WIMStruct *w, int write_flags,
+ unsigned num_threads,
+ wimlib_progress_func_t progress_func)
{
size_t wim_name_len;
int ret;
/* Write the WIM to a temporary file in the same directory as the
* original WIM. */
wim_name_len = strlen(w->filename);
- char tmpfile[wim_name_len + 10];
+ mbchar tmpfile[wim_name_len + 10];
memcpy(tmpfile, w->filename, wim_name_len);
randomize_char_array_with_alnum(tmpfile + wim_name_len, 9);
tmpfile[wim_name_len + 9] = '\0';
/*
* Writes a WIM file to the original file that it was read from, overwriting it.
*/
-WIMLIBAPI int wimlib_overwrite(WIMStruct *w, int write_flags,
- unsigned num_threads,
- wimlib_progress_func_t progress_func)
+WIMLIBAPI int
+wimlib_overwrite(WIMStruct *w, int write_flags,
+ unsigned num_threads,
+ wimlib_progress_func_t progress_func)
{
write_flags &= WIMLIB_WRITE_MASK_PUBLIC;
if (inode->i_nlink >= 2 && dentry_is_first_in_inode(dentry)) {
for (unsigned i = 0; i < inode->i_num_ads; i++) {
- if (inode->i_ads_entries[i].stream_name_len) {
+ if (inode->i_ads_entries[i].stream_name_nbytes) {
lte = inode_stream_lte(inode, i + 1, lookup_table);
if (lte) {
info->hard_link_bytes += inode->i_nlink *
DEBUG("Parsing XML using libxml2 to create XML tree");
- doc = xmlReadMemory(xml_data, res_entry->size,
- "noname.xml", "UTF-16", 0);
+ doc = xmlReadMemory((const char *)xml_data,
+ res_entry->size, "noname.xml", "UTF-16", 0);
if (!doc) {
ERROR("Failed to parse XML data");