6 * Copyright (C) 2012 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/.
24 #include "wimlib_internal.h"
26 #include "lookup_table.h"
32 struct list_head lte_list_head;
35 static int allocate_lte_if_needed(struct dentry *dentry, void *arg)
37 const WIMStruct *src_wim, *dest_wim;
38 struct list_head *lte_list_head;
41 src_wim = ((struct wim_pair*)arg)->src_wim;
42 dest_wim = ((struct wim_pair*)arg)->dest_wim;
43 lte_list_head = &((struct wim_pair*)arg)->lte_list_head;
44 inode = dentry->d_inode;
46 wimlib_assert(!inode->resolved);
48 for (unsigned i = 0; i <= inode->num_ads; i++) {
49 struct lookup_table_entry *src_lte, *dest_lte;
50 src_lte = inode_stream_lte_unresolved(inode, i,
51 src_wim->lookup_table);
53 if (src_lte && ++src_lte->out_refcnt == 1) {
54 dest_lte = inode_stream_lte_unresolved(inode, i,
55 dest_wim->lookup_table);
58 dest_lte = clone_lookup_table_entry(src_lte);
60 return WIMLIB_ERR_NOMEM;
61 list_add_tail(&dest_lte->staging_list, lte_list_head);
69 * This function takes in a dentry that was previously located only in image(s)
70 * in @src_wim, but now is being added to @dest_wim. For each stream associated
71 * with the dentry, if there is already a lookup table entry for that stream in
72 * the lookup table of the destination WIM file, its reference count is
73 * incrementej. Otherwise, a new lookup table entry is created that points back
74 * to the stream in the source WIM file (through the @hash field combined with
75 * the @wim field of the lookup table entry.)
77 static int add_lte_to_dest_wim(struct dentry *dentry, void *arg)
79 WIMStruct *src_wim, *dest_wim;
82 src_wim = ((struct wim_pair*)arg)->src_wim;
83 dest_wim = ((struct wim_pair*)arg)->dest_wim;
84 inode = dentry->d_inode;
86 wimlib_assert(!inode->resolved);
88 for (unsigned i = 0; i <= inode->num_ads; i++) {
89 struct lookup_table_entry *src_lte, *dest_lte;
90 src_lte = inode_stream_lte_unresolved(inode, i,
91 src_wim->lookup_table);
93 if (!src_lte) /* Empty or nonexistent stream. */
96 dest_lte = inode_stream_lte_unresolved(inode, i,
97 dest_wim->lookup_table);
101 struct list_head *lte_list_head;
102 struct list_head *next;
104 lte_list_head = &((struct wim_pair*)arg)->lte_list_head;
105 wimlib_assert(!list_empty(lte_list_head));
107 next = lte_list_head->next;
109 dest_lte = container_of(next, struct lookup_table_entry,
111 dest_lte->part_number = 1;
112 dest_lte->refcnt = 1;
113 wimlib_assert(hashes_equal(dest_lte->hash, src_lte->hash));
115 lookup_table_insert(dest_wim->lookup_table, dest_lte);
122 * Copies an image, or all the images, from a WIM file, into another WIM file.
124 WIMLIBAPI int wimlib_export_image(WIMStruct *src_wim,
127 const char *dest_name,
128 const char *dest_description,
130 WIMStruct **additional_swms,
131 unsigned num_additional_swms,
132 wimlib_progress_func_t progress_func)
137 struct wim_pair wims;
138 struct wim_security_data *sd;
139 struct lookup_table *joined_tab, *src_wim_tab_save;
141 if (dest_wim->hdr.total_parts != 1) {
142 ERROR("Exporting an image to a split WIM is "
144 return WIMLIB_ERR_SPLIT_UNSUPPORTED;
147 if (src_image == WIMLIB_ALL_IMAGES) {
148 if (src_wim->hdr.image_count > 1) {
150 /* multi-image export. */
152 if ((export_flags & WIMLIB_EXPORT_FLAG_BOOT) &&
153 (src_wim->hdr.boot_idx == 0))
155 /* Specifying the boot flag on a multi-image
156 * source WIM makes the boot index default to
157 * the bootable image in the source WIM. It is
158 * an error if there is no such bootable image.
160 ERROR("Cannot specify `boot' flag when "
161 "exporting multiple images from a WIM "
162 "with no bootable images");
163 return WIMLIB_ERR_INVALID_PARAM;
165 if (dest_name || dest_description) {
166 ERROR("Image name or image description was "
167 "specified, but we are exporting "
169 return WIMLIB_ERR_INVALID_PARAM;
171 for (i = 1; i <= src_wim->hdr.image_count; i++) {
172 int new_flags = export_flags;
174 if (i != src_wim->hdr.boot_idx)
175 new_flags &= ~WIMLIB_EXPORT_FLAG_BOOT;
177 ret = wimlib_export_image(src_wim, i, dest_wim,
187 } else if (src_wim->hdr.image_count == 1) {
195 dest_name = wimlib_get_image_name(src_wim, src_image);
196 DEBUG("Using name `%s' for source image %d",
197 dest_name, src_image);
200 if (!dest_description) {
201 dest_description = wimlib_get_image_description(src_wim,
203 DEBUG("Using description `%s' for source image %d",
204 dest_description, src_image);
207 DEBUG("Exporting image %d from `%s'", src_image, src_wim->filename);
209 if (wimlib_image_name_in_use(dest_wim, dest_name)) {
210 ERROR("There is already an image named `%s' in the "
211 "destination WIM", dest_name);
212 return WIMLIB_ERR_IMAGE_NAME_COLLISION;
215 ret = verify_swm_set(src_wim, additional_swms, num_additional_swms);
219 if (num_additional_swms) {
220 ret = new_joined_lookup_table(src_wim, additional_swms,
225 src_wim_tab_save = src_wim->lookup_table;
226 src_wim->lookup_table = joined_tab;
229 ret = select_wim_image(src_wim, src_image);
231 ERROR("Could not select image %d from the WIM `%s' "
232 "to export it", src_image, src_wim->filename);
236 /* Pre-allocate the new lookup table entries that will be needed. This
237 * way, it's not possible to run out of memory part-way through
238 * modifying the lookup table of the destination WIM. */
239 wims.src_wim = src_wim;
240 wims.dest_wim = dest_wim;
241 INIT_LIST_HEAD(&wims.lte_list_head);
242 for_lookup_table_entry(src_wim->lookup_table, lte_zero_out_refcnt, NULL);
243 root = wim_root_dentry(src_wim);
244 for_dentry_in_tree(root, dentry_unresolve_ltes, NULL);
245 ret = for_dentry_in_tree(root, allocate_lte_if_needed, &wims);
249 ret = xml_export_image(src_wim->wim_info, src_image,
250 &dest_wim->wim_info, dest_name, dest_description);
254 sd = wim_security_data(src_wim);
255 ret = add_new_dentry_tree(dest_wim, root, sd);
257 goto out_xml_delete_image;
260 /* All memory allocations have been taken care of, so it's no longer
261 * possible for this function to fail. Go ahead and increment the
262 * reference counts of the dentry tree and security data, then update
263 * the lookup table of the destination WIM and the boot index, if
265 for_dentry_in_tree(root, increment_dentry_refcnt, NULL);
267 for_dentry_in_tree(root, add_lte_to_dest_wim, &wims);
268 wimlib_assert(list_empty(&wims.lte_list_head));
270 if (export_flags & WIMLIB_EXPORT_FLAG_BOOT) {
271 DEBUG("Setting boot_idx to %d", dest_wim->hdr.image_count);
272 wimlib_set_boot_idx(dest_wim, dest_wim->hdr.image_count);
277 out_xml_delete_image:
278 xml_delete_image(&dest_wim->wim_info, dest_wim->hdr.image_count);
281 struct lookup_table_entry *lte, *tmp;
282 list_for_each_entry_safe(lte, tmp, &wims.lte_list_head, staging_list)
283 free_lookup_table_entry(lte);
287 if (num_additional_swms) {
288 free_lookup_table(src_wim->lookup_table);
289 src_wim->lookup_table = src_wim_tab_save;