return ret;
}
+/* Set the unnamed stream of a WIM inode, given a data buffer containing the
+ * stream contents. */
+int
+inode_set_unnamed_stream(struct wim_inode *inode, const void *data, size_t len,
+ struct wim_lookup_table *lookup_table)
+{
+ struct wim_lookup_table_entry *lte, *existing_lte;
+ u8 hash[SHA1_HASH_SIZE];
+ void *buf;
+
+ sha1_buffer(data, len, hash);
+
+ existing_lte = __lookup_resource(lookup_table, hash);
+
+ if (existing_lte) {
+ wimlib_assert(wim_resource_size(existing_lte) == len);
+ lte = existing_lte;
+ lte->refcnt++;
+ } else {
+ void *buf;
+
+ lte = new_lookup_table_entry();
+ if (!lte)
+ return WIMLIB_ERR_NOMEM;
+ buf = MALLOC(len);
+ if (!buf) {
+ free_lookup_table_entry(lte);
+ return WIMLIB_ERR_NOMEM;
+ }
+ memcpy(buf, data, len);
+ lte->resource_location = RESOURCE_IN_ATTACHED_BUFFER;
+ lte->attached_buffer = buf;
+ lte->resource_entry.original_size = len;
+ copy_hash(lte->hash, hash);
+ lookup_table_insert(lookup_table, lte);
+ }
+ inode->i_lte = lte;
+ inode->i_resolved = 1;
+ return 0;
+}
+
/* Remove an alternate data stream from a WIM inode */
void
inode_remove_ads(struct wim_inode *inode, u16 idx,
}
#endif /* !__WIN32__ */
+/* Replace weird characters in filenames and alternate data stream names.
+ *
+ * In particular we do not want the path separator to appear in any names, as
+ * that would make it possible for a "malicious" WIM to extract itself to any
+ * location it wanted to. */
static void
replace_forbidden_characters(utf16lechar *name)
{
if (*p == '/')
#endif
{
+ #ifdef __WIN32__
+ *p = cpu_to_le16(0xfffd);
+ #else
+ *p = '?';
+ #endif
if (name) {
WARNING("File, directory, or stream name \"%"WS"\"\n"
" contains forbidden characters; "
- "replacing them with Unicode codepoint U+001A",
+ "substituting replacement characters.",
name);
name = NULL;
}
- *p = 0x1a;
}
}
}
}
p = get_u64(p, &length);
- p += 8; /* Skip the reserved field */
+ p = get_u64(p, &cur_entry->unused);
p = get_bytes(p, SHA1_HASH_SIZE, cur_entry->hash);
p = get_u16(p, &cur_entry->stream_name_nbytes);
p = get_u32(p, (u32*)&inode->i_security_id);
p = get_u64(p, &dentry->subdir_offset);
- /* 2 unused fields */
- p += 2 * sizeof(u64);
- /*p = get_u64(p, &dentry->unused1);*/
- /*p = get_u64(p, &dentry->unused2);*/
+ p = get_u64(p, &inode->i_unused_1);
+ p = get_u64(p, &inode->i_unused_2);
p = get_u64(p, &inode->i_creation_time);
p = get_u64(p, &inode->i_last_access_time);
p = put_u32(p, inode->i_attributes);
p = put_u32(p, inode->i_security_id);
p = put_u64(p, dentry->subdir_offset);
- p = put_u64(p, 0); /* unused1 */
- p = put_u64(p, 0); /* unused2 */
+ p = put_u64(p, inode->i_unused_1);
+ p = put_u64(p, inode->i_unused_2);
p = put_u64(p, inode->i_creation_time);
p = put_u64(p, inode->i_last_access_time);
p = put_u64(p, inode->i_last_write_time);
hash = inode_stream_hash(inode, 0);
p = put_bytes(p, SHA1_HASH_SIZE, hash);
if (inode->i_attributes & FILE_ATTRIBUTE_REPARSE_POINT) {
- p = put_u32(p, 0);
+ p = put_u32(p, inode->i_rp_unknown_1);
p = put_u32(p, inode->i_reparse_tag);
- p = put_u16(p, 0);
+ p = put_u16(p, inode->i_rp_unknown_2);
p = put_u16(p, inode->i_not_rpfixed);
} else {
u64 link_group_id;
- p = put_u32(p, 0);
+ p = put_u32(p, inode->i_rp_unknown_1);
if (inode->i_nlink == 1)
link_group_id = 0;
else
* alternate data stream entries. */
for (u16 i = 0; i < inode->i_num_ads; i++) {
p = put_u64(p, ads_entry_total_length(&inode->i_ads_entries[i]));
- p = put_u64(p, 0); /* Unused */
+ p = put_u64(p, inode->i_ads_entries[i].unused);
hash = inode_stream_hash(inode, i + 1);
p = put_bytes(p, SHA1_HASH_SIZE, hash);
p = put_u16(p, inode->i_ads_entries[i].stream_name_nbytes);