]> wimlib.net Git - wimlib/blobdiff - src/dentry.c
WIMBoot / system compression: try WOFADK in addition to WOF
[wimlib] / src / dentry.c
index a1a312dbc300cd14fede4339e08b6b6c654a4e7e..13940a32d3b96c2a4c7d6f9a60babea8e3931ceb 100644 (file)
@@ -472,10 +472,10 @@ for_dentry_in_tree_depth(struct wim_dentry *root,
 /*
  * Calculate the full path to @dentry within the WIM image, if not already done.
  *
- * The full name will be saved in the cached value 'dentry->_full_path'.
+ * The full name will be saved in the cached value 'dentry->d_full_path'.
  *
  * Whenever possible, use dentry_full_path() instead of calling this and
- * accessing _full_path directly.
+ * accessing d_full_path directly.
  *
  * Returns 0 or an error code resulting from a failed string conversion.
  */
@@ -486,7 +486,7 @@ calculate_dentry_full_path(struct wim_dentry *dentry)
        size_t dummy;
        const struct wim_dentry *d;
 
-       if (dentry->_full_path)
+       if (dentry->d_full_path)
                return 0;
 
        ulen = 0;
@@ -511,7 +511,7 @@ calculate_dentry_full_path(struct wim_dentry *dentry)
        wimlib_assert(p == ubuf);
 
        return utf16le_to_tstr(ubuf, ulen * sizeof(utf16lechar),
-                              &dentry->_full_path, &dummy);
+                              &dentry->d_full_path, &dummy);
 }
 
 /*
@@ -525,7 +525,7 @@ tchar *
 dentry_full_path(struct wim_dentry *dentry)
 {
        calculate_dentry_full_path(dentry);
-       return dentry->_full_path;
+       return dentry->d_full_path;
 }
 
 static int
@@ -666,10 +666,10 @@ struct wim_dentry *
 get_dentry_child_with_utf16le_name(const struct wim_dentry *dentry,
                                   const utf16lechar *name,
                                   size_t name_nbytes,
-                                  CASE_SENSITIVITY_TYPE case_ctype)
+                                  CASE_SENSITIVITY_TYPE case_type)
 {
        const struct wim_inode *dir = dentry->d_inode;
-       bool ignore_case = will_ignore_case(case_ctype);
+       bool ignore_case = will_ignore_case(case_type);
        struct wim_dentry dummy;
        struct wim_dentry *child;
 
@@ -982,19 +982,6 @@ new_filler_directory(struct wim_dentry **dentry_ret)
        return 0;
 }
 
-static int
-dentry_clear_inode_visited(struct wim_dentry *dentry, void *_ignore)
-{
-       dentry->d_inode->i_visited = 0;
-       return 0;
-}
-
-void
-dentry_tree_clear_inode_visited(struct wim_dentry *root)
-{
-       for_dentry_in_tree(root, dentry_clear_inode_visited, NULL);
-}
-
 /*
  * Free a WIM dentry.
  *
@@ -1008,7 +995,7 @@ free_dentry(struct wim_dentry *dentry)
                d_disassociate(dentry);
                FREE(dentry->d_name);
                FREE(dentry->d_short_name);
-               FREE(dentry->_full_path);
+               FREE(dentry->d_full_path);
                FREE(dentry);
        }
 }
@@ -1240,6 +1227,12 @@ assign_stream_types_encrypted(struct wim_inode *inode)
  * There will be an unnamed data stream, a reparse point stream, or both an
  * unnamed data stream and a reparse point stream.  In addition, there may be
  * named data streams.
+ *
+ * NOTE: if the file has a reparse point stream or at least one named data
+ * stream, then WIMGAPI puts *all* streams in the extra stream entries and
+ * leaves the default stream hash zeroed.  wimlib now does the same.  However,
+ * for input we still support the default hash field being used, since wimlib
+ * used to use it and MS software is somewhat accepting of it as well.
  */
 static void
 assign_stream_types_unencrypted(struct wim_inode *inode)
@@ -1254,7 +1247,10 @@ assign_stream_types_unencrypted(struct wim_inode *inode)
                if (stream_is_named(strm)) {
                        /* Named data stream  */
                        strm->stream_type = STREAM_TYPE_DATA;
-               } else if (!is_zero_hash(strm->_stream_hash)) {
+               } else if (i != 0 || !is_zero_hash(strm->_stream_hash)) {
+                       /* Unnamed stream in the extra stream entries, OR the
+                        * default stream in the dentry provided that it has a
+                        * nonzero hash.  */
                        if ((inode->i_attributes & FILE_ATTRIBUTE_REPARSE_POINT) &&
                            !found_reparse_point_stream) {
                                found_reparse_point_stream = true;
@@ -1263,17 +1259,21 @@ assign_stream_types_unencrypted(struct wim_inode *inode)
                                found_unnamed_data_stream = true;
                                strm->stream_type = STREAM_TYPE_DATA;
                        }
-               } else {
-                       /* If no stream name is specified and the hash is zero,
-                        * then remember this stream for later so that we can
-                        * assign it to the unnamed data stream if we don't find
-                        * a better candidate.  */
+               } else if (!unnamed_stream_with_zero_hash) {
                        unnamed_stream_with_zero_hash = strm;
                }
        }
 
-       if (!found_unnamed_data_stream && unnamed_stream_with_zero_hash != NULL)
-               unnamed_stream_with_zero_hash->stream_type = STREAM_TYPE_DATA;
+       if (unnamed_stream_with_zero_hash) {
+               int type = STREAM_TYPE_UNKNOWN;
+               if ((inode->i_attributes & FILE_ATTRIBUTE_REPARSE_POINT) &&
+                   !found_reparse_point_stream) {
+                       type = STREAM_TYPE_REPARSE_POINT;
+               } else if (!found_unnamed_data_stream) {
+                       type = STREAM_TYPE_DATA;
+               }
+               unnamed_stream_with_zero_hash->stream_type = type;
+       }
 }
 
 /*
@@ -1394,7 +1394,7 @@ read_dentry(const u8 * restrict buf, size_t buf_len,
        u64 calculated_size;
        int ret;
 
-       BUILD_BUG_ON(sizeof(struct wim_dentry_on_disk) != WIM_DENTRY_DISK_SIZE);
+       STATIC_ASSERT(sizeof(struct wim_dentry_on_disk) == WIM_DENTRY_DISK_SIZE);
 
        /* Before reading the whole dentry, we need to read just the length.
         * This is because a dentry of length 8 (that is, just the length field)
@@ -1547,21 +1547,14 @@ dentry_is_dot_or_dotdot(const struct wim_dentry *dentry)
 
 static int
 read_dentry_tree_recursive(const u8 * restrict buf, size_t buf_len,
-                          struct wim_dentry * restrict dir)
+                          struct wim_dentry * restrict dir, unsigned depth)
 {
        u64 cur_offset = dir->d_subdir_offset;
 
-       /* Check for cyclic directory structure, which would cause infinite
-        * recursion if not handled.  */
-       for (struct wim_dentry *d = dir->d_parent;
-            !dentry_is_root(d); d = d->d_parent)
-       {
-               if (unlikely(d->d_subdir_offset == cur_offset)) {
-                       ERROR("Cyclic directory structure detected: children "
-                             "of \"%"TS"\" coincide with children of \"%"TS"\"",
-                             dentry_full_path(dir), dentry_full_path(d));
-                       return WIMLIB_ERR_INVALID_METADATA_RESOURCE;
-               }
+       /* Disallow extremely deep or cyclic directory structures  */
+       if (unlikely(depth >= 16384)) {
+               ERROR("Directory structure too deep!");
+               return WIMLIB_ERR_INVALID_METADATA_RESOURCE;
        }
 
        for (;;) {
@@ -1614,7 +1607,8 @@ read_dentry_tree_recursive(const u8 * restrict buf, size_t buf_len,
                        if (likely(dentry_is_directory(child))) {
                                ret = read_dentry_tree_recursive(buf,
                                                                 buf_len,
-                                                                child);
+                                                                child,
+                                                                depth + 1);
                                if (ret)
                                        return ret;
                        } else {
@@ -1655,8 +1649,6 @@ read_dentry_tree(const u8 *buf, size_t buf_len,
        int ret;
        struct wim_dentry *root;
 
-       DEBUG("Reading dentry tree (root_offset=%"PRIu64")", root_offset);
-
        ret = read_dentry(buf, buf_len, &root_offset, &root);
        if (ret)
                return ret;
@@ -1677,7 +1669,7 @@ read_dentry_tree(const u8 *buf, size_t buf_len,
                }
 
                if (likely(root->d_subdir_offset != 0)) {
-                       ret = read_dentry_tree_recursive(buf, buf_len, root);
+                       ret = read_dentry_tree_recursive(buf, buf_len, root, 0);
                        if (ret)
                                goto err_free_dentry_tree;
                }
@@ -1903,10 +1895,6 @@ write_dir_dentries(struct wim_dentry *dir, void *_pp)
 u8 *
 write_dentry_tree(struct wim_dentry *root, u8 *p)
 {
-       DEBUG("Writing dentry tree.");
-
-       wimlib_assert(root != NULL);
-
        /* write root dentry and end-of-directory entry following it */
        p = write_dentry(root, p);
        *(u64*)p = 0;