]> wimlib.net Git - wimlib/blobdiff - src/extract.c
wimlib_extract_paths(): Canonicalize WIM paths before using them
[wimlib] / src / extract.c
index c6711ec902dd36f43df80b972531bfa14fc22da1..1e31cdb07909fbf309f5f015cf1858c715817dc5 100644 (file)
@@ -1147,7 +1147,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->in_extraction_tree)
+                           && other_dentry->in_extraction_tree
+                           && !other_dentry->extraction_skipped)
                        {
                                DEBUG("Creating %"TS" before %"TS" "
                                      "to guarantee correct DOS name extraction",
@@ -1527,8 +1528,10 @@ extract_streams_from_pipe(struct apply_ctx *ctx)
 
                                /* Extract stream to temporary file.  */
                                ret = create_temporary_file(&tmpfile_fd, &tmpfile_name);
-                               if (ret)
+                               if (ret) {
+                                       lte_unbind_wim_resource_spec(needed_lte);
                                        goto out_free_found_lte;
+                               }
 
                                ret = extract_full_stream_to_fd(needed_lte,
                                                                &tmpfile_fd);
@@ -2374,7 +2377,12 @@ extract_trees(WIMStruct *wim, struct wim_dentry **trees, size_t num_trees,
         * directory tree.  (If not, extract_dentry_to_stdout() will
         * return an error.)  */
        if (extract_flags & WIMLIB_EXTRACT_FLAG_TO_STDOUT) {
-               ret = extract_dentry_to_stdout(ctx.extract_root);
+               ret = 0;
+               for (size_t i = 0; i < num_trees; i++) {
+                       ret = extract_dentry_to_stdout(trees[i]);
+                       if (ret)
+                               break;
+               }
                goto out_teardown_stream_list;
        }
 
@@ -2592,19 +2600,12 @@ extract_tree(WIMStruct *wim, const tchar *wim_source_path,
                             target, extract_flags, progress_func);
 }
 
-/* Validates a single wimlib_extract_command, mostly checking to make sure the
- * extract flags make sense. */
+/* Make sure the extraction flags make sense, and update them if needed.  */
 static int
-check_extract_command(struct wimlib_extract_command *cmd, int wim_header_flags)
+check_extract_flags(int extract_flags,
+                   const u32 wim_header_flags,
+                   int *updated_extract_flags_ret)
 {
-       int extract_flags;
-
-       /* Empty destination path? */
-       if (cmd->fs_dest_path[0] == T('\0'))
-               return WIMLIB_ERR_INVALID_PARAM;
-
-       extract_flags = cmd->extract_flags;
-
        /* Check for invalid flag combinations  */
        if ((extract_flags &
             (WIMLIB_EXTRACT_FLAG_SYMLINK |
@@ -2612,9 +2613,6 @@ check_extract_command(struct wimlib_extract_command *cmd, int wim_header_flags)
                                                 WIMLIB_EXTRACT_FLAG_HARDLINK))
                return WIMLIB_ERR_INVALID_PARAM;
 
-       if (extract_flags & WIMLIB_EXTRACT_FLAG_GLOB_PATHS)
-               return WIMLIB_ERR_INVALID_PARAM;
-
        if ((extract_flags &
             (WIMLIB_EXTRACT_FLAG_NO_ACLS |
              WIMLIB_EXTRACT_FLAG_STRICT_ACLS)) == (WIMLIB_EXTRACT_FLAG_NO_ACLS |
@@ -2632,13 +2630,13 @@ check_extract_command(struct wimlib_extract_command *cmd, int wim_header_flags)
              WIMLIB_EXTRACT_FLAG_FROM_PIPE)) == WIMLIB_EXTRACT_FLAG_RESUME)
                return WIMLIB_ERR_INVALID_PARAM;
 
-       if (extract_flags & WIMLIB_EXTRACT_FLAG_NTFS) {
 #ifndef WITH_NTFS_3G
+       if (extract_flags & WIMLIB_EXTRACT_FLAG_NTFS) {
                ERROR("wimlib was compiled without support for NTFS-3g, so\n"
                      "        we cannot apply a WIM image directly to a NTFS volume.");
                return WIMLIB_ERR_UNSUPPORTED;
-#endif
        }
+#endif
 
        if ((extract_flags & (WIMLIB_EXTRACT_FLAG_RPFIX |
                              WIMLIB_EXTRACT_FLAG_NORPFIX)) == 0)
@@ -2669,7 +2667,8 @@ check_extract_command(struct wimlib_extract_command *cmd, int wim_header_flags)
                }
        }
 
-       cmd->extract_flags = extract_flags;
+       if (updated_extract_flags_ret)
+               *updated_extract_flags_ret = extract_flags;
        return 0;
 }
 
@@ -2700,7 +2699,16 @@ do_wimlib_extract_files(WIMStruct *wim,
 
        /* Check for problems with the extraction commands */
        for (size_t i = 0; i < num_cmds; i++) {
-               ret = check_extract_command(&cmds[i], wim->hdr.flags);
+
+               if (cmds[i].fs_dest_path[0] == T('\0'))
+                       return WIMLIB_ERR_INVALID_PARAM;
+
+               if (cmds[i].extract_flags & WIMLIB_EXTRACT_FLAG_GLOB_PATHS)
+                       return WIMLIB_ERR_INVALID_PARAM;
+
+               ret = check_extract_flags(cmds[i].extract_flags,
+                                         wim->hdr.flags,
+                                         &cmds[i].extract_flags);
                if (ret)
                        return ret;
                if (cmds[i].extract_flags & (WIMLIB_EXTRACT_FLAG_SYMLINK |
@@ -3117,8 +3125,11 @@ wimlib_extract_pathlist(WIMStruct *wim, int image,
        void *mem;
 
        ret = read_path_list_file(path_list_file, &paths, &num_paths, &mem);
-       if (ret)
+       if (ret) {
+               ERROR("Failed to read path list file \"%"TS"\"",
+                     path_list_file);
                return ret;
+       }
 
        ret = wimlib_extract_paths(wim, image, target,
                                   (const tchar * const *)paths, num_paths,
@@ -3167,24 +3178,32 @@ wimlib_extract_paths(WIMStruct *wim,
                     wimlib_progress_func_t progress_func)
 {
        int ret;
-       struct append_dentry_ctx append_dentry_ctx = {
-               .dentries = NULL,
-               .num_dentries = 0,
-               .num_alloc_dentries = 0,
-       };
        struct wim_dentry **trees;
        size_t num_trees;
 
        extract_flags &= WIMLIB_EXTRACT_MASK_PUBLIC;
 
-       if (target == NULL || (num_paths != 0 && paths == NULL))
+       if (wim == NULL || target == NULL || target[0] == T('\0') ||
+           (num_paths != 0 && paths == NULL))
                return WIMLIB_ERR_INVALID_PARAM;
 
+       ret = check_extract_flags(extract_flags, wim->hdr.flags,
+                                 &extract_flags);
+       if (ret)
+               return ret;
+
        ret = select_wim_image(wim, image);
        if (ret)
                return ret;
 
        if (extract_flags & WIMLIB_EXTRACT_FLAG_GLOB_PATHS) {
+
+               struct append_dentry_ctx append_dentry_ctx = {
+                       .dentries = NULL,
+                       .num_dentries = 0,
+                       .num_alloc_dentries = 0,
+               };
+
                u32 wildcard_flags = 0;
 
                if (extract_flags & WIMLIB_EXTRACT_FLAG_STRICT_GLOB)
@@ -3196,10 +3215,17 @@ wimlib_extract_paths(WIMStruct *wim,
                        wildcard_flags |= WILDCARD_FLAG_CASE_INSENSITIVE;
 
                for (size_t i = 0; i < num_paths; i++) {
-                       ret = expand_wildcard(wim, paths[i],
+                       tchar *path = canonicalize_wim_path(paths[i]);
+                       if (path == NULL) {
+                               ret = WIMLIB_ERR_NOMEM;
+                               trees = append_dentry_ctx.dentries;
+                               goto out_free_trees;
+                       }
+                       ret = expand_wildcard(wim, path,
                                              append_dentry_cb,
                                              &append_dentry_ctx,
                                              wildcard_flags);
+                       FREE(path);
                        if (ret) {
                                trees = append_dentry_ctx.dentries;
                                goto out_free_trees;
@@ -3213,8 +3239,16 @@ wimlib_extract_paths(WIMStruct *wim,
                        return WIMLIB_ERR_NOMEM;
 
                for (size_t i = 0; i < num_paths; i++) {
-                       trees[i] = get_dentry(wim, paths[i],
+
+                       tchar *path = canonicalize_wim_path(paths[i]);
+                       if (path == NULL) {
+                               ret = WIMLIB_ERR_NOMEM;
+                               goto out_free_trees;
+                       }
+
+                       trees[i] = get_dentry(wim, path,
                                              WIMLIB_CASE_PLATFORM_DEFAULT);
+                       FREE(path);
                        if (trees[i] == NULL) {
                                  ERROR("Path \"%"TS"\" does not exist "
                                        "in WIM image %d",
@@ -3237,6 +3271,14 @@ wimlib_extract_paths(WIMStruct *wim,
                                ~WIMLIB_EXTRACT_FLAG_GLOB_PATHS)
                                | WIMLIB_EXTRACT_FLAG_PATHMODE),
                            progress_func);
+
+       if (extract_flags & (WIMLIB_EXTRACT_FLAG_SYMLINK |
+                            WIMLIB_EXTRACT_FLAG_HARDLINK))
+       {
+               for_lookup_table_entry(wim->lookup_table,
+                                      lte_free_extracted_file,
+                                      NULL);
+       }
 out_free_trees:
        FREE(trees);
        return ret;