#include "wimlib/reparse.h"
#include "wimlib/resource.h"
#include "wimlib/security.h"
-#include "wimlib/swm.h"
#ifdef __WIN32__
# include "wimlib/win32.h" /* for realpath() equivalent */
#endif
if (!lte)
return 0;
- if (likely(!is_linked_extraction(ctx)) || (lte->out_refcnt == 0 &&
- lte->extracted_file == NULL))
+ /* Tally the size only for each extraction of the stream (not hard
+ * links). */
+ if (!(dentry->d_inode->i_visited &&
+ ctx->supported_features.hard_links) &&
+ (!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++;
}
+ /* Add stream to the extraction_list only one time, even if it's going
+ * to be extracted to multiple locations. */
if (lte->out_refcnt == 0) {
list_add_tail(<e->extraction_list, &ctx->stream_list);
ctx->num_streams_remaining++;
* 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. */
+ * referencing it.
+ *
+ * This uses the i_visited member of the inodes (assumed to be 0 initially). */
static int
dentry_add_streams_to_extract(struct wim_dentry *dentry, void *_ctx)
{
if (dentry->extraction_skipped)
return 0;
- /* Don't process additional hard links. */
- if (inode->i_visited && ctx->supported_features.hard_links)
- return 0;
-
/* The unnamed data stream will always be extracted, except in an
* unlikely case. */
if (!inode_is_encrypted_directory(inode)) {
return 0;
}
+/* This is a wrapper around do_dentry_extract_skeleton() that handles building
+ * the path, doing short name reordering. This is also idempotent; dentries
+ * already processed have skeleton_extracted set and no action is taken. See
+ * apply_operations.requires_short_name_reordering for more details about short
+ * name reordering. */
static int
dentry_extract_skeleton(struct wim_dentry *dentry, void *_ctx)
{
struct wim_dentry *other_dentry;
int ret;
- /* Here we may re-order the extraction of multiple names (hard links)
- * for the same file in the same directory in order to ensure the short
- * (DOS) name is set correctly. A short name is always associated with
- * exactly one long name, and at least on NTFS, only one long name for a
- * file can have a short name associated with it. (More specifically,
- * there can be unlimited names in the POSIX namespace, but only one
- * name can be in the Win32+DOS namespace, or one name in the Win32
- * namespace with a corresponding name in the DOS namespace.) To ensure
- * the short name of a file is associated with the correct long name in
- * a directory, we extract the long name with a corresponding short name
- * before any additional names. This can affect NTFS-3g extraction
- * (which uses ntfs_set_ntfs_dos_name(), which doesn't allow specifying
- * the long name to associate with a short name) and may affect Win32
- * extraction as well (which uses SetFileShortName()). */
-
if (dentry->skeleton_extracted)
return 0;
+
orig_dentry = NULL;
if (ctx->supported_features.short_names
+ && ctx->ops->requires_short_name_reordering
&& !dentry_has_short_name(dentry)
&& !dentry->d_inode->i_dos_name_extracted)
{
inode_for_each_dentry(other_dentry, dentry->d_inode) {
if (dentry_has_short_name(other_dentry)
&& !other_dentry->skeleton_extracted
- && other_dentry->parent == dentry->parent)
+ && other_dentry->in_extraction_tree)
{
DEBUG("Creating %"TS" before %"TS" "
"to guarantee correct DOS name extraction",
return 0;
}
+static int
+dentry_extract_dir_skeleton(struct wim_dentry *dentry, void *_ctx)
+{
+ if (dentry->d_inode->i_attributes & FILE_ATTRIBUTE_DIRECTORY)
+ return dentry_extract_skeleton(dentry, _ctx);
+ 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
* may not be read sequentially by this function. */
if ((found_lte->resource_location != RESOURCE_NONEXISTENT)
&& !(found_lte->resource_entry.flags & WIM_RESHDR_FLAG_METADATA)
- && (needed_lte = __lookup_resource(lookup_table, found_lte->hash))
+ && (needed_lte = lookup_resource(lookup_table, found_lte->hash))
&& (needed_lte->out_refcnt))
{
copy_resource_entry(&needed_lte->resource_entry,
struct apply_ctx *ctx = _args;
int ret;
+ dentry->in_extraction_tree = 1;
+
if (dentry == ctx->extract_root || dentry->extraction_skipped)
return 0;
{
struct wim_inode *inode = dentry->d_inode;
+ dentry->in_extraction_tree = 0;
dentry->extraction_skipped = 0;
dentry->was_hardlinked = 0;
dentry->skeleton_extracted = 0;
return 0;
}
-static int
-dentry_clear_inode_visited(struct wim_dentry *dentry, void *_ignore)
-{
- dentry->d_inode->i_visited = 0;
- return 0;
-}
-
/* Tally the features necessary to extract a dentry tree. */
static void
dentry_tree_get_features(struct wim_dentry *root, struct wim_features *features)
{
memset(features, 0, sizeof(struct wim_features));
for_dentry_in_tree(root, dentry_tally_features, features);
- for_dentry_in_tree(root, dentry_clear_inode_visited, NULL);
+ dentry_tree_clear_inode_visited(root);
}
static u32
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"
ctx.realtarget_nchars = tstrlen(ctx.realtarget);
}
+ if (ctx.ops->requires_short_name_reordering) {
+ ret = for_dentry_in_tree(root, dentry_extract_dir_skeleton,
+ &ctx);
+ if (ret)
+ goto out_free_realtarget;
+ }
+
/* Finally, the important part: extract the tree of files. */
if (extract_flags & (WIMLIB_EXTRACT_FLAG_SEQUENTIAL |
WIMLIB_EXTRACT_FLAG_FROM_PIPE)) {
const struct wimlib_extract_command *cmds,
size_t num_cmds,
int default_extract_flags,
- WIMStruct **additional_swms,
- unsigned num_additional_swms,
wimlib_progress_func_t progress_func)
{
int ret;
default_extract_flags &= WIMLIB_EXTRACT_MASK_PUBLIC;
- ret = verify_swm_set(wim, additional_swms, num_additional_swms);
- if (ret)
- goto out;
-
if (num_cmds == 0)
- goto out;
-
- if (num_additional_swms)
- merge_lookup_tables(wim, additional_swms, num_additional_swms);
+ return 0;
cmds_copy = CALLOC(num_cmds, sizeof(cmds[0]));
- if (!cmds_copy) {
- ret = WIMLIB_ERR_NOMEM;
- goto out_restore_lookup_table;
- }
+ if (!cmds_copy)
+ return WIMLIB_ERR_NOMEM;
for (size_t i = 0; i < num_cmds; i++) {
cmds_copy[i].extract_flags = (default_extract_flags |
FREE(cmds_copy[i].fs_dest_path);
}
FREE(cmds_copy);
-out_restore_lookup_table:
- if (num_additional_swms)
- unmerge_lookup_table(wim);
-out:
return ret;
}
int image,
const tchar *target,
int extract_flags,
- WIMStruct **additional_swms,
- unsigned num_additional_swms,
wimlib_progress_func_t progress_func)
{
int ret;
- if (extract_flags & WIMLIB_EXTRACT_FLAG_FROM_PIPE) {
- wimlib_assert(wim->hdr.part_number == 1);
- wimlib_assert(num_additional_swms == 0);
- } else {
- ret = verify_swm_set(wim, additional_swms, num_additional_swms);
- if (ret)
- return ret;
-
- if (num_additional_swms)
- merge_lookup_tables(wim, additional_swms, num_additional_swms);
- }
-
if (image == WIMLIB_ALL_IMAGES) {
ret = extract_all_images(wim, target, extract_flags,
progress_func);
lte_free_extracted_file,
NULL);
}
- if (num_additional_swms)
- unmerge_lookup_table(wim);
return ret;
}
* wimlib_open_wim(), getting a WIMStruct in this way will result in
* an empty lookup table, no XML data read, and no filename set. */
ret = open_wim_as_WIMStruct(&pipe_fd,
- WIMLIB_OPEN_FLAG_FROM_PIPE |
- WIMLIB_OPEN_FLAG_SPLIT_OK,
+ WIMLIB_OPEN_FLAG_FROM_PIPE,
&pwm, progress_func);
if (ret)
return ret;
/* Extract the image. */
extract_flags |= WIMLIB_EXTRACT_FLAG_FROM_PIPE;
ret = do_wimlib_extract_image(pwm, image, target,
- extract_flags, NULL, 0, progress_func);
+ extract_flags, progress_func);
/* Clean up and return. */
out_wimlib_free:
wimlib_free(pwm);
int image,
const tchar *target,
int extract_flags,
- WIMStruct **additional_swms,
- unsigned num_additional_swms,
wimlib_progress_func_t progress_func)
{
extract_flags &= WIMLIB_EXTRACT_MASK_PUBLIC;
return do_wimlib_extract_image(wim, image, target, extract_flags,
- additional_swms, num_additional_swms,
progress_func);
}