lib_LTLIBRARIES = libwim.la
-libwim_la_LDFLAGS = -version-info 14:0:5 $(WINDOWS_LDFLAGS)
+libwim_la_LDFLAGS = -version-info 15:0:0 $(WINDOWS_LDFLAGS)
libwim_la_SOURCES = \
src/add_image.c \
src/split.c \
src/reparse.c \
src/template.c \
+ src/textfile.c \
src/timestamp.c \
src/update_image.c \
src/util.c \
include/wimlib/security.h \
include/wimlib/security_descriptor.h \
include/wimlib/sha1.h \
+ include/wimlib/textfile.h \
include/wimlib/timestamp.h \
include/wimlib/types.h \
include/wimlib/unix_data.h \
archive. See the documentation for the new '--wimboot' option to
wimcapture and wimapply, respectively, for more information.
+ The shared library version has been bumped up; however, there are only
+ small incompatibilities:
+
+ - wimlib_capture_config has been removed. The library now takes
+ the configuration file directly.
+
Version 1.6.2:
Case-insensitive comparisons of strings (e.g. filenames) containing
UTF-16 codepoints above 32767 are now done correctly.
long reserved;
};
-/** Structure that specifies a list of path patterns. */
-struct wimlib_pattern_list {
- /** Array of patterns. The patterns may be modified by library code,
- * but the @p pats pointer itself will not. See the man page for
- * <b>wimlib-imagex capture</b> for more information about allowed
- * patterns. */
- wimlib_tchar **pats;
-
- /** Number of patterns in the @p pats array. */
- size_t num_pats;
-
- /** Ignored; may be used by the calling code. */
- size_t num_allocated_pats;
-};
-
-/** A structure that contains lists of wildcards that match paths to treat
- * specially when capturing a WIM image. */
-struct wimlib_capture_config {
- /** Paths matching any pattern this list are excluded from being
- * captured, except if the same path appears in @p
- * exclusion_exception_pats. */
- struct wimlib_pattern_list exclusion_pats;
-
- /** Paths matching any pattern in this list are never excluded from
- * being captured. */
- struct wimlib_pattern_list exclusion_exception_pats;
-
- /** Reserved for future capture configuration options. */
- struct wimlib_pattern_list reserved1;
-
- /** Reserved for future capture configuration options. */
- struct wimlib_pattern_list reserved2;
-
- /** Library internal use only. */
- wimlib_tchar *_prefix;
-
- /** Library internal use only. */
- size_t _prefix_num_tchars;
-};
-
/** Set or unset the WIM header flag that marks it read-only
* (WIM_HDR_FLAG_READONLY in Microsoft's documentation), based on the
* ::wimlib_wim_info.is_marked_readonly member of the @p info parameter. This
* such a file is encountered. */
#define WIMLIB_ADD_FLAG_NO_UNSUPPORTED_EXCLUDE 0x00000400
-/** Automatically select a capture configuration appropriate for capturing
- * filesystems containing Windows operating systems. When this flag is
- * specified, the corresponding @p config parameter or member must be @c NULL.
- *
- * Currently, selecting this capture configuration will cause the following
- * files and directories to be excluded from capture:
+/**
+ * Automatically select a capture configuration appropriate for capturing
+ * filesystems containing Windows operating systems. For example,
+ * "pagefile.sys" and "System Volume Information" will be excluded.
*
- * - "\$ntfs.log"
- * - "\hiberfil.sys"
- * - "\pagefile.sys"
- * - "\System Volume Information"
- * - "\RECYCLER"
- * - "\Windows\CSC"
+ * When this flag is specified, the corresponding @p config parameter or member
+ * must be @c NULL.
*
* Note that the default behavior--- that is, when this flag is not specified
* and @p config is @c NULL--- is to use no capture configuration, meaning that
#define WIMLIB_ADD_FLAG_WINCONFIG 0x00000800
/**
- * Capture image as WIMBoot compatible.
+ * Capture image as WIMBoot compatible. In addition, use the capture
+ * configuration file <c>$SOURCE/Windows/System32/WimBootCompress.ini</c> if it
+ * exists, where <c>$SOURCE</c> is the directory being captured.
*
* Note: this will not by itself change the compression type. Before writing
* the WIM file, it's recommended to also do:
* WIM image. */
wimlib_tchar *wim_target_path;
- /** Configuration for excluded files. @c NULL means
- * exclude no files (use no configuration), unless
- * ::WIMLIB_ADD_FLAG_WINCONFIG is specified in @p
- * add_flags. */
- struct wimlib_capture_config *config;
+ /** Path to capture configuration file to use, or @c NULL for default.
+ */
+ wimlib_tchar *config_file;
/** Bitwise OR of WIMLIB_ADD_FLAG_* flags. */
int add_flags;
* Name to give the new image. If @c NULL or empty, the new image is given
* no name. If nonempty, it must specify a name that does not already
* exist in @p wim.
- * @param config
- * Capture configuration that specifies files, directories, or path globs
- * to exclude from being captured. If @c NULL, a dummy configuration where
- * no paths are treated specially is used.
+ * @param config_file
+ * Path to capture configuration file, or @c NULL. This file may specify,
+ * among other things, which files to exclude from capture. See the man
+ * page for <b>wimlib-imagex capture</b> (<b>--config</b> option) for
+ * details of the file format. If @c NULL, the default capture
+ * configuration shall be used. Ordinarily, the default capture
+ * configuration will result in no files being excluded from capture purely
+ * based on name; however, the ::WIMLIB_ADD_FLAG_WINCONFIG and
+ * ::WIMLIB_ADD_FLAG_WIMBOOT flags modify the default.
* @param add_flags
* Bitwise OR of flags prefixed with WIMLIB_ADD_FLAG.
* @param progress_func
wimlib_add_image(WIMStruct *wim,
const wimlib_tchar *source,
const wimlib_tchar *name,
- const struct wimlib_capture_config *config,
+ const wimlib_tchar *config_file,
int add_flags,
wimlib_progress_func_t progress_func);
const struct wimlib_capture_source *sources,
size_t num_sources,
const wimlib_tchar *name,
- const struct wimlib_capture_config *config,
+ const wimlib_tchar *config_file,
int add_flags,
wimlib_progress_func_t progress_func);
#include "wimlib/inode_table.h"
#include "wimlib/list.h"
#include "wimlib/security.h"
+#include "wimlib/textfile.h"
#include "wimlib/util.h"
struct wim_lookup_table;
struct wim_dentry;
struct wim_inode;
+struct capture_config {
+ struct string_set exclusion_pats;
+ struct string_set exclusion_exception_pats;
+ tchar *prefix;
+ size_t prefix_num_tchars;
+ tchar *buf;
+};
+
/* Common parameters to implementations of building an in-memory dentry tree
* from an on-disk directory structure. */
struct add_image_params {
* image so far. */
struct wim_sd_set sd_set;
- /* Pointer to the capture configuration, which indicates whether any
- * files should be excluded from capture or not. */
- struct wimlib_capture_config *config;
+ /* Pointer to the capture configuration. */
+ struct capture_config *config;
/* Flags that affect the capture operation (WIMLIB_ADD_FLAG_*) */
int add_flags;
do_capture_progress(struct add_image_params *params, int status,
const struct wim_inode *inode);
-extern bool
-exclude_path(const tchar *path, size_t path_len,
- const struct wimlib_capture_config *config,
- bool exclude_prefix);
-
-extern struct wimlib_capture_config *
-copy_capture_config(const struct wimlib_capture_config *config);
-
extern int
-copy_and_canonicalize_capture_config(const struct wimlib_capture_config *config,
- struct wimlib_capture_config **config_copy_ret);
+do_read_capture_config_file(const tchar *config_file, tchar *buf, size_t buflen,
+ struct capture_config *config);
extern void
-free_capture_config(struct wimlib_capture_config *config);
+destroy_capture_config(struct capture_config *config);
+
+extern bool
+exclude_path(const tchar *path, size_t path_len,
+ const struct capture_config *config,
+ bool exclude_prefix);
#ifdef WITH_NTFS_3G
--- /dev/null
+#ifndef _WIMLIB_TEXTFILE_H_
+#define _WIMLIB_TEXTFILE_H_
+
+#include <wimlib/types.h>
+
+struct string_set {
+ tchar **strings;
+ size_t num_strings;
+ size_t num_alloc_strings;
+};
+
+#define STRING_SET_INITIALIZER \
+ { .strings = NULL, .num_strings = 0, .num_alloc_strings = 0, }
+
+#define STRING_SET(_strings) \
+ struct string_set _strings = STRING_SET_INITIALIZER
+
+typedef int (*line_mangle_t)(tchar *line, const tchar *filename,
+ unsigned long line_no);
+
+struct text_file_section {
+ const tchar *name;
+ struct string_set *strings;
+};
+
+extern int
+do_load_text_file(const tchar *path, tchar *buf, size_t buflen, tchar **buf_ret,
+ const struct text_file_section *pos_sections,
+ int num_pos_sections, line_mangle_t mangle_line);
+
+static inline int
+load_text_file(const tchar *path, tchar **buf_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, 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,
+ pos_sections, num_pos_sections, mangle_line);
+}
+
+#endif /* _WIMLIB_TEXTFILE_H_ */
* with the "wide-character" functions. */
# define tmemchr wmemchr
# define tmemcpy wmemcpy
+# define tmemmove wmemmove
# define tmempcpy wmempcpy
# define tstrcpy wcscpy
# define tprintf wprintf
* string functions. */
# define tmemchr memchr
# define tmemcpy memcpy
+# define tmemmove memmove
# define tmempcpy mempcpy
# define tstrcpy strcpy
# define tprintf printf
va_end(va);
}
-static void _format_attribute(printf, 1, 2)
-imagex_warning(const tchar *format, ...)
-{
- va_list va;
- va_start(va, format);
- tfputs(T("WARNING: "), stderr);
- tvfprintf(stderr, format, va);
- tputc(T('\n'), stderr);
- va_end(va);
-}
-
/* Print formatted error message to stderr. */
static void _format_attribute(printf, 1, 2)
imagex_error_with_errno(const tchar *format, ...)
return sources;
}
-
-enum capture_config_section {
- CAPTURE_CONFIG_NO_SECTION,
- CAPTURE_CONFIG_EXCLUSION_SECTION,
- CAPTURE_CONFIG_EXCLUSION_EXCEPTION_SECTION,
- CAPTURE_CONFIG_IGNORE_SECTION,
-};
-
-enum {
- CAPTURE_CONFIG_INVALID_SECTION,
- CAPTURE_CONFIG_CHANGED_SECTION,
- CAPTURE_CONFIG_SAME_SECTION,
-};
-
-static int
-check_config_section(tchar *line, size_t len,
- enum capture_config_section *cur_section)
-{
- while (istspace(*line))
- line++;
-
- if (*line != T('['))
- return CAPTURE_CONFIG_SAME_SECTION;
-
- line++;
- tchar *endbrace = tstrrchr(line, T(']'));
- if (!endbrace)
- return CAPTURE_CONFIG_SAME_SECTION;
-
- if (!tmemcmp(line, T("ExclusionList"), endbrace - line)) {
- *cur_section = CAPTURE_CONFIG_EXCLUSION_SECTION;
- } else if (!tmemcmp(line, T("ExclusionException"), endbrace - line)) {
- *cur_section = CAPTURE_CONFIG_EXCLUSION_EXCEPTION_SECTION;
- } else if (!tmemcmp(line, T("CompressionExclusionList"), endbrace - line)) {
- *cur_section = CAPTURE_CONFIG_IGNORE_SECTION;
- tfputs(T("WARNING: Ignoring [CompressionExclusionList] section "
- "of capture config file\n"),
- stderr);
- } else if (!tmemcmp(line, T("AlignmentList"), endbrace - line)) {
- *cur_section = CAPTURE_CONFIG_IGNORE_SECTION;
- tfputs(T("WARNING: Ignoring [AlignmentList] section "
- "of capture config file\n"),
- stderr);
- } else {
- imagex_warning(T("Unknown capture config file section \"%"TS"\""),
- line - 1);
- return CAPTURE_CONFIG_INVALID_SECTION;
- }
- return CAPTURE_CONFIG_CHANGED_SECTION;
-}
-
-
-static bool
-pattern_list_add_pattern(struct wimlib_pattern_list *pat_list,
- tchar *pat)
-{
- if (pat_list->num_pats == pat_list->num_allocated_pats) {
- tchar **pats;
- size_t num_allocated_pats = pat_list->num_pats + 8;
-
- pats = realloc(pat_list->pats,
- num_allocated_pats * sizeof(pat_list->pats[0]));
- if (!pats) {
- imagex_error(T("Out of memory!"));
- return false;
- }
- pat_list->pats = pats;
- pat_list->num_allocated_pats = num_allocated_pats;
- }
- pat_list->pats[pat_list->num_pats++] = pat;
- return true;
-}
-
-static bool
-parse_capture_config_line(tchar *line, size_t len,
- enum capture_config_section *cur_section,
- struct wimlib_capture_config *config)
-{
- tchar *filename;
- int ret;
-
- ret = check_config_section(line, len, cur_section);
- if (ret == CAPTURE_CONFIG_CHANGED_SECTION ||
- ret == CAPTURE_CONFIG_INVALID_SECTION)
- return true;
-
- switch (*cur_section) {
- case CAPTURE_CONFIG_NO_SECTION:
- imagex_error(T("Line \"%"TS"\" is not in a section "
- "(such as [ExclusionList]"), line);
- return false;
- case CAPTURE_CONFIG_EXCLUSION_SECTION:
- if (parse_string(&line, &len, &filename) != PARSE_STRING_SUCCESS)
- return false;
- return pattern_list_add_pattern(&config->exclusion_pats,
- filename);
- case CAPTURE_CONFIG_EXCLUSION_EXCEPTION_SECTION:
- if (parse_string(&line, &len, &filename) != PARSE_STRING_SUCCESS)
- return false;
- return pattern_list_add_pattern(&config->exclusion_exception_pats,
- filename);
- case CAPTURE_CONFIG_IGNORE_SECTION:
- return true;
- }
- return false;
-}
-
-static int
-parse_capture_config(tchar **contents_p, size_t nchars,
- struct wimlib_capture_config *config)
-{
- ssize_t nlines;
- tchar *p;
- size_t i;
- enum capture_config_section cur_section;
-
- memset(config, 0, sizeof(*config));
-
- nlines = text_file_count_lines(contents_p, &nchars);
- if (nlines < 0)
- return -1;
-
- cur_section = CAPTURE_CONFIG_NO_SECTION;
- p = *contents_p;
- for (i = 0; i < nlines; i++) {
- tchar *endp = tmemchr(p, T('\n'), nchars);
- size_t len = endp - p + 1;
- *endp = T('\0');
- if (p != endp && *(endp - 1) == T('\r')) {
- *(endp - 1) = '\0';
- len--;
- }
- if (!is_comment_line(p, len))
- if (!parse_capture_config_line(p, len, &cur_section, config))
- return -1;
- p = endp + 1;
-
- }
- return 0;
-}
-
/* Reads the contents of a file into memory. */
static char *
file_get_contents(const tchar *filename, size_t *len_ret)
tchar *source_copy;
tchar *config_file = NULL;
- tchar *config_str;
- struct wimlib_capture_config *config;
bool source_list = false;
size_t source_list_nchars = 0;
if (compress_slow)
set_compress_slow();
- /* Set default configuration file */
-#ifdef __WIN32__
- if ((add_image_flags & WIMLIB_ADD_IMAGE_FLAG_WIMBOOT) && !config) {
- struct stat st;
-
- config_file = alloca(wcslen(source) * sizeof(wchar_t) + 100);
- swprintf(config_file, L"%ls\\%ls",
- source, L"Windows\\System32\\WimBootCompress.ini");
-
- if (tstat(config_file, &st)) {
- imagex_printf(L"\"%ls\" does not exist; using "
- "default configuration\n",
- config_file);
- config_file = NULL;
- } else {
- add_image_flags &= ~WIMLIB_ADD_IMAGE_FLAG_WINCONFIG;
- }
- }
-#endif
-
if (!tstrcmp(wimfile, T("-"))) {
/* Writing captured WIM to standard output. */
#if 0
source_list_contents = NULL;
}
- if (config_file) {
- /* Read and parse capture configuration file. */
- size_t config_len;
-
- config_str = file_get_text_contents(config_file, &config_len);
- if (!config_str) {
- ret = -1;
- goto out_free_capture_sources;
- }
-
- config = alloca(sizeof(*config));
- ret = parse_capture_config(&config_str, config_len, config);
- if (ret)
- goto out_free_config;
- } else {
- /* No capture configuration file specified; use default
- * configuration for capturing Windows operating systems. */
- config = NULL;
- add_image_flags |= WIMLIB_ADD_FLAG_WINCONFIG;
- }
-
/* Open the existing WIM, or create a new one. */
if (cmd == CMD_APPEND)
ret = wimlib_open_wim(wimfile, open_flags, &wim,
else
ret = wimlib_create_new_wim(compression_type, &wim);
if (ret)
- goto out_free_config;
+ goto out_free_capture_sources;
/* Set chunk size if non-default. */
if (chunk_size != UINT32_MAX) {
capture_sources,
num_sources,
name,
- config,
+ config_file,
add_image_flags,
imagex_progress_func);
if (ret)
free(base_wims);
out_free_wim:
wimlib_free(wim);
-out_free_config:
- if (config) {
- free(config->exclusion_pats.pats);
- free(config->exclusion_exception_pats.pats);
- free(config_str);
- }
out_free_capture_sources:
if (capture_sources_malloced)
free(capture_sources);
int write_flags = 0;
int update_flags = WIMLIB_UPDATE_FLAG_SEND_PROGRESS;
int default_add_flags = WIMLIB_ADD_FLAG_EXCLUDE_VERBOSE |
- WIMLIB_ADD_FLAG_VERBOSE;
+ WIMLIB_ADD_FLAG_VERBOSE |
+ WIMLIB_ADD_FLAG_WINCONFIG;
int default_delete_flags = 0;
unsigned num_threads = 0;
int c;
struct wimlib_update_command *cmds;
size_t num_cmds;
tchar *command_str = NULL;
-
- const tchar *config_file = NULL;
- tchar *config_str;
- struct wimlib_capture_config *config;
+ tchar *config_file = NULL;
for_opt(c, update_options) {
switch (c) {
image = 1;
}
- /* Parse capture configuration file if specified */
- if (config_file) {
- size_t config_len;
-
- config_str = file_get_text_contents(config_file, &config_len);
- if (!config_str) {
- ret = -1;
- goto out_wimlib_free;
- }
-
- config = alloca(sizeof(*config));
- ret = parse_capture_config(&config_str, config_len, config);
- if (ret)
- goto out_free_config;
- } else {
- config = NULL;
- default_add_flags |= WIMLIB_ADD_FLAG_WINCONFIG;
- }
-
/* Read update commands from standard input, or the command string if
* specified. */
if (command_str) {
cmd_file_contents = stdin_get_text_contents(&cmd_file_nchars);
if (!cmd_file_contents) {
ret = -1;
- goto out_free_config;
+ goto out_wimlib_free;
}
/* Parse the update commands */
switch (cmds[i].op) {
case WIMLIB_UPDATE_OP_ADD:
cmds[i].add.add_flags |= default_add_flags;
- cmds[i].add.config = config;
+ cmds[i].add.config_file = config_file;
break;
case WIMLIB_UPDATE_OP_DELETE:
cmds[i].delete_.delete_flags |= default_delete_flags;
free(cmds);
out_free_cmd_file_contents:
free(cmd_file_contents);
-out_free_config:
- if (config) {
- free(config->exclusion_pats.pats);
- free(config->exclusion_exception_pats.pats);
- free(config_str);
- }
out_wimlib_free:
wimlib_free(wim);
out_free_command_str:
capture_sources_to_add_cmds(const struct wimlib_capture_source *sources,
size_t num_sources,
int add_flags,
- const struct wimlib_capture_config *config)
+ const tchar *config_file)
{
struct wimlib_update_command *add_cmds;
sources[i].fs_source_path,
sources[i].wim_target_path);
add_cmds[i].op = WIMLIB_UPDATE_OP_ADD;
- add_cmds[i].add.add_flags = add_flags & ~(WIMLIB_ADD_FLAG_BOOT |
- WIMLIB_ADD_FLAG_WIMBOOT);
- add_cmds[i].add.config = (struct wimlib_capture_config*)config;
+ add_cmds[i].add.add_flags = add_flags & ~WIMLIB_ADD_FLAG_BOOT;
+ add_cmds[i].add.config_file = (tchar *)config_file;
add_cmds[i].add.fs_source_path = sources[i].fs_source_path;
add_cmds[i].add.wim_target_path = sources[i].wim_target_path;
}
const struct wimlib_capture_source *sources,
size_t num_sources,
const tchar *name,
- const struct wimlib_capture_config *config,
+ const tchar *config_file,
int add_flags,
wimlib_progress_func_t progress_func)
{
/* Translate the "capture sources" into generic update commands. */
add_cmds = capture_sources_to_add_cmds(sources, num_sources,
- add_flags, config);
+ add_flags, config_file);
if (add_cmds == NULL) {
ret = WIMLIB_ERR_NOMEM;
goto out_delete_image;
wimlib_add_image(WIMStruct *wim,
const tchar *source,
const tchar *name,
- const struct wimlib_capture_config *config,
+ const tchar *config_file,
int add_flags,
wimlib_progress_func_t progress_func)
{
.reserved = 0,
};
return wimlib_add_image_multisource(wim, &capture_src, 1, name,
- config, add_flags,
+ config_file, add_flags,
progress_func);
}
#include "wimlib/error.h"
#include "wimlib/lookup_table.h"
#include "wimlib/paths.h"
+#include "wimlib/textfile.h"
#include "wimlib/wildcard.h"
#include <string.h>
-static int
-canonicalize_pattern(const tchar *pat, tchar **canonical_pat_ret)
+void
+do_capture_progress(struct add_image_params *params, int status,
+ const struct wim_inode *inode)
{
- tchar *canonical_pat;
+ switch (status) {
+ case WIMLIB_SCAN_DENTRY_OK:
+ if (!(params->add_flags & WIMLIB_ADD_FLAG_VERBOSE))
+ return;
+ case WIMLIB_SCAN_DENTRY_UNSUPPORTED:
+ case WIMLIB_SCAN_DENTRY_EXCLUDED:
+ case WIMLIB_SCAN_DENTRY_EXCLUDED_SYMLINK:
+ if (!(params->add_flags & WIMLIB_ADD_FLAG_EXCLUDE_VERBOSE))
+ return;
+ }
+ params->progress.scan.status = status;
+ if (status == WIMLIB_SCAN_DENTRY_OK && inode->i_nlink == 1) {
+ const struct wim_lookup_table_entry *lte;
+ for (unsigned i = 0; i <= inode->i_num_ads; i++) {
+ lte = inode_stream_lte_resolved(inode, i);
+ if (lte != NULL)
+ params->progress.scan.num_bytes_scanned += lte->size;
+ }
+ if (inode->i_attributes & FILE_ATTRIBUTE_DIRECTORY)
+ params->progress.scan.num_dirs_scanned++;
+ else
+ params->progress.scan.num_nondirs_scanned++;
+ }
+ if (params->progress_func) {
+ params->progress_func(WIMLIB_PROGRESS_MSG_SCAN_DENTRY,
+ ¶ms->progress);
+ }
+}
+static int
+mangle_pat(tchar *pat, const tchar *path, unsigned long line_no)
+{
if (!is_any_path_separator(pat[0]) &&
pat[0] != T('\0') && pat[1] == T(':'))
{
* relative to the current working directory on the c:
* drive. We require paths with drive letters to be
* absolute. */
- ERROR("Invalid path \"%"TS"\"; paths including drive letters "
- "must be absolute!", pat);
- ERROR("Maybe try \"%"TC":\\%"TS"\"?",
- pat[0], pat + 2);
+ ERROR("%"TS":%lu: Invalid path \"%"TS"\"; paths including "
+ "drive letters must be absolute!\n"
+ " Maybe try \"%"TC":\\%"TS"\"?",
+ path, line_no, pat, pat[0], &pat[2]);
return WIMLIB_ERR_INVALID_CAPTURE_CONFIG;
}
- WARNING("Pattern \"%"TS"\" starts with a drive letter, which is "
- "being removed.", pat);
- /* Strip the drive letter */
- pat += 2;
+ WARNING("%"TS":%lu: Pattern \"%"TS"\" starts with a drive "
+ "letter, which is being removed.",
+ path, line_no, pat);
+
+ /* Strip the drive letter. */
+ tmemmove(pat, pat + 2, tstrlen(pat + 2) + 1);
}
- canonical_pat = canonicalize_fs_path(pat);
- if (!canonical_pat)
- return WIMLIB_ERR_NOMEM;
/* Translate all possible path separators into the operating system's
- * preferred path separator. */
- for (tchar *p = canonical_pat; *p; p++)
+ * preferred path separator. */
+ for (tchar *p = pat; *p; p++)
if (is_any_path_separator(*p))
*p = OS_PREFERRED_PATH_SEPARATOR;
- *canonical_pat_ret = canonical_pat;
return 0;
}
-static int
-copy_and_canonicalize_pattern_list(const struct wimlib_pattern_list *list,
- struct wimlib_pattern_list *copy)
-{
- int ret = 0;
-
- copy->pats = CALLOC(list->num_pats, sizeof(list->pats[0]));
- if (!copy->pats)
- return WIMLIB_ERR_NOMEM;
- copy->num_pats = list->num_pats;
- for (size_t i = 0; i < list->num_pats; i++) {
- ret = canonicalize_pattern(list->pats[i], ©->pats[i]);
- if (ret)
- break;
- }
- return ret;
-}
-
int
-copy_and_canonicalize_capture_config(const struct wimlib_capture_config *config,
- struct wimlib_capture_config **config_copy_ret)
+do_read_capture_config_file(const tchar *config_file, tchar *buf, size_t buflen,
+ struct capture_config *config)
{
- struct wimlib_capture_config *config_copy;
int ret;
-
- config_copy = CALLOC(1, sizeof(struct wimlib_capture_config));
- if (!config_copy) {
- ret = WIMLIB_ERR_NOMEM;
- goto out_free_capture_config;
- }
- ret = copy_and_canonicalize_pattern_list(&config->exclusion_pats,
- &config_copy->exclusion_pats);
- if (ret)
- goto out_free_capture_config;
- ret = copy_and_canonicalize_pattern_list(&config->exclusion_exception_pats,
- &config_copy->exclusion_exception_pats);
+ struct text_file_section sections[] = {
+ {T("ExclusionList"),
+ &config->exclusion_pats},
+ {T("ExclusionException"),
+ &config->exclusion_exception_pats},
+ };
+
+ ret = do_load_text_file(config_file, buf, buflen, &buf,
+ sections, ARRAY_LEN(sections), mangle_pat);
if (ret)
- goto out_free_capture_config;
- *config_copy_ret = config_copy;
- goto out;
-out_free_capture_config:
- free_capture_config(config_copy);
-out:
- return ret;
-}
+ return ret;
-static void
-destroy_pattern_list(struct wimlib_pattern_list *list)
-{
- for (size_t i = 0; i < list->num_pats; i++)
- FREE(list->pats[i]);
- FREE(list->pats);
+ config->buf = buf;
+ return 0;
}
void
-free_capture_config(struct wimlib_capture_config *config)
+destroy_capture_config(struct capture_config *config)
{
- if (config) {
- destroy_pattern_list(&config->exclusion_pats);
- destroy_pattern_list(&config->exclusion_exception_pats);
- FREE(config);
- }
+ FREE(config->exclusion_pats.strings);
+ FREE(config->exclusion_exception_pats.strings);
+ FREE(config->buf);
}
static bool
match_pattern(const tchar *path,
const tchar *path_basename,
- const struct wimlib_pattern_list *list)
+ const struct string_set *list)
{
- for (size_t i = 0; i < list->num_pats; i++) {
+ for (size_t i = 0; i < list->num_strings; i++) {
- const tchar *pat = list->pats[i];
+ const tchar *pat = list->strings[i];
const tchar *string;
if (*pat == OS_PREFERRED_PATH_SEPARATOR) {
return false;
}
-void
-do_capture_progress(struct add_image_params *params, int status,
- const struct wim_inode *inode)
-{
- switch (status) {
- case WIMLIB_SCAN_DENTRY_OK:
- if (!(params->add_flags & WIMLIB_ADD_FLAG_VERBOSE))
- return;
- case WIMLIB_SCAN_DENTRY_UNSUPPORTED:
- case WIMLIB_SCAN_DENTRY_EXCLUDED:
- case WIMLIB_SCAN_DENTRY_EXCLUDED_SYMLINK:
- if (!(params->add_flags & WIMLIB_ADD_FLAG_EXCLUDE_VERBOSE))
- return;
- }
- params->progress.scan.status = status;
- if (status == WIMLIB_SCAN_DENTRY_OK && inode->i_nlink == 1) {
- const struct wim_lookup_table_entry *lte;
- for (unsigned i = 0; i <= inode->i_num_ads; i++) {
- lte = inode_stream_lte_resolved(inode, i);
- if (lte != NULL)
- params->progress.scan.num_bytes_scanned += lte->size;
- }
- if (inode->i_attributes & FILE_ATTRIBUTE_DIRECTORY)
- params->progress.scan.num_dirs_scanned++;
- else
- params->progress.scan.num_nondirs_scanned++;
- }
- if (params->progress_func) {
- params->progress_func(WIMLIB_PROGRESS_MSG_SCAN_DENTRY,
- ¶ms->progress);
- }
-}
-
/* Return true if the image capture configuration file indicates we should
* exclude the filename @path from capture.
*
*/
bool
exclude_path(const tchar *path, size_t path_len,
- const struct wimlib_capture_config *config, bool exclude_prefix)
+ const struct capture_config *config, bool exclude_prefix)
{
if (!config)
return false;
const tchar *basename = path_basename_with_len(path, path_len);
if (exclude_prefix) {
- wimlib_assert(path_len >= config->_prefix_num_tchars);
- if (!tmemcmp(config->_prefix, path, config->_prefix_num_tchars) &&
- path[config->_prefix_num_tchars] == OS_PREFERRED_PATH_SEPARATOR)
+ wimlib_assert(path_len >= config->prefix_num_tchars);
+ if (!tmemcmp(config->prefix, path, config->prefix_num_tchars) &&
+ path[config->prefix_num_tchars] == OS_PREFERRED_PATH_SEPARATOR)
{
- path += config->_prefix_num_tchars;
+ path += config->prefix_num_tchars;
}
}
return match_pattern(path, basename, &config->exclusion_pats) &&
# include "config.h"
#endif
-#include "wimlib/encoding.h"
-#include "wimlib/error.h"
-#include "wimlib/file_io.h"
#include "wimlib/pathlist.h"
-#include "wimlib/util.h"
-
-#include <ctype.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <string.h>
-#include <sys/stat.h>
-#include <unistd.h>
-
-static int
-read_file_contents(const tchar *path, char **buf_ret, size_t *bufsize_ret)
-{
- int raw_fd;
- struct filedes fd;
- struct stat st;
- void *buf;
- int ret;
- int errno_save;
-
- raw_fd = topen(path, O_RDONLY | O_BINARY);
- if (raw_fd < 0) {
- ERROR_WITH_ERRNO("Can't open \"%"TS"\"", path);
- return WIMLIB_ERR_OPEN;
- }
- if (fstat(raw_fd, &st)) {
- ERROR_WITH_ERRNO("Can't stat \"%"TS"\"", path);
- close(raw_fd);
- return WIMLIB_ERR_STAT;
- }
- if ((size_t)st.st_size != st.st_size ||
- (buf = MALLOC(st.st_size)) == NULL)
- {
- close(raw_fd);
- ERROR("Not enough memory to read \"%"TS"\"", path);
- return WIMLIB_ERR_NOMEM;
- }
-
- filedes_init(&fd, raw_fd);
- ret = full_read(&fd, buf, st.st_size);
- errno_save = errno;
- filedes_close(&fd);
- errno = errno_save;
- if (ret) {
- ERROR_WITH_ERRNO("Error reading \"%"TS"\"", path);
- FREE(buf);
- return ret;
- }
-
- *buf_ret = buf;
- *bufsize_ret = st.st_size;
- return 0;
-}
-
-static int
-read_utf8_file_contents(const tchar *path, tchar **buf_ret, size_t *buflen_ret)
-{
- int ret;
- char *buf_utf8;
- size_t bufsize_utf8;
- size_t offset_utf8;
- tchar *buf_tstr;
- size_t bufsize_tstr;
-
- ret = read_file_contents(path, &buf_utf8, &bufsize_utf8);
- if (ret)
- return ret;
-
- /* Ignore UTF-8 BOM. */
- if (bufsize_utf8 >= 3 && (u8)buf_utf8[0] == 0xef &&
- (u8)buf_utf8[1] == 0xbb && (u8)buf_utf8[2] == 0xbf)
- offset_utf8 = 3;
- else
- offset_utf8 = 0;
-
- ret = utf8_to_tstr(buf_utf8 + offset_utf8, bufsize_utf8 - offset_utf8,
- &buf_tstr, &bufsize_tstr);
- FREE(buf_utf8);
- if (ret)
- return ret;
-
- *buf_ret = buf_tstr;
- *buflen_ret = bufsize_tstr / sizeof(tchar);
- return 0;
-}
-
-static int
-parse_path_list_file(tchar *buf, size_t buflen,
- tchar ***paths_ret, size_t *num_paths_ret)
-{
- tchar **paths = NULL;
- size_t num_paths = 0;
- size_t num_alloc_paths = 0;
- tchar *nl;
- tchar *p;
-
- for (p = buf; p != buf + buflen; p = nl + 1) {
- tchar *line_begin, *line_end;
- size_t line_len;
-
- nl = tmemchr(p, T('\n'), buf + buflen - p);
- if (nl == NULL)
- break;
-
- line_begin = p;
- line_end = nl;
-
- /* Ignore leading whitespace. */
- while (line_begin < nl && istspace(*line_begin))
- line_begin++;
-
- /* Ignore trailing whitespace. */
- while (line_end > line_begin && istspace(*(line_end - 1)))
- line_end--;
-
- line_len = line_end - line_begin;
-
- /* Ignore comments and empty lines. */
- if (line_len == 0 || *line_begin == T(';'))
- continue;
-
- if (num_paths == num_alloc_paths) {
- tchar **new_paths;
- size_t new_num_alloc_paths = max(num_alloc_paths + 8,
- num_alloc_paths * 3 / 2);
-
- new_paths = REALLOC(paths, new_num_alloc_paths *
- sizeof(paths[0]));
- if (new_paths == NULL)
- goto oom;
- paths = new_paths;
- num_alloc_paths = new_num_alloc_paths;
- }
-
- *line_end = T('\0');
- paths[num_paths++] = line_begin;
- }
-
- *paths_ret = paths;
- *num_paths_ret = num_paths;
- return 0;
-
-oom:
- FREE(paths);
- return WIMLIB_ERR_NOMEM;
-}
+#include "wimlib/textfile.h"
int
read_path_list_file(const tchar *listfile,
tchar ***paths_ret, size_t *num_paths_ret,
void **mem_ret)
{
- int ret;
+ STRING_SET(paths);
+ struct text_file_section tmp = {
+ .name = T(""),
+ .strings = &paths,
+ };
tchar *buf;
- size_t buflen;
+ int ret;
- ret = read_utf8_file_contents(listfile, &buf, &buflen);
+ ret = load_text_file(listfile, &buf, &tmp, 1, NULL);
if (ret)
return ret;
- buf[buflen++] = T('\n');
-
- ret = parse_path_list_file(buf, buflen, paths_ret, num_paths_ret);
- if (ret) {
- FREE(buf);
- return ret;
- }
- *mem_ret = buf;
+ *paths_ret = paths.strings;
+ *num_paths_ret = paths.num_strings;
+ *mem_ret = (void *)buf;
return 0;
}
--- /dev/null
+/*
+ * textfile.c
+ */
+
+/*
+ * Copyright (C) 2014 Eric Biggers
+ *
+ * This file is part of wimlib, a library for working with WIM files.
+ *
+ * wimlib is free software; you can redistribute it and/or modify it under the
+ * terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 3 of the License, or (at your option)
+ * any later version.
+ *
+ * wimlib is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ * A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with wimlib; if not, see http://www.gnu.org/licenses/.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include "wimlib/assert.h"
+#include "wimlib/encoding.h"
+#include "wimlib/error.h"
+#include "wimlib/file_io.h"
+#include "wimlib/textfile.h"
+#include "wimlib/util.h"
+
+#include <ctype.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <unistd.h>
+
+static int
+read_file_contents(const tchar *path, u8 **buf_ret, size_t *bufsize_ret)
+{
+ int raw_fd;
+ struct filedes fd;
+ struct stat st;
+ u8 *buf;
+ int ret;
+ int errno_save;
+
+ if (!path || !*path)
+ return WIMLIB_ERR_INVALID_PARAM;
+
+ raw_fd = topen(path, O_RDONLY | O_BINARY);
+ if (raw_fd < 0) {
+ ERROR_WITH_ERRNO("Can't open \"%"TS"\"", path);
+ return WIMLIB_ERR_OPEN;
+ }
+ if (fstat(raw_fd, &st)) {
+ ERROR_WITH_ERRNO("Can't stat \"%"TS"\"", path);
+ close(raw_fd);
+ return WIMLIB_ERR_STAT;
+ }
+ if ((size_t)st.st_size != st.st_size ||
+ (buf = MALLOC(st.st_size)) == NULL)
+ {
+ close(raw_fd);
+ ERROR("Not enough memory to read \"%"TS"\"", path);
+ return WIMLIB_ERR_NOMEM;
+ }
+
+ filedes_init(&fd, raw_fd);
+ ret = full_read(&fd, buf, st.st_size);
+ errno_save = errno;
+ filedes_close(&fd);
+ errno = errno_save;
+ if (ret) {
+ ERROR_WITH_ERRNO("Error reading \"%"TS"\"", path);
+ FREE(buf);
+ return ret;
+ }
+
+ *buf_ret = buf;
+ *bufsize_ret = st.st_size;
+ return 0;
+}
+
+static int
+read_text_file_contents(const tchar *path,
+ tchar **buf_ret, size_t *buflen_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;
+
+ /* Guess the encoding: UTF-8 or UTF-16LE. (Something weirder and you're
+ * out of luck, sorry...) */
+ if (bufsize_raw >= 2 &&
+ buf_raw[0] == 0xFF &&
+ buf_raw[1] == 0xFE)
+ {
+ utf8 = false;
+ offset_raw = 2;
+ }
+ else if (bufsize_raw >= 2 &&
+ buf_raw[0] <= 0x7F &&
+ buf_raw[1] == 0x00)
+ {
+ utf8 = false;
+ offset_raw = 0;
+ }
+ else if (bufsize_raw >= 3 &&
+ buf_raw[0] == 0xEF &&
+ buf_raw[1] == 0xBB &&
+ buf_raw[2] == 0xBF)
+ {
+ utf8 = true;
+ offset_raw = 3;
+ }
+ else
+ {
+ utf8 = true;
+ offset_raw = 0;
+ }
+
+ if (utf8) {
+ ret = utf8_to_tstr((const char *)(buf_raw + offset_raw),
+ bufsize_raw - offset_raw,
+ &buf_tstr, &bufsize_tstr);
+ } else {
+ #if TCHAR_IS_UTF16LE
+ bufsize_tstr = bufsize_raw - offset_raw;
+ buf_tstr = MALLOC(bufsize_tstr + 2);
+ if (buf_tstr) {
+ memcpy(buf_tstr, buf_raw + offset_raw, bufsize_tstr);
+ ((u8*)buf_tstr)[bufsize_tstr + 0] = 0;
+ ((u8*)buf_tstr)[bufsize_tstr + 1] = 0;
+ } else {
+ ret = WIMLIB_ERR_NOMEM;
+ }
+ #else
+ ret = utf16le_to_tstr((const utf16lechar *)(buf_raw + offset_raw),
+ bufsize_raw - offset_raw,
+ &buf_tstr, &bufsize_tstr);
+ #endif
+ }
+ FREE(buf_raw);
+ if (ret)
+ return ret;
+
+ *buf_ret = buf_tstr;
+ *buflen_ret = bufsize_tstr / sizeof(tchar);
+ return 0;
+}
+
+static int
+string_set_append(struct string_set *set, tchar *str)
+{
+ size_t num_alloc_strings = set->num_alloc_strings;
+
+ if (set->num_strings == num_alloc_strings) {
+ tchar **new_strings;
+
+ num_alloc_strings = max(num_alloc_strings * 3 / 2,
+ num_alloc_strings + 4);
+ new_strings = REALLOC(set->strings,
+ sizeof(set->strings[0]) * num_alloc_strings);
+ if (!new_strings)
+ return WIMLIB_ERR_NOMEM;
+ set->strings = new_strings;
+ set->num_alloc_strings = num_alloc_strings;
+ }
+ set->strings[set->num_strings++] = str;
+ return 0;
+}
+
+#define NOT_IN_SECTION -1
+#define IN_UNKNOWN_SECTION -2
+
+static int
+parse_text_file(const tchar *path, tchar *buf, size_t buflen,
+ const struct text_file_section *pos_sections,
+ int num_pos_sections, line_mangle_t mangle_line)
+{
+ int current_section = NOT_IN_SECTION;
+ bool have_named_sections = false;
+ tchar *p;
+ tchar *nl;
+ unsigned long line_no = 1;
+
+ for (int i = 0; i < num_pos_sections; i++) {
+ if (*pos_sections[i].name)
+ have_named_sections = true;
+ else
+ current_section = i;
+ }
+
+ for (p = buf; p != buf + buflen; p = nl + 1, line_no++) {
+ tchar *line_begin, *line_end;
+ size_t line_len;
+ int ret;
+
+ nl = tmemchr(p, T('\n'), buf + buflen - p);
+ if (!nl)
+ break;
+
+ line_begin = p;
+ line_end = nl;
+
+ /* Ignore leading whitespace. */
+ while (line_begin < nl && istspace(*line_begin))
+ line_begin++;
+
+ /* Ignore trailing whitespace. */
+ while (line_end > line_begin && istspace(*(line_end - 1)))
+ line_end--;
+
+ line_len = line_end - line_begin;
+
+ /* Ignore comments and empty lines. */
+ if (line_len == 0 || *line_begin == T(';') || *line_begin == T('#'))
+ continue;
+
+ line_begin[line_len] = T('\0');
+
+ /* Check for beginning of new section. */
+ if (line_begin[0] == T('[') &&
+ line_begin[line_len - 1] == T(']') &&
+ have_named_sections)
+ {
+ line_begin[line_len - 1] = T('\0');
+ current_section = IN_UNKNOWN_SECTION;
+ for (int i = 0; i < num_pos_sections; i++) {
+ if (!tstrcmp(line_begin + 1,
+ pos_sections[i].name))
+ {
+ current_section = i;
+ break;
+ }
+ }
+ line_begin[line_len - 1] = T(']');
+ if (current_section < 0)
+ 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);
+ continue;
+ }
+
+ if (mangle_line) {
+ ret = (*mangle_line)(line_begin, path, line_no);
+ if (ret)
+ return ret;
+ }
+
+ ret = string_set_append(pos_sections[current_section].strings,
+ line_begin);
+ if (ret)
+ return ret;
+ }
+ return 0;
+}
+
+/**
+ * do_load_text_file -
+ *
+ * Read and parse lines from a text file from an on-disk file or a buffer.
+ * The file may contain sections, like in an INI file.
+ *
+ * @path
+ * Path to the file on disk to read, or a dummy name for the buffer.
+ * @buf
+ * 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.
+ * @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
+ * an allocated buffer that must be freed when finished with the lines.
+ * @pos_sections
+ * Specifications of allowed sections in the file. Each such specification
+ * consists of the name of the section (e.g. [ExclusionList], like in the
+ * INI file format), along with a pointer to the list of lines parsed for
+ * that section. Use an empty name to indicate the destination of lines
+ * not in any section.
+ * @num_pos_sections
+ * Length of @pos_sections array.
+ * @mangle_line
+ * Optional callback to modify each line being read.
+ *
+ * Returns 0 on success or a positive error code on failure.
+ *
+ * Unknown sections are ignored (warning printed).
+ */
+int
+do_load_text_file(const tchar *path,
+ tchar *buf, size_t buflen,
+ tchar **buf_ret,
+ const struct text_file_section *pos_sections,
+ int num_pos_sections,
+ line_mangle_t mangle_line)
+{
+ int ret;
+ bool pathmode = (buf == NULL);
+
+ if (pathmode) {
+ ret = read_text_file_contents(path, &buf, &buflen);
+ 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,
+ num_pos_sections, mangle_line);
+ if (ret) {
+ for (int i = 0; i < num_pos_sections; i++)
+ FREE(pos_sections[i].strings->strings);
+ if (pathmode)
+ FREE(buf);
+ return ret;
+ }
+
+ *buf_ret = buf;
+ return 0;
+}
*/
/*
- * Copyright (C) 2013 Eric Biggers
+ * Copyright (C) 2013, 2014 Eric Biggers
*
* This file is part of wimlib, a library for working with WIM files.
*
#include "wimlib/xml.h"
#include <errno.h>
+#include <sys/stat.h>
/* Overlays @branch onto @target, both of which must be directories. */
static int
}
}
+const tchar wincfg[] =
+T(
+"[ExclusionList]\n"
+"/$ntfs.log\n"
+"/hiberfil.sys\n"
+"/pagefile.sys\n"
+"/System Volume Information\n"
+"/RECYCLER\n"
+"/Windows/CSC\n"
+);
+
+static int
+get_capture_config(const tchar *config_file, struct capture_config *config,
+ int add_flags, const tchar *fs_source_path)
+{
+ int ret;
+ tchar *tmp_config_file = NULL;
+
+ memset(config, 0, sizeof(*config));
+
+ /* For WIMBoot capture, check for default capture configuration file
+ * unless one was explicitly specified. */
+ if (!config_file && (add_flags & WIMLIB_ADD_FLAG_WIMBOOT)) {
+
+ /* XXX: Handle loading file correctly when in NTFS volume. */
+
+ const tchar *wimboot_cfgfile =
+ T("/Windows/System32/WimBootCompress.ini");
+ size_t len = tstrlen(fs_source_path) +
+ tstrlen(wimboot_cfgfile);
+ tmp_config_file = MALLOC((len + 1) * sizeof(tchar));
+ struct stat st;
+
+ tsprintf(tmp_config_file, T("%"TS"%"TS),
+ fs_source_path, wimboot_cfgfile);
+ if (!tstat(tmp_config_file, &st)) {
+ config_file = tmp_config_file;
+ add_flags &= ~WIMLIB_ADD_FLAG_WINCONFIG;
+ } else {
+ WARNING("\"%"TS"\" does not exist.\n"
+ " Using default capture configuration!",
+ tmp_config_file);
+ }
+ }
+
+ 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);
+ } else if (config_file) {
+ /* Use the specified configuration file. */
+ ret = do_read_capture_config_file(config_file, NULL, 0, config);
+ } else {
+ /* ... Or don't use any configuration file at all. No files
+ * will be excluded from capture, all files will be compressed,
+ * etc. */
+ ret = 0;
+ }
+ FREE(tmp_config_file);
+ return ret;
+}
+
static int
execute_add_command(WIMStruct *wim,
const struct wimlib_update_command *add_cmd,
int (*capture_tree)(struct wim_dentry **,
const tchar *,
struct add_image_params *);
- struct wimlib_capture_config *config;
+ const tchar *config_file;
+ struct capture_config config;
#ifdef WITH_NTFS_3G
struct _ntfs_volume *ntfs_vol = NULL;
#endif
add_flags = add_cmd->add.add_flags;
fs_source_path = add_cmd->add.fs_source_path;
wim_target_path = add_cmd->add.wim_target_path;
- config = add_cmd->add.config;
+ config_file = add_cmd->add.config_file;
+
DEBUG("fs_source_path=\"%"TS"\", wim_target_path=\"%"TS"\", add_flags=%#x",
fs_source_path, wim_target_path, add_flags);
extra_arg = NULL;
}
+ ret = get_capture_config(config_file, &config,
+ add_flags, fs_source_path);
+ if (ret)
+ goto out;
ret = init_inode_table(¶ms.inode_table, 9001);
if (ret)
- goto out;
+ goto out_destroy_config;
ret = init_sd_set(¶ms.sd_set, imd->security_data);
if (ret)
INIT_LIST_HEAD(&unhashed_streams);
params.lookup_table = wim->lookup_table;
params.unhashed_streams = &unhashed_streams;
- params.config = config;
+ params.config = &config;
params.add_flags = add_flags;
params.extra_arg = extra_arg;
params.progress.scan.wim_target_path = wim_target_path;
if (progress_func)
progress_func(WIMLIB_PROGRESS_MSG_SCAN_BEGIN, ¶ms.progress);
- if (config) {
- config->_prefix = fs_source_path;
- config->_prefix_num_tchars = tstrlen(fs_source_path);
- }
+
+ config.prefix = fs_source_path;
+ config.prefix_num_tchars = tstrlen(fs_source_path);
if (wim_target_path[0] == T('\0'))
params.add_flags |= WIMLIB_ADD_FLAG_ROOT;
destroy_sd_set(¶ms.sd_set, rollback_sd);
out_destroy_inode_table:
destroy_inode_table(¶ms.inode_table);
+out_destroy_config:
+ destroy_capture_config(&config);
out:
return ret;
}
}
-tchar *winpats[] = {
- T("/$ntfs.log"),
- T("/hiberfil.sys"),
- T("/pagefile.sys"),
- T("/System Volume Information"),
- T("/RECYCLER"),
- T("/Windows/CSC"),
-};
-
-static const struct wimlib_capture_config winconfig = {
- .exclusion_pats = {
- .num_pats = ARRAY_LEN(winpats),
- .pats = winpats,
- },
-};
-
static int
check_add_command(struct wimlib_update_command *cmd,
const struct wim_header *hdr)
if (add_flags & ~(WIMLIB_ADD_FLAG_NTFS |
WIMLIB_ADD_FLAG_DEREFERENCE |
WIMLIB_ADD_FLAG_VERBOSE |
- /* BOOT doesn't make sense for wimlib_update_image().
- * Same with WIMBOOT. */
+ /* BOOT doesn't make sense for wimlib_update_image(). */
/*WIMLIB_ADD_FLAG_BOOT |*/
- /*WIMLIB_ADD_FLAG_WIMBOOT |*/
+ WIMLIB_ADD_FLAG_WIMBOOT |
WIMLIB_ADD_FLAG_UNIX_DATA |
WIMLIB_ADD_FLAG_NO_ACLS |
WIMLIB_ADD_FLAG_STRICT_ACLS |
case WIMLIB_UPDATE_OP_ADD:
FREE(cmds[i].add.fs_source_path);
FREE(cmds[i].add.wim_target_path);
- free_capture_config(cmds[i].add.config);
+ FREE(cmds[i].add.config_file);
break;
case WIMLIB_UPDATE_OP_DELETE:
FREE(cmds[i].delete_.wim_path);
{
int ret;
struct wimlib_update_command *cmds_copy;
- const struct wimlib_capture_config *config;
cmds_copy = CALLOC(num_cmds, sizeof(cmds[0]));
if (!cmds_copy)
if (!cmds_copy[i].add.fs_source_path ||
!cmds_copy[i].add.wim_target_path)
goto oom;
- config = cmds[i].add.config;
- if (cmds[i].add.add_flags & WIMLIB_ADD_FLAG_WINCONFIG)
- config = &winconfig;
- if (config) {
- ret = copy_and_canonicalize_capture_config(config,
- &cmds_copy[i].add.config);
- if (ret)
- goto err;
+ if (cmds[i].add.config_file) {
+ cmds_copy[i].add.config_file = TSTRDUP(cmds[i].add.config_file);
+ if (!cmds_copy[i].add.config_file)
+ goto oom;
}
cmds_copy[i].add.add_flags = cmds[i].add.add_flags;
break;
* along with wimlib; if not, see http://www.gnu.org/licenses/.
*/
-#ifndef __WIN32__
-# error "This file contains Windows code!"
-#endif
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
+#ifdef __WIN32__
+
#include "wimlib/win32_common.h"
#include "wimlib/win32.h"
#include "wimlib/assert.h"
out:
return ret;
}
+
+#endif /* __WIN32__ */
/* Update pattern prefix. */
if (params->config != NULL)
{
- params->config->_prefix = TSTRDUP(path);
- params->config->_prefix_num_tchars = path_nchars;
- if (params->config->_prefix == NULL)
+ params->config->prefix = TSTRDUP(path);
+ params->config->prefix_num_tchars = path_nchars;
+ if (params->config->prefix == NULL)
{
ret = WIMLIB_ERR_NOMEM;
goto out_free_path;
path_nchars, params,
&state, vol_flags);
if (params->config != NULL)
- FREE(params->config->_prefix);
+ FREE(params->config->prefix);
out_free_path:
FREE(path);
if (ret == 0)