int open_flags = 0;
int write_flags = WIMLIB_WRITE_FLAG_SOFT_DELETE;
int update_flags = 0;
- int default_add_flags = 0;
+ int default_add_flags = WIMLIB_ADD_IMAGE_FLAG_EXCLUDE_VERBOSE;
int default_delete_flags = 0;
unsigned num_threads = 0;
int c;
#endif
static int
-canonicalize_pat(tchar **pat_p)
+canonicalize_pattern(const tchar *pat, tchar **canonical_pat_ret)
{
- tchar *pat = *pat_p;
+ tchar *canonical_pat;
- /* Turn all backslashes in the pattern into forward slashes. */
- zap_backslashes(pat);
-
- if (*pat != T('/') && *pat != T('\0') && *(pat + 1) == T(':')) {
+ if (pat[0] != T('/') && pat[0] != T('\\') &&
+ pat[0] != T('\0') && pat[1] == T(':'))
+ {
/* Pattern begins with drive letter */
- if (*(pat + 2) != T('/')) {
+ if (pat[2] != T('/') && pat[2] != T('\\')) {
/* 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
ERROR("Invalid path \"%"TS"\"; paths including drive letters "
"must be absolute!", pat);
ERROR("Maybe try \"%"TC":/%"TS"\"?",
- *pat, pat + 2);
+ pat[0], pat + 2);
return WIMLIB_ERR_INVALID_CAPTURE_CONFIG;
}
"being removed.", pat);
/* Strip the drive letter */
pat += 2;
- *pat_p = pat;
}
+ canonical_pat = canonicalize_fs_path(pat);
+ if (!canonical_pat)
+ return WIMLIB_ERR_NOMEM;
+ *canonical_pat_ret = canonical_pat;
return 0;
}
static int
-canonicalize_pat_list(struct wimlib_pattern_list *pat_list)
+copy_and_canonicalize_pattern_list(const struct wimlib_pattern_list *list,
+ struct wimlib_pattern_list *copy)
{
int ret = 0;
- for (size_t i = 0; i < pat_list->num_pats; i++) {
- ret = canonicalize_pat(&pat_list->pats[i]);
+
+ 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;
}
}
int
-canonicalize_capture_config(struct wimlib_capture_config *config)
+copy_and_canonicalize_capture_config(const struct wimlib_capture_config *config,
+ struct wimlib_capture_config **config_copy_ret)
{
- int ret = canonicalize_pat_list(&config->exclusion_pats);
- if (ret)
- return ret;
- return canonicalize_pat_list(&config->exclusion_exception_pats);
-}
+ struct wimlib_capture_config *config_copy;
+ int ret;
-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;
+ config_copy = CALLOC(1, sizeof(struct wimlib_capture_config));
+ if (!config_copy) {
+ ret = WIMLIB_ERR_NOMEM;
+ goto out_free_capture_config;
}
- 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(©->exclusion_pats, &config->exclusion_pats))
- goto oom;
- if (!copy_pattern_list(©->exclusion_exception_pats,
- &config->exclusion_exception_pats))
- goto oom;
+ 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);
+ if (ret)
+ goto out_free_capture_config;
+ *config_copy_ret = config_copy;
goto out;
-oom:
- free_capture_config(copy);
- copy = NULL;
+out_free_capture_config:
+ free_capture_config(config_copy);
out:
- return copy;
+ return ret;
}
static void
const struct wim_header *hdr)
{
int add_flags = cmd->add.add_flags;
+
+ /* Are we adding the entire image or not? An empty wim_target_path
+ * indicates that the tree we're adding is to be placed in the root of
+ * the image. We consider this to be capturing the entire image,
+ * although it could potentially be an overlay on an existing root as
+ * well. */
bool is_entire_image = cmd->add.wim_target_path[0] == T('\0');
- int ret;
+
#ifdef __WIN32__
+ /* Check for flags not supported on Windows */
if (add_flags & WIMLIB_ADD_IMAGE_FLAG_NTFS) {
ERROR("wimlib was compiled without support for NTFS-3g, so");
ERROR("we cannot capture a WIM image directly from a NTFS volume");
}
#endif
+ /* VERBOSE implies EXCLUDE_VERBOSE */
if (add_flags & WIMLIB_ADD_IMAGE_FLAG_VERBOSE)
add_flags |= WIMLIB_ADD_IMAGE_FLAG_EXCLUDE_VERBOSE;
+ /* Check for contradictory reparse point fixup flags */
if ((add_flags & (WIMLIB_ADD_IMAGE_FLAG_RPFIX |
WIMLIB_ADD_IMAGE_FLAG_NORPFIX)) ==
(WIMLIB_ADD_IMAGE_FLAG_RPFIX |
return WIMLIB_ERR_INVALID_PARAM;
}
+ /* Set default behavior on reparse point fixups if requested */
if ((add_flags & (WIMLIB_ADD_IMAGE_FLAG_RPFIX |
WIMLIB_ADD_IMAGE_FLAG_NORPFIX)) == 0)
{
return WIMLIB_ERR_INVALID_PARAM;
}
}
- ret = canonicalize_capture_config(cmd->add.config);
- if (ret)
- return ret;
cmd->add.add_flags = add_flags;
return 0;
}
!cmds_copy[i].add.wim_target_path)
goto oom;
if (cmds[i].add.config) {
- cmds_copy[i].add.config =
- copy_capture_config(cmds[i].add.config);
- if (!cmds_copy[i].add.config)
- goto oom;
+ ret = copy_and_canonicalize_capture_config(cmds[i].add.config,
+ &cmds_copy[i].add.config);
+ if (ret)
+ goto err;
}
cmds_copy[i].add.add_flags = cmds[i].add.add_flags;
break;
goto out;
}
+/*
+ * Entry point for making a series of updates to a WIM image.
+ */
WIMLIBAPI int
wimlib_update_image(WIMStruct *wim,
int image,
DEBUG("Updating image %d with %zu commands", image, num_cmds);
+ /* Refuse to update a split WIM. */
if (wim->hdr.total_parts != 1) {
ERROR("Cannot update a split WIM!");
ret = WIMLIB_ERR_SPLIT_UNSUPPORTED;
goto out;
}
+ /* Load the metadata for the image to modify (if not loaded already) */
ret = select_wim_image(wim, image);
if (ret)
goto out;
- DEBUG("Selected image %d for update", image);
-
+ /* Short circuit a successful return if no commands were specified.
+ * Avoids problems with trying to allocate 0 bytes of memory. */
if (num_cmds == 0)
goto out;
DEBUG("Preparing %zu update commands", num_cmds);
+ /* Make a copy of the update commands, in the process doing certain
+ * canonicalizations on paths (e.g. translating backslashes to forward
+ * slashes). This is done to avoid modifying the caller's copy of the
+ * commands. */
ret = copy_update_commands(cmds, num_cmds, &cmds_copy);
if (ret)
goto out;
+ /* Perform additional checks on the update commands before we execute
+ * them. */
ret = check_update_commands(cmds_copy, num_cmds, &wim->hdr);
if (ret)
goto out_free_cmds_copy;
+ /* Actually execute the update commands. */
DEBUG("Executing %zu update commands", num_cmds);
-
ret = execute_update_commands(wim, cmds_copy, num_cmds, progress_func);
if (ret)
goto out_free_cmds_copy;
+
+ /* Statistics about the WIM image, such as the numbers of files and
+ * directories, may have changed. Call xml_update_image_info() to
+ * recalculate these statistics. */
xml_update_image_info(wim, wim->current_image);
out_free_cmds_copy:
free_update_commands(cmds_copy, num_cmds);
int unmount_flags,
wimlib_progress_func_t progress_func);
-/** XXX */
+/**
+ * Update a WIM image by adding, deleting, and/or renaming files or directories.
+ *
+ * @param wim
+ * Pointer to the ::WIMStruct for the WIM file to update.
+ * @param image
+ * The 1-based index of the image in the WIM to update. It cannot be
+ * ::WIMLIB_ALL_IMAGES.
+ * @param cmds
+ * An array of ::wimlib_update_command's that specify the update operations
+ * to perform.
+ * @param num_cmds
+ * Number of commands in @a cmds.
+ * @param update_flags
+ * Reserved; must be 0.
+ * @param progress_func
+ * If non-NULL, a function that will be called periodically with the
+ * progress of the current operation.
+ *
+ * @return 0 on success; nonzero on error. There are many possible error codes
+ * (TODO: document them.)
+ */
extern int
wimlib_update_image(WIMStruct *wim,
int image,
copy_capture_config(const struct wimlib_capture_config *config);
extern int
-canonicalize_capture_config(struct wimlib_capture_config *config);
+copy_and_canonicalize_capture_config(const struct wimlib_capture_config *config,
+ struct wimlib_capture_config **config_copy_ret);
extern void
free_capture_config(struct wimlib_capture_config *config);