-
-static int
-ref_stream_to_extract(struct wim_lookup_table_entry *lte,
- struct wim_dentry *dentry, struct apply_ctx *ctx)
-{
- if (!lte)
- return 0;
-
- /* Tally the size only for each extraction of the stream (not hard
- * links). */
- if (!(dentry->d_inode->i_visited &&
- ctx->supported_features.hard_links) &&
- (!is_linked_extraction(ctx) || (lte->out_refcnt == 0 &&
- lte->extracted_file == NULL)))
- {
- ctx->progress.extract.total_bytes += wim_resource_size(lte);
- ctx->progress.extract.num_streams++;
- }
-
- /* Add stream to the extraction_list only one time, even if it's going
- * to be extracted to multiple locations. */
- if (lte->out_refcnt == 0) {
- list_add_tail(<e->extraction_list, &ctx->stream_list);
- ctx->num_streams_remaining++;
- }
-
- if (ctx->extract_flags & WIMLIB_EXTRACT_FLAG_SEQUENTIAL) {
- struct wim_dentry **lte_dentries;
-
- /* Append dentry to this stream's array of dentries referencing
- * it. Use inline array to avoid memory allocation until the
- * number of dentries becomes too large. */
- if (lte->out_refcnt < ARRAY_LEN(lte->inline_lte_dentries)) {
- lte_dentries = lte->inline_lte_dentries;
- } else {
- struct wim_dentry **prev_lte_dentries;
- size_t alloc_lte_dentries;
-
- if (lte->out_refcnt == ARRAY_LEN(lte->inline_lte_dentries)) {
- prev_lte_dentries = NULL;
- alloc_lte_dentries = ARRAY_LEN(lte->inline_lte_dentries);
- } else {
- prev_lte_dentries = lte->lte_dentries;
- alloc_lte_dentries = lte->alloc_lte_dentries;
- }
-
- if (lte->out_refcnt == alloc_lte_dentries) {
- alloc_lte_dentries *= 2;
- lte_dentries = REALLOC(prev_lte_dentries,
- alloc_lte_dentries *
- sizeof(lte_dentries[0]));
- if (!lte_dentries)
- return WIMLIB_ERR_NOMEM;
- if (prev_lte_dentries == NULL) {
- memcpy(lte_dentries,
- lte->inline_lte_dentries,
- sizeof(lte->inline_lte_dentries));
- }
- lte->lte_dentries = lte_dentries;
- lte->alloc_lte_dentries = alloc_lte_dentries;
- }
- lte_dentries = lte->lte_dentries;
- }
- lte_dentries[lte->out_refcnt] = dentry;
- }
- lte->out_refcnt++;
- return 0;
-}
-
-/* Given a WIM dentry in the tree to be extracted, iterate through streams that
- * need to be extracted. For each one, add it to the list of streams to be
- * extracted (ctx->stream_list) if not already done so, and also update the
- * progress information (ctx->progress) with the stream. Furthermore, if doing
- * a sequential extraction, build a mapping from each the stream to the dentries
- * referencing it.
- *
- * This uses the i_visited member of the inodes (assumed to be 0 initially). */
-static int
-dentry_add_streams_to_extract(struct wim_dentry *dentry, void *_ctx)
-{
- struct apply_ctx *ctx = _ctx;
- struct wim_inode *inode = dentry->d_inode;
- int ret;
-
- /* Don't process dentries marked as skipped. */
- if (dentry->extraction_skipped)
- return 0;
-
- /* The unnamed data stream will always be extracted, except in an
- * unlikely case. */
- if (!inode_is_encrypted_directory(inode)) {
- ret = ref_stream_to_extract(inode_unnamed_lte_resolved(inode),
- dentry, ctx);
- if (ret)
- return ret;
- }
-
- /* Named data streams will be extracted only if supported in the current
- * extraction mode and volume, and to avoid complications, if not doing
- * a linked extraction. */
- if (can_extract_named_data_streams(ctx)) {
- for (u16 i = 0; i < inode->i_num_ads; i++) {
- if (!ads_entry_is_named_stream(&inode->i_ads_entries[i]))
- continue;
- ret = ref_stream_to_extract(inode->i_ads_entries[i].lte,
- dentry, ctx);
- if (ret)
- return ret;
- }
- }
- inode->i_visited = 1;
- return 0;
-}
-