]> wimlib.net Git - wimlib/blob - src/add_image.c
compiler.h: remove _may_alias_attribute
[wimlib] / src / add_image.c
1 /*
2  * add_image.c - Add an image to a WIMStruct.
3  */
4
5 /*
6  * Copyright (C) 2012-2016 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 /* API function documented in wimlib.h  */
34 WIMLIBAPI int
35 wimlib_add_empty_image(WIMStruct *wim, const tchar *name, int *new_idx_ret)
36 {
37         struct wim_image_metadata *imd;
38         int ret;
39
40         if (wimlib_image_name_in_use(wim, name)) {
41                 ERROR("There is already an image named \"%"TS"\" in the WIM!",
42                       name);
43                 return WIMLIB_ERR_IMAGE_NAME_COLLISION;
44         }
45
46         imd = new_empty_image_metadata();
47         if (!imd)
48                 return WIMLIB_ERR_NOMEM;
49
50         ret = append_image_metadata(wim, imd);
51         if (ret)
52                 goto err_put_imd;
53
54         ret = xml_add_image(wim->xml_info, name);
55         if (ret)
56                 goto err_undo_append;
57
58         if (new_idx_ret)
59                 *new_idx_ret = wim->hdr.image_count;
60         return 0;
61
62 err_undo_append:
63         wim->hdr.image_count--;
64 err_put_imd:
65         put_image_metadata(imd);
66         return ret;
67 }
68
69 /* Translate the 'struct wimlib_capture_source's passed to
70  * wimlib_add_image_multisource() into 'struct wimlib_update_command's for
71  * wimlib_update_image().  */
72 static struct wimlib_update_command *
73 capture_sources_to_add_cmds(const struct wimlib_capture_source *sources,
74                             size_t num_sources,
75                             int add_flags,
76                             const tchar *config_file)
77 {
78         struct wimlib_update_command *add_cmds;
79
80         add_cmds = CALLOC(num_sources, sizeof(add_cmds[0]));
81         if (!add_cmds)
82                 return NULL;
83
84         /* WIMLIB_ADD_FLAG_BOOT is handled by wimlib_add_image_multisource(),
85          * not wimlib_update_image(), so mask it out.
86          *
87          * However, WIMLIB_ADD_FLAG_WIMBOOT is handled by both.  */
88         add_flags &= ~WIMLIB_ADD_FLAG_BOOT;
89
90         for (size_t i = 0; i < num_sources; i++) {
91                 add_cmds[i].op = WIMLIB_UPDATE_OP_ADD;
92                 add_cmds[i].add.fs_source_path = sources[i].fs_source_path;
93                 add_cmds[i].add.wim_target_path = sources[i].wim_target_path;
94                 add_cmds[i].add.add_flags = add_flags;
95                 add_cmds[i].add.config_file = (tchar *)config_file;
96         }
97         return add_cmds;
98 }
99
100 /* API function documented in wimlib.h  */
101 WIMLIBAPI int
102 wimlib_add_image_multisource(WIMStruct *wim,
103                              const struct wimlib_capture_source *sources,
104                              size_t num_sources,
105                              const tchar *name,
106                              const tchar *config_file,
107                              int add_flags)
108 {
109         int ret;
110         struct wimlib_update_command *add_cmds;
111
112         /* Make sure no reserved fields are set.  */
113         for (size_t i = 0; i < num_sources; i++)
114                 if (sources[i].reserved != 0)
115                         return WIMLIB_ERR_INVALID_PARAM;
116
117         /* Add the new image (initially empty).  */
118         ret = wimlib_add_empty_image(wim, name, NULL);
119         if (ret)
120                 return ret;
121
122         /* Translate the "capture sources" into generic update commands.  */
123         ret = WIMLIB_ERR_NOMEM;
124         add_cmds = capture_sources_to_add_cmds(sources, num_sources,
125                                                add_flags, config_file);
126         if (!add_cmds)
127                 goto out_delete_image;
128
129         /* Delegate the work to wimlib_update_image().  */
130         ret = wimlib_update_image(wim, wim->hdr.image_count, add_cmds,
131                                   num_sources, 0);
132         FREE(add_cmds);
133         if (ret)
134                 goto out_delete_image;
135
136         /* If requested, mark the new image as WIMBoot-compatible.  */
137         if (add_flags & WIMLIB_ADD_FLAG_WIMBOOT) {
138                 ret = xml_set_wimboot(wim->xml_info, wim->hdr.image_count);
139                 if (ret)
140                         goto out_delete_image;
141         }
142
143         /* If requested, set this image as the WIM's bootable image.  */
144         if (add_flags & WIMLIB_ADD_FLAG_BOOT)
145                 wim->hdr.boot_idx = wim->hdr.image_count;
146
147         return 0;
148
149 out_delete_image:
150         /* Unsuccessful; rollback by removing the new image.  */
151         delete_wim_image(wim, wim->hdr.image_count);
152         return ret;
153 }
154
155 /* API function documented in wimlib.h  */
156 WIMLIBAPI int
157 wimlib_add_image(WIMStruct *wim,
158                  const tchar *source,
159                  const tchar *name,
160                  const tchar *config_file,
161                  int add_flags)
162 {
163         /* Use the more general wimlib_add_image_multisource().  */
164         const struct wimlib_capture_source capture_src = {
165                 .fs_source_path = (tchar *)source,
166                 .wim_target_path = WIMLIB_WIM_ROOT_PATH,
167                 .reserved = 0,
168         };
169         return wimlib_add_image_multisource(wim, &capture_src, 1, name,
170                                             config_file, add_flags);
171 }