From: Eric Biggers Date: Fri, 18 Apr 2014 05:53:15 +0000 (-0500) Subject: Add WIMLIB_EXTRACT_FLAG_WIMBOOT X-Git-Tag: v1.7.0~290 X-Git-Url: https://wimlib.net/git/?p=wimlib;a=commitdiff_plain;h=ccdd5a74123ebf14353a9569bf014fb2e7774d1e Add WIMLIB_EXTRACT_FLAG_WIMBOOT --- diff --git a/include/wimlib.h b/include/wimlib.h index 17d76b5a..31fab04d 100644 --- a/include/wimlib.h +++ b/include/wimlib.h @@ -1227,7 +1227,7 @@ struct wimlib_dir_entry { #define WIMLIB_REPARSE_TAG_DFS 0x8000000A #define WIMLIB_REPARSE_TAG_DFSR 0x80000012 #define WIMLIB_REPARSE_TAG_FILTER_MANAGER 0x8000000B -#define WIMLIB_REPARSE_TAG_WIMBOOT 0x80000017 +#define WIMLIB_REPARSE_TAG_WOF 0x80000017 #define WIMLIB_REPARSE_TAG_SYMLINK 0xA000000C /** If the file is a reparse point (FILE_ATTRIBUTE_DIRECTORY set in the * attributes), this will give the reparse tag. This tells you whether @@ -1382,7 +1382,20 @@ typedef int (*wimlib_iterate_lookup_table_callback_t)(const struct wimlib_resour */ #define WIMLIB_ADD_FLAG_WINCONFIG 0x00000800 -/** Capture image as WIMBoot compatible. */ +/** + * Capture image as WIMBoot compatible. + * + * Note: this will not by itself change the compression type. Before writing + * the WIM file, it's recommended to also do: + * + * \code + * wimlib_set_output_compression_type(wim, WIMLIB_COMPRESSION_TYPE_XPRESS); + * wimlib_set_output_chunk_size(wim, 4096); + * \endcode + * + * since that makes access to the data faster (at the cost of a worse + * compression ratio compared to the 32768-byte LZX chunks usually used). + */ #define WIMLIB_ADD_FLAG_WIMBOOT 0x00001000 #define WIMLIB_ADD_IMAGE_FLAG_NTFS WIMLIB_ADD_FLAG_NTFS @@ -1560,6 +1573,9 @@ typedef int (*wimlib_iterate_lookup_table_callback_t)(const struct wimlib_resour */ #define WIMLIB_EXTRACT_FLAG_NO_PRESERVE_DIR_STRUCTURE 0x00200000 +/** Windows only: Extract files as "pointers" back to the WIM archive. */ +#define WIMLIB_EXTRACT_FLAG_WIMBOOT 0x00400000 + /** @} */ /** @ingroup G_mounting_wim_images * @{ */ @@ -1979,6 +1995,7 @@ enum wimlib_error_code { WIMLIB_ERR_WRITE, WIMLIB_ERR_XML, WIMLIB_ERR_WIM_IS_ENCRYPTED, + WIMLIB_ERR_WIMBOOT, }; @@ -2408,6 +2425,9 @@ wimlib_extract_files(WIMStruct *wim, * names is not supported --- on Windows, this occurs if the target volume * does not support short names, while on non-Windows, this occurs if * ::WIMLIB_EXTRACT_FLAG_NTFS was not specified in @p extract_flags. + * @retval ::WIMLIB_ERR_WIMBOOT + * ::WIMLIB_EXTRACT_FLAG_WIMBOOT was specified in @p extract_flags, but + * there was a problem creating WIMBoot pointer files. * @retval ::WIMLIB_ERR_WRITE * Failed to write data to a file being extracted. */ diff --git a/src/extract.c b/src/extract.c index 8331001f..6512917c 100644 --- a/src/extract.c +++ b/src/extract.c @@ -94,7 +94,8 @@ WIMLIB_EXTRACT_FLAG_GLOB_PATHS | \ WIMLIB_EXTRACT_FLAG_STRICT_GLOB | \ WIMLIB_EXTRACT_FLAG_NO_ATTRIBUTES | \ - WIMLIB_EXTRACT_FLAG_NO_PRESERVE_DIR_STRUCTURE) + WIMLIB_EXTRACT_FLAG_NO_PRESERVE_DIR_STRUCTURE | \ + WIMLIB_EXTRACT_FLAG_WIMBOOT) static bool dentry_in_list(const struct wim_dentry *dentry) @@ -2744,6 +2745,13 @@ check_extract_flags(const WIMStruct *wim, int *extract_flags_p) } #endif +#ifndef __WIN32__ + if (extract_flags & WIMLIB_EXTRACT_FLAG_WIMBOOT) { + ERROR("WIMBoot extraction is only supported on Windows!"); + return WIMLIB_ERR_UNSUPPORTED; + } +#endif + if ((extract_flags & (WIMLIB_EXTRACT_FLAG_RPFIX | WIMLIB_EXTRACT_FLAG_NORPFIX | WIMLIB_EXTRACT_FLAG_IMAGEMODE)) == diff --git a/src/util.c b/src/util.c index b69d9bff..3053fd9e 100644 --- a/src/util.c +++ b/src/util.c @@ -425,6 +425,8 @@ static const tchar *error_strings[] = { = T("The XML data of the WIM is invalid"), [WIMLIB_ERR_WIM_IS_ENCRYPTED] = T("The WIM file (or parts of it) is encrypted"), + [WIMLIB_ERR_WIMBOOT] + = T("Failed to set WIMBoot pointer data"), }; /* API function documented in wimlib.h */ diff --git a/src/win32_apply.c b/src/win32_apply.c index af8a4ef9..87582d60 100644 --- a/src/win32_apply.c +++ b/src/win32_apply.c @@ -32,6 +32,22 @@ #include "wimlib/apply.h" #include "wimlib/error.h" #include "wimlib/lookup_table.h" +#include "wimlib/xml.h" +#include "wimlib/wim.h" +#include "wimlib/wimboot.h" + +static void +ctx_save_data_source_id(struct apply_ctx *ctx, u64 data_source_id) +{ + ctx->private[0] = data_source_id & 0xFFFFFFFF; + ctx->private[1] = data_source_id >> 32; +} + +static u64 +ctx_get_data_source_id(const struct apply_ctx *ctx) +{ + return (u32)ctx->private[0] | ((u64)(u32)ctx->private[1] << 32); +} static int win32_start_extract(const wchar_t *path, struct apply_ctx *ctx) @@ -78,6 +94,24 @@ win32_start_extract(const wchar_t *path, struct apply_ctx *ctx) if (supports_SetFileShortName) ctx->supported_features.short_names = 1; + + if (ctx->extract_flags & WIMLIB_EXTRACT_FLAG_WIMBOOT) { + + u64 data_source_id; + + if (!wim_info_get_wimboot(ctx->wim->wim_info, + ctx->wim->current_image)) + WARNING("Image is not marked as WIMBoot compatible!"); + + ret = wimboot_alloc_data_source_id(ctx->wim->filename, + ctx->wim->current_image, + path, &data_source_id); + if (ret) + return ret; + + ctx_save_data_source_id(ctx, data_source_id); + } + return 0; } @@ -265,6 +299,16 @@ win32_extract_unnamed_stream(file_spec_t file, struct wim_lookup_table_entry *lte, struct apply_ctx *ctx) { + if (ctx->extract_flags & WIMLIB_EXTRACT_FLAG_WIMBOOT + && lte + && lte->resource_location == RESOURCE_IN_WIM + && lte->rspec->wim == ctx->wim) + { + return wimboot_set_pointer(file.path, + ctx_get_data_source_id(ctx), + lte->hash); + } + return win32_extract_stream(file.path, NULL, 0, lte, ctx); }