/* API function documented in wimlib.h */ WIMLIBAPI void wimlib_free(WIMStruct *wim) { if (!wim) return; while (!list_empty(&wim->subwims)) { WIMStruct *subwim; subwim = list_entry(wim->subwims.next, WIMStruct, subwim_node); list_del(&subwim->subwim_node); wimlib_free(subwim); } if (filedes_valid(&wim->in_fd)) filedes_close(&wim->in_fd); if (filedes_valid(&wim->out_fd)) filedes_close(&wim->out_fd); free_blob_table(wim->blob_table); wimlib_free_decompressor(wim->decompressor); FREE(wim->filename); free_wim_info(wim->wim_info); if (wim->image_metadata) { for (unsigned i = 0; i < wim->hdr.image_count; i++) put_image_metadata(wim->image_metadata[i], NULL); FREE(wim->image_metadata); } FREE(wim); }
/* API function documented in wimlib.h */ WIMLIBAPI int wimlib_add_empty_image(WIMStruct *wim, const tchar *name, int *new_idx_ret) { int ret; ret = can_modify_wim(wim); if (ret) 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); return WIMLIB_ERR_IMAGE_NAME_COLLISION; } ret = add_empty_image_metadata(wim); if (ret) return ret; ret = xml_add_image(wim, name); 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; return 0; }
/* API function documented in wimlib.h */ WIMLIBAPI int wimlib_add_image_multisource(WIMStruct *wim, const struct wimlib_capture_source *sources, size_t num_sources, const tchar *name, const tchar *config_file, int add_flags) { int ret; struct wimlib_update_command *add_cmds; /* 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). */ ret = wimlib_add_empty_image(wim, name, NULL); if (ret) return ret; /* 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_file); if (!add_cmds) goto out_delete_image; /* Delegate the work to wimlib_update_image(). */ ret = wimlib_update_image(wim, wim->hdr.image_count, add_cmds, num_sources, 0); FREE(add_cmds); if (ret) goto out_delete_image; /* 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; /* 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: /* 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--; return ret; }
/* 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_empty_image_metadata(WIMStruct *wim) { 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) goto out; metadata_lte->flags = WIM_RESHDR_FLAG_METADATA; metadata_lte->unhashed = 1; /* Create empty security data (no security descriptors). */ sd = new_wim_security_data(); if (!sd) goto out_free_metadata_lte; 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; /* Append as next image index. */ ret = append_image_metadata(wim, imd); if (ret) 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; }
/* Internal method for single-image deletion. This doesn't set the * image_deletion_occurred' flag on the WIMStruct. */ int delete_wim_image(WIMStruct *wim, int image) { int ret; /* Load the metadata for the image to be deleted. This is necessary * because streams referenced by files in the image need to have their * reference counts decremented. */ ret = select_wim_image(wim, image); if (ret) return ret; /* Release the reference to the image metadata and decrement reference * counts on the streams referenced by files in the image. */ put_image_metadata(wim->image_metadata[image - 1], wim->lookup_table); /* Remove the empty slot from the image metadata array. */ memmove(&wim->image_metadata[image - 1], &wim->image_metadata[image], (wim->hdr.image_count - image) * sizeof(wim->image_metadata[0])); /* Decrement the image count. */ --wim->hdr.image_count; /* Remove the image from the XML information. */ xml_delete_image(&wim->wim_info, image); /* Fix the boot index. */ if (wim->hdr.boot_idx == image) wim->hdr.boot_idx = 0; else if (wim->hdr.boot_idx > image) wim->hdr.boot_idx--; /* The image is no longer valid. */ wim->current_image = WIMLIB_NO_IMAGE; return 0; }