X-Git-Url: https://wimlib.net/git/?a=blobdiff_plain;f=src%2Fdentry.c;h=4f842eaa6a413d3588be38f1a58f85ef2600429c;hb=f1c9d53eb97205b17092ba6de50f0967932861ed;hp=5c6f97566f74510eb460f84b8ff2792ce8a0fdb3;hpb=8214debe2f127bc6d56407c1fb4bee194af83478;p=wimlib diff --git a/src/dentry.c b/src/dentry.c index 5c6f9756..4f842eaa 100644 --- a/src/dentry.c +++ b/src/dentry.c @@ -1227,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) @@ -1241,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; @@ -1250,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; + } } /* @@ -1534,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 (;;) { @@ -1601,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 { @@ -1662,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; }