X-Git-Url: https://wimlib.net/git/?p=wimlib;a=blobdiff_plain;f=src%2Fdentry.c;h=8a285e25a0b6f4590a4efac5d3e622eced0e8b42;hp=6d104ee5a990d843d13c5d508cb621e95836f1bd;hb=72f16c2c9e53f83210e8679f487d4a64d8c897e7;hpb=599038a018d59ae50adca3ead59bfbb83aadef59 diff --git a/src/dentry.c b/src/dentry.c index 6d104ee5..8a285e25 100644 --- a/src/dentry.c +++ b/src/dentry.c @@ -85,6 +85,12 @@ static u64 __dentry_total_length(const struct dentry *dentry, u64 length) 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) @@ -341,8 +347,7 @@ void calculate_subdir_offsets(struct dentry *dentry, u64 *subdir_offset_p) /* 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); @@ -474,6 +479,8 @@ int print_dentry(struct dentry *dentry, void *lookup_table) { const u8 *hash; struct lookup_table_entry *lte; + time_t time; + char *p; printf("[DENTRY]\n"); printf("Length = %"PRIu64"\n", dentry->length); @@ -498,9 +505,21 @@ int print_dentry(struct dentry *dentry, void *lookup_table) 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); @@ -1049,7 +1068,7 @@ int read_dentry(const u8 metadata_resource[], u64 metadata_resource_len, dentry_common_init(dentry); /*Make sure the dentry really fits into the metadata resource.*/ - if (offset + 8 > metadata_resource_len) { + if (offset + 8 > metadata_resource_len || offset + 8 < offset) { ERROR("Directory entry starting at %"PRIu64" ends past the " "end of the metadata resource (size %"PRIu64")", offset, metadata_resource_len); @@ -1073,7 +1092,9 @@ int read_dentry(const u8 metadata_resource[], u64 metadata_resource_len, * not too short, read the rest of it (excluding the alternate data * streams, but including the file name and short name variable-length * fields) into memory. */ - if (offset + dentry->length >= metadata_resource_len) { + if (offset + dentry->length >= metadata_resource_len + || offset + dentry->length < offset) + { ERROR("Directory entry at offset %"PRIu64" and with size " "%"PRIu64" ends past the end of the metadata resource " "(size %"PRIu64")", @@ -1262,6 +1283,76 @@ out_free_file_name: return ret; } +/* Run some miscellaneous verifications on a WIM dentry */ +int verify_dentry(struct dentry *dentry, void *wim) +{ + const WIMStruct *w = wim; + const struct lookup_table *table = w->lookup_table; + const struct wim_security_data *sd = wim_const_security_data(w); + int ret = WIMLIB_ERR_INVALID_DENTRY; + + /* Check the security ID */ + if (dentry->security_id < -1) { + ERROR("Dentry `%s' has an invalid security ID (%d)", + dentry->full_path_utf8, dentry->security_id); + goto out; + } + if (dentry->security_id >= sd->num_entries) { + ERROR("Dentry `%s' has an invalid security ID (%d) " + "(there are only %u entries in the security table)", + dentry->full_path_utf8, dentry->security_id, + sd->num_entries); + goto out; + } + + /* Check that lookup table entries for all the resources exist, except + * if the SHA1 message digest is all 0's, which indicates there is + * intentionally no resource there. */ + if (w->hdr.total_parts == 1) { + for (unsigned i = 0; i <= dentry->num_ads; i++) { + struct lookup_table_entry *lte; + const u8 *hash; + hash = dentry_stream_hash_unresolved(dentry, i); + lte = __lookup_resource(table, hash); + if (!lte && !is_zero_hash(hash)) { + ERROR("Could not find lookup table entry for stream " + "%u of dentry `%s'", i, dentry->full_path_utf8); + goto out; + } + } + } + + /* 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)) { + num_unnamed_streams++; + unnamed_stream_idx = i; + } + } + if (num_unnamed_streams > 1) { + ERROR("Dentry `%s' has multiple (%u) un-named streams", + dentry->full_path_utf8, num_unnamed_streams); + goto out; + } + +#if 0 + /* Check timestamps */ + if (dentry->last_access_time < dentry->creation_time || + dentry->last_write_time < dentry->creation_time) { + WARNING("Dentry `%s' was created after it was last accessed or " + "written to", dentry->full_path_utf8); + } +#endif + + ret = 0; +out: + return ret; +} + /* * Writes a WIM dentry to an output buffer. *