2 * add_image.c - Add an image to a WIM file.
6 * Copyright (C) 2012, 2013, 2014 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/error.h"
30 #include "wimlib/lookup_table.h"
31 #include "wimlib/metadata.h"
32 #include "wimlib/security.h"
33 #include "wimlib/xml.h"
35 /* Creates and appends a 'struct wim_image_metadata' for an empty image.
37 * The resulting image will be the last in the WIM, so its index will be
38 * the new value of wim->hdr.image_count. */
40 add_empty_image_metadata(WIMStruct *wim)
43 struct wim_lookup_table_entry *metadata_lte;
44 struct wim_security_data *sd;
45 struct wim_image_metadata *imd;
47 /* Create lookup table entry for this metadata resource (for now really
48 * just a dummy entry). */
49 ret = WIMLIB_ERR_NOMEM;
50 metadata_lte = new_lookup_table_entry();
54 metadata_lte->flags = WIM_RESHDR_FLAG_METADATA;
55 metadata_lte->unhashed = 1;
57 /* Create empty security data (no security descriptors). */
58 sd = new_wim_security_data();
60 goto out_free_metadata_lte;
62 imd = new_image_metadata();
64 goto out_free_security_data;
66 /* A NULL root_dentry indicates a completely empty image, without even a
68 imd->root_dentry = NULL;
69 imd->metadata_lte = metadata_lte;
70 imd->security_data = sd;
73 /* Append as next image index. */
74 ret = append_image_metadata(wim, imd);
76 put_image_metadata(imd, NULL);
79 out_free_security_data:
80 free_wim_security_data(sd);
81 out_free_metadata_lte:
82 free_lookup_table_entry(metadata_lte);
87 /* API function documented in wimlib.h */
89 wimlib_add_empty_image(WIMStruct *wim, const tchar *name, int *new_idx_ret)
93 ret = can_modify_wim(wim);
100 if (wimlib_image_name_in_use(wim, name)) {
101 ERROR("There is already an image named \"%"TS"\" in the WIM!",
103 return WIMLIB_ERR_IMAGE_NAME_COLLISION;
106 ret = add_empty_image_metadata(wim);
110 ret = xml_add_image(wim, name);
112 put_image_metadata(wim->image_metadata[--wim->hdr.image_count],
118 *new_idx_ret = wim->hdr.image_count;
122 /* Translate the 'struct wimlib_capture_source's passed to
123 * wimlib_add_image_multisource() into 'struct wimlib_update_command's for
124 * wimlib_update_image(). */
125 static struct wimlib_update_command *
126 capture_sources_to_add_cmds(const struct wimlib_capture_source *sources,
129 const tchar *config_file)
131 struct wimlib_update_command *add_cmds;
133 add_cmds = CALLOC(num_sources, sizeof(add_cmds[0]));
137 /* WIMLIB_ADD_FLAG_BOOT is handled by wimlib_add_image_multisource(),
138 * not wimlib_update_image(), so mask it out.
140 * However, WIMLIB_ADD_FLAG_WIMBOOT is handled by both. */
141 add_flags &= ~WIMLIB_ADD_FLAG_BOOT;
143 for (size_t i = 0; i < num_sources; i++) {
144 add_cmds[i].op = WIMLIB_UPDATE_OP_ADD;
145 add_cmds[i].add.fs_source_path = sources[i].fs_source_path;
146 add_cmds[i].add.wim_target_path = sources[i].wim_target_path;
147 add_cmds[i].add.add_flags = add_flags;
148 add_cmds[i].add.config_file = (tchar *)config_file;
153 /* API function documented in wimlib.h */
155 wimlib_add_image_multisource(WIMStruct *wim,
156 const struct wimlib_capture_source *sources,
159 const tchar *config_file,
163 struct wimlib_update_command *add_cmds;
165 /* Make sure no reserved fields are set. */
166 for (size_t i = 0; i < num_sources; i++)
167 if (sources[i].reserved != 0)
168 return WIMLIB_ERR_INVALID_PARAM;
170 /* Add the new image (initially empty). */
171 ret = wimlib_add_empty_image(wim, name, NULL);
175 /* Translate the "capture sources" into generic update commands. */
176 ret = WIMLIB_ERR_NOMEM;
177 add_cmds = capture_sources_to_add_cmds(sources, num_sources,
178 add_flags, config_file);
180 goto out_delete_image;
182 /* Delegate the work to wimlib_update_image(). */
183 ret = wimlib_update_image(wim, wim->hdr.image_count, add_cmds,
187 goto out_delete_image;
189 /* If requested, set this image as the WIM's bootable image. */
190 if (add_flags & WIMLIB_ADD_FLAG_BOOT)
191 wim->hdr.boot_idx = wim->hdr.image_count;
193 /* If requested, mark new image as WIMBoot-compatible. */
194 if (add_flags & WIMLIB_ADD_FLAG_WIMBOOT)
195 wim_info_set_wimboot(wim->wim_info, wim->hdr.image_count, true);
200 /* Unsuccessful; rollback the WIM to its original state. */
202 /* wimlib_update_image() is now all-or-nothing, so no dentries remain
203 * and there's no need to pass the lookup table here. */
204 put_image_metadata(wim->image_metadata[wim->hdr.image_count - 1], NULL);
206 xml_delete_image(&wim->wim_info, wim->hdr.image_count);
207 wim->hdr.image_count--;
211 /* API function documented in wimlib.h */
213 wimlib_add_image(WIMStruct *wim,
216 const tchar *config_file,
219 /* Use the more general wimlib_add_image_multisource(). */
220 const struct wimlib_capture_source capture_src = {
221 .fs_source_path = (tchar *)source,
222 .wim_target_path = WIMLIB_WIM_ROOT_PATH,
225 return wimlib_add_image_multisource(wim, &capture_src, 1, name,
226 config_file, add_flags);