#include "wimlib/assert.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/wildcard.h"
-#ifdef __WIN32__
-# include "wimlib/win32.h" /* for fnmatch() equivalent */
-#else
-# include <fnmatch.h>
-#endif
#include <string.h>
+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);
+ }
+}
static int
-canonicalize_pattern(const tchar *pat, tchar **canonical_pat_ret)
+mangle_pat(tchar *pat, const tchar *path, unsigned long line_no)
{
- tchar *canonical_pat;
+ /* Remove quotes */
+ if (pat[0] == T('"') || pat[0] == T('\'')) {
+ tchar quote = pat[0];
+ tchar *last = pat + tstrlen(pat) - 1;
+ if (last > pat && *last == quote) {
+ tmemmove(pat, pat + 1, last - (pat + 1));
+ *(last - 1) = T('\0');
+ }
+ }
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) {
DEBUG("\"%"TS"\" matches the pattern \"%"TS"\"",
string, pat);
return true;
- } else {
- DEBUG2("\"%"TS"\" does not match the pattern \"%"TS"\"",
- string, pat);
}
}
return false;
}
-void
-do_capture_progress(struct add_image_params *params, int status)
-{
- 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:
- if (!(params->add_flags & WIMLIB_ADD_FLAG_EXCLUDE_VERBOSE))
- return;
- }
- params->progress.scan.status = status;
- 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) &&