2 * add_image.c - Add an image to a WIM file.
6 * Copyright (C) 2012, 2013, 2014 Eric Biggers
8 * This file is free software; you can redistribute it and/or modify it under
9 * the terms of the GNU Lesser General Public License as published by the Free
10 * Software Foundation; either version 3 of the License, or (at your option) any
13 * This file is distributed in the hope that it will be useful, but WITHOUT
14 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
15 * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
18 * You should have received a copy of the GNU Lesser General Public License
19 * along with this file; if not, see http://www.gnu.org/licenses/.
27 #include "wimlib/blob_table.h"
28 #include "wimlib/error.h"
29 #include "wimlib/metadata.h"
30 #include "wimlib/security.h"
31 #include "wimlib/xml.h"
33 /* Creates and appends a 'struct wim_image_metadata' for an empty image.
35 * The resulting image will be the last in the WIM, so its index will be
36 * the new value of wim->hdr.image_count. */
38 add_empty_image_metadata(WIMStruct *wim)
41 struct blob_descriptor *metadata_blob;
42 struct wim_security_data *sd;
43 struct wim_image_metadata *imd;
45 /* Create a blob descriptor for the new metadata resource. */
46 ret = WIMLIB_ERR_NOMEM;
47 metadata_blob = new_blob_descriptor();
51 metadata_blob->refcnt = 1;
52 metadata_blob->unhashed = 1;
53 metadata_blob->is_metadata = 1;
55 /* Create empty security data (no security descriptors). */
56 sd = new_wim_security_data();
58 goto out_free_metadata_blob;
60 imd = new_image_metadata();
62 goto out_free_security_data;
64 /* A NULL root_dentry indicates a completely empty image, without even a
66 imd->root_dentry = NULL;
67 imd->metadata_blob = metadata_blob;
68 imd->security_data = sd;
71 /* Append as next image index. */
72 ret = append_image_metadata(wim, imd);
74 put_image_metadata(imd, NULL);
77 out_free_security_data:
78 free_wim_security_data(sd);
79 out_free_metadata_blob:
80 free_blob_descriptor(metadata_blob);
85 /* API function documented in wimlib.h */
87 wimlib_add_empty_image(WIMStruct *wim, const tchar *name, int *new_idx_ret)
94 if (wimlib_image_name_in_use(wim, name)) {
95 ERROR("There is already an image named \"%"TS"\" in the WIM!",
97 return WIMLIB_ERR_IMAGE_NAME_COLLISION;
100 ret = add_empty_image_metadata(wim);
104 ret = xml_add_image(wim, name);
106 put_image_metadata(wim->image_metadata[--wim->hdr.image_count],
112 *new_idx_ret = wim->hdr.image_count;
116 /* Translate the 'struct wimlib_capture_source's passed to
117 * wimlib_add_image_multisource() into 'struct wimlib_update_command's for
118 * wimlib_update_image(). */
119 static struct wimlib_update_command *
120 capture_sources_to_add_cmds(const struct wimlib_capture_source *sources,
123 const tchar *config_file)
125 struct wimlib_update_command *add_cmds;
127 add_cmds = CALLOC(num_sources, sizeof(add_cmds[0]));
131 /* WIMLIB_ADD_FLAG_BOOT is handled by wimlib_add_image_multisource(),
132 * not wimlib_update_image(), so mask it out.
134 * However, WIMLIB_ADD_FLAG_WIMBOOT is handled by both. */
135 add_flags &= ~WIMLIB_ADD_FLAG_BOOT;
137 for (size_t i = 0; i < num_sources; i++) {
138 add_cmds[i].op = WIMLIB_UPDATE_OP_ADD;
139 add_cmds[i].add.fs_source_path = sources[i].fs_source_path;
140 add_cmds[i].add.wim_target_path = sources[i].wim_target_path;
141 add_cmds[i].add.add_flags = add_flags;
142 add_cmds[i].add.config_file = (tchar *)config_file;
147 /* API function documented in wimlib.h */
149 wimlib_add_image_multisource(WIMStruct *wim,
150 const struct wimlib_capture_source *sources,
153 const tchar *config_file,
157 struct wimlib_update_command *add_cmds;
159 /* Make sure no reserved fields are set. */
160 for (size_t i = 0; i < num_sources; i++)
161 if (sources[i].reserved != 0)
162 return WIMLIB_ERR_INVALID_PARAM;
164 /* Add the new image (initially empty). */
165 ret = wimlib_add_empty_image(wim, name, NULL);
169 /* Translate the "capture sources" into generic update commands. */
170 ret = WIMLIB_ERR_NOMEM;
171 add_cmds = capture_sources_to_add_cmds(sources, num_sources,
172 add_flags, config_file);
174 goto out_delete_image;
176 /* Delegate the work to wimlib_update_image(). */
177 ret = wimlib_update_image(wim, wim->hdr.image_count, add_cmds,
181 goto out_delete_image;
183 /* If requested, set this image as the WIM's bootable image. */
184 if (add_flags & WIMLIB_ADD_FLAG_BOOT)
185 wim->hdr.boot_idx = wim->hdr.image_count;
187 /* If requested, mark new image as WIMBoot-compatible. */
188 if (add_flags & WIMLIB_ADD_FLAG_WIMBOOT)
189 wim_info_set_wimboot(wim->wim_info, wim->hdr.image_count, true);
194 /* Unsuccessful; rollback by removing the new image. */
195 delete_wim_image(wim, wim->hdr.image_count);
199 /* API function documented in wimlib.h */
201 wimlib_add_image(WIMStruct *wim,
204 const tchar *config_file,
207 /* Use the more general wimlib_add_image_multisource(). */
208 const struct wimlib_capture_source capture_src = {
209 .fs_source_path = (tchar *)source,
210 .wim_target_path = WIMLIB_WIM_ROOT_PATH,
213 return wimlib_add_image_multisource(wim, &capture_src, 1, name,
214 config_file, add_flags);