]> wimlib.net Git - wimlib/blobdiff - src/capture_common.c
Parse capture configuration file in library
[wimlib] / src / capture_common.c
index ef4fa5d63f1d1bd52ba47930dccf0987b19a18c1..d955c368c88eadfad151f98a6543d2c259ddec77 100644 (file)
@@ -1,3 +1,7 @@
+/*
+ * capture_common.c - Mostly code to handle excluding paths from capture.
+ */
+
 /*
  * Copyright (C) 2013 Eric Biggers
  *
  * along with wimlib; if not, see http://www.gnu.org/licenses/.
  */
 
-#include "wimlib_internal.h"
+#ifdef HAVE_CONFIG_H
+#  include "config.h"
+#endif
+
+#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"
 
 #include <string.h>
 
-#ifdef __WIN32__
-#  include "win32.h"
-#else
-#  include <fnmatch.h>
-#endif
+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,
+                                     &params->progress);
+       }
+}
 
 static int
-canonicalize_pat(tchar **pat_p)
+mangle_pat(tchar *pat, const tchar *path, unsigned long line_no)
 {
-       tchar *pat = *pat_p;
-
-       /* Turn all backslashes in the pattern into forward slashes. */
-       zap_backslashes(pat);
-
-       if (*pat != T('/') && *pat != T('\0') && *(pat + 1) == T(':')) {
+       if (!is_any_path_separator(pat[0]) &&
+           pat[0] != T('\0') && pat[1] == T(':'))
+       {
                /* Pattern begins with drive letter */
-               if (*(pat + 2) != T('/')) {
+               if (!is_any_path_separator(pat[2])) {
                        /* Something like c:file, which is actually a path
                         * 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, 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;
-               *pat_p = pat;
-       }
-       return 0;
-}
+               WARNING("%"TS":%lu: Pattern \"%"TS"\" starts with a drive "
+                       "letter, which is being removed.",
+                       path, line_no, pat);
 
-static int
-canonicalize_pat_list(struct wimlib_pattern_list *pat_list)
-{
-       int ret = 0;
-       for (size_t i = 0; i < pat_list->num_pats; i++) {
-               ret = canonicalize_pat(&pat_list->pats[i]);
-               if (ret)
-                       break;
+               /* Strip the drive letter.  */
+               tmemmove(pat, pat + 2, tstrlen(pat + 2) + 1);
        }
-       return ret;
+
+       /* Translate all possible path separators into the operating system's
+        * preferred path separator.  */
+       for (tchar *p = pat; *p; p++)
+               if (is_any_path_separator(*p))
+                       *p = OS_PREFERRED_PATH_SEPARATOR;
+       return 0;
 }
 
 int
-canonicalize_capture_config(struct wimlib_capture_config *config)
+do_read_capture_config_file(const tchar *config_file, tchar *buf, size_t buflen,
+                           struct capture_config *config)
 {
-       int ret = canonicalize_pat_list(&config->exclusion_pats);
+       int ret;
+       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)
                return ret;
-       return canonicalize_pat_list(&config->exclusion_exception_pats);
-}
-
-static bool
-copy_pattern_list(struct wimlib_pattern_list *copy,
-                 const struct wimlib_pattern_list *list)
-{
-       copy->pats = CALLOC(list->num_pats, sizeof(list->pats[0]));
-       if (!copy->pats)
-               return false;
-       copy->num_pats = list->num_pats;
-       for (size_t i = 0; i < list->num_pats; i++) {
-               copy->pats[i] = TSTRDUP(list->pats[i]);
-               if (!copy->pats[i])
-                       return false;
-       }
-       return true;
-}
 
-struct wimlib_capture_config *
-copy_capture_config(const struct wimlib_capture_config *config)
-{
-       struct wimlib_capture_config *copy;
-
-       copy = CALLOC(1, sizeof(struct wimlib_capture_config));
-       if (!copy)
-               goto oom;
-       if (!copy_pattern_list(&copy->exclusion_pats, &config->exclusion_pats))
-               goto oom;
-       if (!copy_pattern_list(&copy->exclusion_exception_pats,
-                              &config->exclusion_exception_pats))
-               goto oom;
-       goto out;
-oom:
-       free_capture_config(copy);
-       copy = NULL;
-out:
-       return copy;
-}
-
-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 == T('/')) {
+               if (*pat == OS_PREFERRED_PATH_SEPARATOR) {
                        /* Absolute path from root of capture */
                        string = path;
                } else {
-                       if (tstrchr(pat, T('/')))
+                       if (tstrchr(pat, OS_PREFERRED_PATH_SEPARATOR))
                                /* Relative path from root of capture */
                                string = path + 1;
                        else
@@ -160,16 +159,13 @@ match_pattern(const tchar *path,
                 * replacement function in win32.c. */
                if (fnmatch(pat, string, FNM_PATHNAME | FNM_NOESCAPE
                                #ifdef FNM_CASEFOLD
-                                       | FNM_CASEFOLD
+                                       | FNM_CASEFOLD
                                #endif
                            ) == 0)
                {
                        DEBUG("\"%"TS"\" matches the pattern \"%"TS"\"",
                              string, pat);
                        return true;
-               } else {
-                       DEBUG2("\"%"TS"\" does not match the pattern \"%"TS"\"",
-                              string, pat);
                }
        }
        return false;
@@ -186,15 +182,17 @@ match_pattern(const tchar *path,
  */
 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] == T('/'))
+               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) &&