XBPS Library API 20240111
The X Binary Package System
plist_find.c
1/*-
2 * Copyright (c) 2008-2016 Juan Romero Pardines.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
15 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
16 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
17 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
18 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
19 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
20 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
21 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
23 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 */
25
26#include <stdio.h>
27#include <stdbool.h>
28#include <stdlib.h>
29#include <string.h>
30#include <errno.h>
31#include <fcntl.h>
32#include <dirent.h>
33#include <pthread.h>
34
35#include "xbps_api_impl.h"
36
37static xbps_dictionary_t
38get_pkg_in_array(xbps_array_t array, const char *str, xbps_trans_type_t tt, bool virtual)
39{
40 xbps_object_t obj;
41 xbps_object_iterator_t iter;
43 bool found = false;
44
45 assert(array);
46 assert(str);
47
48 iter = xbps_array_iterator(array);
49 if (!iter)
50 return NULL;
51
52 while ((obj = xbps_object_iterator_next(iter))) {
53 const char *pkgver = NULL;
54 char pkgname[XBPS_NAME_SIZE] = {0};
55
56 if (!xbps_dictionary_get_cstring_nocopy(obj, "pkgver", &pkgver)) {
57 continue;
58 }
59 if (virtual) {
60 /*
61 * Check if package pattern matches
62 * any virtual package version in dictionary.
63 */
64 found = xbps_match_virtual_pkg_in_dict(obj, str);
65 if (found)
66 break;
67 } else if (xbps_pkgpattern_version(str)) {
68 /* match by pattern against pkgver */
69 if (xbps_pkgpattern_match(pkgver, str)) {
70 found = true;
71 break;
72 }
73 } else if (xbps_pkg_version(str)) {
74 /* match by exact pkgver */
75 if (strcmp(str, pkgver) == 0) {
76 found = true;
77 break;
78 }
79 } else {
80 if (!xbps_pkg_name(pkgname, sizeof(pkgname), pkgver)) {
81 abort();
82 }
83 /* match by pkgname */
84 if (strcmp(pkgname, str) == 0) {
85 found = true;
86 break;
87 }
88 }
89 }
90 xbps_object_iterator_release(iter);
91
92 ttype = xbps_transaction_pkg_type(obj);
93 if (found && tt && (ttype != tt)) {
94 found = false;
95 }
96 if (!found) {
97 errno = ENOENT;
98 return NULL;
99 }
100 return obj;
101}
102
103xbps_dictionary_t HIDDEN
104xbps_find_pkg_in_array(xbps_array_t a, const char *s, xbps_trans_type_t tt)
105{
106 assert(xbps_object_type(a) == XBPS_TYPE_ARRAY);
107 assert(s);
108
109 return get_pkg_in_array(a, s, tt, false);
110}
111
112xbps_dictionary_t HIDDEN
113xbps_find_virtualpkg_in_array(struct xbps_handle *x,
114 xbps_array_t a,
115 const char *s,
117{
118 xbps_dictionary_t pkgd;
119 const char *vpkg;
120
121 assert(x);
122 assert(xbps_object_type(a) == XBPS_TYPE_ARRAY);
123 assert(s);
124
125 if ((vpkg = vpkg_user_conf(x, s, false))) {
126 if ((pkgd = get_pkg_in_array(a, vpkg, tt, true)))
127 return pkgd;
128 }
129
130 return get_pkg_in_array(a, s, tt, true);
131}
132
133static xbps_dictionary_t
134match_pkg_by_pkgver(xbps_dictionary_t repod, const char *p)
135{
136 xbps_dictionary_t d = NULL;
137 const char *pkgver = NULL;
138 char pkgname[XBPS_NAME_SIZE] = {0};
139
140 assert(repod);
141 assert(p);
142
143 /* exact match by pkgver */
144 if (!xbps_pkg_name(pkgname, sizeof(pkgname), p))
145 return NULL;
146
147 d = xbps_dictionary_get(repod, pkgname);
148 if (d) {
149 xbps_dictionary_get_cstring_nocopy(d, "pkgver", &pkgver);
150 if (strcmp(pkgver, p)) {
151 d = NULL;
152 errno = ENOENT;
153 }
154 }
155
156 return d;
157}
158
159static xbps_dictionary_t
160match_pkg_by_pattern(xbps_dictionary_t repod, const char *p)
161{
162 xbps_dictionary_t d = NULL;
163 const char *pkgver = NULL;
164 char pkgname[XBPS_NAME_SIZE] = {0};
165
166 assert(repod);
167 assert(p);
168
169 /* match by pkgpattern in pkgver */
170 if (!xbps_pkgpattern_name(pkgname, sizeof(pkgname), p)) {
171 if (xbps_pkg_name(pkgname, sizeof(pkgname), p)) {
172 return match_pkg_by_pkgver(repod, p);
173 }
174 return NULL;
175 }
176
177 d = xbps_dictionary_get(repod, pkgname);
178 if (d) {
179 xbps_dictionary_get_cstring_nocopy(d, "pkgver", &pkgver);
180 assert(pkgver);
181 if (!xbps_pkgpattern_match(pkgver, p)) {
182 d = NULL;
183 errno = ENOENT;
184 }
185 }
186
187 return d;
188}
189
190const char HIDDEN *
191vpkg_user_conf(struct xbps_handle *xhp, const char *vpkg, bool only_conf)
192{
193 xbps_dictionary_t d;
194 xbps_object_t obj;
195 xbps_object_iterator_t iter;
196 const char *pkg = NULL;
197 bool found = false;
198
199 assert(xhp);
200 assert(vpkg);
201
202 if (only_conf) {
203 d = xhp->vpkgd_conf;
204 } else {
205 d = xhp->vpkgd;
206 /* init pkgdb just in case to detect vpkgs */
207 (void)xbps_pkgdb_init(xhp);
208 }
209
210 if (d == NULL)
211 return NULL;
212
213 iter = xbps_dictionary_iterator(d);
214 assert(iter);
215
216 while ((obj = xbps_object_iterator_next(iter))) {
217 xbps_string_t rpkg;
218 char buf[XBPS_NAME_SIZE] = {0};
219 char *vpkgver = NULL, *vpkgname = NULL;
220 const char *vpkg_conf = NULL;
221
222 vpkg_conf = xbps_dictionary_keysym_cstring_nocopy(obj);
223 rpkg = xbps_dictionary_get_keysym(xhp->vpkgd, obj);
224 pkg = xbps_string_cstring_nocopy(rpkg);
225
226 if (xbps_pkg_version(vpkg_conf)) {
227 if (!xbps_pkg_name(buf, sizeof(buf), vpkg_conf)) {
228 abort();
229 }
230 vpkgname = strdup(buf);
231 } else {
232 vpkgname = strdup(vpkg_conf);
233 }
234 assert(vpkgname);
235
236 if (xbps_pkgpattern_version(vpkg)) {
237 if (xbps_pkg_version(vpkg_conf)) {
238 if (!xbps_pkgpattern_match(vpkg_conf, vpkg)) {
239 free(vpkgname);
240 continue;
241 }
242 } else {
243 vpkgver = xbps_xasprintf("%s-999999_1", vpkg_conf);
244 if (!xbps_pkgpattern_match(vpkgver, vpkg)) {
245 free(vpkgver);
246 free(vpkgname);
247 continue;
248 }
249 free(vpkgver);
250 }
251 } else if (xbps_pkg_version(vpkg)) {
252 if (!xbps_pkg_name(buf, sizeof(buf), vpkg)) {
253 abort();
254 }
255 if (strcmp(buf, vpkgname)) {
256 free(vpkgname);
257 continue;
258 }
259 } else {
260 if (strcmp(vpkg, vpkgname)) {
261 free(vpkgname);
262 continue;
263 }
264 }
265 xbps_dbg_printf("%s: vpkg_conf %s pkg %s vpkgname %s\n", __func__, vpkg_conf, pkg, vpkgname);
266 free(vpkgname);
267 found = true;
268 break;
269 }
270 xbps_object_iterator_release(iter);
271
272 return found ? pkg : NULL;
273}
274
275xbps_dictionary_t HIDDEN
276xbps_find_virtualpkg_in_conf(struct xbps_handle *xhp,
277 xbps_dictionary_t d,
278 const char *pkg)
279{
280 xbps_dictionary_t pkgd;
281 const char *vpkg;
282
283 /* Try matching vpkg from configuration files */
284 vpkg = vpkg_user_conf(xhp, pkg, true);
285 if (vpkg != NULL) {
286 if (xbps_pkgpattern_version(vpkg))
287 pkgd = match_pkg_by_pattern(d, vpkg);
288 else if (xbps_pkg_version(vpkg))
289 pkgd = match_pkg_by_pkgver(d, vpkg);
290 else
291 pkgd = xbps_dictionary_get(d, vpkg);
292
293 if (pkgd)
294 return pkgd;
295 }
296
297 return NULL;
298}
299
300xbps_dictionary_t HIDDEN
301xbps_find_virtualpkg_in_dict(struct xbps_handle *xhp,
302 xbps_dictionary_t d,
303 const char *pkg)
304{
305 xbps_object_t obj;
306 xbps_object_iterator_t iter;
307 xbps_dictionary_t pkgd = NULL;
308 const char *vpkg;
309
310 /* Try matching vpkg via xhp->vpkgd */
311 vpkg = vpkg_user_conf(xhp, pkg, false);
312 if (vpkg != NULL) {
313 if (xbps_pkgpattern_version(vpkg))
314 pkgd = match_pkg_by_pattern(d, vpkg);
315 else if (xbps_pkg_version(vpkg))
316 pkgd = match_pkg_by_pkgver(d, vpkg);
317 else
318 pkgd = xbps_dictionary_get(d, vpkg);
319
320 if (pkgd)
321 return pkgd;
322 }
323 /* ... otherwise match the first one in dictionary */
324 iter = xbps_dictionary_iterator(d);
325 assert(iter);
326
327 while ((obj = xbps_object_iterator_next(iter))) {
328 pkgd = xbps_dictionary_get_keysym(d, obj);
329 if (xbps_match_virtual_pkg_in_dict(pkgd, pkg)) {
330 xbps_object_iterator_release(iter);
331 return pkgd;
332 }
333 }
334 xbps_object_iterator_release(iter);
335
336 return NULL;
337}
338
339xbps_dictionary_t HIDDEN
340xbps_find_pkg_in_dict(xbps_dictionary_t d, const char *pkg)
341{
342 xbps_dictionary_t pkgd = NULL;
343
345 pkgd = match_pkg_by_pattern(d, pkg);
346 else if (xbps_pkg_version(pkg))
347 pkgd = match_pkg_by_pkgver(d, pkg);
348 else
349 pkgd = xbps_dictionary_get(d, pkg);
350
351 return pkgd;
352}
Generic XBPS structure handler for initialization.
Definition xbps.h:550
bool xbps_match_virtual_pkg_in_dict(xbps_dictionary_t pkgd, const char *str)
Definition plist_match.c:58
xbps_trans_type_t xbps_transaction_pkg_type(xbps_dictionary_t pkg_repod)
xbps_trans_type_t
Definition xbps.h:1320
char * xbps_xasprintf(const char *fmt,...) __attribute__((format(printf
const char * xbps_pkgpattern_version(const char *pattern)
Definition util.c:317
bool xbps_pkg_name(char *dst, size_t len, const char *pkg)
Definition util.c:253
int xbps_pkgpattern_match(const char *pkgver, const char *pattern)
Definition util.c:530
const char * xbps_pkg_version(const char *pkg)
Definition util.c:124
bool xbps_pkgpattern_name(char *dst, size_t len, const char *pattern)
Definition util.c:289