From 0e8a218c22b3c5d42ccc368b3b45d270f942cfde Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Thu, 24 Apr 2014 13:01:01 -0500 Subject: [PATCH 1/1] Pay attention to PrepopulateList during WIMBoot application --- include/wimlib/apply.h | 2 +- include/wimlib/capture.h | 14 +++- include/wimlib/textfile.h | 18 ++---- src/capture_common.c | 13 ++-- src/extract.c | 3 +- src/ntfs-3g_apply.c | 3 +- src/pathlist.c | 4 +- src/textfile.c | 71 +++++++++++---------- src/unix_apply.c | 2 +- src/update_image.c | 22 ++----- src/win32_apply.c | 131 +++++++++++++++++++++++++++++++++++++- 11 files changed, 200 insertions(+), 83 deletions(-) diff --git a/include/wimlib/apply.h b/include/wimlib/apply.h index a93bc7ec..7b4ffe3e 100644 --- a/include/wimlib/apply.h +++ b/include/wimlib/apply.h @@ -72,7 +72,7 @@ struct apply_operations { /* REQUIRED: Extract unnamed data stream. */ int (*extract_unnamed_stream) (file_spec_t file, struct wim_lookup_table_entry *lte, - struct apply_ctx *ctx); + struct apply_ctx *ctx, struct wim_dentry *dentry); /* OPTIONAL: Extracted named data stream. In start_extract(), set * ctx->supported_features.alternate_data_streams if supported. */ diff --git a/include/wimlib/capture.h b/include/wimlib/capture.h index 995a60f3..aa9c4cda 100644 --- a/include/wimlib/capture.h +++ b/include/wimlib/capture.h @@ -17,7 +17,7 @@ struct capture_config { struct string_set exclusion_exception_pats; tchar *prefix; size_t prefix_num_tchars; - tchar *buf; + void *buf; }; /* Common parameters to implementations of building an in-memory dentry tree @@ -65,12 +65,20 @@ do_capture_progress(struct add_image_params *params, int status, const struct wim_inode *inode); extern int -do_read_capture_config_file(const tchar *config_file, tchar *buf, size_t buflen, - struct capture_config *config); +mangle_pat(tchar *pat, const tchar *path, unsigned long line_no); + +extern int +do_read_capture_config_file(const tchar *config_file, const void *buf, + size_t bufsize, struct capture_config *config); extern void destroy_capture_config(struct capture_config *config); +extern bool +match_pattern(const tchar *path, + const tchar *path_basename, + const struct string_set *list); + extern bool exclude_path(const tchar *path, size_t path_len, const struct capture_config *config, diff --git a/include/wimlib/textfile.h b/include/wimlib/textfile.h index bc2068ff..b4e3885a 100644 --- a/include/wimlib/textfile.h +++ b/include/wimlib/textfile.h @@ -24,29 +24,21 @@ struct text_file_section { }; #define LOAD_TEXT_FILE_REMOVE_QUOTES 0x00000001 +#define LOAD_TEXT_FILE_NO_WARNINGS 0x00000002 extern int -do_load_text_file(const tchar *path, tchar *buf, size_t buflen, tchar **buf_ret, +do_load_text_file(const tchar *path, + const void *buf, size_t bufsize, void **mem_ret, const struct text_file_section *pos_sections, int num_pos_sections, int flags, line_mangle_t mangle_line); static inline int -load_text_file(const tchar *path, tchar **buf_ret, +load_text_file(const tchar *path, void **mem_ret, const struct text_file_section *pos_sections, int num_pos_sections, line_mangle_t mangle_line) { - return do_load_text_file(path, NULL, 0, buf_ret, - pos_sections, num_pos_sections, - LOAD_TEXT_FILE_REMOVE_QUOTES, mangle_line); -} - -static inline int -load_text_buffer(tchar *buf, size_t buflen, - const struct text_file_section *pos_sections, - int num_pos_sections, line_mangle_t mangle_line) -{ - return do_load_text_file(NULL, buf, buflen, &buf, + return do_load_text_file(path, NULL, 0, mem_ret, pos_sections, num_pos_sections, LOAD_TEXT_FILE_REMOVE_QUOTES, mangle_line); } diff --git a/src/capture_common.c b/src/capture_common.c index 35aaee69..00f8eabc 100644 --- a/src/capture_common.c +++ b/src/capture_common.c @@ -69,7 +69,7 @@ do_capture_progress(struct add_image_params *params, int status, } } -static int +int mangle_pat(tchar *pat, const tchar *path, unsigned long line_no) { if (!is_any_path_separator(pat[0]) && @@ -105,8 +105,8 @@ mangle_pat(tchar *pat, const tchar *path, unsigned long line_no) } int -do_read_capture_config_file(const tchar *config_file, tchar *buf, size_t buflen, - struct capture_config *config) +do_read_capture_config_file(const tchar *config_file, const void *buf, + size_t bufsize, struct capture_config *config) { int ret; struct text_file_section sections[] = { @@ -115,14 +115,15 @@ do_read_capture_config_file(const tchar *config_file, tchar *buf, size_t buflen, {T("ExclusionException"), &config->exclusion_exception_pats}, }; + void *mem; - ret = do_load_text_file(config_file, buf, buflen, &buf, + ret = do_load_text_file(config_file, buf, bufsize, &mem, sections, ARRAY_LEN(sections), LOAD_TEXT_FILE_REMOVE_QUOTES, mangle_pat); if (ret) return ret; - config->buf = buf; + config->buf = mem; return 0; } @@ -134,7 +135,7 @@ destroy_capture_config(struct capture_config *config) FREE(config->buf); } -static bool +bool match_pattern(const tchar *path, const tchar *path_basename, const struct string_set *list) diff --git a/src/extract.c b/src/extract.c index 33770722..c6a3b561 100644 --- a/src/extract.c +++ b/src/extract.c @@ -494,7 +494,8 @@ extract_streams(const tchar *path, struct apply_ctx *ctx, } } else { ret = ctx->ops->extract_unnamed_stream( - file_spec, lte, ctx); + file_spec, lte, ctx, + dentry); if (ret) goto error; } diff --git a/src/ntfs-3g_apply.c b/src/ntfs-3g_apply.c index 86a28c10..0d054edb 100644 --- a/src/ntfs-3g_apply.c +++ b/src/ntfs-3g_apply.c @@ -284,7 +284,8 @@ out: static int ntfs_3g_extract_unnamed_stream(file_spec_t file, struct wim_lookup_table_entry *lte, - struct apply_ctx *ctx) + struct apply_ctx *ctx, + struct wim_dentry *_ignore) { return ntfs_3g_extract_stream(file, NULL, 0, lte, ctx); } diff --git a/src/pathlist.c b/src/pathlist.c index c366ed7f..1bb20cff 100644 --- a/src/pathlist.c +++ b/src/pathlist.c @@ -40,7 +40,7 @@ read_path_list_file(const tchar *listfile, .name = T(""), .strings = &paths, }; - tchar *buf; + void *buf; int ret; ret = load_text_file(listfile, &buf, &tmp, 1, NULL); @@ -49,6 +49,6 @@ read_path_list_file(const tchar *listfile, *paths_ret = paths.strings; *num_paths_ret = paths.num_strings; - *mem_ret = (void *)buf; + *mem_ret = buf; return 0; } diff --git a/src/textfile.c b/src/textfile.c index c42a1724..a2b630a7 100644 --- a/src/textfile.c +++ b/src/textfile.c @@ -40,12 +40,12 @@ #include static int -read_file_contents(const tchar *path, u8 **buf_ret, size_t *bufsize_ret) +read_file_contents(const tchar *path, void **buf_ret, size_t *bufsize_ret) { int raw_fd; struct filedes fd; struct stat st; - u8 *buf; + void *buf; int ret; int errno_save; @@ -87,20 +87,14 @@ read_file_contents(const tchar *path, u8 **buf_ret, size_t *bufsize_ret) } static int -read_text_file_contents(const tchar *path, - tchar **buf_ret, size_t *buflen_ret) +translate_text_buffer(const u8 *buf_raw, size_t bufsize_raw, + tchar **tstr_ret, size_t *tstr_nchars_ret) { - int ret; - u8 *buf_raw; - size_t bufsize_raw; size_t offset_raw; bool utf8; tchar *buf_tstr; size_t bufsize_tstr; - - ret = read_file_contents(path, &buf_raw, &bufsize_raw); - if (ret) - return ret; + int ret; /* Guess the encoding: UTF-8 or UTF-16LE. (Something weirder and you're * out of luck, sorry...) */ @@ -144,6 +138,7 @@ read_text_file_contents(const tchar *path, memcpy(buf_tstr, buf_raw + offset_raw, bufsize_tstr); ((u8*)buf_tstr)[bufsize_tstr + 0] = 0; ((u8*)buf_tstr)[bufsize_tstr + 1] = 0; + ret = 0; } else { ret = WIMLIB_ERR_NOMEM; } @@ -153,12 +148,11 @@ read_text_file_contents(const tchar *path, &buf_tstr, &bufsize_tstr); #endif } - FREE(buf_raw); if (ret) return ret; - *buf_ret = buf_tstr; - *buflen_ret = bufsize_tstr / sizeof(tchar); + *tstr_ret = buf_tstr; + *tstr_nchars_ret = bufsize_tstr / sizeof(tchar); return 0; } @@ -248,16 +242,22 @@ parse_text_file(const tchar *path, tchar *buf, size_t buflen, } } line_begin[line_len - 1] = T(']'); - if (current_section < 0) - WARNING("%"TS":%lu: Unrecognized section \"%"TS"\"", - path, line_no, line_begin); + if (current_section < 0) { + if (!(flags & LOAD_TEXT_FILE_NO_WARNINGS)) { + WARNING("%"TS":%lu: Unrecognized section \"%"TS"\"", + path, line_no, line_begin); + } + } continue; } if (current_section < 0) { - if (current_section == NOT_IN_SECTION) - WARNING("%"TS":%lu: Not in a bracketed section!", - path, line_no); + if (current_section == NOT_IN_SECTION) { + if (!(flags & LOAD_TEXT_FILE_NO_WARNINGS)) { + WARNING("%"TS":%lu: Not in a bracketed section!", + path, line_no); + } + } continue; } @@ -300,7 +300,7 @@ parse_text_file(const tchar *path, tchar *buf, size_t buflen, * If NULL, the data will be read from the @path file. Otherwise the data * will be read from this buffer, which must be newline-terminated. * @buflen - * Length of buffer in 'tchars'; ignored if @buf is NULL. + * Length of buffer in bytes; ignored if @buf is NULL. * @buf_ret * On success, a pointer to a buffer backing the parsed lines is stored * here. If @buf is not NULL, this will be @buf. Otherwise, this will be @@ -324,8 +324,8 @@ parse_text_file(const tchar *path, tchar *buf, size_t buflen, */ int do_load_text_file(const tchar *path, - tchar *buf, size_t buflen, - tchar **buf_ret, + const void *buf, size_t bufsize, + void **mem_ret, const struct text_file_section *pos_sections, int num_pos_sections, int flags, @@ -333,29 +333,32 @@ do_load_text_file(const tchar *path, { int ret; bool pathmode = (buf == NULL); + tchar *tstr; + size_t tstr_nchars; if (pathmode) { - ret = read_text_file_contents(path, &buf, &buflen); + ret = read_file_contents(path, (void **)&buf, &bufsize); if (ret) return ret; - - /* Overwrite '\0' with '\n' to avoid special case of last line - * not terminated with '\n'. */ - buf[buflen++] = T('\n'); - } else { - wimlib_assert(buflen > 0 && buf[buflen - 1] == T('\n')); } - ret = parse_text_file(path, buf, buflen, pos_sections, + ret = translate_text_buffer(buf, bufsize, &tstr, &tstr_nchars); + if (pathmode) + FREE((void *)buf); + if (ret) + return ret; + + tstr[tstr_nchars++] = T('\n'); + + ret = parse_text_file(path, tstr, tstr_nchars, pos_sections, num_pos_sections, flags, mangle_line); if (ret) { for (int i = 0; i < num_pos_sections; i++) FREE(pos_sections[i].strings->strings); - if (pathmode) - FREE(buf); + FREE(tstr); return ret; } - *buf_ret = buf; + *mem_ret = tstr; return 0; } diff --git a/src/unix_apply.c b/src/unix_apply.c index 8d549f60..d1888446 100644 --- a/src/unix_apply.c +++ b/src/unix_apply.c @@ -115,7 +115,7 @@ unix_create_symlink(const tchar *oldpath, const tchar *newpath, static int unix_extract_unnamed_stream(file_spec_t file, struct wim_lookup_table_entry *lte, - struct apply_ctx *ctx) + struct apply_ctx *ctx, struct wim_dentry *_ignore) { const char *path = file.path; struct filedes fd; diff --git a/src/update_image.c b/src/update_image.c index 82aac7ff..05861f2d 100644 --- a/src/update_image.c +++ b/src/update_image.c @@ -165,16 +165,14 @@ attach_branch(struct wim_dentry **root_p, struct wim_dentry *branch, } } -const tchar wincfg[] = -T( +static const char wincfg[] = "[ExclusionList]\n" "/$ntfs.log\n" "/hiberfil.sys\n" "/pagefile.sys\n" "/System Volume Information\n" "/RECYCLER\n" -"/Windows/CSC\n" -); +"/Windows/CSC\n"; static int get_capture_config(const tchar *config_file, struct capture_config *config, @@ -211,23 +209,11 @@ get_capture_config(const tchar *config_file, struct capture_config *config, } if (add_flags & WIMLIB_ADD_FLAG_WINCONFIG) { - /* Use Windows default. */ - - tchar *wincfg_copy; - const size_t wincfg_len = ARRAY_LEN(wincfg) - 1; - if (config_file) return WIMLIB_ERR_INVALID_PARAM; - - wincfg_copy = memdup(wincfg, wincfg_len * sizeof(wincfg[0])); - if (!wincfg_copy) - return WIMLIB_ERR_NOMEM; - - ret = do_read_capture_config_file(T("wincfg"), wincfg_copy, - wincfg_len, config); - if (ret) - FREE(wincfg_copy); + ret = do_read_capture_config_file(T("wincfg"), wincfg, + sizeof(wincfg) - 1, config); } else if (config_file) { /* Use the specified configuration file. */ ret = do_read_capture_config_file(config_file, NULL, 0, config); diff --git a/src/win32_apply.c b/src/win32_apply.c index 87582d60..2b0d5a4b 100644 --- a/src/win32_apply.c +++ b/src/win32_apply.c @@ -30,8 +30,12 @@ #include "wimlib/win32_common.h" #include "wimlib/apply.h" +#include "wimlib/capture.h" +#include "wimlib/dentry.h" #include "wimlib/error.h" #include "wimlib/lookup_table.h" +#include "wimlib/paths.h" +#include "wimlib/textfile.h" #include "wimlib/xml.h" #include "wimlib/wim.h" #include "wimlib/wimboot.h" @@ -49,6 +53,110 @@ ctx_get_data_source_id(const struct apply_ctx *ctx) return (u32)ctx->private[0] | ((u64)(u32)ctx->private[1] << 32); } +static void +set_prepopulate_pats(struct apply_ctx *ctx, struct string_set *s) +{ + ctx->private[2] = (intptr_t)s; +} + +static struct string_set * +alloc_prepopulate_pats(struct apply_ctx *ctx) +{ + struct string_set *s = CALLOC(1, sizeof(*s)); + set_prepopulate_pats(ctx, s); + return s; +} + +static struct string_set * +get_prepopulate_pats(struct apply_ctx *ctx) +{ + return (struct string_set *)(ctx->private[2]); +} + +static void +free_prepopulate_pats(struct apply_ctx *ctx) +{ + struct string_set *s; + + s = get_prepopulate_pats(ctx); + if (s) { + FREE(s->strings); + FREE(s); + } + set_prepopulate_pats(ctx, NULL); + + FREE((void *)ctx->private[3]); + ctx->private[3] = (intptr_t)NULL; +} + +static int +load_prepopulate_pats(struct apply_ctx *ctx) +{ + int ret; + struct wim_dentry *dentry; + struct wim_lookup_table_entry *lte; + struct string_set *s; + const tchar *path = WIMLIB_WIM_PATH_SEPARATOR_STRING T("Windows") + WIMLIB_WIM_PATH_SEPARATOR_STRING T("System32") + WIMLIB_WIM_PATH_SEPARATOR_STRING T("WimBootCompress.ini"); + void *buf; + void *mem; + struct text_file_section sec; + + dentry = get_dentry(ctx->wim, path, WIMLIB_CASE_INSENSITIVE); + if (!dentry || + (dentry->d_inode->i_attributes & (FILE_ATTRIBUTE_DIRECTORY | + FILE_ATTRIBUTE_REPARSE_POINT | + FILE_ATTRIBUTE_ENCRYPTED)) || + !(lte = inode_unnamed_lte(dentry->d_inode, ctx->wim->lookup_table))) + { + WARNING("%"TS" does not exist in WIM image!", path); + return WIMLIB_ERR_PATH_DOES_NOT_EXIST; + } + + ret = read_full_stream_into_alloc_buf(lte, &buf); + if (ret) + return ret; + + s = alloc_prepopulate_pats(ctx); + if (!s) { + FREE(buf); + return WIMLIB_ERR_NOMEM; + } + + sec.name = T("PrepopulateList"); + sec.strings = s; + + ret = do_load_text_file(path, buf, lte->size, &mem, &sec, 1, + LOAD_TEXT_FILE_REMOVE_QUOTES | + LOAD_TEXT_FILE_NO_WARNINGS, + mangle_pat); + FREE(buf); + if (ret) { + free_prepopulate_pats(ctx); + return ret; + } + ctx->private[3] = (intptr_t)mem; + return 0; +} + +static bool +in_prepopulate_list(struct wim_dentry *dentry, + struct apply_ctx *ctx) +{ + struct string_set *pats; + const tchar *path; + + pats = get_prepopulate_pats(ctx); + if (!pats) + return false; + path = dentry_full_path(dentry); + if (!path) + return false; + + return match_pattern(path, path_basename(path), pats); +} + static int win32_start_extract(const wchar_t *path, struct apply_ctx *ctx) { @@ -97,6 +205,10 @@ win32_start_extract(const wchar_t *path, struct apply_ctx *ctx) if (ctx->extract_flags & WIMLIB_EXTRACT_FLAG_WIMBOOT) { + ret = load_prepopulate_pats(ctx); + if (ret == WIMLIB_ERR_NOMEM) + return ret; + u64 data_source_id; if (!wim_info_get_wimboot(ctx->wim->wim_info, @@ -106,8 +218,10 @@ win32_start_extract(const wchar_t *path, struct apply_ctx *ctx) ret = wimboot_alloc_data_source_id(ctx->wim->filename, ctx->wim->current_image, path, &data_source_id); - if (ret) + if (ret) { + free_prepopulate_pats(ctx); return ret; + } ctx_save_data_source_id(ctx, data_source_id); } @@ -115,6 +229,13 @@ win32_start_extract(const wchar_t *path, struct apply_ctx *ctx) return 0; } +static int +win32_finish_extract(struct apply_ctx *ctx) +{ + free_prepopulate_pats(ctx); + return 0; +} + /* Delete a non-directory file, working around Windows quirks. */ static BOOL win32_delete_file_wrapper(const wchar_t *path) @@ -297,12 +418,14 @@ error: static int win32_extract_unnamed_stream(file_spec_t file, struct wim_lookup_table_entry *lte, - struct apply_ctx *ctx) + struct apply_ctx *ctx, + struct wim_dentry *dentry) { if (ctx->extract_flags & WIMLIB_EXTRACT_FLAG_WIMBOOT && lte && lte->resource_location == RESOURCE_IN_WIM - && lte->rspec->wim == ctx->wim) + && lte->rspec->wim == ctx->wim + && !in_prepopulate_list(dentry, ctx)) { return wimboot_set_pointer(file.path, ctx_get_data_source_id(ctx), @@ -767,6 +890,8 @@ const struct apply_operations win32_apply_ops = { .target_is_root = win32_path_is_root_of_drive, .start_extract = win32_start_extract, + .finish_extract = win32_finish_extract, + .abort_extract = win32_finish_extract, .create_file = win32_create_file, .create_directory = win32_create_directory, .create_hardlink = win32_create_hardlink, -- 2.43.0