]> wimlib.net Git - wimlib/blob - src/export_image.c
Remove unneeded parameter from compression functions
[wimlib] / src / export_image.c
1 /*
2  * export_image.c
3  */
4
5 /*
6  * Copyright (C) 2012, 2013 Eric Biggers
7  *
8  * This file is part of wimlib, a library for working with WIM files.
9  *
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)
13  * any later version.
14  *
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
18  * details.
19  *
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/.
22  */
23
24 #include "wimlib_internal.h"
25 #include "dentry.h"
26 #include "lookup_table.h"
27 #include "xml.h"
28
29 static int
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)
34 {
35         struct wim_lookup_table_entry *src_lte, *dest_lte;
36         unsigned i;
37
38         inode_unresolve_ltes(inode);
39         for (i = 0; i <= inode->i_num_ads; i++) {
40                 src_lte = inode_stream_lte_unresolved(inode, i,
41                                                       src_lookup_table);
42                 if (src_lte && src_lte->out_refcnt == 0) {
43                         src_lte->out_refcnt = 1;
44                         dest_lte = inode_stream_lte_unresolved(inode, i,
45                                                                dest_lookup_table);
46                         if (!dest_lte) {
47                                 dest_lte = clone_lookup_table_entry(src_lte);
48                                 if (!dest_lte)
49                                         return WIMLIB_ERR_NOMEM;
50                                 list_add_tail(&dest_lte->staging_list, lte_list_head);
51                         }
52                 }
53         }
54         return 0;
55 }
56
57 static void
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)
62 {
63         struct wim_lookup_table_entry *src_lte, *dest_lte;
64         unsigned i;
65         struct wim_dentry *dentry;
66
67         inode_for_each_dentry(dentry, inode)
68                 dentry->refcnt++;
69
70         for (i = 0; i <= inode->i_num_ads; i++) {
71                 src_lte = inode_stream_lte_unresolved(inode, i, src_lookup_table);
72                 if (src_lte) {
73                         dest_lte = inode_stream_lte_unresolved(inode, i,
74                                                                dest_lookup_table);
75                         if (!dest_lte) {
76                                 struct list_head *next;
77
78                                 wimlib_assert(!list_empty(lte_list_head));
79                                 next = lte_list_head->next;
80                                 list_del(next);
81                                 dest_lte = container_of(next,
82                                                         struct wim_lookup_table_entry,
83                                                         staging_list);
84                                 dest_lte->part_number = 1;
85                                 dest_lte->refcnt = 0;
86                                 wimlib_assert(hashes_equal(dest_lte->hash, src_lte->hash));
87                                 lookup_table_insert(dest_lookup_table, dest_lte);
88                         }
89                         dest_lte->refcnt += inode->i_nlink;
90                 }
91         }
92 }
93
94 /*
95  * Copies an image, or all the images, from a WIM file, into another WIM file.
96  */
97 WIMLIBAPI int
98 wimlib_export_image(WIMStruct *src_wim,
99                     int src_image,
100                     WIMStruct *dest_wim,
101                     const tchar *dest_name,
102                     const tchar *dest_description,
103                     int export_flags,
104                     WIMStruct **additional_swms,
105                     unsigned num_additional_swms,
106                     wimlib_progress_func_t progress_func)
107 {
108         int ret;
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;
115
116         if (dest_wim->hdr.total_parts != 1) {
117                 ERROR("Exporting an image to a split WIM is "
118                       "unsupported");
119                 return WIMLIB_ERR_SPLIT_UNSUPPORTED;
120         }
121
122         if (src_image == WIMLIB_ALL_IMAGES) {
123                 if (src_wim->hdr.image_count > 1) {
124
125                         /* multi-image export. */
126
127                         if ((export_flags & WIMLIB_EXPORT_FLAG_BOOT) &&
128                               (src_wim->hdr.boot_idx == 0))
129                         {
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.
134                                  * */
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;
139                         }
140                         if (dest_name || dest_description) {
141                                 ERROR("Image name or image description was "
142                                       "specified, but we are exporting "
143                                       "multiple images");
144                                 return WIMLIB_ERR_INVALID_PARAM;
145                         }
146                         for (int i = 1; i <= src_wim->hdr.image_count; i++) {
147                                 int new_flags = export_flags;
148
149                                 if (i != src_wim->hdr.boot_idx)
150                                         new_flags &= ~WIMLIB_EXPORT_FLAG_BOOT;
151
152                                 ret = wimlib_export_image(src_wim, i, dest_wim,
153                                                           NULL, NULL,
154                                                           new_flags,
155                                                           additional_swms,
156                                                           num_additional_swms,
157                                                           progress_func);
158                                 if (ret != 0)
159                                         return ret;
160                         }
161                         return 0;
162                 } else if (src_wim->hdr.image_count == 1) {
163                         src_image = 1;
164                 } else {
165                         return 0;
166                 }
167         }
168
169         if (!dest_name) {
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);
173         }
174
175         if (!dest_description) {
176                 dest_description = wimlib_get_image_description(src_wim,
177                                                                 src_image);
178                 DEBUG("Using description `%"TS"' for source image %d",
179                       dest_description, src_image);
180         }
181
182         DEBUG("Exporting image %d from `%"TS"'", src_image, src_wim->filename);
183
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;
188         }
189
190         ret = verify_swm_set(src_wim, additional_swms, num_additional_swms);
191         if (ret != 0)
192                 return ret;
193
194         if (num_additional_swms) {
195                 ret = new_joined_lookup_table(src_wim, additional_swms,
196                                               num_additional_swms,
197                                               &joined_tab);
198                 if (ret != 0)
199                         return ret;
200                 src_wim_tab_save = src_wim->lookup_table;
201                 src_wim->lookup_table = joined_tab;
202         }
203
204         ret = select_wim_image(src_wim, src_image);
205         if (ret != 0) {
206                 ERROR("Could not select image %d from the WIM `%"TS"' "
207                       "to export it", src_image, src_wim->filename);
208                 goto out;
209         }
210
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(&lte_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,
221                                                  &lte_list_head);
222                 if (ret != 0)
223                         goto out_free_ltes;
224         }
225
226         ret = xml_export_image(src_wim->wim_info, src_image,
227                                &dest_wim->wim_info, dest_name,
228                                dest_description);
229         if (ret != 0)
230                 goto out_free_ltes;
231
232         sd = src_imd->security_data;
233         ret = add_new_dentry_tree(dest_wim, src_imd->root_dentry, sd);
234         if (ret != 0)
235                 goto out_xml_delete_image;
236
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;
241
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
246          * needed. */
247         sd->refcnt++;
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,
252                                          &lte_list_head);
253         }
254
255         if (export_flags & WIMLIB_EXPORT_FLAG_BOOT)
256                 wimlib_set_boot_idx(dest_wim, dest_wim->hdr.image_count);
257         ret = 0;
258         goto out;
259
260 out_xml_delete_image:
261         xml_delete_image(&dest_wim->wim_info, dest_wim->hdr.image_count + 1);
262 out_free_ltes:
263         {
264                 struct wim_lookup_table_entry *lte, *tmp;
265                 list_for_each_entry_safe(lte, tmp, &lte_list_head, staging_list)
266                         free_lookup_table_entry(lte);
267         }
268
269 out:
270         if (num_additional_swms) {
271                 free_lookup_table(src_wim->lookup_table);
272                 src_wim->lookup_table = src_wim_tab_save;
273         }
274         return ret;
275 }