X-Git-Url: https://wimlib.net/git/?a=blobdiff_plain;f=src%2Fextract.c;h=4bde82ab866c2c33c229793421d3b5acdc0da35d;hb=5c3e789acfd123d4ae6d3b17a22c06f9ac25a35c;hp=8e695f665e879c6a5adae98535abd82b0320fb0d;hpb=320e646b45b894a25c4239d5a71d3bd9c2ec793b;p=wimlib diff --git a/src/extract.c b/src/extract.c index 8e695f66..4bde82ab 100644 --- a/src/extract.c +++ b/src/extract.c @@ -71,7 +71,31 @@ #define WIMLIB_EXTRACT_FLAG_FROM_PIPE 0x40000000 #define WIMLIB_EXTRACT_FLAG_FILEMODE 0x20000000 #define WIMLIB_EXTRACT_FLAG_IMAGEMODE 0x10000000 -#define WIMLIB_EXTRACT_MASK_PUBLIC 0x0fffffff + +/* Keep in sync with wimlib.h */ +#define WIMLIB_EXTRACT_MASK_PUBLIC \ + (WIMLIB_EXTRACT_FLAG_NTFS | \ + WIMLIB_EXTRACT_FLAG_HARDLINK | \ + WIMLIB_EXTRACT_FLAG_SYMLINK | \ + WIMLIB_EXTRACT_FLAG_VERBOSE | \ + WIMLIB_EXTRACT_FLAG_SEQUENTIAL | \ + WIMLIB_EXTRACT_FLAG_UNIX_DATA | \ + WIMLIB_EXTRACT_FLAG_NO_ACLS | \ + WIMLIB_EXTRACT_FLAG_STRICT_ACLS | \ + WIMLIB_EXTRACT_FLAG_RPFIX | \ + WIMLIB_EXTRACT_FLAG_NORPFIX | \ + WIMLIB_EXTRACT_FLAG_TO_STDOUT | \ + WIMLIB_EXTRACT_FLAG_REPLACE_INVALID_FILENAMES | \ + WIMLIB_EXTRACT_FLAG_ALL_CASE_CONFLICTS | \ + WIMLIB_EXTRACT_FLAG_STRICT_TIMESTAMPS | \ + WIMLIB_EXTRACT_FLAG_STRICT_SHORT_NAMES | \ + WIMLIB_EXTRACT_FLAG_STRICT_SYMLINKS | \ + WIMLIB_EXTRACT_FLAG_RESUME | \ + WIMLIB_EXTRACT_FLAG_FILE_ORDER | \ + WIMLIB_EXTRACT_FLAG_GLOB_PATHS | \ + WIMLIB_EXTRACT_FLAG_STRICT_GLOB | \ + WIMLIB_EXTRACT_FLAG_NO_ATTRIBUTES | \ + WIMLIB_EXTRACT_FLAG_NO_PRESERVE_DIR_STRUCTURE) /* Given a WIM dentry in the tree to be extracted, resolve all streams in the * corresponding inode and set 'out_refcnt' in each to 0. */ @@ -1383,32 +1407,17 @@ out_delete_tmpfile: static int extract_stream_list(struct apply_ctx *ctx) { - 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 = { - .begin_stream = begin_extract_stream_to_tmpfile, - .begin_stream_ctx = ctx, - .consume_chunk = extract_chunk_to_fd, - .consume_chunk_ctx = &ctx->tmpfile_fd, - .end_stream = end_extract_stream_to_tmpfile, - .end_stream_ctx = ctx, - }; - return read_stream_list(&ctx->stream_list, - offsetof(struct wim_lookup_table_entry, extraction_list), - &cbs, VERIFY_STREAM_HASHES); - } else { - /* Extract the streams in unsorted order. */ - struct wim_lookup_table_entry *lte; - int ret; - - list_for_each_entry(lte, &ctx->stream_list, extraction_list) { - ret = extract_stream_instances(lte, lte, ctx); - if (ret) - return ret; - } - return 0; - } + struct read_stream_list_callbacks cbs = { + .begin_stream = begin_extract_stream_to_tmpfile, + .begin_stream_ctx = ctx, + .consume_chunk = extract_chunk_to_fd, + .consume_chunk_ctx = &ctx->tmpfile_fd, + .end_stream = end_extract_stream_to_tmpfile, + .end_stream_ctx = ctx, + }; + return read_stream_list(&ctx->stream_list, + offsetof(struct wim_lookup_table_entry, extraction_list), + &cbs, VERIFY_STREAM_HASHES); } #define PWM_ALLOW_WIM_HDR 0x00001 @@ -1956,212 +1965,144 @@ compute_supported_attributes_mask(const struct wim_features *supported_features) static int do_feature_check(const struct wim_features *required_features, const struct wim_features *supported_features, - int extract_flags, - const struct apply_operations *ops, - bool warn) + int extract_flags, const struct apply_operations *ops) { - const tchar *loc = T("the extraction operation");; - const tchar *mode = T("this extraction mode"); - - if (warn) { - /* We're an archive program, so theoretically we can do what we want - * with FILE_ATTRIBUTE_ARCHIVE (which is a dumb flag anyway). Don't - * bother the user about it. */ -#if 0 - if (required_features->archive_files && !supported_features->archive_files) - { - WARNING( - "%lu files in %"TS" are marked as archived, but this attribute\n" - " is not supported in %"TS".", - required_features->archive_files, loc, mode); - } -#endif - - if (required_features->hidden_files && !supported_features->hidden_files) - { - WARNING( - "%lu files in %"TS" are marked as hidden, but this\n" - " attribute is not supported in %"TS".", - required_features->hidden_files, loc, mode); - } - - if (required_features->system_files && !supported_features->system_files) - { - WARNING( - "%lu files in %"TS" are marked as system files,\n" - " but this attribute is not supported in %"TS".", - required_features->system_files, loc, mode); - } - - if (required_features->compressed_files && !supported_features->compressed_files) - { - WARNING( - "%lu files in %"TS" are marked as being transparently\n" - " compressed, but transparent compression is not supported in\n" - " %"TS". These files will be extracted as uncompressed.", - required_features->compressed_files, loc, mode); - } - - if (required_features->encrypted_files && !supported_features->encrypted_files) - { - WARNING( - "%lu files in %"TS" are marked as being encrypted,\n" - " but encryption is not supported in %"TS". These files\n" - " will not be extracted.", - required_features->encrypted_files, loc, mode); - } - - if (required_features->encrypted_directories && - !supported_features->encrypted_directories) - { - WARNING( - "%lu directories in %"TS" are marked as being encrypted,\n" - " but encryption is not supported in %"TS".\n" - " These directories will be extracted as unencrypted.", - required_features->encrypted_directories, loc, mode); - } + /* File attributes. */ + if (!(extract_flags & WIMLIB_EXTRACT_FLAG_NO_ATTRIBUTES)) { + /* Note: Don't bother the user about FILE_ATTRIBUTE_ARCHIVE. + * We're an archive program, so theoretically we can do what we + * want with it. */ + + if (required_features->hidden_files && + !supported_features->hidden_files) + WARNING("Ignoring FILE_ATTRIBUTE_HIDDEN of %lu files", + required_features->hidden_files); + + if (required_features->system_files && + !supported_features->system_files) + WARNING("Ignoring FILE_ATTRIBUTE_SYSTEM of %lu files", + required_features->system_files); + + if (required_features->compressed_files && + !supported_features->compressed_files) + WARNING("Ignoring FILE_ATTRIBUTE_COMPRESSED of %lu files", + required_features->compressed_files); if (required_features->not_context_indexed_files && !supported_features->not_context_indexed_files) - { - WARNING( - "%lu files in %"TS" are marked as not content indexed,\n" - " but this attribute is not supported in %"TS".", - required_features->not_context_indexed_files, loc, mode); - } + WARNING("Ignoring FILE_ATTRIBUTE_NOT_CONTENT_INDEXED of %lu files", + required_features->not_context_indexed_files); - if (required_features->sparse_files && !supported_features->sparse_files) - { - WARNING( - "%lu files in %"TS" are marked as sparse, but creating\n" - " sparse files is not supported in %"TS". These files\n" - " will be extracted as non-sparse.", - required_features->sparse_files, loc, mode); - } + if (required_features->sparse_files && + !supported_features->sparse_files) + WARNING("Ignoring FILE_ATTRIBUTE_SPARSE_FILE of %lu files", + required_features->sparse_files); - if (required_features->named_data_streams && - !supported_features->named_data_streams) - { - WARNING( - "%lu files in %"TS" contain one or more alternate (named)\n" - " data streams, which are not supported in %"TS".\n" - " Alternate data streams will NOT be extracted.", - required_features->named_data_streams, loc, mode); - } - - if (unlikely(extract_flags & (WIMLIB_EXTRACT_FLAG_HARDLINK | - WIMLIB_EXTRACT_FLAG_SYMLINK)) && - required_features->named_data_streams && - supported_features->named_data_streams) - { - WARNING( - "%lu files in %"TS" contain one or more alternate (named)\n" - " data streams, which are not supported in linked extraction mode.\n" - " Alternate data streams will NOT be extracted.", - required_features->named_data_streams, loc); - } - - if (required_features->hard_links && !supported_features->hard_links) - { - WARNING( - "%lu files in %"TS" are hard links, but hard links are\n" - " not supported in %"TS". Hard links will be extracted as\n" - " duplicate copies of the linked files.", - required_features->hard_links, loc, mode); - } - - if (required_features->reparse_points && !supported_features->reparse_points) - { - if (supported_features->symlink_reparse_points) { - if (required_features->other_reparse_points) { - WARNING( - "%lu files in %"TS" are reparse points that are neither\n" - " symbolic links nor junction points and are not supported in\n" - " %"TS". These reparse points will not be extracted.", - required_features->other_reparse_points, loc, - mode); - } - } else { - WARNING( - "%lu files in %"TS" are reparse points, which are\n" - " not supported in %"TS" and will not be extracted.", - required_features->reparse_points, loc, mode); - } - } + if (required_features->encrypted_directories && + !supported_features->encrypted_directories) + WARNING("Ignoring FILE_ATTRIBUTE_ENCRYPTED of %lu directories", + required_features->encrypted_directories); + } - if (required_features->security_descriptors && - !supported_features->security_descriptors) - { - WARNING( - "%lu files in %"TS" have Windows NT security descriptors,\n" - " but extracting security descriptors is not supported in\n" - " %"TS". No security descriptors will be extracted.", - required_features->security_descriptors, loc, mode); - } + /* Encrypted files. */ + if (required_features->encrypted_files && + !supported_features->encrypted_files) + WARNING("Ignoring %lu encrypted files", + required_features->encrypted_files); - if (required_features->short_names && !supported_features->short_names) - { - WARNING( - "%lu files in %"TS" have short (DOS) names, but\n" - " extracting short names is not supported in %"TS".\n" - " Short names will not be extracted.\n", - required_features->short_names, loc, mode); - } + /* Named data streams. */ + if (required_features->named_data_streams && + (!supported_features->named_data_streams || + (extract_flags & (WIMLIB_EXTRACT_FLAG_SYMLINK | + WIMLIB_EXTRACT_FLAG_HARDLINK)))) + WARNING("Ignoring named data streams of %lu files", + required_features->named_data_streams); + + /* Hard links. */ + if ((extract_flags & WIMLIB_EXTRACT_FLAG_HARDLINK) && + !supported_features->hard_links) + { + ERROR("Extraction backend does not support hard links!"); + return WIMLIB_ERR_UNSUPPORTED; } + if (required_features->hard_links && !supported_features->hard_links) + WARNING("Extracting %lu hard links as independent files", + required_features->hard_links); - if ((extract_flags & WIMLIB_EXTRACT_FLAG_UNIX_DATA) && - required_features->unix_data && !supported_features->unix_data) + /* Symbolic links and reparse points. */ + if ((extract_flags & WIMLIB_EXTRACT_FLAG_SYMLINK) && + !supported_features->symlink_reparse_points) { - ERROR("Extracting UNIX data is not supported in %"TS, mode); + ERROR("Extraction backend does not support symbolic links!"); return WIMLIB_ERR_UNSUPPORTED; } - if ((extract_flags & WIMLIB_EXTRACT_FLAG_STRICT_SHORT_NAMES) && - required_features->short_names && !supported_features->short_names) + if ((extract_flags & WIMLIB_EXTRACT_FLAG_STRICT_SYMLINKS) && + required_features->symlink_reparse_points && + !supported_features->symlink_reparse_points && + !supported_features->reparse_points) { - ERROR("Extracting short names is not supported in %"TS"", mode); + ERROR("Extraction backend does not support symbolic links!"); return WIMLIB_ERR_UNSUPPORTED; } - if ((extract_flags & WIMLIB_EXTRACT_FLAG_STRICT_TIMESTAMPS) && - !ops->set_timestamps) + if (required_features->reparse_points && + !supported_features->reparse_points) { - ERROR("Extracting timestamps is not supported in %"TS"", mode); - return WIMLIB_ERR_UNSUPPORTED; + if (supported_features->symlink_reparse_points) { + if (required_features->other_reparse_points) { + WARNING("Ignoring %lu non-symlink/junction " + "reparse point files", + required_features->other_reparse_points); + } + } else { + WARNING("Ignoring %lu reparse point files", + required_features->reparse_points); + } } + + /* Security descriptors. */ if (((extract_flags & (WIMLIB_EXTRACT_FLAG_STRICT_ACLS | WIMLIB_EXTRACT_FLAG_UNIX_DATA)) == WIMLIB_EXTRACT_FLAG_STRICT_ACLS) && required_features->security_descriptors && !supported_features->security_descriptors) { - ERROR("Extracting security descriptors is not supported in %"TS, mode); + ERROR("Extraction backend does not support security descriptors!"); return WIMLIB_ERR_UNSUPPORTED; } + if (!(extract_flags & WIMLIB_EXTRACT_FLAG_NO_ACLS) && + required_features->security_descriptors && + !supported_features->security_descriptors) + WARNING("Ignoring Windows NT security descriptors of %lu files", + required_features->security_descriptors); - if ((extract_flags & WIMLIB_EXTRACT_FLAG_HARDLINK) && - !supported_features->hard_links) + /* UNIX data. */ + if ((extract_flags & WIMLIB_EXTRACT_FLAG_UNIX_DATA) && + required_features->unix_data && !supported_features->unix_data) { - ERROR("Hard link extraction mode requested, but " - "%"TS" does not support hard links!", mode); + ERROR("Extraction backend does not support UNIX data!"); return WIMLIB_ERR_UNSUPPORTED; } - if ((extract_flags & WIMLIB_EXTRACT_FLAG_STRICT_SYMLINKS) && - required_features->symlink_reparse_points && - !(supported_features->symlink_reparse_points || - supported_features->reparse_points)) + /* DOS Names. */ + if (required_features->short_names && + !supported_features->short_names) { - ERROR("Extracting symbolic links is not supported in %"TS, mode); - return WIMLIB_ERR_UNSUPPORTED; + if (extract_flags & WIMLIB_EXTRACT_FLAG_STRICT_SHORT_NAMES) { + ERROR("Extraction backend does not support DOS names!"); + return WIMLIB_ERR_UNSUPPORTED; + } + WARNING("Ignoring DOS names of %lu files", + required_features->short_names); } - if ((extract_flags & WIMLIB_EXTRACT_FLAG_SYMLINK) && - !supported_features->symlink_reparse_points) + /* Timestamps. */ + if ((extract_flags & WIMLIB_EXTRACT_FLAG_STRICT_TIMESTAMPS) && + !ops->set_timestamps) { - ERROR("Symbolic link extraction mode requested, but " - "%"TS" does not support symbolic " - "links!", mode); + ERROR("Extraction backend does not support timestamps!"); return WIMLIB_ERR_UNSUPPORTED; } + return 0; } @@ -2297,7 +2238,7 @@ extract_trees(WIMStruct *wim, struct wim_dentry **trees, size_t num_trees, /* Get and check the features required to extract the dentry tree. */ dentry_tree_get_features(ctx.extract_root, &required_features); ret = do_feature_check(&required_features, &ctx.supported_features, - extract_flags, ctx.ops, true); + extract_flags, ctx.ops); if (ret) goto out_finish_or_abort_extract; @@ -2562,7 +2503,9 @@ check_extract_flags(const WIMStruct *wim, int *extract_flags_p) #endif if ((extract_flags & (WIMLIB_EXTRACT_FLAG_RPFIX | - WIMLIB_EXTRACT_FLAG_NORPFIX)) == 0) + WIMLIB_EXTRACT_FLAG_NORPFIX | + WIMLIB_EXTRACT_FLAG_IMAGEMODE)) == + WIMLIB_EXTRACT_FLAG_IMAGEMODE) { /* Do reparse point fixups by default if the WIM header says * they are enabled. */ @@ -2842,7 +2785,8 @@ do_wimlib_extract_image(WIMStruct *wim, int ret; if (extract_flags & (WIMLIB_EXTRACT_FLAG_NO_PRESERVE_DIR_STRUCTURE | - WIMLIB_EXTRACT_FLAG_TO_STDOUT)) + WIMLIB_EXTRACT_FLAG_TO_STDOUT | + WIMLIB_EXTRACT_FLAG_GLOB_PATHS)) return WIMLIB_ERR_INVALID_PARAM; if (image == WIMLIB_ALL_IMAGES) @@ -2881,9 +2825,12 @@ wimlib_extract_files(WIMStruct *wim, default_extract_flags |= WIMLIB_EXTRACT_FLAG_NO_PRESERVE_DIR_STRUCTURE; for (size_t i = 0; i < num_cmds; i++) { - int cmd_flags = ((cmds[i].extract_flags | - default_extract_flags) & - WIMLIB_EXTRACT_MASK_PUBLIC); + int cmd_flags = (cmds[i].extract_flags | + default_extract_flags); + + if (cmd_flags & ~WIMLIB_EXTRACT_MASK_PUBLIC) + return WIMLIB_ERR_INVALID_PARAM; + int cmd_link_flags = (cmd_flags & (WIMLIB_EXTRACT_FLAG_SYMLINK | WIMLIB_EXTRACT_FLAG_HARDLINK)); if (i == 0) { @@ -2904,9 +2851,8 @@ wimlib_extract_files(WIMStruct *wim, } for (size_t i = 0; i < num_cmds; i++) { - int extract_flags = ((cmds[i].extract_flags | - default_extract_flags) & - WIMLIB_EXTRACT_MASK_PUBLIC); + int extract_flags = (cmds[i].extract_flags | + default_extract_flags); const tchar *target = cmds[i].fs_dest_path; const tchar *wim_source_path = cmds[i].wim_source_path; @@ -2933,7 +2879,8 @@ wimlib_extract_paths(WIMStruct *wim, { int ret; - extract_flags &= WIMLIB_EXTRACT_MASK_PUBLIC; + if (extract_flags & ~WIMLIB_EXTRACT_MASK_PUBLIC) + return WIMLIB_ERR_INVALID_PARAM; ret = do_wimlib_extract_paths(wim, image, target, paths, num_paths, extract_flags, progress_func); @@ -2979,7 +2926,8 @@ wimlib_extract_image_from_pipe(int pipe_fd, const tchar *image_num_or_name, int image; unsigned i; - extract_flags &= WIMLIB_EXTRACT_MASK_PUBLIC; + if (extract_flags & ~WIMLIB_EXTRACT_MASK_PUBLIC) + return WIMLIB_ERR_INVALID_PARAM; if (extract_flags & WIMLIB_EXTRACT_FLAG_FILE_ORDER) return WIMLIB_ERR_INVALID_PARAM; @@ -3136,7 +3084,8 @@ wimlib_extract_image(WIMStruct *wim, int extract_flags, wimlib_progress_func_t progress_func) { - extract_flags &= WIMLIB_EXTRACT_MASK_PUBLIC; + if (extract_flags & ~WIMLIB_EXTRACT_MASK_PUBLIC) + return WIMLIB_ERR_INVALID_PARAM; return do_wimlib_extract_image(wim, image, target, extract_flags, progress_func); }