-/* Given a WIM dentry in the tree to be extracted, resolve all streams in the
- * corresponding inode and set 'out_refcnt' in each to 0. */
-static int
-dentry_resolve_and_zero_lte_refcnt(struct wim_dentry *dentry, void *_ctx)
-{
- struct apply_ctx *ctx = _ctx;
- struct wim_inode *inode = dentry->d_inode;
- struct wim_lookup_table_entry *lte;
- int ret;
- bool force = false;
-
- if (dentry->extraction_skipped)
- return 0;
-
- /* Special case: when extracting from a pipe, the WIM lookup table is
- * initially empty, so "resolving" an inode's streams is initially not
- * possible. However, we still need to keep track of which streams,
- * identified by SHA1 message digests, need to be extracted, so we
- * "resolve" the inode's streams anyway by allocating new entries. */
- if (ctx->extract_flags & WIMLIB_EXTRACT_FLAG_FROM_PIPE)
- force = true;
- ret = inode_resolve_ltes(inode, ctx->wim->lookup_table, force);
- if (ret)
- return ret;
- for (unsigned i = 0; i <= inode->i_num_ads; i++) {
- lte = inode_stream_lte_resolved(inode, i);
- if (lte)
- lte->out_refcnt = 0;
- }
- return 0;
-}
-
-static inline bool
-is_linked_extraction(const struct apply_ctx *ctx)
-{
- return 0 != (ctx->extract_flags & (WIMLIB_EXTRACT_FLAG_HARDLINK |
- WIMLIB_EXTRACT_FLAG_SYMLINK));
-}
-
-static inline bool
-can_extract_named_data_streams(const struct apply_ctx *ctx)
-{
- return ctx->supported_features.named_data_streams &&
- !is_linked_extraction(ctx);
-}
-
-static int
-ref_stream_to_extract(struct wim_lookup_table_entry *lte,
- struct wim_dentry *dentry, struct apply_ctx *ctx)
-{
- if (!lte)
- return 0;
-
- if (likely(!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++;
- }
-
- 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. */
-static int
-dentry_add_streams_to_extract(struct wim_dentry *dentry, void *_ctx)