-
-/* Reads the children of a dentry, and all their children, ..., etc. from the
- * metadata resource and into the dentry tree.
- *
- * @metadata_resource: An array that contains the uncompressed metadata
- * resource for the WIM file.
- *
- * @metadata_resource_len: The length of the uncompressed metadata resource, in
- * bytes.
- *
- * @dentry: A pointer to a `struct dentry' that is the root of the directory
- * tree and has already been read from the metadata resource. It
- * does not need to be the real root because this procedure is
- * called recursively.
- *
- * @return: Zero on success, nonzero on failure.
- */
-int read_dentry_tree(const u8 metadata_resource[], u64 metadata_resource_len,
- struct dentry *dentry)
-{
- u64 cur_offset = dentry->subdir_offset;
- struct dentry *prev_child = NULL;
- struct dentry *first_child = NULL;
- struct dentry *child;
- struct dentry cur_child;
- int ret;
-
- /*
- * If @dentry has no child dentries, nothing more needs to be done for
- * this branch. This is the case for regular files, symbolic links, and
- * *possibly* empty directories (although an empty directory may also
- * have one child dentry that is the special end-of-directory dentry)
- */
- if (cur_offset == 0)
- return 0;
-
- /* Find and read all the children of @dentry. */
- while (1) {
-
- /* Read next child of @dentry into @cur_child. */
- ret = read_dentry(metadata_resource, metadata_resource_len,
- cur_offset, &cur_child);
- if (ret != 0)
- break;
-
- /* Check for end of directory. */
- if (cur_child.length == 0)
- break;
-
- /* Not end of directory. Allocate this child permanently and
- * link it to the parent and previous child. */
- child = MALLOC(sizeof(struct dentry));
- if (!child) {
- ERROR("Failed to allocate %zu bytes for new dentry",
- sizeof(struct dentry));
- ret = WIMLIB_ERR_NOMEM;
- break;
- }
- memcpy(child, &cur_child, sizeof(struct dentry));
-
- if (prev_child) {
- prev_child->next = child;
- child->prev = prev_child;
- } else {
- first_child = child;
- }
-
- child->parent = dentry;
- prev_child = child;
- list_add(&child->inode_dentry_list, &child->inode->dentry_list);
-
- /* If there are children of this child, call this procedure
- * recursively. */
- if (child->subdir_offset != 0) {
- ret = read_dentry_tree(metadata_resource,
- metadata_resource_len, child);
- if (ret != 0)
- break;
- }
-
- /* Advance to the offset of the next child. Note: We need to
- * advance by the TOTAL length of the dentry, not by the length
- * child->length, which although it does take into account the
- * padding, it DOES NOT take into account alternate stream
- * entries. */
- cur_offset += dentry_total_length(child);
- }
-
- /* Link last child to first one, and set parent's children pointer to
- * the first child. */
- if (prev_child) {
- prev_child->next = first_child;
- first_child->prev = prev_child;
- }
- dentry->children = first_child;
- return ret;
-}