#include "wimlib/error.h"
#include "wimlib/lookup_table.h"
#include "wimlib/metadata.h"
+#include "wimlib/pathlist.h"
#include "wimlib/paths.h"
#include "wimlib/reparse.h"
#include "wimlib/resource.h"
# include "wimlib/win32.h" /* for realpath() equivalent */
#endif
#include "wimlib/xml.h"
+#include "wimlib/wildcard.h"
#include "wimlib/wim.h"
#include <errno.h>
ctx->num_streams_remaining++;
}
- if (ctx->extract_flags & WIMLIB_EXTRACT_FLAG_SEQUENTIAL) {
+ if (!(ctx->extract_flags & WIMLIB_EXTRACT_FLAG_FILE_ORDER)) {
struct wim_dentry **lte_dentries;
/* Append dentry to this stream's array of dentries referencing
* This function operates slightly differently depending on whether @lte_spec is
* NULL or not. When @lte_spec is NULL, the behavior is to extract the default
* file contents (unnamed stream), and, if named data streams are supported in
- * the extract mode and volume, any named data streams. When @lte_spec is NULL,
- * the behavior is to extract only all copies of the stream @lte_spec, and in
- * addition use @lte_spec to set the reparse data or create the symbolic link if
- * appropriate.
+ * the extract mode and volume, any named data streams. When @lte_spec is not
+ * NULL, the behavior is to extract only all copies of the stream @lte_spec, and
+ * in addition use @lte_spec to set the reparse data or create the symbolic link
+ * if appropriate.
*
* @path
* Path to file to extract (as can be passed to apply_operations
return 0;
}
-/* Create a file or directory, then immediately extract all streams. This
- * assumes that WIMLIB_EXTRACT_FLAG_SEQUENTIAL is not specified, since the WIM
+/* Create a file or directory, then immediately extract all streams. The WIM
* may not be read sequentially by this function. */
static int
dentry_extract(struct wim_dentry *dentry, void *_ctx)
static int
extract_stream_list(struct apply_ctx *ctx)
{
- if (ctx->extract_flags & WIMLIB_EXTRACT_FLAG_SEQUENTIAL) {
+ if (!(ctx->extract_flags & WIMLIB_EXTRACT_FLAG_FILE_ORDER)) {
/* Sequential extraction: read the streams in the order in which
* they appear in the WIM file. */
struct read_stream_list_callbacks cbs = {
return 0;
}
- if (buf.stream_hdr.magic != PWM_STREAM_MAGIC) {
+ if (le64_to_cpu(buf.stream_hdr.magic) != PWM_STREAM_MAGIC) {
ERROR("Data read on pipe is invalid (expected stream header).");
return WIMLIB_ERR_INVALID_PIPABLE_WIM;
}
&& (needed_lte = lookup_resource(lookup_table, found_lte->hash))
&& (needed_lte->out_refcnt))
{
- char *tmpfile_name = NULL;
+ tchar *tmpfile_name = NULL;
struct wim_lookup_table_entry *lte_override;
struct wim_lookup_table_entry tmpfile_lte;
}
/* Finally, the important part: extract the tree of files. */
- if (extract_flags & (WIMLIB_EXTRACT_FLAG_SEQUENTIAL |
- WIMLIB_EXTRACT_FLAG_FROM_PIPE)) {
+ if (!(extract_flags & WIMLIB_EXTRACT_FLAG_FILE_ORDER)) {
/* Sequential extraction requested, so two passes are needed
* (one for directory structure, one for streams.) */
if (progress_func)
out_teardown_stream_list:
/* Free memory allocated as part of the mapping from each
* wim_lookup_table_entry to the dentries that reference it. */
- if (ctx.extract_flags & WIMLIB_EXTRACT_FLAG_SEQUENTIAL)
+ if (!(ctx.extract_flags & WIMLIB_EXTRACT_FLAG_FILE_ORDER))
list_for_each_entry(lte, &ctx.stream_list, extraction_list)
if (lte->out_refcnt > ARRAY_LEN(lte->inline_lte_dentries))
FREE(lte->lte_dentries);
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 |
* corresponding file or symbolic link data. This needs to be handled
* better. */
if ((extract_flags & (WIMLIB_EXTRACT_FLAG_UNIX_DATA |
- WIMLIB_EXTRACT_FLAG_SEQUENTIAL))
- == (WIMLIB_EXTRACT_FLAG_UNIX_DATA |
- WIMLIB_EXTRACT_FLAG_SEQUENTIAL))
+ WIMLIB_EXTRACT_FLAG_FILE_ORDER))
+ == WIMLIB_EXTRACT_FLAG_UNIX_DATA)
{
if (extract_flags & WIMLIB_EXTRACT_FLAG_FROM_PIPE) {
WARNING("Setting UNIX file/owner group may "
" symbolic links "
"when applying from a pipe.");
} else {
- extract_flags &= ~WIMLIB_EXTRACT_FLAG_SEQUENTIAL;
+ extract_flags |= WIMLIB_EXTRACT_FLAG_FILE_ORDER;
WARNING("Disabling sequential extraction for "
"UNIX data mode");
}
if (extract_flags & WIMLIB_EXTRACT_FLAG_TO_STDOUT)
return WIMLIB_ERR_INVALID_PARAM;
- extract_flags |= WIMLIB_EXTRACT_FLAG_SEQUENTIAL;
-
/* Read the WIM header from the pipe and get a WIMStruct to represent
* the pipable WIM. Caveats: Unlike getting a WIMStruct with
* wimlib_open_wim(), getting a WIMStruct in this way will result in
return do_wimlib_extract_image(wim, image, target, extract_flags,
progress_func);
}
+
+/* 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)
+ 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;
+}
+
+/* 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;
+ tchar **expanded_paths;
+ size_t num_expanded_paths;
+ struct wimlib_extract_command *cmds;
+
+ ret = select_wim_image(wim, image);
+ if (ret)
+ return ret;
+
+ if (extract_flags & WIMLIB_EXTRACT_FLAG_GLOB_PATHS) {
+ int 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 (extract_flags & WIMLIB_EXTRACT_FLAG_CASE_INSENSITIVE_GLOB)
+ wildcard_flags |= WILDCARD_FLAG_CASE_INSENSITIVE;
+
+ ret = expand_wildcard_wim_paths(wim, paths, num_paths,
+ &expanded_paths,
+ &num_expanded_paths,
+ wildcard_flags);
+ if (ret)
+ return ret;
+ } else {
+ expanded_paths = (tchar**)paths;
+ num_expanded_paths = num_paths;
+ }
+
+ cmds = CALLOC(num_expanded_paths, sizeof(cmds[0]));
+ if (cmds == NULL) {
+ ret = WIMLIB_ERR_NOMEM;
+ goto out_free_expanded_paths;
+ }
+
+ for (size_t i = 0; i < num_expanded_paths; i++) {
+ cmds[i].wim_source_path = expanded_paths[i];
+ cmds[i].extract_flags = 0;
+
+ tchar *dest_path;
+ size_t dest_len = 0;
+ dest_len += tstrlen(target);
+ dest_len += 1;
+ dest_len += tstrlen(expanded_paths[i]);
+ dest_len += 1;
+
+ dest_path = MALLOC(dest_len * sizeof(tchar));
+ if (dest_path == NULL) {
+ ret = WIMLIB_ERR_NOMEM;
+ goto out_free_extraction_cmds;
+ }
+ tchar *p = dest_path;
+ p = tmempcpy(p, target, tstrlen(target));
+ *p++ = OS_PREFERRED_PATH_SEPARATOR;
+ for (tchar *path_p = expanded_paths[i]; *path_p != '\0'; path_p++) {
+ if (is_any_path_separator(*path_p))
+ *p++ = OS_PREFERRED_PATH_SEPARATOR;
+ else
+ *p++ = *path_p;
+ }
+ *p++ = T('\0');
+ wimlib_assert(p - dest_path == dest_len);
+ cmds[i].fs_dest_path = dest_path;
+ }
+
+ ret = wimlib_extract_files(wim, image,
+ cmds, num_expanded_paths,
+ extract_flags & ~WIMLIB_EXTRACT_FLAG_GLOB_PATHS,
+ progress_func);
+out_free_extraction_cmds:
+ for (size_t i = 0; i < num_expanded_paths; i++)
+ FREE(cmds[i].fs_dest_path);
+ FREE(cmds);
+out_free_expanded_paths:
+ if (extract_flags & WIMLIB_EXTRACT_FLAG_GLOB_PATHS) {
+ for (size_t i = 0; i < num_expanded_paths; i++)
+ FREE(expanded_paths[i]);
+ FREE(expanded_paths);
+ }
+ return ret;
+}