X-Git-Url: https://wimlib.net/git/?p=wimlib;a=blobdiff_plain;f=src%2Fadd_image.c;h=cd270390c3f7185a8b6f10e0dca9eecf633072ef;hp=746c06a92dd43ed6d1cf0c427b5e1080988699ec;hb=b5b9681794d1f5f13350e3567f6f6e74f5c779cf;hpb=61db93f82eca3fe9f7676355c709c58cc425a6ad diff --git a/src/add_image.c b/src/add_image.c index 746c06a9..cd270390 100644 --- a/src/add_image.c +++ b/src/add_image.c @@ -3,7 +3,7 @@ */ /* - * Copyright (C) 2012, 2013 Eric Biggers + * Copyright (C) 2012, 2013, 2014 Eric Biggers * * This file is part of wimlib, a library for working with WIM files. * @@ -26,45 +26,61 @@ #endif #include "wimlib.h" -#include "wimlib/capture.h" #include "wimlib/error.h" #include "wimlib/lookup_table.h" #include "wimlib/metadata.h" +#include "wimlib/security.h" #include "wimlib/xml.h" -/* - * Adds the dentry tree and security data for a new image to the image metadata - * array of the WIMStruct. - */ +/* Creates and appends a 'struct wim_image_metadata' for an empty image. + * + * The resulting image will be the last in the WIM, so its index will be + * the new value of wim->hdr.image_count. */ static int -add_new_dentry_tree(WIMStruct *wim, struct wim_dentry *root_dentry, - struct wim_security_data *sd) +add_empty_image_metadata(WIMStruct *wim) { - struct wim_image_metadata *new_imd; - struct wim_lookup_table_entry *metadata_lte; int ret; + struct wim_lookup_table_entry *metadata_lte; + struct wim_security_data *sd; + struct wim_image_metadata *imd; + /* Create lookup table entry for this metadata resource (for now really + * just a dummy entry). */ + ret = WIMLIB_ERR_NOMEM; metadata_lte = new_lookup_table_entry(); if (!metadata_lte) - return WIMLIB_ERR_NOMEM; + goto out; - metadata_lte->resource_entry.flags = WIM_RESHDR_FLAG_METADATA; + metadata_lte->flags = WIM_RESHDR_FLAG_METADATA; metadata_lte->unhashed = 1; - new_imd = new_image_metadata(); - if (!new_imd) { - free_lookup_table_entry(metadata_lte); - return WIMLIB_ERR_NOMEM; - } + /* Create empty security data (no security descriptors). */ + sd = new_wim_security_data(); + if (!sd) + goto out_free_metadata_lte; - new_imd->root_dentry = root_dentry; - new_imd->metadata_lte = metadata_lte; - new_imd->security_data = sd; - new_imd->modified = 1; + imd = new_image_metadata(); + if (!imd) + goto out_free_security_data; + + /* A NULL root_dentry indicates a completely empty image, without even a + * root directory. */ + imd->root_dentry = NULL; + imd->metadata_lte = metadata_lte; + imd->security_data = sd; + imd->modified = 1; - ret = append_image_metadata(wim, new_imd); + /* Append as next image index. */ + ret = append_image_metadata(wim, imd); if (ret) - put_image_metadata(new_imd, NULL); + put_image_metadata(imd, NULL); + goto out; + +out_free_security_data: + free_wim_security_data(sd); +out_free_metadata_lte: + free_lookup_table_entry(metadata_lte); +out: return ret; } @@ -73,77 +89,63 @@ WIMLIBAPI int wimlib_add_empty_image(WIMStruct *wim, const tchar *name, int *new_idx_ret) { int ret; - struct wim_security_data *sd; - - DEBUG("Adding empty image \"%"TS"\"", name); - - if (name == NULL) - name = T(""); ret = can_modify_wim(wim); if (ret) - goto out; + return ret; + + if (!name) + name = T(""); if (wimlib_image_name_in_use(wim, name)) { ERROR("There is already an image named \"%"TS"\" in the WIM!", name); - ret = WIMLIB_ERR_IMAGE_NAME_COLLISION; - goto out; - } - - sd = new_wim_security_data(); - if (!sd) { - ret = WIMLIB_ERR_NOMEM; - goto out; + return WIMLIB_ERR_IMAGE_NAME_COLLISION; } - ret = add_new_dentry_tree(wim, NULL, sd); + ret = add_empty_image_metadata(wim); if (ret) - goto out_free_security_data; + return ret; ret = xml_add_image(wim, name); - if (ret) - goto out_put_image_metadata; + if (ret) { + put_image_metadata(wim->image_metadata[--wim->hdr.image_count], + NULL); + return ret; + } if (new_idx_ret) *new_idx_ret = wim->hdr.image_count; - DEBUG("Successfully added new image (index %d)", - wim->hdr.image_count); - goto out; -out_put_image_metadata: - put_image_metadata(wim->image_metadata[--wim->hdr.image_count], - wim->lookup_table); - goto out; -out_free_security_data: - free_wim_security_data(sd); -out: - return ret; + return 0; } +/* Translate the 'struct wimlib_capture_source's passed to + * wimlib_add_image_multisource() into 'struct wimlib_update_command's for + * wimlib_update_image(). */ static struct wimlib_update_command * 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; - DEBUG("Translating %zu capture sources to `struct wimlib_update_command's", - num_sources); add_cmds = CALLOC(num_sources, sizeof(add_cmds[0])); - if (add_cmds) { - for (size_t i = 0; i < num_sources; i++) { - DEBUG("Source %zu of %zu: fs_source_path=\"%"TS"\", " - "wim_target_path=\"%"TS"\"", - i + 1, num_sources, - 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; - add_cmds[i].add.config = (struct wimlib_capture_config*)config; - add_cmds[i].add.fs_source_path = sources[i].fs_source_path; - add_cmds[i].add.wim_target_path = sources[i].wim_target_path; - } + if (!add_cmds) + return NULL; + + /* WIMLIB_ADD_FLAG_BOOT is handled by wimlib_add_image_multisource(), + * not wimlib_update_image(), so mask it out. + * + * However, WIMLIB_ADD_FLAG_WIMBOOT is handled by both. */ + add_flags &= ~WIMLIB_ADD_FLAG_BOOT; + + for (size_t i = 0; i < num_sources; i++) { + add_cmds[i].op = WIMLIB_UPDATE_OP_ADD; + add_cmds[i].add.fs_source_path = sources[i].fs_source_path; + add_cmds[i].add.wim_target_path = sources[i].wim_target_path; + add_cmds[i].add.add_flags = add_flags; + add_cmds[i].add.config_file = (tchar *)config_file; } return add_cmds; } @@ -154,48 +156,55 @@ wimlib_add_image_multisource(WIMStruct *wim, const struct wimlib_capture_source *sources, size_t num_sources, const tchar *name, - const struct wimlib_capture_config *config, - int add_flags, - wimlib_progress_func_t progress_func) + const tchar *config_file, + int add_flags) { int ret; struct wimlib_update_command *add_cmds; - DEBUG("Adding image \"%"TS"\" from %zu sources (add_flags=%#x)", - name, num_sources, add_flags); + /* Make sure no reserved fields are set. */ + for (size_t i = 0; i < num_sources; i++) + if (sources[i].reserved != 0) + return WIMLIB_ERR_INVALID_PARAM; - /* Add the new image (initially empty) */ + /* Add the new image (initially empty). */ ret = wimlib_add_empty_image(wim, name, NULL); if (ret) - goto out; + return ret; - /* Translate the "capture sources" into generic update commands. */ + /* Translate the "capture sources" into generic update commands. */ + ret = WIMLIB_ERR_NOMEM; add_cmds = capture_sources_to_add_cmds(sources, num_sources, - add_flags, config); - if (!add_cmds) { - ret = WIMLIB_ERR_NOMEM; + add_flags, config_file); + if (!add_cmds) goto out_delete_image; - } - /* Delegate the work to wimlib_update_image(). */ + /* Delegate the work to wimlib_update_image(). */ ret = wimlib_update_image(wim, wim->hdr.image_count, add_cmds, - num_sources, 0, progress_func); + num_sources, 0); FREE(add_cmds); if (ret) goto out_delete_image; - /* Success; set boot index if requested. */ + /* If requested, set this image as the WIM's bootable image. */ if (add_flags & WIMLIB_ADD_FLAG_BOOT) wim->hdr.boot_idx = wim->hdr.image_count; - ret = 0; - goto out; + + /* If requested, mark new image as WIMBoot-compatible. */ + if (add_flags & WIMLIB_ADD_FLAG_WIMBOOT) + wim_info_set_wimboot(wim->wim_info, wim->hdr.image_count, true); + + return 0; + out_delete_image: - /* Roll back the image we added */ - put_image_metadata(wim->image_metadata[wim->hdr.image_count - 1], - wim->lookup_table); + /* Unsuccessful; rollback the WIM to its original state. */ + + /* wimlib_update_image() is now all-or-nothing, so no dentries remain + * and there's no need to pass the lookup table here. */ + put_image_metadata(wim->image_metadata[wim->hdr.image_count - 1], NULL); + xml_delete_image(&wim->wim_info, wim->hdr.image_count); wim->hdr.image_count--; -out: return ret; } @@ -204,18 +213,15 @@ WIMLIBAPI int wimlib_add_image(WIMStruct *wim, const tchar *source, const tchar *name, - const struct wimlib_capture_config *config, - int add_flags, - wimlib_progress_func_t progress_func) + const tchar *config_file, + int add_flags) { - /* Delegate the work to the more general wimlib_add_image_multisource(). - * */ + /* Use the more general wimlib_add_image_multisource(). */ const struct wimlib_capture_source capture_src = { - .fs_source_path = (tchar*)source, - .wim_target_path = T(""), + .fs_source_path = (tchar *)source, + .wim_target_path = WIMLIB_WIM_ROOT_PATH, .reserved = 0, }; return wimlib_add_image_multisource(wim, &capture_src, 1, name, - config, add_flags, - progress_func); + config_file, add_flags); }