-
-/* API function documented in wimlib.h */
-WIMLIBAPI int
-wimlib_extract_pathlist(WIMStruct *wim, int image,
- const tchar *target,
- const tchar *path_list_file,
- int extract_flags,
- wimlib_progress_func_t progress_func)
-{
- int ret;
- tchar **paths;
- size_t num_paths;
- void *mem;
-
- ret = read_path_list_file(path_list_file, &paths, &num_paths, &mem);
- 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,
- extract_flags, progress_func);
- FREE(paths);
- FREE(mem);
- return ret;
-}
-
-struct append_dentry_ctx {
- struct wim_dentry **dentries;
- size_t num_dentries;
- size_t num_alloc_dentries;
-};
-
-static int
-append_dentry_cb(struct wim_dentry *dentry, void *_ctx)
-{
- struct append_dentry_ctx *ctx = _ctx;
-
- if (ctx->num_dentries == ctx->num_alloc_dentries) {
- struct wim_dentry **new_dentries;
- size_t new_length;
-
- new_length = max(ctx->num_alloc_dentries + 8,
- ctx->num_alloc_dentries * 3 / 2);
- new_dentries = REALLOC(ctx->dentries,
- new_length * sizeof(ctx->dentries[0]));
- if (new_dentries == NULL)
- return WIMLIB_ERR_NOMEM;
- ctx->dentries = new_dentries;
- ctx->num_alloc_dentries = new_length;
- }
- ctx->dentries[ctx->num_dentries++] = dentry;
- return 0;
-}
-
-/* API function documented in wimlib.h */
-WIMLIBAPI int
-wimlib_extract_paths(WIMStruct *wim,
- int image,
- const tchar *target,
- const tchar * const *paths,
- size_t num_paths,
- int extract_flags,
- wimlib_progress_func_t progress_func)
-{
- int ret;
- struct wim_dentry **trees;
- size_t num_trees;
-
- extract_flags &= WIMLIB_EXTRACT_MASK_PUBLIC;
-
- 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)
- wildcard_flags |= WILDCARD_FLAG_ERROR_IF_NO_MATCH;
- else
- wildcard_flags |= WILDCARD_FLAG_WARN_IF_NO_MATCH;
-
- if (default_ignore_case)
- wildcard_flags |= WILDCARD_FLAG_CASE_INSENSITIVE;
-
- for (size_t i = 0; i < num_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;
- }
- }
- trees = append_dentry_ctx.dentries;
- num_trees = append_dentry_ctx.num_dentries;
- } else {
- trees = MALLOC(num_paths * sizeof(trees[0]));
- if (trees == NULL)
- return WIMLIB_ERR_NOMEM;
-
- for (size_t i = 0; i < num_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",
- paths[i], wim->current_image);
- ret = WIMLIB_ERR_PATH_DOES_NOT_EXIST;
- goto out_free_trees;
- }
- }
- num_trees = num_paths;
- }
-
- if (num_trees == 0) {
- ret = 0;
- goto out_free_trees;
- }
-
- ret = extract_trees(wim, trees, num_trees,
- T(""), target,
- ((extract_flags &
- ~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;
-}