]> wimlib.net Git - wimlib/blobdiff - src/extract.c
extract_streams_from_pipe(): Fix
[wimlib] / src / extract.c
index 115d5ead871486172627e7b0aa74d0e562edf1a0..1907e699315e16e7c94029af63c4872b2e887af8 100644 (file)
@@ -129,7 +129,7 @@ ref_stream_to_extract(struct wim_lookup_table_entry *lte,
            (!is_linked_extraction(ctx) || (lte->out_refcnt == 0 &&
                                            lte->extracted_file == NULL)))
        {
-               ctx->progress.extract.total_bytes += wim_resource_size(lte);
+               ctx->progress.extract.total_bytes += lte->size;
                ctx->progress.extract.num_streams++;
        }
 
@@ -237,7 +237,7 @@ update_extract_progress(struct apply_ctx *ctx,
        wimlib_progress_func_t progress_func = ctx->progress_func;
        union wimlib_progress_info *progress = &ctx->progress;
 
-       progress->extract.completed_bytes += wim_resource_size(lte);
+       progress->extract.completed_bytes += lte->size;
        if (progress_func &&
            progress->extract.completed_bytes >= ctx->next_progress)
        {
@@ -1143,7 +1143,8 @@ dentry_extract_skeleton(struct wim_dentry *dentry, void *_ctx)
        {
                inode_for_each_dentry(other_dentry, dentry->d_inode) {
                        if (dentry_has_short_name(other_dentry)
-                           && !other_dentry->skeleton_extracted)
+                           && !other_dentry->skeleton_extracted
+                           && other_dentry->in_extraction_tree)
                        {
                                DEBUG("Creating %"TS" before %"TS" "
                                      "to guarantee correct DOS name extraction",
@@ -1256,8 +1257,7 @@ extract_stream_instances(struct wim_lookup_table_entry *lte,
                        goto out_free_lte_tmp;
                }
                filedes_init(&fd, raw_fd);
-               ret = extract_wim_resource_to_fd(lte, &fd,
-                                                wim_resource_size(lte));
+               ret = extract_stream_to_fd(lte, &fd, lte->size);
                if (filedes_close(&fd) && !ret)
                        ret = WIMLIB_ERR_WRITE;
                if (ret)
@@ -1326,12 +1326,14 @@ extract_stream_list(struct apply_ctx *ctx)
 /* Read the header from a stream in a pipable WIM.  */
 static int
 read_pwm_stream_header(WIMStruct *pwm, struct wim_lookup_table_entry *lte,
+                      struct wim_resource_spec *rspec,
                       int flags, struct wim_header_disk *hdr_ret)
 {
        union {
                struct pwm_stream_hdr stream_hdr;
                struct wim_header_disk pwm_hdr;
        } buf;
+       struct wim_reshdr reshdr;
        int ret;
 
        ret = full_read(&pwm->in_fd, &buf.stream_hdr, sizeof(buf.stream_hdr));
@@ -1355,20 +1357,17 @@ read_pwm_stream_header(WIMStruct *pwm, struct wim_lookup_table_entry *lte,
                return WIMLIB_ERR_INVALID_PIPABLE_WIM;
        }
 
-       lte->resource_entry.original_size = le64_to_cpu(buf.stream_hdr.uncompressed_size);
        copy_hash(lte->hash, buf.stream_hdr.hash);
-       lte->resource_entry.flags = le32_to_cpu(buf.stream_hdr.flags);
-       lte->resource_entry.offset = pwm->in_fd.offset;
-       lte->resource_location = RESOURCE_IN_WIM;
-       lte->wim = pwm;
-       if (lte->resource_entry.flags & WIM_RESHDR_FLAG_COMPRESSED) {
-               lte->compression_type = pwm->compression_type;
-               lte->resource_entry.size = 0;
-       } else {
-               lte->compression_type = WIMLIB_COMPRESSION_TYPE_NONE;
-               lte->resource_entry.size = lte->resource_entry.original_size;
-       }
-       lte->is_pipable = 1;
+
+       reshdr.size_in_wim = 0;
+       reshdr.flags = le32_to_cpu(buf.stream_hdr.flags);
+       reshdr.offset_in_wim = pwm->in_fd.offset;
+       reshdr.uncompressed_size = le64_to_cpu(buf.stream_hdr.uncompressed_size);
+       wim_res_hdr_to_spec(&reshdr, pwm, rspec);
+       lte_bind_wim_resource_spec(lte, rspec);
+       lte->flags = rspec->flags;
+       lte->size = rspec->uncompressed_size;
+       lte->offset_in_res = 0;
        return 0;
 
 read_error:
@@ -1377,13 +1376,22 @@ read_error:
        return ret;
 }
 
+static int
+skip_pwm_chunk_cb(const void *chunk, size_t chunk_size, void *_ctx)
+{
+       return 0;
+}
+
 /* Skip over an unneeded stream in a pipable WIM being read from a pipe.  */
 static int
 skip_pwm_stream(struct wim_lookup_table_entry *lte)
 {
-       return read_partial_wim_resource(lte, wim_resource_size(lte),
-                                        NULL, NULL,
-                                        WIMLIB_READ_RESOURCE_FLAG_SEEK_ONLY,
+       return read_partial_wim_resource(lte,
+                                        lte->size,
+                                        skip_pwm_chunk_cb,
+                                        lte_cchunk_size(lte),
+                                        NULL,
+                                        WIMLIB_READ_RESOURCE_FLAG_RAW_CHUNKS,
                                         0);
 }
 
@@ -1391,6 +1399,7 @@ static int
 extract_streams_from_pipe(struct apply_ctx *ctx)
 {
        struct wim_lookup_table_entry *found_lte;
+       struct wim_resource_spec *rspec;
        struct wim_lookup_table_entry *needed_lte;
        struct wim_lookup_table *lookup_table;
        struct wim_header_disk pwm_hdr;
@@ -1399,9 +1408,13 @@ extract_streams_from_pipe(struct apply_ctx *ctx)
 
        ret = WIMLIB_ERR_NOMEM;
        found_lte = new_lookup_table_entry();
-       if (!found_lte)
+       if (found_lte == NULL)
                goto out;
 
+       rspec = MALLOC(sizeof(struct wim_resource_spec));
+       if (rspec == NULL)
+               goto out_free_found_lte;
+
        lookup_table = ctx->wim->lookup_table;
        pwm_flags = PWM_ALLOW_WIM_HDR;
        if ((ctx->extract_flags & WIMLIB_EXTRACT_FLAG_RESUME))
@@ -1413,8 +1426,10 @@ extract_streams_from_pipe(struct apply_ctx *ctx)
                ctx->progress_func(WIMLIB_PROGRESS_MSG_EXTRACT_SPWM_PART_BEGIN,
                                   &ctx->progress);
        while (ctx->num_streams_remaining) {
-               ret = read_pwm_stream_header(ctx->wim, found_lte, pwm_flags,
-                                            &pwm_hdr);
+               if (found_lte->resource_location != RESOURCE_NONEXISTENT)
+                       lte_unbind_wim_resource_spec(found_lte);
+               ret = read_pwm_stream_header(ctx->wim, found_lte, rspec,
+                                            pwm_flags, &pwm_hdr);
                if (ret) {
                        if (ret == WIMLIB_ERR_UNEXPECTED_END_OF_FILE &&
                            (ctx->extract_flags & WIMLIB_EXTRACT_FLAG_RESUME))
@@ -1425,18 +1440,18 @@ extract_streams_from_pipe(struct apply_ctx *ctx)
                }
 
                if ((found_lte->resource_location != RESOURCE_NONEXISTENT)
-                   && !(found_lte->resource_entry.flags & WIM_RESHDR_FLAG_METADATA)
+                   && !(found_lte->flags & WIM_RESHDR_FLAG_METADATA)
                    && (needed_lte = lookup_resource(lookup_table, found_lte->hash))
                    && (needed_lte->out_refcnt))
                {
-                       copy_resource_entry(&needed_lte->resource_entry,
-                                           &found_lte->resource_entry);
-                       needed_lte->resource_location = found_lte->resource_location;
-                       needed_lte->wim               = found_lte->wim;
-                       needed_lte->compression_type  = found_lte->compression_type;
-                       needed_lte->is_pipable        = found_lte->is_pipable;
-
+                       lte_unbind_wim_resource_spec(found_lte);
+                       lte_bind_wim_resource_spec(needed_lte, rspec);
+                       needed_lte->offset_in_res = found_lte->offset_in_res;
+                       needed_lte->flags = found_lte->flags;
+                       needed_lte->size = found_lte->size;
                        ret = extract_stream_instances(needed_lte, ctx, false);
+                       lte_unbind_wim_resource_spec(needed_lte);
+
                        if (ret)
                                goto out_free_found_lte;
                        ctx->num_streams_remaining--;
@@ -1468,6 +1483,8 @@ extract_streams_from_pipe(struct apply_ctx *ctx)
        }
        ret = 0;
 out_free_found_lte:
+       if (found_lte->resource_location != RESOURCE_IN_WIM)
+               FREE(rspec);
        free_lookup_table_entry(found_lte);
 out:
        return ret;
@@ -1527,8 +1544,7 @@ extract_dentry_to_stdout(struct wim_dentry *dentry)
                if (lte) {
                        struct filedes _stdout;
                        filedes_init(&_stdout, STDOUT_FILENO);
-                       ret = extract_wim_resource_to_fd(lte, &_stdout,
-                                                        wim_resource_size(lte));
+                       ret = extract_stream_to_fd(lte, &_stdout, lte->size);
                }
        }
        return ret;
@@ -1623,6 +1639,8 @@ dentry_calculate_extraction_path(struct wim_dentry *dentry, void *_args)
        struct apply_ctx *ctx = _args;
        int ret;
 
+       dentry->in_extraction_tree = 1;
+
        if (dentry == ctx->extract_root || dentry->extraction_skipped)
                return 0;
 
@@ -1742,6 +1760,7 @@ dentry_reset_needs_extraction(struct wim_dentry *dentry, void *_ignore)
 {
        struct wim_inode *inode = dentry->d_inode;
 
+       dentry->in_extraction_tree = 0;
        dentry->extraction_skipped = 0;
        dentry->was_hardlinked = 0;
        dentry->skeleton_extracted = 0;
@@ -2061,7 +2080,7 @@ do_extract_warnings(struct apply_ctx *ctx)
            ctx->no_security_descriptors == 0)
                return;
 
-       WARNING("Extraction of \"%"TS"\" complete, but with one or more warnings:",
+       WARNING("Extraction to \"%"TS"\" complete, but with one or more warnings:",
                ctx->target);
        if (ctx->partial_security_descriptors != 0) {
                WARNING("- Could only partially set the security descriptor\n"
@@ -2636,7 +2655,7 @@ extract_single_image(WIMStruct *wim, int image,
 {
        int ret;
        tchar *target_copy = canonicalize_fs_path(target);
-       if (!target_copy)
+       if (target_copy == NULL)
                return WIMLIB_ERR_NOMEM;
        struct wimlib_extract_command cmd = {
                .wim_source_path = T(""),
@@ -2808,11 +2827,12 @@ wimlib_extract_image_from_pipe(int pipe_fd, const tchar *image_num_or_name,
         * WIMs.)  */
        {
                struct wim_lookup_table_entry xml_lte;
-               ret = read_pwm_stream_header(pwm, &xml_lte, 0, NULL);
+               struct wim_resource_spec xml_rspec;
+               ret = read_pwm_stream_header(pwm, &xml_lte, &xml_rspec, 0, NULL);
                if (ret)
                        goto out_wimlib_free;
 
-               if (!(xml_lte.resource_entry.flags & WIM_RESHDR_FLAG_METADATA))
+               if (!(xml_lte.flags & WIM_RESHDR_FLAG_METADATA))
                {
                        ERROR("Expected XML data, but found non-metadata "
                              "stream.");
@@ -2820,12 +2840,12 @@ wimlib_extract_image_from_pipe(int pipe_fd, const tchar *image_num_or_name,
                        goto out_wimlib_free;
                }
 
-               copy_resource_entry(&pwm->hdr.xml_res_entry,
-                                   &xml_lte.resource_entry);
+               wim_res_spec_to_hdr(&xml_rspec, &pwm->hdr.xml_data_reshdr);
 
                ret = read_wim_xml_data(pwm);
                if (ret)
                        goto out_wimlib_free;
+
                if (wim_info_get_num_images(pwm->wim_info) != pwm->hdr.image_count) {
                        ERROR("Image count in XML data is not the same as in WIM header.");
                        ret = WIMLIB_ERR_XML;
@@ -2861,22 +2881,29 @@ wimlib_extract_image_from_pipe(int pipe_fd, const tchar *image_num_or_name,
        for (i = 1; i <= pwm->hdr.image_count; i++) {
                struct wim_lookup_table_entry *metadata_lte;
                struct wim_image_metadata *imd;
+               struct wim_resource_spec *metadata_rspec;
 
                metadata_lte = new_lookup_table_entry();
-               if (!metadata_lte) {
+               if (metadata_lte == NULL) {
+                       ret = WIMLIB_ERR_NOMEM;
+                       goto out_wimlib_free;
+               }
+               metadata_rspec = MALLOC(sizeof(struct wim_resource_spec));
+               if (metadata_rspec == NULL) {
                        ret = WIMLIB_ERR_NOMEM;
+                       free_lookup_table_entry(metadata_lte);
                        goto out_wimlib_free;
                }
 
-               ret = read_pwm_stream_header(pwm, metadata_lte, 0, NULL);
+               ret = read_pwm_stream_header(pwm, metadata_lte, metadata_rspec, 0, NULL);
                imd = pwm->image_metadata[i - 1];
                imd->metadata_lte = metadata_lte;
-               if (ret)
+               if (ret) {
+                       FREE(metadata_rspec);
                        goto out_wimlib_free;
+               }
 
-               if (!(metadata_lte->resource_entry.flags &
-                     WIM_RESHDR_FLAG_METADATA))
-               {
+               if (!(metadata_lte->flags & WIM_RESHDR_FLAG_METADATA)) {
                        ERROR("Expected metadata resource, but found "
                              "non-metadata stream.");
                        ret = WIMLIB_ERR_INVALID_PIPABLE_WIM;