/* Return %true iff the alternate data stream entry @entry has the UTF-8 stream
* name @name that has length @name_len bytes. */
-static inline bool ads_entry_has_name(const struct ads_entry *entry,
+static inline bool ads_entry_has_name(const struct wim_ads_entry *entry,
const char *name, size_t name_len)
{
if (entry->stream_name_utf8_len != name_len)
/*
* Changes the name of an alternate data stream */
-static int change_ads_name(struct ads_entry *entry, const char *new_name)
+static int change_ads_name(struct wim_ads_entry *entry, const char *new_name)
{
return get_names(&entry->stream_name, &entry->stream_name_utf8,
&entry->stream_name_len,
/* Returns the total length of a WIM alternate data stream entry on-disk,
* including the stream name, the null terminator, AND the padding after the
* entry to align the next ADS entry or dentry on an 8-byte boundary. */
-static u64 ads_entry_total_length(const struct ads_entry *entry)
+static u64 ads_entry_total_length(const struct wim_ads_entry *entry)
{
u64 len = WIM_ADS_ENTRY_DISK_SIZE;
if (entry->stream_name_len)
printf("Full Path (UTF-8) = \"%s\"\n", dentry->full_path_utf8);
lte = inode_stream_lte(dentry->d_inode, 0, lookup_table);
if (lte) {
- print_lookup_table_entry(lte);
+ print_lookup_table_entry(lte, stdout);
} else {
hash = inode_stream_hash(inode, 0);
if (hash) {
print_hash(hash);
putchar('\n');
}
- print_lookup_table_entry(inode_stream_lte(inode, i + 1,
- lookup_table));
+ print_lookup_table_entry(inode_stream_lte(inode, i + 1, lookup_table),
+ stdout);
}
return 0;
}
}
-static int init_ads_entry(struct ads_entry *ads_entry, const char *name)
+static int init_ads_entry(struct wim_ads_entry *ads_entry, const char *name)
{
int ret = 0;
memset(ads_entry, 0, sizeof(*ads_entry));
return ret;
}
-static void destroy_ads_entry(struct ads_entry *ads_entry)
+static void destroy_ads_entry(struct wim_ads_entry *ads_entry)
{
FREE(ads_entry->stream_name);
FREE(ads_entry->stream_name_utf8);
return true;
}
-#ifdef WITH_FUSE
-/*
- * Unlink a dentry from the directory tree.
- *
- * Note: This merely removes it from the in-memory tree structure.
- */
+/* Unlink a WIM dentry from the directory entry tree. */
void unlink_dentry(struct wim_dentry *dentry)
{
struct wim_dentry *parent = dentry->parent;
return;
rb_erase(&dentry->rb_node, &parent->d_inode->i_children);
}
-#endif
-#ifdef WITH_FUSE
-/* Returns the alternate data stream entry belonging to @inode that has the
- * stream name @stream_name. */
-struct ads_entry *inode_get_ads_entry(struct wim_inode *inode,
+/*
+ * Returns the alternate data stream entry belonging to @inode that has the
+ * stream name @stream_name.
+ */
+struct wim_ads_entry *inode_get_ads_entry(struct wim_inode *inode,
const char *stream_name,
u16 *idx_ret)
{
}
return NULL;
}
-#endif
-#if defined(WITH_FUSE) || defined(WITH_NTFS_3G)
/*
- * Add an alternate stream entry to an inode and return a pointer to it, or NULL
- * if memory could not be allocated.
+ * Add an alternate stream entry to a WIM inode and return a pointer to it, or
+ * NULL if memory could not be allocated.
*/
-struct ads_entry *inode_add_ads(struct wim_inode *inode, const char *stream_name)
+struct wim_ads_entry *inode_add_ads(struct wim_inode *inode, const char *stream_name)
{
u16 num_ads;
- struct ads_entry *ads_entries;
- struct ads_entry *new_entry;
+ struct wim_ads_entry *ads_entries;
+ struct wim_ads_entry *new_entry;
DEBUG("Add alternate data stream \"%s\"", stream_name);
inode->i_num_ads = num_ads;
return new_entry;
}
-#endif
-#ifdef WITH_FUSE
-/* Remove an alternate data stream from the inode */
+int inode_add_ads_with_data(struct wim_inode *inode, const char *name,
+ const u8 *value, size_t size,
+ struct wim_lookup_table *lookup_table)
+{
+ int ret = WIMLIB_ERR_NOMEM;
+ struct wim_ads_entry *new_ads_entry;
+ struct wim_lookup_table_entry *existing_lte;
+ struct wim_lookup_table_entry *lte;
+ u8 value_hash[SHA1_HASH_SIZE];
+
+ wimlib_assert(inode->i_resolved);
+ new_ads_entry = inode_add_ads(inode, name);
+ if (!new_ads_entry)
+ goto out;
+ sha1_buffer((const u8*)value, size, value_hash);
+ existing_lte = __lookup_resource(lookup_table, value_hash);
+ if (existing_lte) {
+ lte = existing_lte;
+ lte->refcnt++;
+ } else {
+ u8 *value_copy;
+ lte = new_lookup_table_entry();
+ if (!lte)
+ goto out_free_ads_entry;
+ value_copy = MALLOC(size);
+ if (!value_copy) {
+ FREE(lte);
+ goto out_free_ads_entry;
+ }
+ memcpy(value_copy, value, size);
+ lte->resource_location = RESOURCE_IN_ATTACHED_BUFFER;
+ lte->attached_buffer = value_copy;
+ lte->resource_entry.original_size = size;
+ lte->resource_entry.size = size;
+ lte->resource_entry.flags = 0;
+ copy_hash(lte->hash, value_hash);
+ lookup_table_insert(lookup_table, lte);
+ }
+ new_ads_entry->lte = lte;
+ ret = 0;
+ goto out;
+out_free_ads_entry:
+ inode_remove_ads(inode, new_ads_entry - inode->i_ads_entries,
+ lookup_table);
+out:
+ return ret;
+}
+
+/* Remove an alternate data stream from a WIM inode */
void inode_remove_ads(struct wim_inode *inode, u16 idx,
struct wim_lookup_table *lookup_table)
{
- struct ads_entry *ads_entry;
+ struct wim_ads_entry *ads_entry;
struct wim_lookup_table_entry *lte;
wimlib_assert(idx < inode->i_num_ads);
destroy_ads_entry(ads_entry);
- memcpy(&inode->i_ads_entries[idx],
- &inode->i_ads_entries[idx + 1],
- (inode->i_num_ads - idx - 1) * sizeof(inode->i_ads_entries[0]));
+ memmove(&inode->i_ads_entries[idx],
+ &inode->i_ads_entries[idx + 1],
+ (inode->i_num_ads - idx - 1) * sizeof(inode->i_ads_entries[0]));
inode->i_num_ads--;
}
-#endif
+int inode_get_unix_data(const struct wim_inode *inode,
+ struct wimlib_unix_data *unix_data,
+ u16 *stream_idx_ret)
+{
+ const struct wim_ads_entry *ads_entry;
+ const struct wim_lookup_table_entry *lte;
+ size_t size;
+ int ret;
+
+ wimlib_assert(inode->i_resolved);
+
+ ads_entry = inode_get_ads_entry((struct wim_inode*)inode,
+ WIMLIB_UNIX_DATA_TAG, NULL);
+ if (!ads_entry)
+ return NO_UNIX_DATA;
+
+ if (stream_idx_ret)
+ *stream_idx_ret = ads_entry - inode->i_ads_entries;
+
+ lte = ads_entry->lte;
+ if (!lte)
+ return NO_UNIX_DATA;
+
+ size = wim_resource_size(lte);
+ if (size != sizeof(struct wimlib_unix_data))
+ return BAD_UNIX_DATA;
+ ret = read_full_wim_resource(lte, (u8*)unix_data, 0);
+ if (ret)
+ return ret;
+
+ if (unix_data->version != 0)
+ return BAD_UNIX_DATA;
+ return 0;
+}
+
+int inode_set_unix_data(struct wim_inode *inode,
+ uid_t uid, gid_t gid, mode_t mode,
+ struct wim_lookup_table *lookup_table,
+ int which)
+{
+ struct wimlib_unix_data unix_data;
+ int ret;
+ bool have_good_unix_data = false;
+ bool have_unix_data = false;
+ u16 stream_idx;
+
+ if (!(which & UNIX_DATA_CREATE)) {
+ ret = inode_get_unix_data(inode, &unix_data, &stream_idx);
+ if (ret == 0 || ret == BAD_UNIX_DATA || ret > 0)
+ have_unix_data = true;
+ if (ret == 0)
+ have_good_unix_data = true;
+ }
+ unix_data.version = 0;
+ if (which & UNIX_DATA_UID || !have_good_unix_data)
+ unix_data.uid = uid;
+ if (which & UNIX_DATA_GID || !have_good_unix_data)
+ unix_data.gid = gid;
+ 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,
+ sizeof(struct wimlib_unix_data),
+ lookup_table);
+ if (ret == 0 && have_unix_data)
+ inode_remove_ads(inode, stream_idx, lookup_table);
+ return ret;
+}
/*
- * Reads the alternate data stream entries for a dentry.
+ * Reads the alternate data stream entries of a WIM dentry.
*
* @p: Pointer to buffer that starts with the first alternate stream entry.
*
*
* The format of the on-disk alternate stream entries is as follows:
*
- * struct ads_entry_on_disk {
+ * struct wim_ads_entry_on_disk {
* u64 length; // Length of the entry, in bytes. This includes
* all fields (including the stream name and
* null terminator if present, AND the padding!).
* In addition, the entries are 8-byte aligned.
*
* Return 0 on success or nonzero on failure. On success, inode->i_ads_entries
- * is set to an array of `struct ads_entry's of length inode->i_num_ads. On
+ * is set to an array of `struct wim_ads_entry's of length inode->i_num_ads. On
* failure, @inode is not modified.
*/
static int read_ads_entries(const u8 *p, struct wim_inode *inode,
u64 remaining_size)
{
u16 num_ads;
- struct ads_entry *ads_entries;
+ struct wim_ads_entry *ads_entries;
int ret;
num_ads = inode->i_num_ads;
}
for (u16 i = 0; i < num_ads; i++) {
- struct ads_entry *cur_entry;
+ struct wim_ads_entry *cur_entry;
u64 length;
u64 length_no_padding;
u64 total_length;
}
/*
- * Reads a directory entry, including all alternate data stream entries that
+ * Reads a WIM directory entry, including all alternate data stream entries that
* follow it, from the WIM image's metadata resource.
*
* @metadata_resource: Buffer containing the uncompressed metadata resource.
* u64 reserved1; (always 0)
* u64 reserved2; (always 0)
* };*/
- DEBUG("Dentry for file or directory `%s' has %zu extra "
+ DEBUG("Dentry for file or directory `%s' has %"PRIu64" extra "
"bytes of data",
file_name_utf8, dentry->length - calculated_size);
}
* recursively writing the directory trees rooted at each of the child
* dentries, since the on-disk dentries for a dentry's children are
* always located at consecutive positions in the metadata resource! */
- for_dentry_in_rbtree(parent->d_inode->i_children.rb_node, write_dentry_cb, &p);
+ for_dentry_child(parent, write_dentry_cb, &p);
/* write end of directory entry */
p = put_u64(p, 0);
/* Recurse on children. */
- for_dentry_in_rbtree(parent->d_inode->i_children.rb_node,
- write_dentry_tree_recursive_cb, &p);
+ for_dentry_child(parent, write_dentry_tree_recursive_cb, &p);
return p;
}