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/.
24 #include "wimlib_internal.h"
26 #include "lookup_table.h"
30 inode_allocate_needed_ltes(struct wim_inode *inode,
31 struct wim_lookup_table *src_lookup_table,
32 struct wim_lookup_table *dest_lookup_table,
33 struct list_head *lte_list_head)
35 struct wim_lookup_table_entry *src_lte, *dest_lte;
38 inode_unresolve_ltes(inode);
39 for (i = 0; i <= inode->i_num_ads; i++) {
40 src_lte = inode_stream_lte_unresolved(inode, i,
42 if (src_lte && src_lte->out_refcnt == 0) {
43 src_lte->out_refcnt = 1;
44 dest_lte = inode_stream_lte_unresolved(inode, i,
47 dest_lte = clone_lookup_table_entry(src_lte);
49 return WIMLIB_ERR_NOMEM;
50 list_add_tail(&dest_lte->staging_list, lte_list_head);
58 inode_move_ltes_to_table(struct wim_inode *inode,
59 struct wim_lookup_table *src_lookup_table,
60 struct wim_lookup_table *dest_lookup_table,
61 struct list_head *lte_list_head)
63 struct wim_lookup_table_entry *src_lte, *dest_lte;
65 struct wim_dentry *dentry;
67 inode_for_each_dentry(dentry, inode)
70 for (i = 0; i <= inode->i_num_ads; i++) {
71 src_lte = inode_stream_lte_unresolved(inode, i, src_lookup_table);
73 dest_lte = inode_stream_lte_unresolved(inode, i,
76 struct list_head *next;
78 wimlib_assert(!list_empty(lte_list_head));
79 next = lte_list_head->next;
81 dest_lte = container_of(next,
82 struct wim_lookup_table_entry,
84 dest_lte->part_number = 1;
86 wimlib_assert(hashes_equal(dest_lte->hash, src_lte->hash));
87 lookup_table_insert(dest_lookup_table, dest_lte);
89 dest_lte->refcnt += inode->i_nlink;
95 * Copies an image, or all the images, from a WIM file, into another WIM file.
98 wimlib_export_image(WIMStruct *src_wim,
101 const tchar *dest_name,
102 const tchar *dest_description,
104 WIMStruct **additional_swms,
105 unsigned num_additional_swms,
106 wimlib_progress_func_t progress_func)
109 struct wim_security_data *sd;
110 struct wim_lookup_table *joined_tab, *src_wim_tab_save;
111 struct wim_image_metadata *src_imd;
112 struct hlist_node *cur_node;
113 struct list_head lte_list_head;
114 struct wim_inode *inode;
116 if (dest_wim->hdr.total_parts != 1) {
117 ERROR("Exporting an image to a split WIM is "
119 return WIMLIB_ERR_SPLIT_UNSUPPORTED;
122 if (src_image == WIMLIB_ALL_IMAGES) {
123 if (src_wim->hdr.image_count > 1) {
125 /* multi-image export. */
127 if ((export_flags & WIMLIB_EXPORT_FLAG_BOOT) &&
128 (src_wim->hdr.boot_idx == 0))
130 /* Specifying the boot flag on a multi-image
131 * source WIM makes the boot index default to
132 * the bootable image in the source WIM. It is
133 * an error if there is no such bootable image.
135 ERROR("Cannot specify `boot' flag when "
136 "exporting multiple images from a WIM "
137 "with no bootable images");
138 return WIMLIB_ERR_INVALID_PARAM;
140 if (dest_name || dest_description) {
141 ERROR("Image name or image description was "
142 "specified, but we are exporting "
144 return WIMLIB_ERR_INVALID_PARAM;
146 for (int i = 1; i <= src_wim->hdr.image_count; i++) {
147 int new_flags = export_flags;
149 if (i != src_wim->hdr.boot_idx)
150 new_flags &= ~WIMLIB_EXPORT_FLAG_BOOT;
152 ret = wimlib_export_image(src_wim, i, dest_wim,
162 } else if (src_wim->hdr.image_count == 1) {
170 dest_name = wimlib_get_image_name(src_wim, src_image);
171 DEBUG("Using name `%"TS"' for source image %d",
172 dest_name, src_image);
175 if (!dest_description) {
176 dest_description = wimlib_get_image_description(src_wim,
178 DEBUG("Using description `%"TS"' for source image %d",
179 dest_description, src_image);
182 DEBUG("Exporting image %d from `%"TS"'", src_image, src_wim->filename);
184 if (wimlib_image_name_in_use(dest_wim, dest_name)) {
185 ERROR("There is already an image named `%"TS"' in the "
186 "destination WIM", dest_name);
187 return WIMLIB_ERR_IMAGE_NAME_COLLISION;
190 ret = verify_swm_set(src_wim, additional_swms, num_additional_swms);
194 if (num_additional_swms) {
195 ret = new_joined_lookup_table(src_wim, additional_swms,
200 src_wim_tab_save = src_wim->lookup_table;
201 src_wim->lookup_table = joined_tab;
204 ret = select_wim_image(src_wim, src_image);
206 ERROR("Could not select image %d from the WIM `%"TS"' "
207 "to export it", src_image, src_wim->filename);
211 /* Pre-allocate the new lookup table entries that will be needed. This
212 * way, it's not possible to run out of memory part-way through
213 * modifying the lookup table of the destination WIM. */
214 for_lookup_table_entry(src_wim->lookup_table, lte_zero_out_refcnt, NULL);
215 src_imd = wim_get_current_image_metadata(src_wim);
216 INIT_LIST_HEAD(<e_list_head);
217 hlist_for_each_entry(inode, cur_node, &src_imd->inode_list, i_hlist) {
218 ret = inode_allocate_needed_ltes(inode,
219 src_wim->lookup_table,
220 dest_wim->lookup_table,
226 ret = xml_export_image(src_wim->wim_info, src_image,
227 &dest_wim->wim_info, dest_name,
232 sd = src_imd->security_data;
233 ret = add_new_dentry_tree(dest_wim, src_imd->root_dentry, sd);
235 goto out_xml_delete_image;
237 dest_wim->image_metadata[
238 dest_wim->hdr.image_count - 1].inode_list = src_imd->inode_list;
239 if (src_imd->inode_list.first)
240 src_imd->inode_list.first->pprev = NULL;
242 /* All memory allocations have been taken care of, so it's no longer
243 * possible for this function to fail. Go ahead and increment the
244 * reference counts of the dentry tree and security data, then update
245 * the lookup table of the destination WIM and the boot index, if
248 hlist_for_each_entry(inode, cur_node, &src_imd->inode_list, i_hlist) {
249 inode_move_ltes_to_table(inode,
250 src_wim->lookup_table,
251 dest_wim->lookup_table,
255 if (export_flags & WIMLIB_EXPORT_FLAG_BOOT)
256 wimlib_set_boot_idx(dest_wim, dest_wim->hdr.image_count);
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, staging_list)
266 free_lookup_table_entry(lte);
270 if (num_additional_swms) {
271 free_lookup_table(src_wim->lookup_table);
272 src_wim->lookup_table = src_wim_tab_save;