4 * Reference resources from external WIM file(s).
8 * Copyright (C) 2013 Eric Biggers
10 * This file is part of wimlib, a library for working with WIM files.
12 * wimlib is free software; you can redistribute it and/or modify it under the
13 * terms of the GNU General Public License as published by the Free
14 * Software Foundation; either version 3 of the License, or (at your option)
17 * wimlib is distributed in the hope that it will be useful, but WITHOUT ANY
18 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
19 * A PARTICULAR PURPOSE. See the GNU General Public License for more
22 * You should have received a copy of the GNU General Public License
23 * along with wimlib; if not, see http://www.gnu.org/licenses/.
31 #include "wimlib/error.h"
32 #include "wimlib/glob.h"
33 #include "wimlib/lookup_table.h"
34 #include "wimlib/wim.h"
36 #define WIMLIB_REF_MASK_PUBLIC (WIMLIB_REF_FLAG_GLOB_ENABLE | \
37 WIMLIB_REF_FLAG_GLOB_ERR_ON_NOMATCH)
39 #define WIMLIB_REF_FLAG_GIFT 0x80000000
41 struct lookup_tables {
42 struct wim_lookup_table *src_table;
43 struct wim_lookup_table *dest_table;
47 lte_gift(struct wim_lookup_table_entry *lte, void *_tables)
49 struct lookup_tables *tables = _tables;
50 struct wim_lookup_table *src_table = tables->src_table;
51 struct wim_lookup_table *dest_table = tables->dest_table;
53 lookup_table_unlink(src_table, lte);
54 if (lookup_stream(dest_table, lte->hash)) {
55 free_lookup_table_entry(lte);
58 lookup_table_insert(dest_table, lte);
64 lte_clone_if_new(struct wim_lookup_table_entry *lte, void *_lookup_table)
66 struct wim_lookup_table *lookup_table = _lookup_table;
68 if (lookup_stream(lookup_table, lte->hash))
69 return 0; /* Resource already present. */
71 lte = clone_lookup_table_entry(lte);
73 return WIMLIB_ERR_NOMEM;
75 lookup_table_insert(lookup_table, lte);
80 lte_delete_if_new(struct wim_lookup_table_entry *lte, void *_lookup_table)
82 struct wim_lookup_table *lookup_table = _lookup_table;
84 if (lte->out_refcnt) {
85 lookup_table_unlink(lookup_table, lte);
86 free_lookup_table_entry(lte);
92 do_wimlib_reference_resources(WIMStruct *wim, WIMStruct **resource_wims,
93 unsigned num_resource_wims, int ref_flags)
98 if (ref_flags & WIMLIB_REF_FLAG_GIFT) {
99 struct lookup_tables tables;
101 tables.dest_table = wim->lookup_table;
103 for (i = 0; i < num_resource_wims; i++) {
105 tables.src_table = resource_wims[i]->lookup_table;
107 ret = for_lookup_table_entry(resource_wims[i]->lookup_table,
113 for (i = 0; i < num_resource_wims; i++) {
114 ret = for_lookup_table_entry(resource_wims[i]->lookup_table,
115 lte_clone_if_new, wim->lookup_table);
123 for_lookup_table_entry(wim->lookup_table, lte_delete_if_new,
128 /* API function documented in wimlib.h */
130 wimlib_reference_resources(WIMStruct *wim,
131 WIMStruct **resource_wims, unsigned num_resource_wims,
137 return WIMLIB_ERR_INVALID_PARAM;
139 if (num_resource_wims != 0 && resource_wims == NULL)
140 return WIMLIB_ERR_INVALID_PARAM;
142 if (ref_flags & ~WIMLIB_REF_MASK_PUBLIC)
143 return WIMLIB_ERR_INVALID_PARAM;
145 for (i = 0; i < num_resource_wims; i++)
146 if (resource_wims[i] == NULL)
147 return WIMLIB_ERR_INVALID_PARAM;
149 return do_wimlib_reference_resources(wim, resource_wims,
150 num_resource_wims, ref_flags);
154 reference_resource_paths(WIMStruct *wim,
155 const tchar * const *resource_wimfiles,
156 unsigned num_resource_wimfiles,
159 wimlib_progress_func_t progress_func)
161 WIMStruct **resource_wims;
165 resource_wims = CALLOC(num_resource_wimfiles, sizeof(resource_wims[0]));
167 return WIMLIB_ERR_NOMEM;
169 for (i = 0; i < num_resource_wimfiles; i++) {
170 DEBUG("Referencing resources from path \"%"TS"\"",
171 resource_wimfiles[i]);
172 ret = wimlib_open_wim(resource_wimfiles[i], open_flags,
173 &resource_wims[i], progress_func);
175 goto out_free_resource_wims;
178 ret = do_wimlib_reference_resources(wim, resource_wims,
179 num_resource_wimfiles,
180 ref_flags | WIMLIB_REF_FLAG_GIFT);
182 goto out_free_resource_wims;
184 for (i = 0; i < num_resource_wimfiles; i++)
185 list_add_tail(&resource_wims[i]->subwim_node, &wim->subwims);
190 out_free_resource_wims:
191 for (i = 0; i < num_resource_wimfiles; i++)
192 wimlib_free(resource_wims[i]);
199 reference_resource_glob(WIMStruct *wim, const tchar *refglob,
200 int ref_flags, int open_flags,
201 wimlib_progress_func_t progress_func)
206 /* Note: glob() is replaced in Windows native builds. */
207 ret = tglob(refglob, GLOB_ERR | GLOB_NOSORT, NULL, &globbuf);
209 if (ret == GLOB_NOMATCH) {
210 if (ref_flags & WIMLIB_REF_FLAG_GLOB_ERR_ON_NOMATCH) {
211 ERROR("Found no files for glob \"%"TS"\"", refglob);
212 return WIMLIB_ERR_GLOB_HAD_NO_MATCHES;
214 return reference_resource_paths(wim,
222 ERROR_WITH_ERRNO("Failed to process glob \"%"TS"\"", refglob);
223 if (ret == GLOB_NOSPACE)
224 return WIMLIB_ERR_NOMEM;
226 return WIMLIB_ERR_READ;
230 ret = reference_resource_paths(wim,
231 (const tchar * const *)globbuf.gl_pathv,
240 /* API function documented in wimlib.h */
242 wimlib_reference_resource_files(WIMStruct *wim,
243 const tchar * const * resource_wimfiles_or_globs,
247 wimlib_progress_func_t progress_func)
252 if (ref_flags & ~WIMLIB_REF_MASK_PUBLIC)
253 return WIMLIB_ERR_INVALID_PARAM;
255 if (ref_flags & WIMLIB_REF_FLAG_GLOB_ENABLE) {
256 for (i = 0; i < count; i++) {
257 ret = reference_resource_glob(wim,
258 resource_wimfiles_or_globs[i],
267 return reference_resource_paths(wim, resource_wimfiles_or_globs,
269 open_flags, progress_func);