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;
}
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);
}
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;
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) {