2 * add_image.c - Add an image to a WIM file.
6 * Copyright (C) 2012, 2013 Eric Biggers
8 * This file is part of wimlib, a library for working with WIM files.
10 * wimlib is free software; you can redistribute it and/or modify it under the
11 * terms of the GNU General Public License as published by the Free
12 * Software Foundation; either version 3 of the License, or (at your option)
15 * wimlib is distributed in the hope that it will be useful, but WITHOUT ANY
16 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
17 * A PARTICULAR PURPOSE. See the GNU General Public License for more
20 * You should have received a copy of the GNU General Public License
21 * along with wimlib; if not, see http://www.gnu.org/licenses/.
29 #include "wimlib/capture.h"
30 #include "wimlib/error.h"
31 #include "wimlib/lookup_table.h"
32 #include "wimlib/metadata.h"
33 #include "wimlib/xml.h"
36 * Adds the dentry tree and security data for a new image to the image metadata
37 * array of the WIMStruct.
40 add_new_dentry_tree(WIMStruct *wim, struct wim_dentry *root_dentry,
41 struct wim_security_data *sd)
43 struct wim_image_metadata *new_imd;
44 struct wim_lookup_table_entry *metadata_lte;
47 metadata_lte = new_lookup_table_entry();
49 return WIMLIB_ERR_NOMEM;
51 metadata_lte->resource_entry.flags = WIM_RESHDR_FLAG_METADATA;
52 metadata_lte->unhashed = 1;
54 new_imd = new_image_metadata();
56 free_lookup_table_entry(metadata_lte);
57 return WIMLIB_ERR_NOMEM;
60 new_imd->root_dentry = root_dentry;
61 new_imd->metadata_lte = metadata_lte;
62 new_imd->security_data = sd;
63 new_imd->modified = 1;
65 ret = append_image_metadata(wim, new_imd);
67 put_image_metadata(new_imd, NULL);
71 /* Append an empty image to the WIMStruct. */
73 wimlib_add_empty_image(WIMStruct *wim, const tchar *name, int *new_idx_ret)
76 struct wim_security_data *sd;
78 DEBUG("Adding empty image \"%"TS"\"", name);
80 if (name == NULL || name[0] == T('\0')) {
81 ERROR("Must specify a non-empty string for the image name");
82 ret = WIMLIB_ERR_INVALID_PARAM;
86 if (wim->hdr.total_parts != 1) {
87 ERROR("Cannot add an image to a split WIM");
88 ret = WIMLIB_ERR_SPLIT_UNSUPPORTED;
92 if (wimlib_image_name_in_use(wim, name)) {
93 ERROR("There is already an image named \"%"TS"\" in the WIM!",
95 ret = WIMLIB_ERR_IMAGE_NAME_COLLISION;
99 sd = new_wim_security_data();
101 ret = WIMLIB_ERR_NOMEM;
105 ret = add_new_dentry_tree(wim, NULL, sd);
107 goto out_free_security_data;
109 ret = xml_add_image(wim, name);
111 goto out_put_image_metadata;
114 *new_idx_ret = wim->hdr.image_count;
115 DEBUG("Successfully added new image (index %d)",
116 wim->hdr.image_count);
118 out_put_image_metadata:
119 put_image_metadata(wim->image_metadata[--wim->hdr.image_count],
122 out_free_security_data:
123 free_security_data(sd);
128 static struct wimlib_update_command *
129 capture_sources_to_add_cmds(const struct wimlib_capture_source *sources,
132 const struct wimlib_capture_config *config)
134 struct wimlib_update_command *add_cmds;
136 DEBUG("Translating %zu capture sources to `struct wimlib_update_command's",
138 add_cmds = CALLOC(num_sources, sizeof(add_cmds[0]));
140 for (size_t i = 0; i < num_sources; i++) {
141 DEBUG("Source %zu of %zu: fs_source_path=\"%"TS"\", "
142 "wim_target_path=\"%"TS"\"",
144 sources[i].fs_source_path,
145 sources[i].wim_target_path);
146 add_cmds[i].op = WIMLIB_UPDATE_OP_ADD;
147 add_cmds[i].add.add_flags = add_flags;
148 add_cmds[i].add.config = (struct wimlib_capture_config*)config;
149 add_cmds[i].add.fs_source_path = sources[i].fs_source_path;
150 add_cmds[i].add.wim_target_path = sources[i].wim_target_path;
156 /* Adds an image to the WIMStruct from multiple on-disk directory trees, or a
159 wimlib_add_image_multisource(WIMStruct *wim,
160 const struct wimlib_capture_source *sources,
163 const struct wimlib_capture_config *config,
165 wimlib_progress_func_t progress_func)
168 struct wimlib_update_command *add_cmds;
170 DEBUG("Adding image \"%"TS"\" from %zu sources (add_flags=%#x)",
171 name, num_sources, add_flags);
173 /* Add the new image (initially empty) */
174 ret = wimlib_add_empty_image(wim, name, NULL);
178 /* Translate the "capture sources" into generic update commands. */
179 add_cmds = capture_sources_to_add_cmds(sources, num_sources,
182 ret = WIMLIB_ERR_NOMEM;
183 goto out_delete_image;
186 /* Delegate the work to wimlib_update_image(). */
187 ret = wimlib_update_image(wim, wim->hdr.image_count, add_cmds,
188 num_sources, 0, progress_func);
191 goto out_delete_image;
193 /* Success; set boot index if requested. */
194 if (add_flags & WIMLIB_ADD_FLAG_BOOT)
195 wim->hdr.boot_idx = wim->hdr.image_count;
199 /* Roll back the image we added */
200 put_image_metadata(wim->image_metadata[wim->hdr.image_count - 1],
202 xml_delete_image(&wim->wim_info, wim->hdr.image_count);
203 wim->hdr.image_count--;
208 /* Adds an image to the WIMStruct from an on-disk directory tree or NTFS volume. */
210 wimlib_add_image(WIMStruct *wim,
213 const struct wimlib_capture_config *config,
215 wimlib_progress_func_t progress_func)
217 /* Delegate the work to the more general wimlib_add_image_multisource().
219 const struct wimlib_capture_source capture_src = {
220 .fs_source_path = (tchar*)source,
221 .wim_target_path = T(""),
224 return wimlib_add_image_multisource(wim, &capture_src, 1, name,