]> wimlib.net Git - wimlib/blobdiff - src/dentry.c
Timestamp printing UTC
[wimlib] / src / dentry.c
index 6d104ee5a990d843d13c5d508cb621e95836f1bd..8a285e25a0b6f4590a4efac5d3e622eced0e8b42 100644 (file)
@@ -85,6 +85,12 @@ static u64 __dentry_total_length(const struct dentry *dentry, u64 length)
        return (length + 7) & ~7;
 }
 
        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)
 /* 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 {
                /* 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);
 
                        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;
 {
        const u8 *hash;
        struct lookup_table_entry *lte;
+       time_t time;
+       char *p;
 
        printf("[DENTRY]\n");
        printf("Length            = %"PRIu64"\n", dentry->length);
 
        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);
        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("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.*/
        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);
                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. */
         * 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")",
                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;
 }
 
        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.
  *
 /* 
  * Writes a WIM dentry to an output buffer.
  *