]> wimlib.net Git - wimlib/blobdiff - src/dentry.c
write_xml_data() cleanup
[wimlib] / src / dentry.c
index 7d17fb9c9db0408d3486c0ef0d1f2e705607d42c..4a7b1f363db071c85050d862194d249ab5bc52ac 100644 (file)
@@ -953,19 +953,19 @@ int verify_dentry(struct dentry *dentry, void *wim)
 {
        const WIMStruct *w = wim;
        const struct inode *inode = dentry->d_inode;
-       int ret = WIMLIB_ERR_INVALID_DENTRY;
+       int ret;
 
        if (!dentry->d_inode->verified) {
                ret = verify_inode(dentry->d_inode, w);
                if (ret != 0)
-                       goto out;
+                       return ret;
        }
 
        /* 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;
+               return WIMLIB_ERR_INVALID_DENTRY;
        }
 
        /* Make sure root dentry is unnamed */
@@ -973,7 +973,7 @@ int verify_dentry(struct dentry *dentry, void *wim)
                if (dentry->file_name_len) {
                        ERROR("The root dentry is named `%s', but it must "
                              "be unnamed", dentry->file_name_utf8);
-                       goto out;
+                       return WIMLIB_ERR_INVALID_DENTRY;
                }
        }
 
@@ -986,9 +986,7 @@ int verify_dentry(struct dentry *dentry, void *wim)
        }
 #endif
 
-       ret = 0;
-out:
-       return ret;
+       return 0;
 }
 
 
@@ -1455,7 +1453,7 @@ int read_dentry(const u8 metadata_resource[], u64 metadata_resource_len,
 
                p = get_bytes(p, short_name_len, short_name);
                if (*(u16*)p)
-                       WARNING("Expected two zero bytes following the file name "
+                       WARNING("Expected two zero bytes following the short name of "
                                "`%s', but found non-zero bytes", file_name_utf8);
                p += 2;
        }
@@ -1470,18 +1468,35 @@ int read_dentry(const u8 metadata_resource[], u64 metadata_resource_len,
         * included in the dentry->length field for some reason.
         */
        if (inode->num_ads != 0) {
-               if (calculated_size > metadata_resource_len - offset) {
-                       ERROR("Not enough space in metadata resource for "
-                             "alternate stream entries");
-                       ret = WIMLIB_ERR_INVALID_DENTRY;
-                       goto out_free_short_name;
+
+               /* Trying different lengths is just a hack to make sure we have
+                * a chance of reading the ADS entries correctly despite the
+                * poor documentation. */
+
+               if (calculated_size != dentry->length) {
+                       WARNING("Trying calculated dentry length (%"PRIu64") "
+                               "instead of dentry->length field (%"PRIu64") "
+                               "to read ADS entries",
+                               calculated_size, dentry->length);
                }
-               ret = read_ads_entries(&metadata_resource[offset + calculated_size],
-                                      inode,
-                                      metadata_resource_len - offset - calculated_size);
-               if (ret != 0)
-                       goto out_free_short_name;
+               u64 lengths_to_try[3] = {calculated_size,
+                                        dentry->length + 7 & ~7,
+                                        dentry->length};
+               ret = WIMLIB_ERR_INVALID_DENTRY;
+               for (size_t i = 0; i < ARRAY_LEN(lengths_to_try); i++) {
+                       if (lengths_to_try[i] > metadata_resource_len - offset)
+                               continue;
+                       ret = read_ads_entries(&metadata_resource[offset + lengths_to_try[i]],
+                                              inode,
+                                              metadata_resource_len - offset - lengths_to_try[i]);
+                       if (ret == 0)
+                               goto out;
+               }
+               ERROR("Failed to read alternate data stream "
+                     "entries of `%s'", dentry->file_name_utf8);
+               goto out_free_short_name;
        }
+out:
 
        /* We've read all the data for this dentry.  Set the names and their
         * lengths, and we've done. */