4 * Reference resources from external WIM file(s).
8 * Copyright (C) 2013 Eric Biggers
10 * This file is free software; you can redistribute it and/or modify it under
11 * the terms of the GNU Lesser General Public License as published by the Free
12 * Software Foundation; either version 3 of the License, or (at your option) any
15 * This file is distributed in the hope that it will be useful, but WITHOUT
16 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
17 * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
20 * You should have received a copy of the GNU Lesser General Public License
21 * along with this file; if not, see http://www.gnu.org/licenses/.
29 #include "wimlib/error.h"
30 #include "wimlib/glob.h"
31 #include "wimlib/lookup_table.h"
32 #include "wimlib/wim.h"
34 #define WIMLIB_REF_MASK_PUBLIC (WIMLIB_REF_FLAG_GLOB_ENABLE | \
35 WIMLIB_REF_FLAG_GLOB_ERR_ON_NOMATCH)
37 #define WIMLIB_REF_FLAG_GIFT 0x80000000
39 struct lookup_tables {
40 struct wim_lookup_table *src_table;
41 struct wim_lookup_table *dest_table;
45 lte_gift(struct wim_lookup_table_entry *lte, void *_tables)
47 struct lookup_tables *tables = _tables;
48 struct wim_lookup_table *src_table = tables->src_table;
49 struct wim_lookup_table *dest_table = tables->dest_table;
51 lookup_table_unlink(src_table, lte);
52 if (lookup_stream(dest_table, lte->hash)) {
53 free_lookup_table_entry(lte);
56 lookup_table_insert(dest_table, lte);
62 lte_clone_if_new(struct wim_lookup_table_entry *lte, void *_lookup_table)
64 struct wim_lookup_table *lookup_table = _lookup_table;
66 if (lookup_stream(lookup_table, lte->hash))
67 return 0; /* Resource already present. */
69 lte = clone_lookup_table_entry(lte);
71 return WIMLIB_ERR_NOMEM;
73 lookup_table_insert(lookup_table, lte);
78 lte_delete_if_new(struct wim_lookup_table_entry *lte, void *_lookup_table)
80 struct wim_lookup_table *lookup_table = _lookup_table;
82 if (lte->out_refcnt) {
83 lookup_table_unlink(lookup_table, lte);
84 free_lookup_table_entry(lte);
90 do_wimlib_reference_resources(WIMStruct *wim, WIMStruct **resource_wims,
91 unsigned num_resource_wims, int ref_flags)
96 if (ref_flags & WIMLIB_REF_FLAG_GIFT) {
97 struct lookup_tables tables;
99 tables.dest_table = wim->lookup_table;
101 for (i = 0; i < num_resource_wims; i++) {
103 tables.src_table = resource_wims[i]->lookup_table;
105 ret = for_lookup_table_entry(resource_wims[i]->lookup_table,
111 for (i = 0; i < num_resource_wims; i++) {
112 ret = for_lookup_table_entry(resource_wims[i]->lookup_table,
113 lte_clone_if_new, wim->lookup_table);
121 for_lookup_table_entry(wim->lookup_table, lte_delete_if_new,
126 /* API function documented in wimlib.h */
128 wimlib_reference_resources(WIMStruct *wim,
129 WIMStruct **resource_wims, unsigned num_resource_wims,
135 return WIMLIB_ERR_INVALID_PARAM;
137 if (num_resource_wims != 0 && resource_wims == NULL)
138 return WIMLIB_ERR_INVALID_PARAM;
140 if (ref_flags & ~WIMLIB_REF_MASK_PUBLIC)
141 return WIMLIB_ERR_INVALID_PARAM;
143 for (i = 0; i < num_resource_wims; i++)
144 if (resource_wims[i] == NULL)
145 return WIMLIB_ERR_INVALID_PARAM;
147 return do_wimlib_reference_resources(wim, resource_wims,
148 num_resource_wims, ref_flags);
152 reference_resource_paths(WIMStruct *wim,
153 const tchar * const *resource_wimfiles,
154 unsigned num_resource_wimfiles,
158 WIMStruct **resource_wims;
162 resource_wims = CALLOC(num_resource_wimfiles, sizeof(resource_wims[0]));
164 return WIMLIB_ERR_NOMEM;
166 for (i = 0; i < num_resource_wimfiles; i++) {
167 DEBUG("Referencing resources from path \"%"TS"\"",
168 resource_wimfiles[i]);
169 ret = wimlib_open_wim_with_progress(resource_wimfiles[i],
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)
205 /* Note: glob() is replaced in Windows native builds. */
206 ret = tglob(refglob, GLOB_ERR | GLOB_NOSORT, NULL, &globbuf);
208 if (ret == GLOB_NOMATCH) {
209 if (ref_flags & WIMLIB_REF_FLAG_GLOB_ERR_ON_NOMATCH) {
210 ERROR("Found no files for glob \"%"TS"\"", refglob);
211 return WIMLIB_ERR_GLOB_HAD_NO_MATCHES;
213 return reference_resource_paths(wim,
220 ERROR_WITH_ERRNO("Failed to process glob \"%"TS"\"", refglob);
221 if (ret == GLOB_NOSPACE)
222 return WIMLIB_ERR_NOMEM;
224 return WIMLIB_ERR_READ;
228 ret = reference_resource_paths(wim,
229 (const tchar * const *)globbuf.gl_pathv,
237 /* API function documented in wimlib.h */
239 wimlib_reference_resource_files(WIMStruct *wim,
240 const tchar * const * resource_wimfiles_or_globs,
248 if (ref_flags & ~WIMLIB_REF_MASK_PUBLIC)
249 return WIMLIB_ERR_INVALID_PARAM;
251 if (ref_flags & WIMLIB_REF_FLAG_GLOB_ENABLE) {
252 for (i = 0; i < count; i++) {
253 ret = reference_resource_glob(wim,
254 resource_wimfiles_or_globs[i],
262 return reference_resource_paths(wim, resource_wimfiles_or_globs,
263 count, ref_flags, open_flags);