4 * Reference blobs from external WIM file(s).
8 * Copyright (C) 2013, 2014, 2015 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 https://www.gnu.org/licenses/.
29 #include "wimlib/blob_table.h"
30 #include "wimlib/error.h"
31 #include "wimlib/glob.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 struct reference_info {
39 struct list_head new_blobs;
41 struct blob_table *src_table;
45 init_reference_info(struct reference_info *info, WIMStruct *dest_wim,
48 info->dest_wim = dest_wim;
49 INIT_LIST_HEAD(&info->new_blobs);
50 info->ref_flags = ref_flags;
54 rollback_reference_info(struct reference_info *info)
56 struct blob_descriptor *blob;
58 while (!list_empty(&info->new_blobs)) {
59 blob = list_first_entry(&info->new_blobs,
60 struct blob_descriptor, blob_table_list);
61 list_del(&blob->blob_table_list);
62 blob_table_unlink(info->dest_wim->blob_table, blob);
63 free_blob_descriptor(blob);
68 need_blob(const struct reference_info *info, const struct blob_descriptor *blob)
70 return !lookup_blob(info->dest_wim->blob_table, blob->hash);
74 reference_blob(struct reference_info *info, struct blob_descriptor *blob)
76 blob_table_insert(info->dest_wim->blob_table, blob);
77 list_add(&blob->blob_table_list, &info->new_blobs);
81 blob_clone_if_new(struct blob_descriptor *blob, void *_info)
83 struct reference_info *info = _info;
85 if (need_blob(info, blob)) {
86 blob = clone_blob_descriptor(blob);
88 return WIMLIB_ERR_NOMEM;
89 reference_blob(info, blob);
94 /* API function documented in wimlib.h */
96 wimlib_reference_resources(WIMStruct *wim, WIMStruct **resource_wims,
97 unsigned num_resource_wims, int ref_flags)
100 struct reference_info info;
104 return WIMLIB_ERR_INVALID_PARAM;
106 if (num_resource_wims != 0 && resource_wims == NULL)
107 return WIMLIB_ERR_INVALID_PARAM;
109 if (ref_flags & ~WIMLIB_REF_MASK_PUBLIC)
110 return WIMLIB_ERR_INVALID_PARAM;
112 for (i = 0; i < num_resource_wims; i++)
113 if (resource_wims[i] == NULL)
114 return WIMLIB_ERR_INVALID_PARAM;
116 init_reference_info(&info, wim, ref_flags);
118 for (i = 0; i < num_resource_wims; i++) {
119 ret = for_blob_in_table(resource_wims[i]->blob_table,
120 blob_clone_if_new, &info);
126 rollback_reference_info(&info);
131 blob_gift(struct blob_descriptor *blob, void *_info)
133 struct reference_info *info = _info;
135 blob_table_unlink(info->src_table, blob);
136 if (need_blob(info, blob))
137 reference_blob(info, blob);
139 free_blob_descriptor(blob);
144 reference_resource_path(struct reference_info *info, const tchar *path,
150 ret = wimlib_open_wim_with_progress(path, open_flags, &src_wim,
151 info->dest_wim->progfunc,
152 info->dest_wim->progctx);
156 info->src_table = src_wim->blob_table;
157 for_blob_in_table(src_wim->blob_table, blob_gift, info);
158 wimlib_free(src_wim);
163 reference_resource_paths(struct reference_info *info,
164 const tchar * const *paths, unsigned num_paths,
167 for (unsigned i = 0; i < num_paths; i++) {
168 int ret = reference_resource_path(info, paths[i], open_flags);
176 reference_resource_glob(struct reference_info *info,
177 const tchar *refglob, int open_flags)
182 /* Note: glob() is replaced in Windows native builds. */
183 ret = tglob(refglob, GLOB_ERR | GLOB_NOSORT, NULL, &globbuf);
185 if (ret == GLOB_NOMATCH) {
186 if (info->ref_flags &
187 WIMLIB_REF_FLAG_GLOB_ERR_ON_NOMATCH)
189 ERROR("Found no files for glob \"%"TS"\"", refglob);
190 return WIMLIB_ERR_GLOB_HAD_NO_MATCHES;
192 return reference_resource_path(info,
196 ERROR_WITH_ERRNO("Failed to process glob \"%"TS"\"", refglob);
197 if (ret == GLOB_NOSPACE)
198 return WIMLIB_ERR_NOMEM;
199 return WIMLIB_ERR_READ;
202 ret = reference_resource_paths(info,
203 (const tchar * const *)globbuf.gl_pathv,
211 reference_resource_globs(struct reference_info *info,
212 const tchar * const *globs, unsigned num_globs,
215 for (unsigned i = 0; i < num_globs; i++) {
216 int ret = reference_resource_glob(info, globs[i], open_flags);
223 /* API function documented in wimlib.h */
225 wimlib_reference_resource_files(WIMStruct *wim,
226 const tchar * const *paths_or_globs,
227 unsigned count, int ref_flags, int open_flags)
229 struct reference_info info;
232 if (ref_flags & ~WIMLIB_REF_MASK_PUBLIC)
233 return WIMLIB_ERR_INVALID_PARAM;
235 init_reference_info(&info, wim, ref_flags);
237 if (ref_flags & WIMLIB_REF_FLAG_GLOB_ENABLE)
238 ret = reference_resource_globs(&info, paths_or_globs, count, open_flags);
240 ret = reference_resource_paths(&info, paths_or_globs, count, open_flags);
243 rollback_reference_info(&info);