]> wimlib.net Git - wimlib/blob - src/reference.c
win32_set_security_descriptor(): Do not request MAXIMUM_ALLOWED
[wimlib] / src / reference.c
1 /*
2  * reference.c
3  *
4  * Reference resources from external WIM file(s).
5  */
6
7 /*
8  * Copyright (C) 2013 Eric Biggers
9  *
10  * This file is part of wimlib, a library for working with WIM files.
11  *
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)
15  * any later version.
16  *
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
20  * details.
21  *
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/.
24  */
25
26 #ifdef HAVE_CONFIG_H
27 #  include "config.h"
28 #endif
29
30 #include "wimlib.h"
31 #include "wimlib/error.h"
32 #include "wimlib/glob.h"
33 #include "wimlib/lookup_table.h"
34 #include "wimlib/wim.h"
35
36 static int
37 lte_clone_if_new(struct wim_lookup_table_entry *lte, void *_lookup_table)
38 {
39         struct wim_lookup_table *lookup_table = _lookup_table;
40
41         if (lookup_stream(lookup_table, lte->hash))
42                 return 0;  /*  Resource already present.  */
43
44         lte = clone_lookup_table_entry(lte);
45         if (lte == NULL)
46                 return WIMLIB_ERR_NOMEM;
47         lte->out_refcnt = 1;
48         lookup_table_insert(lookup_table, lte);
49         return 0;
50 }
51
52 static int
53 lte_delete_if_new(struct wim_lookup_table_entry *lte, void *_lookup_table)
54 {
55         struct wim_lookup_table *lookup_table = _lookup_table;
56
57         if (lte->out_refcnt) {
58                 lookup_table_unlink(lookup_table, lte);
59                 free_lookup_table_entry(lte);
60         }
61         return 0;
62 }
63
64 /* API function documented in wimlib.h  */
65 WIMLIBAPI int
66 wimlib_reference_resources(WIMStruct *wim,
67                            WIMStruct **resource_wims, unsigned num_resource_wims,
68                            int ref_flags)
69 {
70         int ret;
71         unsigned i;
72
73         if (wim == NULL)
74                 return WIMLIB_ERR_INVALID_PARAM;
75
76         if (num_resource_wims != 0 && resource_wims == NULL)
77                 return WIMLIB_ERR_INVALID_PARAM;
78
79         for (i = 0; i < num_resource_wims; i++)
80                 if (resource_wims[i] == NULL)
81                         return WIMLIB_ERR_INVALID_PARAM;
82
83         for_lookup_table_entry(wim->lookup_table, lte_zero_out_refcnt, NULL);
84
85         for (i = 0; i < num_resource_wims; i++) {
86                 ret = for_lookup_table_entry(resource_wims[i]->lookup_table,
87                                              lte_clone_if_new,
88                                              wim->lookup_table);
89                 if (ret)
90                         goto out_rollback;
91         }
92         return 0;
93
94 out_rollback:
95         for_lookup_table_entry(wim->lookup_table, lte_delete_if_new,
96                                wim->lookup_table);
97         return ret;
98 }
99
100 static int
101 reference_resource_paths(WIMStruct *wim,
102                          const tchar * const *resource_wimfiles,
103                          unsigned num_resource_wimfiles,
104                          int ref_flags,
105                          int open_flags,
106                          wimlib_progress_func_t progress_func)
107 {
108         WIMStruct **resource_wims;
109         unsigned i;
110         int ret;
111
112         resource_wims = CALLOC(num_resource_wimfiles, sizeof(resource_wims[0]));
113         if (!resource_wims)
114                 return WIMLIB_ERR_NOMEM;
115
116         for (i = 0; i < num_resource_wimfiles; i++) {
117                 DEBUG("Referencing resources from path \"%"TS"\"",
118                       resource_wimfiles[i]);
119                 ret = wimlib_open_wim(resource_wimfiles[i], open_flags,
120                                       &resource_wims[i], progress_func);
121                 if (ret)
122                         goto out_free_resource_wims;
123         }
124
125         ret = wimlib_reference_resources(wim, resource_wims,
126                                          num_resource_wimfiles, ref_flags);
127         if (ret)
128                 goto out_free_resource_wims;
129
130         for (i = 0; i < num_resource_wimfiles; i++)
131                 list_add_tail(&resource_wims[i]->subwim_node, &wim->subwims);
132
133         ret = 0;
134         goto out_free_array;
135
136 out_free_resource_wims:
137         for (i = 0; i < num_resource_wimfiles; i++)
138                 wimlib_free(resource_wims[i]);
139 out_free_array:
140         FREE(resource_wims);
141         return ret;
142 }
143
144 static int
145 reference_resource_glob(WIMStruct *wim, const tchar *refglob,
146                         int ref_flags, int open_flags,
147                         wimlib_progress_func_t progress_func)
148 {
149         glob_t globbuf;
150         int ret;
151
152         /* Note: glob() is replaced in Windows native builds.  */
153         ret = tglob(refglob, GLOB_ERR | GLOB_NOSORT, NULL, &globbuf);
154         if (ret) {
155                 if (ret == GLOB_NOMATCH) {
156                         if (ref_flags & WIMLIB_REF_FLAG_GLOB_ERR_ON_NOMATCH) {
157                                 ERROR("Found no files for glob \"%"TS"\"", refglob);
158                                 return WIMLIB_ERR_GLOB_HAD_NO_MATCHES;
159                         } else {
160                                 return reference_resource_paths(wim,
161                                                                 &refglob,
162                                                                 1,
163                                                                 ref_flags,
164                                                                 open_flags,
165                                                                 progress_func);
166                         }
167                 } else {
168                         ERROR_WITH_ERRNO("Failed to process glob \"%"TS"\"", refglob);
169                         if (ret == GLOB_NOSPACE)
170                                 return WIMLIB_ERR_NOMEM;
171                         else
172                                 return WIMLIB_ERR_READ;
173                 }
174         }
175
176         ret = reference_resource_paths(wim,
177                                        (const tchar * const *)globbuf.gl_pathv,
178                                        globbuf.gl_pathc,
179                                        ref_flags,
180                                        open_flags,
181                                        progress_func);
182         globfree(&globbuf);
183         return ret;
184 }
185
186 /* API function documented in wimlib.h  */
187 WIMLIBAPI int
188 wimlib_reference_resource_files(WIMStruct *wim,
189                                 const tchar * const * resource_wimfiles_or_globs,
190                                 unsigned count,
191                                 int ref_flags,
192                                 int open_flags,
193                                 wimlib_progress_func_t progress_func)
194 {
195         unsigned i;
196         int ret;
197
198         if (ref_flags & WIMLIB_REF_FLAG_GLOB_ENABLE) {
199                 for (i = 0; i < count; i++) {
200                         ret = reference_resource_glob(wim,
201                                                       resource_wimfiles_or_globs[i],
202                                                       ref_flags,
203                                                       open_flags,
204                                                       progress_func);
205                         if (ret)
206                                 return ret;
207                 }
208                 return 0;
209         } else {
210                 return reference_resource_paths(wim, resource_wimfiles_or_globs,
211                                                 count, ref_flags,
212                                                 open_flags, progress_func);
213         }
214 }