return (length + 7) & ~7;
}
+u64 dentry_correct_total_length(const struct dentry *dentry)
+{
+ return __dentry_total_length(dentry,
+ dentry_correct_length_unaligned(dentry));
+}
+
/* Real length of a dentry, including the alternate data stream entries, which
* are not included in the dentry->length field... */
u64 dentry_total_length(const struct dentry *dentry)
dentry->attributes = FILE_ATTRIBUTE_NORMAL;
}
if (sizeof(ino_t) >= 8)
- dentry->hard_link = (u64)stbuf->st_ino;
+ dentry->link_group_id = (u64)stbuf->st_ino;
else
- dentry->hard_link = (u64)stbuf->st_ino |
+ dentry->link_group_id = (u64)stbuf->st_ino |
((u64)stbuf->st_dev << (sizeof(ino_t) * 8));
/* Set timestamps */
dentry->creation_time = timespec_to_wim_timestamp(&stbuf->st_mtim);
DEBUG("Add alternate data stream %s:%s",
dentry->file_name_utf8, stream_name);
- if (dentry->num_ads == 0xffff)
+ if (dentry->num_ads == 0xffff) {
+ ERROR("Too many alternate data streams in one dentry!");
return NULL;
+ }
num_ads = dentry->num_ads + 1;
ads_entries = REALLOC(dentry->ads_entries,
num_ads * sizeof(struct ads_entry));
- if (!ads_entries)
+ if (!ads_entries) {
+ ERROR("Failed to allocate memory for new alternate data stream");
return NULL;
+ }
if (ads_entries != dentry->ads_entries) {
/* We moved the ADS entries. Adjust the stream lists. */
for (u16 i = 0; i < dentry->num_ads; i++) {
/* Advance the subdir offset by the amount of space the children
* of this dentry take up. */
do {
- *subdir_offset_p += __dentry_total_length(child,
- dentry_correct_length(child));
+ *subdir_offset_p += dentry_correct_total_length(child);
child = child->next;
} while (child != dentry->children);
{
const u8 *hash;
struct lookup_table_entry *lte;
+ time_t time;
+ char *p;
printf("[DENTRY]\n");
printf("Length = %"PRIu64"\n", dentry->length);
#endif
/* Translate the timestamps into something readable */
- time_t creat_time = wim_timestamp_to_unix(dentry->creation_time);
- time_t access_time = wim_timestamp_to_unix(dentry->last_access_time);
- time_t mod_time = wim_timestamp_to_unix(dentry->last_write_time);
- printf("Creation Time = %s", asctime(gmtime(&creat_time)));
- printf("Last Access Time = %s", asctime(gmtime(&access_time)));
- printf("Last Write Time = %s", asctime(gmtime(&mod_time)));
+ time = wim_timestamp_to_unix(dentry->creation_time);
+ p = asctime(gmtime(&time));
+ *(strrchr(p, '\n')) = '\0';
+ printf("Creation Time = %s UTC\n", p);
+
+ time = wim_timestamp_to_unix(dentry->last_access_time);
+ p = asctime(gmtime(&time));
+ *(strrchr(p, '\n')) = '\0';
+ printf("Last Access Time = %s UTC\n", p);
+
+ time = wim_timestamp_to_unix(dentry->last_write_time);
+ p = asctime(gmtime(&time));
+ *(strrchr(p, '\n')) = '\0';
+ printf("Last Write Time = %s UTC\n", p);
printf("Reparse Tag = 0x%"PRIx32"\n", dentry->reparse_tag);
- printf("Hard Link Group = 0x%"PRIx64"\n", dentry->hard_link);
+ printf("Hard Link Group = 0x%"PRIx64"\n", dentry->link_group_id);
printf("Number of Alternate Data Streams = %hu\n", dentry->num_ads);
printf("Filename = \"");
print_string(dentry->file_name, dentry->file_name_len);
}
dentry->ads_entries_status = ADS_ENTRIES_USER;
}
- struct list_head *next;
list_del(&dentry->link_group_list);
free_dentry(dentry);
}
ret = get_names(&dentry->file_name, &dentry->file_name_utf8,
&dentry->file_name_len, &dentry->file_name_utf8_len,
new_name);
+ FREE(dentry->short_name);
+ dentry->short_name_len = 0;
if (ret == 0)
dentry->length = dentry_correct_length(dentry);
return ret;
u64 length_no_padding;
u64 total_length;
size_t utf8_len;
- const char *p_save = p;
+ const u8 *p_save = p;
/* Read the base stream entry, excluding the stream name. */
if (remaining_size < WIM_ADS_ENTRY_DISK_SIZE) {
if (remaining_size < length_no_padding) {
ERROR("Stream entries go past end of metadata resource");
ERROR("(remaining_size = %"PRIu64" bytes, "
- "length_no_padding = %"PRIu16" bytes)",
+ "length_no_padding = %"PRIu64" bytes)",
remaining_size, length_no_padding);
ret = WIMLIB_ERR_INVALID_DENTRY;
goto out_free_ads_entries;
char *short_name = NULL;
u16 short_name_len;
u16 file_name_len;
- size_t file_name_utf8_len;
+ size_t file_name_utf8_len = 0;
int ret;
dentry_common_init(dentry);
p += 4;
} else {
p = get_u32(p, &dentry->reparse_tag);
- p = get_u64(p, &dentry->hard_link);
+ p = get_u64(p, &dentry->link_group_id);
}
/* By the way, the reparse_reserved field does not actually exist (at
* u64 reserved1; (always 0)
* u64 reserved2; (always 0)
* };*/
- WARNING("Dentry for file or directory `%s' has %zu extra "
- "bytes of data",
- file_name_utf8, dentry->length - calculated_size);
+ DEBUG("Dentry for file or directory `%s' has %zu extra "
+ "bytes of data",
+ file_name_utf8, dentry->length - calculated_size);
}
/* Read the short filename if present. Note: if there is no short
/* Make sure there is only one un-named stream. */
unsigned num_unnamed_streams = 0;
- unsigned unnamed_stream_idx;
for (unsigned i = 0; i <= dentry->num_ads; i++) {
const u8 *hash;
hash = dentry_stream_hash_unresolved(dentry, i);
- if (!dentry_stream_name_len(dentry, i) && !is_zero_hash(hash)) {
+ if (!dentry_stream_name_len(dentry, i) && !is_zero_hash(hash))
num_unnamed_streams++;
- unnamed_stream_idx = i;
- }
}
if (num_unnamed_streams > 1) {
ERROR("Dentry `%s' has multiple (%u) un-named streams",
goto out;
}
+ /* Cannot have a short name but no long name */
+ if (dentry->short_name_len && !dentry->file_name_len) {
+ ERROR("Dentry `%s' has a short name but no long name",
+ dentry->full_path_utf8);
+ goto out;
+ }
+
+ /* Make sure root dentry is unnamed */
+ if (dentry_is_root(dentry)) {
+ if (dentry->file_name_len) {
+ ERROR("The root dentry is named `%s', but it must "
+ "be unnamed", dentry->file_name_utf8);
+ goto out;
+ }
+ }
+
#if 0
/* Check timestamps */
if (dentry->last_access_time < dentry->creation_time ||
static u8 *write_dentry(const struct dentry *dentry, u8 *p)
{
u8 *orig_p = p;
- unsigned padding;
const u8 *hash;
/* We calculate the correct length of the dentry ourselves because the
p = put_u64(p, dentry->creation_time);
p = put_u64(p, dentry->last_access_time);
p = put_u64(p, dentry->last_write_time);
- if (dentry->resolved && dentry->lte)
- hash = dentry->lte->hash;
- else
- hash = dentry->hash;
+ hash = dentry_stream_hash(dentry, 0);
p = put_bytes(p, SHA1_HASH_SIZE, hash);
if (dentry->attributes & FILE_ATTRIBUTE_REPARSE_POINT) {
p = put_zeroes(p, 4);
p = put_u32(p, dentry->reparse_tag);
p = put_zeroes(p, 4);
} else {
- u64 hard_link;
+ u64 link_group_id;
p = put_u32(p, 0);
if (dentry->link_group_list.next == &dentry->link_group_list)
- hard_link = 0;
+ link_group_id = 0;
else
- hard_link = dentry->hard_link;
- p = put_u64(p, hard_link);
+ link_group_id = dentry->link_group_id;
+ p = put_u64(p, link_group_id);
}
p = put_u16(p, dentry->num_ads);
p = put_u16(p, dentry->short_name_len);
for (u16 i = 0; i < dentry->num_ads; i++) {
p = put_u64(p, ads_entry_total_length(&dentry->ads_entries[i]));
p = put_u64(p, 0); /* Unused */
- if (dentry->resolved && dentry->ads_entries[i].lte)
- hash = dentry->ads_entries[i].lte->hash;
- else
- hash = dentry->ads_entries[i].hash;
+ hash = dentry_stream_hash(dentry, i + 1);
p = put_bytes(p, SHA1_HASH_SIZE, hash);
p = put_u16(p, dentry->ads_entries[i].stream_name_len);
if (dentry->ads_entries[i].stream_name_len) {