6 * Copyright (C) 2012, 2013 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/dentry.h"
30 #include "wimlib/error.h"
31 #include "wimlib/lookup_table.h"
32 #include "wimlib/metadata.h"
33 #include "wimlib/swm.h"
34 #include "wimlib/xml.h"
37 inode_allocate_needed_ltes(struct wim_inode *inode,
38 struct wim_lookup_table *src_lookup_table,
39 struct wim_lookup_table *dest_lookup_table,
40 struct list_head *lte_list_head)
42 struct wim_lookup_table_entry *src_lte, *dest_lte;
45 inode_unresolve_ltes(inode);
46 for (i = 0; i <= inode->i_num_ads; i++) {
47 src_lte = inode_stream_lte_unresolved(inode, i,
49 if (src_lte && src_lte->out_refcnt == 0) {
50 src_lte->out_refcnt = 1;
51 dest_lte = inode_stream_lte_unresolved(inode, i,
54 dest_lte = clone_lookup_table_entry(src_lte);
56 return WIMLIB_ERR_NOMEM;
57 list_add_tail(&dest_lte->export_stream_list,
66 inode_move_ltes_to_table(struct wim_inode *inode,
67 struct wim_lookup_table *src_lookup_table,
68 struct wim_lookup_table *dest_lookup_table,
69 struct list_head *lte_list_head)
71 struct wim_lookup_table_entry *src_lte, *dest_lte;
74 for (i = 0; i <= inode->i_num_ads; i++) {
75 src_lte = inode_stream_lte_unresolved(inode, i, src_lookup_table);
77 dest_lte = inode_stream_lte_unresolved(inode, i,
80 struct list_head *next;
82 wimlib_assert(!list_empty(lte_list_head));
83 next = lte_list_head->next;
85 dest_lte = container_of(next,
86 struct wim_lookup_table_entry,
88 dest_lte->part_number = 1;
90 wimlib_assert(hashes_equal(dest_lte->hash, src_lte->hash));
91 lookup_table_insert(dest_lookup_table, dest_lte);
93 dest_lte->refcnt += inode->i_nlink;
99 * Exports an image, or all the images, from a WIM file, into another WIM file.
102 wimlib_export_image(WIMStruct *src_wim,
105 const tchar *dest_name,
106 const tchar *dest_description,
108 WIMStruct **additional_swms,
109 unsigned num_additional_swms,
110 wimlib_progress_func_t progress_func)
113 struct wim_image_metadata *src_imd;
114 struct list_head lte_list_head;
115 struct wim_inode *inode;
117 ret = can_modify_wim(dest_wim);
121 if (src_image == WIMLIB_ALL_IMAGES) {
122 if (src_wim->hdr.image_count > 1) {
124 /* multi-image export. */
126 if ((export_flags & WIMLIB_EXPORT_FLAG_BOOT) &&
127 (src_wim->hdr.boot_idx == 0))
129 /* Specifying the boot flag on a multi-image
130 * source WIM makes the boot index default to
131 * the bootable image in the source WIM. It is
132 * an error if there is no such bootable image.
134 ERROR("Cannot specify `boot' flag when "
135 "exporting multiple images from a WIM "
136 "with no bootable images");
137 return WIMLIB_ERR_INVALID_PARAM;
139 if (dest_name || dest_description) {
140 ERROR("Image name or image description was "
141 "specified, but we are exporting "
143 return WIMLIB_ERR_INVALID_PARAM;
145 for (int i = 1; i <= src_wim->hdr.image_count; i++) {
146 int new_flags = export_flags;
148 if (i != src_wim->hdr.boot_idx)
149 new_flags &= ~WIMLIB_EXPORT_FLAG_BOOT;
151 ret = wimlib_export_image(src_wim, i, dest_wim,
161 } else if (src_wim->hdr.image_count == 1) {
169 dest_name = wimlib_get_image_name(src_wim, src_image);
170 DEBUG("Using name `%"TS"' for source image %d",
171 dest_name, src_image);
174 if (!dest_description) {
175 dest_description = wimlib_get_image_description(src_wim,
177 DEBUG("Using description `%"TS"' for source image %d",
178 dest_description, src_image);
181 DEBUG("Exporting image %d from `%"TS"'", src_image, src_wim->filename);
183 if (wimlib_image_name_in_use(dest_wim, dest_name)) {
184 ERROR("There is already an image named `%"TS"' in the "
185 "destination WIM", dest_name);
186 return WIMLIB_ERR_IMAGE_NAME_COLLISION;
189 ret = verify_swm_set(src_wim, additional_swms, num_additional_swms);
193 ret = wim_checksum_unhashed_streams(src_wim);
196 ret = wim_checksum_unhashed_streams(dest_wim);
200 if (num_additional_swms)
201 merge_lookup_tables(src_wim, additional_swms, num_additional_swms);
203 ret = select_wim_image(src_wim, src_image);
205 ERROR("Could not select image %d from the WIM `%"TS"' "
206 "to export it", src_image, src_wim->filename);
210 /* Pre-allocate the new lookup table entries that will be needed. This
211 * way, it's not possible to run out of memory part-way through
212 * modifying the lookup table of the destination WIM. */
213 for_lookup_table_entry(src_wim->lookup_table, lte_zero_out_refcnt, NULL);
214 src_imd = wim_get_current_image_metadata(src_wim);
215 INIT_LIST_HEAD(<e_list_head);
216 image_for_each_inode(inode, src_imd) {
217 ret = inode_allocate_needed_ltes(inode,
218 src_wim->lookup_table,
219 dest_wim->lookup_table,
225 ret = xml_export_image(src_wim->wim_info, src_image,
226 &dest_wim->wim_info, dest_name,
231 ret = append_image_metadata(dest_wim, src_imd);
233 goto out_xml_delete_image;
235 /* The `struct image_metadata' is now referenced by both the @src_wim
236 * and the @dest_wim. */
238 src_imd->modified = 1;
240 /* All memory allocations have been taken care of, so it's no longer
241 * possible for this function to fail. Go ahead and update the lookup
242 * table of the destination WIM and the boot index, if needed. */
243 image_for_each_inode(inode, src_imd) {
244 inode_move_ltes_to_table(inode,
245 src_wim->lookup_table,
246 dest_wim->lookup_table,
250 if (export_flags & WIMLIB_EXPORT_FLAG_BOOT)
251 dest_wim->hdr.boot_idx = dest_wim->hdr.image_count;
252 if (src_wim->hdr.flags & WIM_HDR_FLAG_RP_FIX)
254 /* Set the reparse point fixup flag on the destination WIM if
255 * the flag is set on the source WIM. */
256 dest_wim->hdr.flags |= WIM_HDR_FLAG_RP_FIX;
260 out_xml_delete_image:
261 xml_delete_image(&dest_wim->wim_info, dest_wim->hdr.image_count + 1);
264 struct wim_lookup_table_entry *lte, *tmp;
265 list_for_each_entry_safe(lte, tmp, <e_list_head, export_stream_list)
266 free_lookup_table_entry(lte);
269 if (num_additional_swms)
270 unmerge_lookup_table(src_wim);