XBPS Library API 20250531
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 *xhp,
114 xbps_array_t a,
115 const char *s,
117{
118 xbps_dictionary_t pkgd;
119 const char *vpkg;
120
121 assert(xhp);
122 assert(xbps_object_type(a) == XBPS_TYPE_ARRAY);
123 assert(s);
124
125 if ((vpkg = vpkg_user_conf(xhp, s))) {
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)
192{
193 char namebuf[XBPS_NAME_SIZE];
194 xbps_dictionary_t providers;
195 xbps_object_t obj;
196 xbps_object_iterator_t iter;
197 const char *pkg = NULL;
198 const char *pkgname;
199 bool found = false;
200 enum { PKGPATTERN, PKGVER, PKGNAME } match;
201
202 assert(vpkg);
203
204
205 if (xbps_pkgpattern_name(namebuf, sizeof(namebuf), vpkg)) {
206 match = PKGPATTERN;
207 pkgname = namebuf;
208 } else if (xbps_pkg_name(namebuf, sizeof(namebuf), vpkg)) {
209 match = PKGVER;
210 pkgname = namebuf;
211 } else {
212 match = PKGNAME;
213 pkgname = vpkg;
214 }
215
216 providers = xbps_dictionary_get(xhp->vpkgd, pkgname);
217 if (!providers)
218 return NULL;
219
220 iter = xbps_dictionary_iterator(providers);
221 assert(iter);
222
223 while ((obj = xbps_object_iterator_next(iter))) {
224 xbps_string_t rpkg;
225 char buf[XBPS_NAME_SIZE] = {0};
226 const char *vpkg_conf = NULL, *vpkgname = NULL;
227
228 vpkg_conf = xbps_dictionary_keysym_cstring_nocopy(obj);
229 rpkg = xbps_dictionary_get_keysym(providers, obj);
230 pkg = xbps_string_cstring_nocopy(rpkg);
231
232 if (xbps_pkg_version(vpkg_conf)) {
233 if (!xbps_pkg_name(buf, sizeof(buf), vpkg_conf)) {
234 abort();
235 }
236 vpkgname = buf;
237 } else {
238 vpkgname = vpkg_conf;
239 }
240
241 switch (match) {
242 case PKGPATTERN:
243 if (xbps_pkg_version(vpkg_conf)) {
244 if (!xbps_pkgpattern_match(vpkg_conf, vpkg)) {
245 continue;
246 }
247 } else {
248 xbps_warn_printf("invalid: %s\n", vpkg_conf);
249 }
250 break;
251 case PKGVER:
252 if (strcmp(buf, vpkgname) != 0) {
253 continue;
254 }
255 break;
256 case PKGNAME:
257 if (strcmp(vpkg, vpkgname) != 0) {
258 continue;
259 }
260 break;
261 }
262 xbps_dbg_printf("%s: vpkg_conf %s pkg %s vpkgname %s\n", __func__, vpkg_conf, pkg, vpkgname);
263 found = true;
264 break;
265 }
266 xbps_object_iterator_release(iter);
267
268 return found ? pkg : NULL;
269}
270
271xbps_dictionary_t HIDDEN
272xbps_find_virtualpkg_in_conf(struct xbps_handle *xhp,
273 xbps_dictionary_t d,
274 const char *pkg)
275{
276 xbps_object_iterator_t iter;
277 xbps_object_t obj;
278 xbps_dictionary_t providers;
279 xbps_dictionary_t pkgd = NULL;
280 const char *cur;
281
282 if (!xhp->vpkgd_conf)
283 return NULL;
284
285 providers = xbps_dictionary_get(xhp->vpkgd_conf, pkg);
286 if (!providers)
287 return NULL;
288
289 iter = xbps_dictionary_iterator(providers);
290 assert(iter);
291
292 while ((obj = xbps_object_iterator_next(iter))) {
293 xbps_string_t rpkg;
294 char buf[XBPS_NAME_SIZE] = {0};
295 const char *vpkg_conf = NULL, *vpkgname = NULL;
296
297 vpkg_conf = xbps_dictionary_keysym_cstring_nocopy(obj);
298 rpkg = xbps_dictionary_get_keysym(providers, obj);
299 cur = xbps_string_cstring_nocopy(rpkg);
300 assert(cur);
301 if (xbps_pkg_version(vpkg_conf)) {
302 if (!xbps_pkg_name(buf, sizeof(buf), vpkg_conf)) {
303 abort();
304 }
305 vpkgname = buf;
306 } else {
307 vpkgname = vpkg_conf;
308 }
309
310 if (xbps_pkgpattern_version(pkg)) {
311 if (xbps_pkg_version(vpkg_conf)) {
312 if (!xbps_pkgpattern_match(vpkg_conf, pkg)) {
313 continue;
314 }
315 } else {
316 char *vpkgver = xbps_xasprintf("%s-999999_1", vpkg_conf);
317 if (!xbps_pkgpattern_match(vpkgver, pkg)) {
318 free(vpkgver);
319 continue;
320 }
321 free(vpkgver);
322 }
323 } else if (xbps_pkg_version(pkg)) {
324 // XXX: this is the old behaviour of only matching pkgname's,
325 // this is kinda wrong when compared to matching patterns
326 // where all variants are tried.
327 if (!xbps_pkg_name(buf, sizeof(buf), pkg)) {
328 abort();
329 }
330 if (strcmp(buf, vpkgname)) {
331 continue;
332 }
333 } else {
334 if (strcmp(pkg, vpkgname)) {
335 continue;
336 }
337 }
338 xbps_dbg_printf("%s: found: %s %s %s\n", __func__, vpkg_conf, cur, vpkgname);
339
340 /* Try matching vpkg from configuration files */
342 pkgd = match_pkg_by_pattern(d, cur);
343 else if (xbps_pkg_version(cur))
344 pkgd = match_pkg_by_pkgver(d, cur);
345 else
346 pkgd = xbps_dictionary_get(d, cur);
347 break;
348 }
349 xbps_object_iterator_release(iter);
350
351 return pkgd;
352}
353
354xbps_dictionary_t HIDDEN
355xbps_find_virtualpkg_in_dict(struct xbps_handle *xhp,
356 xbps_dictionary_t d,
357 const char *pkg)
358{
359 xbps_object_t obj;
360 xbps_object_iterator_t iter;
361 xbps_dictionary_t pkgd = NULL;
362 const char *vpkg;
363
364 // XXX: this is bad, dict != pkgdb,
365 /* Try matching vpkg via xhp->vpkgd */
366 vpkg = vpkg_user_conf(xhp, pkg);
367 if (vpkg != NULL) {
368 if (xbps_pkgpattern_version(vpkg))
369 pkgd = match_pkg_by_pattern(d, vpkg);
370 else if (xbps_pkg_version(vpkg))
371 pkgd = match_pkg_by_pkgver(d, vpkg);
372 else
373 pkgd = xbps_dictionary_get(d, vpkg);
374
375 if (pkgd)
376 return pkgd;
377 }
378 /* ... otherwise match the first one in dictionary */
379 iter = xbps_dictionary_iterator(d);
380 assert(iter);
381
382 while ((obj = xbps_object_iterator_next(iter))) {
383 pkgd = xbps_dictionary_get_keysym(d, obj);
384 if (xbps_match_virtual_pkg_in_dict(pkgd, pkg)) {
385 xbps_object_iterator_release(iter);
386 return pkgd;
387 }
388 }
389 xbps_object_iterator_release(iter);
390
391 return NULL;
392}
393
394xbps_dictionary_t HIDDEN
395xbps_find_pkg_in_dict(xbps_dictionary_t d, const char *pkg)
396{
397 xbps_dictionary_t pkgd = NULL;
398
400 pkgd = match_pkg_by_pattern(d, pkg);
401 else if (xbps_pkg_version(pkg))
402 pkgd = match_pkg_by_pkgver(d, pkg);
403 else
404 pkgd = xbps_dictionary_get(d, pkg);
405
406 return pkgd;
407}
Generic XBPS structure handler for initialization.
Definition xbps.h:559
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:1329
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