X-Git-Url: https://wimlib.net/git/?a=blobdiff_plain;f=src%2Fupdate_image.c;h=8f981ec640def7e1095246b1be3b9e763703f1e3;hb=5944d11442d5df847c3393951a8563412d16e640;hp=763f4dc410948e95251537cf6c8cf6705980df3d;hpb=01c6f902b2a48a33af3f94e29791f85c68df91d0;p=wimlib diff --git a/src/update_image.c b/src/update_image.c index 763f4dc4..8f981ec6 100644 --- a/src/update_image.c +++ b/src/update_image.c @@ -180,7 +180,6 @@ execute_add_command(WIMStruct *wim, int (*capture_tree)(struct wim_dentry **, const tchar *, struct add_image_params *); - union wimlib_progress_info progress; struct wimlib_capture_config *config; #ifdef WITH_NTFS_3G struct _ntfs_volume *ntfs_vol = NULL; @@ -190,6 +189,7 @@ execute_add_command(WIMStruct *wim, bool rollback_sd = true; wimlib_assert(add_cmd->op == WIMLIB_UPDATE_OP_ADD); + 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; @@ -197,6 +197,8 @@ execute_add_command(WIMStruct *wim, DEBUG("fs_source_path=\"%"TS"\", wim_target_path=\"%"TS"\", add_flags=%#x", fs_source_path, wim_target_path, add_flags); + memset(¶ms, 0, sizeof(params)); + imd = wim->image_metadata[wim->current_image - 1]; if (add_flags & WIMLIB_ADD_FLAG_NTFS) { @@ -221,6 +223,7 @@ execute_add_command(WIMStruct *wim, extra_arg = NULL; } + ret = init_inode_table(¶ms.inode_table, 9001); if (ret) goto out; @@ -234,15 +237,13 @@ execute_add_command(WIMStruct *wim, params.lookup_table = wim->lookup_table; params.config = config; params.add_flags = add_flags; - params.progress_func = progress_func; params.extra_arg = extra_arg; - if (progress_func) { - memset(&progress, 0, sizeof(progress)); - progress.scan.source = fs_source_path; - progress.scan.wim_target_path = wim_target_path; - progress_func(WIMLIB_PROGRESS_MSG_SCAN_BEGIN, &progress); - } + params.progress_func = progress_func; + params.progress.scan.source = fs_source_path; + 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); @@ -251,11 +252,9 @@ execute_add_command(WIMStruct *wim, if (wim_target_path[0] == T('\0')) params.add_flags |= WIMLIB_ADD_FLAG_ROOT; ret = (*capture_tree)(&branch, fs_source_path, ¶ms); - if (ret) { - ERROR("Failed to build dentry tree for \"%"TS"\"", - fs_source_path); + if (ret) goto out_destroy_sd_set; - } + if (branch) { /* Use the target name, not the source name, for * the root of each branch from a capture @@ -271,7 +270,7 @@ execute_add_command(WIMStruct *wim, goto out_ntfs_umount; } if (progress_func) - progress_func(WIMLIB_PROGRESS_MSG_SCAN_END, &progress); + progress_func(WIMLIB_PROGRESS_MSG_SCAN_END, ¶ms.progress); list_splice_tail(&unhashed_streams, &imd->unhashed_streams); #ifdef WITH_NTFS_3G imd->ntfs_vol = ntfs_vol; @@ -306,8 +305,8 @@ execute_delete_command(WIMStruct *wim, bool is_root; wimlib_assert(delete_cmd->op == WIMLIB_UPDATE_OP_DELETE); - flags = delete_cmd->delete.delete_flags; - wim_path = delete_cmd->delete.wim_path; + flags = delete_cmd->delete_.delete_flags; + wim_path = delete_cmd->delete_.wim_path; DEBUG("Deleting WIM path \"%"TS"\" (flags=%#x)", wim_path, flags); @@ -383,7 +382,7 @@ rename_wim_path(WIMStruct *wim, const tchar *from, const tchar *to) * directory */ if (!dentry_is_directory(dst)) return -ENOTDIR; - if (inode_has_children(dst->d_inode)) + if (dentry_has_children(dst)) return -ENOTEMPTY; } parent_of_dst = dst->parent; @@ -470,12 +469,23 @@ static int execute_update_commands(WIMStruct *wim, const struct wimlib_update_command *cmds, size_t num_cmds, + int update_flags, wimlib_progress_func_t progress_func) { int ret = 0; + union wimlib_progress_info info; + info.update.completed_commands = 0; + info.update.total_commands = num_cmds; for (size_t i = 0; i < num_cmds; i++) { DEBUG("Executing update command %zu of %zu (op=%"TS")", i + 1, num_cmds, update_op_to_str(cmds[i].op)); + if (update_flags & WIMLIB_UPDATE_FLAG_SEND_PROGRESS && + progress_func) + { + info.update.command = &cmds[i]; + (*progress_func)(WIMLIB_PROGRESS_MSG_UPDATE_BEGIN_COMMAND, + &info); + } switch (cmds[i].op) { case WIMLIB_UPDATE_OP_ADD: ret = execute_add_command(wim, &cmds[i], progress_func); @@ -491,10 +501,34 @@ execute_update_commands(WIMStruct *wim, } if (ret) break; + info.update.completed_commands++; + if (update_flags & WIMLIB_UPDATE_FLAG_SEND_PROGRESS && + progress_func) + { + (*progress_func)(WIMLIB_PROGRESS_MSG_UPDATE_END_COMMAND, + &info); + } } 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) @@ -610,7 +644,7 @@ free_update_commands(struct wimlib_update_command *cmds, size_t num_cmds) free_capture_config(cmds[i].add.config); break; case WIMLIB_UPDATE_OP_DELETE: - FREE(cmds[i].delete.wim_path); + FREE(cmds[i].delete_.wim_path); break; case WIMLIB_UPDATE_OP_RENAME: FREE(cmds[i].rename.wim_source_path); @@ -629,6 +663,7 @@ copy_update_commands(const struct wimlib_update_command *cmds, { 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) @@ -645,8 +680,11 @@ copy_update_commands(const struct wimlib_update_command *cmds, if (!cmds_copy[i].add.fs_source_path || !cmds_copy[i].add.wim_target_path) goto oom; - if (cmds[i].add.config) { - ret = copy_and_canonicalize_capture_config(cmds[i].add.config, + 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; @@ -654,11 +692,11 @@ copy_update_commands(const struct wimlib_update_command *cmds, cmds_copy[i].add.add_flags = cmds[i].add.add_flags; break; case WIMLIB_UPDATE_OP_DELETE: - cmds_copy[i].delete.wim_path = - canonicalize_wim_path(cmds[i].delete.wim_path); - if (!cmds_copy[i].delete.wim_path) + cmds_copy[i].delete_.wim_path = + canonicalize_wim_path(cmds[i].delete_.wim_path); + if (!cmds_copy[i].delete_.wim_path) goto oom; - cmds_copy[i].delete.delete_flags = cmds[i].delete.delete_flags; + cmds_copy[i].delete_.delete_flags = cmds[i].delete_.delete_flags; break; case WIMLIB_UPDATE_OP_RENAME: cmds_copy[i].rename.wim_source_path = @@ -686,9 +724,7 @@ err: goto out; } -/* - * Entry point for making a series of updates to a WIM image. - */ +/* API function documented in wimlib.h */ WIMLIBAPI int wimlib_update_image(WIMStruct *wim, int image, @@ -699,15 +735,21 @@ wimlib_update_image(WIMStruct *wim, { int ret; struct wimlib_update_command *cmds_copy; + bool deletion_requested = false; 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; + for (size_t i = 0; i < num_cmds; i++) + if (cmds[i].op == WIMLIB_UPDATE_OP_DELETE) + deletion_requested = true; + + if (deletion_requested) + ret = can_delete_from_wim(wim); + else + ret = can_modify_wim(wim); + + if (ret) goto out; - } /* Load the metadata for the image to modify (if not loaded already) */ ret = select_wim_image(wim, image); @@ -737,7 +779,8 @@ wimlib_update_image(WIMStruct *wim, /* Actually execute the update commands. */ DEBUG("Executing %zu update commands", num_cmds); - ret = execute_update_commands(wim, cmds_copy, num_cmds, progress_func); + ret = execute_update_commands(wim, cmds_copy, num_cmds, update_flags, + progress_func); if (ret) goto out_free_cmds_copy;