/* 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. */
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
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,
};
#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);
}
}
}
-static int
+int
mangle_pat(tchar *pat, const tchar *path, unsigned long line_no)
{
if (!is_any_path_separator(pat[0]) &&
}
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[] = {
{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;
}
FREE(config->buf);
}
-static bool
+bool
match_pattern(const tchar *path,
const tchar *path_basename,
const struct string_set *list)
}
} else {
ret = ctx->ops->extract_unnamed_stream(
- file_spec, lte, ctx);
+ file_spec, lte, ctx,
+ dentry);
if (ret)
goto error;
}
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);
}
.name = T(""),
.strings = &paths,
};
- tchar *buf;
+ void *buf;
int ret;
ret = load_text_file(listfile, &buf, &tmp, 1, NULL);
*paths_ret = paths.strings;
*num_paths_ret = paths.num_strings;
- *mem_ret = (void *)buf;
+ *mem_ret = buf;
return 0;
}
#include <unistd.h>
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;
}
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...) */
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;
}
&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;
}
}
}
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;
}
* 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
*/
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,
{
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;
}
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;
}
}
-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,
}
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);
#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"
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)
{
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,
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);
}
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)
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),
.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,