le64 unused_1;
le64 unused_2;
-
/* Creation time, last access time, and last write time, in
* 100-nanosecond intervals since 12:00 a.m UTC January 1, 1601. They
* should correspond to the times gotten by calling GetFileTime() on
/* Followed by variable length short name, in UTF16-LE, if
* short_name_nbytes != 0. Includes null terminator. */
/*utf16lechar short_name[];*/
+
+ /* And optionally followed by a variable-length series of tagged items;
+ * see tagged_items.c. */
} _packed_attribute;
/* Calculates the unaligned length, in bytes, of an on-disk WIM dentry that has
}
/* Calculates the unaligned length, in bytes, of an on-disk WIM dentry, based on
- * the file name length and short name length. Note that dentry->length is
- * ignored; also, this excludes any alternate data stream entries that may
- * follow the dentry. */
+ * the file name length, short name length, and optional tagged items. Note
+ * that dentry->length is ignored; also, this excludes any alternate data stream
+ * entries that may follow the dentry. */
static u64
dentry_correct_length_aligned(const struct wim_dentry *dentry)
{
len = dentry_correct_length_unaligned(dentry->file_name_nbytes,
dentry->short_name_nbytes);
+
+ if (dentry->d_inode->i_extra_size) {
+ len = (len + 7) & ~7;
+ len += dentry->d_inode->i_extra_size;
+ }
+
return (len + 7) & ~7;
}
do {
ulen += d->file_name_nbytes / sizeof(utf16lechar);
ulen++;
- d = d->parent; /* assumes d == d->parent for root */
+ d = d->d_parent; /* assumes d == d->d_parent for root */
} while (!dentry_is_root(d));
utf16lechar ubuf[ulen];
p -= d->file_name_nbytes / sizeof(utf16lechar);
memcpy(p, d->file_name, d->file_name_nbytes);
*--p = cpu_to_le16(WIM_PATH_SEPARATOR);
- d = d->parent; /* assumes d == d->parent for root */
+ d = d->d_parent; /* assumes d == d->d_parent for root */
} while (!dentry_is_root(d));
wimlib_assert(p == ubuf);
/* Start with the root directory of the image. Note: this will be NULL
* if an image has been added directly with wimlib_add_empty_image() but
* no files have been added yet; in that case we fail with ENOENT. */
- cur_dentry = wim_root_dentry(wim);
+ cur_dentry = wim_get_current_root_dentry(wim);
name_start = path;
for (;;) {
if (stream_name) {
struct wim_ads_entry *ads_entry;
- u16 ads_idx;
- ads_entry = inode_get_ads_entry(inode, stream_name,
- &ads_idx);
- if (ads_entry) {
- stream_idx = ads_idx + 1;
- lte = ads_entry->lte;
- } else {
- return -ENOENT;
- }
+
+ ads_entry = inode_get_ads_entry(inode, stream_name);
+ if (!ads_entry)
+ return -errno;
+
+ stream_idx = ads_entry - inode->i_ads_entries + 1;
+ lte = ads_entry->lte;
} else {
lte = inode_unnamed_stream_resolved(inode, &stream_idx);
}
return ret;
}
}
- dentry->parent = dentry;
+ dentry->d_parent = dentry;
*dentry_ret = dentry;
return 0;
}
} else {
INIT_LIST_HEAD(&child->d_ci_conflict_list);
}
- child->parent = parent;
+ child->d_parent = parent;
return NULL;
}
if (dentry_is_root(dentry))
return;
- dir = dentry->parent->d_inode;
+ dir = dentry->d_parent->d_inode;
dir_unindex_child(dir, dentry);
list_del(&dentry->d_ci_conflict_list);
}
+static int
+read_extra_data(const u8 *p, const u8 *end, struct wim_inode *inode)
+{
+ while (((uintptr_t)p & 7) && p < end)
+ p++;
+
+ if (unlikely(p < end)) {
+ inode->i_extra = memdup(p, end - p);
+ if (!inode->i_extra)
+ return WIMLIB_ERR_NOMEM;
+ inode->i_extra_size = end - p;
+ }
+ return 0;
+}
+
/* Reads a WIM directory entry, including all alternate data stream entries that
* follow it, from the WIM image's metadata resource. */
static int
p += short_name_nbytes + 2;
}
+ /* Read extra data at end of dentry (but before alternate data stream
+ * entries). This may contain tagged items. */
+ ret = read_extra_data(p, &buf[offset + dentry->length], inode);
+ if (ret)
+ goto err_free_dentry;
+
/* Align the dentry length. */
dentry->length = (dentry->length + 7) & ~7;
inode,
buf_len - offset - dentry->length)))
{
- ERROR("Failed to read alternate data stream "
- "entries of WIM dentry \"%"WS"\"",
- dentry->file_name);
goto err_free_dentry;
}
}
/* Check for cyclic directory structure, which would cause infinite
* recursion if not handled. */
- for (struct wim_dentry *d = dir->parent;
- !dentry_is_root(d); d = d->parent)
+ for (struct wim_dentry *d = dir->d_parent;
+ !dentry_is_root(d); d = d->d_parent)
{
if (unlikely(d->subdir_offset == cur_offset)) {
ERROR("Cyclic directory structure detected: children "
disk_dentry->attributes = cpu_to_le32(inode->i_attributes);
disk_dentry->security_id = cpu_to_le32(inode->i_security_id);
disk_dentry->subdir_offset = cpu_to_le64(dentry->subdir_offset);
+
+ /* UNIX data uses the two 8-byte reserved fields. So if no UNIX data
+ * exists, they get set to 0, just as we would do anyway. */
disk_dentry->unused_1 = cpu_to_le64(0);
disk_dentry->unused_2 = cpu_to_le64(0);
+
disk_dentry->creation_time = cpu_to_le64(inode->i_creation_time);
disk_dentry->last_access_time = cpu_to_le64(inode->i_last_access_time);
disk_dentry->last_write_time = cpu_to_le64(inode->i_last_write_time);
while ((uintptr_t)p & 7)
*p++ = 0;
+ if (inode->i_extra_size) {
+ /* Extra tagged items --- not usually present. */
+ p = mempcpy(p, inode->i_extra, inode->i_extra_size);
+ while ((uintptr_t)p & 7)
+ *p++ = 0;
+ }
+
disk_dentry->length = cpu_to_le64(p - orig_p);
if (use_dummy_stream) {