]> wimlib.net Git - wimlib/blob - src/add_image.c
Use HTTPS for all links to website
[wimlib] / src / add_image.c
1 /*
2  * add_image.c - Add an image to a WIM file.
3  */
4
5 /*
6  * Copyright (C) 2012, 2013, 2014 Eric Biggers
7  *
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
11  * later version.
12  *
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
16  * details.
17  *
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/.
20  */
21
22 #ifdef HAVE_CONFIG_H
23 #  include "config.h"
24 #endif
25
26 #include "wimlib.h"
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"
32
33 /* Creates and appends a 'struct wim_image_metadata' for an empty image.
34  *
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.  */
37 static int
38 add_empty_image_metadata(WIMStruct *wim)
39 {
40         int ret;
41         struct blob_descriptor *metadata_blob;
42         struct wim_security_data *sd;
43         struct wim_image_metadata *imd;
44
45         /* Create a blob descriptor for the new metadata resource.  */
46         ret = WIMLIB_ERR_NOMEM;
47         metadata_blob = new_blob_descriptor();
48         if (!metadata_blob)
49                 goto out;
50
51         metadata_blob->refcnt = 1;
52         metadata_blob->is_metadata = 1;
53
54         /* Create empty security data (no security descriptors).  */
55         sd = new_wim_security_data();
56         if (!sd)
57                 goto out_free_metadata_blob;
58
59         imd = new_image_metadata();
60         if (!imd)
61                 goto out_free_security_data;
62
63         /* A NULL root_dentry indicates a completely empty image, without even a
64          * root directory.  */
65         imd->root_dentry = NULL;
66         imd->metadata_blob = metadata_blob;
67         imd->security_data = sd;
68
69         /* Append as next image index.  */
70         ret = append_image_metadata(wim, imd);
71         if (ret)
72                 put_image_metadata(imd, NULL);
73         goto out;
74
75 out_free_security_data:
76         free_wim_security_data(sd);
77 out_free_metadata_blob:
78         free_blob_descriptor(metadata_blob);
79 out:
80         return ret;
81 }
82
83 /* API function documented in wimlib.h  */
84 WIMLIBAPI int
85 wimlib_add_empty_image(WIMStruct *wim, const tchar *name, int *new_idx_ret)
86 {
87         int ret;
88
89         if (wimlib_image_name_in_use(wim, name)) {
90                 ERROR("There is already an image named \"%"TS"\" in the WIM!",
91                       name);
92                 return WIMLIB_ERR_IMAGE_NAME_COLLISION;
93         }
94
95         ret = add_empty_image_metadata(wim);
96         if (ret)
97                 return ret;
98
99         ret = xml_add_image(wim->xml_info, name);
100         if (ret) {
101                 put_image_metadata(wim->image_metadata[--wim->hdr.image_count],
102                                    NULL);
103                 return ret;
104         }
105
106         if (new_idx_ret)
107                 *new_idx_ret = wim->hdr.image_count;
108         return 0;
109 }
110
111 /* Translate the 'struct wimlib_capture_source's passed to
112  * wimlib_add_image_multisource() into 'struct wimlib_update_command's for
113  * wimlib_update_image().  */
114 static struct wimlib_update_command *
115 capture_sources_to_add_cmds(const struct wimlib_capture_source *sources,
116                             size_t num_sources,
117                             int add_flags,
118                             const tchar *config_file)
119 {
120         struct wimlib_update_command *add_cmds;
121
122         add_cmds = CALLOC(num_sources, sizeof(add_cmds[0]));
123         if (!add_cmds)
124                 return NULL;
125
126         /* WIMLIB_ADD_FLAG_BOOT is handled by wimlib_add_image_multisource(),
127          * not wimlib_update_image(), so mask it out.
128          *
129          * However, WIMLIB_ADD_FLAG_WIMBOOT is handled by both.  */
130         add_flags &= ~WIMLIB_ADD_FLAG_BOOT;
131
132         for (size_t i = 0; i < num_sources; i++) {
133                 add_cmds[i].op = WIMLIB_UPDATE_OP_ADD;
134                 add_cmds[i].add.fs_source_path = sources[i].fs_source_path;
135                 add_cmds[i].add.wim_target_path = sources[i].wim_target_path;
136                 add_cmds[i].add.add_flags = add_flags;
137                 add_cmds[i].add.config_file = (tchar *)config_file;
138         }
139         return add_cmds;
140 }
141
142 /* API function documented in wimlib.h  */
143 WIMLIBAPI int
144 wimlib_add_image_multisource(WIMStruct *wim,
145                              const struct wimlib_capture_source *sources,
146                              size_t num_sources,
147                              const tchar *name,
148                              const tchar *config_file,
149                              int add_flags)
150 {
151         int ret;
152         struct wimlib_update_command *add_cmds;
153
154         /* Make sure no reserved fields are set.  */
155         for (size_t i = 0; i < num_sources; i++)
156                 if (sources[i].reserved != 0)
157                         return WIMLIB_ERR_INVALID_PARAM;
158
159         /* Add the new image (initially empty).  */
160         ret = wimlib_add_empty_image(wim, name, NULL);
161         if (ret)
162                 return ret;
163
164         /* Translate the "capture sources" into generic update commands.  */
165         ret = WIMLIB_ERR_NOMEM;
166         add_cmds = capture_sources_to_add_cmds(sources, num_sources,
167                                                add_flags, config_file);
168         if (!add_cmds)
169                 goto out_delete_image;
170
171         /* Delegate the work to wimlib_update_image().  */
172         ret = wimlib_update_image(wim, wim->hdr.image_count, add_cmds,
173                                   num_sources, 0);
174         FREE(add_cmds);
175         if (ret)
176                 goto out_delete_image;
177
178         /* If requested, mark the new image as WIMBoot-compatible.  */
179         if (add_flags & WIMLIB_ADD_FLAG_WIMBOOT) {
180                 ret = xml_set_wimboot(wim->xml_info, wim->hdr.image_count);
181                 if (ret)
182                         goto out_delete_image;
183         }
184
185         /* If requested, set this image as the WIM's bootable image.  */
186         if (add_flags & WIMLIB_ADD_FLAG_BOOT)
187                 wim->hdr.boot_idx = wim->hdr.image_count;
188
189         return 0;
190
191 out_delete_image:
192         /* Unsuccessful; rollback by removing the new image.  */
193         delete_wim_image(wim, wim->hdr.image_count);
194         return ret;
195 }
196
197 /* API function documented in wimlib.h  */
198 WIMLIBAPI int
199 wimlib_add_image(WIMStruct *wim,
200                  const tchar *source,
201                  const tchar *name,
202                  const tchar *config_file,
203                  int add_flags)
204 {
205         /* Use the more general wimlib_add_image_multisource().  */
206         const struct wimlib_capture_source capture_src = {
207                 .fs_source_path = (tchar *)source,
208                 .wim_target_path = WIMLIB_WIM_ROOT_PATH,
209                 .reserved = 0,
210         };
211         return wimlib_add_image_multisource(wim, &capture_src, 1, name,
212                                             config_file, add_flags);
213 }