XBPS Library API 20250813
The X Binary Package System
util.c
1/*-
2 * Copyright (c) 2008-2015 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 "compat.h"
27
28#include <sys/stat.h>
29#include <sys/utsname.h>
30
31#include <ctype.h>
32#include <errno.h>
33#include <fnmatch.h>
34#include <libgen.h>
35#include <limits.h>
36#include <stdarg.h>
37#include <stdbool.h>
38#include <stdio.h>
39#include <stdlib.h>
40#include <string.h>
41#include <unistd.h>
42
43#include "xbps_api_impl.h"
44
45static bool
46is_revision(const char *str)
47{
48 if (str == NULL || *str == '\0')
49 return false;
50 /* allow underscore for accepting perl-Digest-1.17_01_1 etc. */
51 while (isdigit((unsigned char)*str) || *str == '_')
52 ++str;
53 return *str == '\0';
54}
55
56/**
57 * @file lib/util.c
58 * @brief Utility routines
59 * @defgroup util Utility functions
60 */
61bool
63{
64 assert(uri != NULL);
65
66 if ((strncmp(uri, "http://", 7) == 0) ||
67 (strncmp(uri, "https://", 8) == 0) ||
68 (strncmp(uri, "ftp://", 6) == 0))
69 return true;
70
71 return false;
72}
73
74int
75xbps_pkg_is_installed(struct xbps_handle *xhp, const char *pkg)
76{
77 xbps_dictionary_t dict;
78 pkg_state_t state;
79
80 assert(xhp);
81 assert(pkg);
82
83 if (((dict = xbps_pkgdb_get_virtualpkg(xhp, pkg)) == NULL) &&
84 ((dict = xbps_pkgdb_get_pkg(xhp, pkg)) == NULL))
85 return 0; /* not installed */
86 /*
87 * Check that package state is fully installed, not
88 * unpacked or something else.
89 */
90 if (xbps_pkg_state_dictionary(dict, &state) != 0)
91 return -1; /* error */
92 if (state == XBPS_PKG_STATE_INSTALLED || state == XBPS_PKG_STATE_UNPACKED)
93 return 1;
94
95 return 0; /* not fully installed */
96}
97
98bool
99xbps_pkg_is_ignored(struct xbps_handle *xhp, const char *pkg)
100{
101 char pkgname[XBPS_NAME_SIZE];
102 bool rv = false;
103
104 assert(xhp);
105 assert(pkg);
106
107 if (!xhp->ignored_pkgs)
108 return false;
109
110 if (xbps_pkgpattern_name(pkgname, XBPS_NAME_SIZE, pkg) ||
111 xbps_pkg_name(pkgname, XBPS_NAME_SIZE, pkg)) {
112 rv = xbps_match_string_in_array(xhp->ignored_pkgs, pkgname);
113 return rv;
114 }
115
116 return xbps_match_string_in_array(xhp->ignored_pkgs, pkg);
117}
118
119const char *
120xbps_pkg_version(const char *pkg)
121{
122 const char *p, *r;
123 size_t p_len;
124
125 assert(pkg);
126
127 if ((p = strrchr(pkg, '-')) == NULL)
128 return NULL;
129
130 ++p; /* skip first '-' */
131 p_len = strlen(p);
132 for (unsigned int i = 0; i < p_len; i++) {
133 if (p[i] == '_')
134 break;
135 if (isdigit((unsigned char)p[i]) && (r = strchr(p + i + 1, '_'))) {
136 if (!is_revision(r + 1)) {
137 break;
138 }
139 return p;
140 }
141 }
142 return NULL;
143}
144
145char *
146xbps_binpkg_pkgver(const char *pkg)
147{
148 const char *fname;
149 char *p, *p1, *res;
150 unsigned int len;
151
152 assert(pkg);
153
154 /* skip path if found, only interested in filename */
155 if ((fname = strrchr(pkg, '/')))
156 fname++;
157 else
158 fname = pkg;
159
160 /* 5 == .xbps */
161 if ((len = strlen(fname)) < 5)
162 return NULL;
163 len -= 5;
164
165 p = malloc(len+1);
166 assert(p);
167 (void)memcpy(p, fname, len);
168 p[len] = '\0';
169 if (!(p1 = strrchr(p, '.'))) {
170 free(p);
171 return NULL;
172 }
173 p[strlen(p)-strlen(p1)] = '\0';
174
175 /* sanity check it's a proper pkgver string */
176 if (xbps_pkg_version(p) == NULL) {
177 free(p);
178 return NULL;
179 }
180 res = strdup(p);
181 assert(res);
182
183 free(p);
184 return res;
185}
186
187char *
188xbps_binpkg_arch(const char *pkg)
189{
190 const char *fname;
191 char *p, *p1, *res;
192 unsigned int len;
193
194 assert(pkg);
195
196 /* skip path if found, only interested in filename */
197 if ((fname = strrchr(pkg, '/')))
198 fname++;
199 else
200 fname = pkg;
201
202 /* 5 == .xbps */
203 if ((len = strlen(fname)) < 5)
204 return NULL;
205 len -= 5;
206
207 p = malloc(len+1);
208 assert(p);
209 (void)memcpy(p, fname, len);
210 p[len] = '\0';
211 if (!(p1 = strrchr(p, '.'))) {
212 free(p);
213 return NULL;
214 }
215 res = strdup(p1 + 1);
216 assert(res);
217
218 free(p);
219 return res;
220}
221
222const char *
223xbps_pkg_revision(const char *pkg)
224{
225 const char *p, *r;
226 size_t p_len;
227
228 assert(pkg);
229
230 if ((p = strrchr(pkg, '-')) == NULL)
231 return NULL;
232
233 ++p; /* skip first '-' */
234 p_len = strlen(p);
235 for (unsigned int i = 0; i < p_len; i++) {
236 if (p[i] == '_')
237 break;
238 if (isdigit((unsigned char)p[i]) && (r = strchr(p + i + 1, '_'))) {
239 if (!is_revision(r + 1)) {
240 break;
241 }
242 return strrchr(r, '_') + 1;
243 }
244 }
245 return NULL;
246}
247
248bool
249xbps_pkg_name(char *dst, size_t len, const char *pkg)
250{
251 const char *p, *r;
252 size_t plen;
253 bool valid = false;
254
255 assert(dst);
256 assert(pkg);
257
258 if ((p = strrchr(pkg, '-')) == NULL)
259 return false;
260
261 plen = strlen(p);
262 /* i = 1 skips first '-' */
263 for (unsigned int i = 1; i < plen; i++) {
264 if (p[i] == '_')
265 break;
266 if (isdigit((unsigned char)p[i]) && (r = strchr(p + i + 1, '_'))) {
267 valid = is_revision(r + 1);
268 break;
269 }
270 }
271 if (!valid)
272 return false;
273
274 plen = strlen(pkg) - strlen(p) + 1;
275 if (plen > len)
276 return false;
277
278 memcpy(dst, pkg, plen-1);
279 dst[plen-1] = '\0';
280
281 return true;
282}
283
284bool
285xbps_pkgpattern_name(char *dst, size_t len, const char *pkg)
286{
287 const char *res;
288 size_t plen;
289
290 assert(dst);
291 assert(pkg);
292
293 if ((res = strpbrk(pkg, "><*?[]")) == NULL)
294 return false;
295
296 plen = strlen(pkg) - strlen(res) + 1;
297 if (strlen(pkg) < plen-2)
298 return false;
299
300 if (pkg[plen-2] == '-')
301 plen--;
302
303 if (plen > len)
304 return false;
305
306 memcpy(dst, pkg, plen-1);
307 dst[plen-1] = '\0';
308
309 return true;
310}
311
312const char *
314{
315 assert(pkg != NULL);
316
317 return strpbrk(pkg, "><*?[]");
318}
319
320ssize_t
321xbps_pkg_path(struct xbps_handle *xhp, char *dst, size_t dstsz, xbps_dictionary_t pkgd)
322{
323 const char *pkgver = NULL, *arch = NULL, *repoloc = NULL;
324 int l;
325
326 if (!xbps_dictionary_get_cstring_nocopy(pkgd, "pkgver", &pkgver) ||
327 !xbps_dictionary_get_cstring_nocopy(pkgd, "architecture", &arch) ||
328 !xbps_dictionary_get_cstring_nocopy(pkgd, "repository", &repoloc))
329 return -EINVAL;
330
331 if (xbps_repository_is_remote(repoloc))
332 repoloc = xhp->cachedir;
333
334 l = snprintf(dst, dstsz, "%s/%s.%s.xbps", repoloc, pkgver, arch);
335 if (l < 0 || (size_t)l >= dstsz)
336 return -ENOBUFS;
337
338 return l;
339}
340
341ssize_t
342xbps_pkg_url(struct xbps_handle *xhp UNUSED, char *dst, size_t dstsz, xbps_dictionary_t pkgd)
343{
344 const char *pkgver = NULL, *arch = NULL, *repoloc = NULL;
345 int l;
346
347 if (!xbps_dictionary_get_cstring_nocopy(pkgd, "pkgver", &pkgver) ||
348 !xbps_dictionary_get_cstring_nocopy(pkgd, "architecture", &arch) ||
349 !xbps_dictionary_get_cstring_nocopy(pkgd, "repository", &repoloc))
350 return -EINVAL;
351
352 l = snprintf(dst, dstsz, "%s/%s.%s.xbps", repoloc, pkgver, arch);
353 if (l < 0 || (size_t)l >= dstsz)
354 return -ENOBUFS;
355
356 return l;
357}
358
359ssize_t
360xbps_pkg_path_or_url(struct xbps_handle *xhp UNUSED, char *dst, size_t dstsz, xbps_dictionary_t pkgd)
361{
362 const char *pkgver = NULL, *arch = NULL, *repoloc = NULL;
363 int l;
364
365 if (!xbps_dictionary_get_cstring_nocopy(pkgd, "pkgver", &pkgver) ||
366 !xbps_dictionary_get_cstring_nocopy(pkgd, "architecture", &arch) ||
367 !xbps_dictionary_get_cstring_nocopy(pkgd, "repository", &repoloc))
368 return -EINVAL;
369
370 if (xbps_repository_is_remote(repoloc)) {
371 l = snprintf(dst, dstsz, "%s/%s.%s.xbps", xhp->cachedir,
372 pkgver, arch);
373 if (l < 0 || (size_t)l >= dstsz)
374 return -ENOBUFS;
375 if (access(dst, R_OK) == 0)
376 return l;
377 if (errno != ENOENT)
378 return -errno;
379 }
380
381 l = snprintf(dst, dstsz, "%s/%s.%s.xbps", repoloc, pkgver, arch);
382 if (l < 0 || (size_t)l >= dstsz)
383 return -ENOBUFS;
384
385 return l;
386}
387
388char *
389xbps_repository_pkg_path(struct xbps_handle *xhp, xbps_dictionary_t pkg_repod)
390{
391 const char *pkgver, *arch, *repoloc;
392 char *lbinpkg = NULL;
393
394 assert(xhp);
395 assert(xbps_object_type(pkg_repod) == XBPS_TYPE_DICTIONARY);
396
397 if (!xbps_dictionary_get_cstring_nocopy(pkg_repod,
398 "pkgver", &pkgver))
399 return NULL;
400 if (!xbps_dictionary_get_cstring_nocopy(pkg_repod,
401 "architecture", &arch))
402 return NULL;
403 if (!xbps_dictionary_get_cstring_nocopy(pkg_repod,
404 "repository", &repoloc))
405 return NULL;
406
407 if (xbps_repository_is_remote(repoloc)) {
408 /*
409 * First check if binpkg is available in cachedir.
410 */
411 lbinpkg = xbps_xasprintf("%s/%s.%s.xbps", xhp->cachedir,
412 pkgver, arch);
413 if (access(lbinpkg, R_OK) == 0)
414 return lbinpkg;
415
416 free(lbinpkg);
417 }
418 /*
419 * Local and remote repositories use the same path.
420 */
421 return xbps_xasprintf("%s/%s.%s.xbps", repoloc, pkgver, arch);
422}
423
424bool
425xbps_binpkg_exists(struct xbps_handle *xhp, xbps_dictionary_t pkgd)
426{
427 char path[PATH_MAX];
428 const char *pkgver, *arch, *repoloc;
429
430 assert(xhp);
431 assert(xbps_object_type(pkgd) == XBPS_TYPE_DICTIONARY);
432
433 if (!xbps_dictionary_get_cstring_nocopy(pkgd,
434 "pkgver", &pkgver))
435 return NULL;
436 if (!xbps_dictionary_get_cstring_nocopy(pkgd,
437 "architecture", &arch))
438 return NULL;
439 if (!xbps_dictionary_get_cstring_nocopy(pkgd,
440 "repository", &repoloc))
441 return NULL;
442
443 snprintf(path, sizeof(path), "%s/%s.%s.xbps",
444 xbps_repository_is_remote(repoloc) ? xhp->cachedir : repoloc,
445 pkgver, arch);
446
447 return access(path, R_OK) == 0;
448}
449
450bool
451xbps_remote_binpkg_exists(struct xbps_handle *xhp, xbps_dictionary_t pkgd)
452{
453 char path[PATH_MAX];
454 const char *pkgver, *arch;
455
456 assert(xhp);
457 assert(xbps_object_type(pkgd) == XBPS_TYPE_DICTIONARY);
458
459 if (!xbps_dictionary_get_cstring_nocopy(pkgd,
460 "pkgver", &pkgver))
461 return NULL;
462 if (!xbps_dictionary_get_cstring_nocopy(pkgd,
463 "architecture", &arch))
464 return NULL;
465
466 snprintf(path, sizeof(path), "%s/%s.%s.xbps.sig2", xhp->cachedir,
467 pkgver, arch);
468
469 /* check if the signature file exists */
470 if (access(path, R_OK) != 0)
471 return false;
472
473 /* strip the .sig2 suffix and check if binpkg file exists */
474 path[strlen(path)-sizeof (".sig2")+1] = '\0';
475
476 return access(path, R_OK) == 0;
477}
478
479bool
480xbps_pkg_arch_match(struct xbps_handle *xhp, const char *orig,
481 const char *target)
482{
483 const char *arch;
484
485 assert(xhp);
486 assert(orig);
487
488 if (xhp->target_arch)
489 arch = xhp->target_arch;
490 else
491 arch = xhp->native_arch;
492
493 if (target == NULL) {
494 if ((strcmp(orig, "noarch") == 0) ||
495 (strcmp(orig, arch) == 0))
496 return true;
497 } else {
498 if ((strcmp(orig, "noarch") == 0) ||
499 (strcmp(orig, target) == 0))
500 return true;
501 }
502 return false;
503}
504
505char *
506xbps_xasprintf(const char *fmt, ...)
507{
508 va_list ap;
509 char *buf = NULL;
510
511 va_start(ap, fmt);
512 if (vasprintf(&buf, fmt, ap) == -1) {
513 va_end(ap);
514 assert(buf);
515 }
516 va_end(ap);
517 assert(buf);
518
519 return buf;
520}
521
522/*
523 * Match pkg against pattern, return 1 if matching, 0 otherwise or -1 on error.
524 */
525int
526xbps_pkgpattern_match(const char *pkg, const char *pattern)
527{
528 assert(pkg);
529 assert(pattern);
530
531 /* simple match on "pkg" against "pattern" */
532 if (strcmp(pattern, pkg) == 0)
533 return 1;
534
535 /* perform relational dewey match on version number */
536 if (strpbrk(pattern, "<>") != NULL)
537 return dewey_match(pattern, pkg);
538
539 /* glob match */
540 if (strpbrk(pattern, "*?[]") != NULL)
541 if (fnmatch(pattern, pkg, FNM_PERIOD) == 0)
542 return 1;
543
544 /* no match */
545 return 0;
546}
547
548/*
549 * Small wrapper for NetBSD's humanize_number(3) with some
550 * defaults set that we care about.
551 */
552int
553xbps_humanize_number(char *buf, int64_t bytes)
554{
555 assert(buf != NULL);
556
557 return humanize_number(buf, 7, bytes, "B",
558 HN_AUTOSCALE, HN_DECIMAL|HN_NOSPACE);
559}
560
561size_t
562xbps_strlcat(char *dest, const char *src, size_t siz)
563{
564 assert(dest);
565 assert(src);
566
567 return strlcat(dest, src, siz);
568}
569
570size_t
571xbps_strlcpy(char *dest, const char *src, size_t siz)
572{
573 assert(dest);
574 assert(src);
575
576 return strlcpy(dest, src, siz);
577}
578
579/*
580 * Check if pkg is explicitly marked to replace a specific installed version.
581 */
582bool
583xbps_pkg_reverts(xbps_dictionary_t pkg, const char *pkgver)
584{
585 unsigned int i;
586 xbps_array_t reverts;
587 const char *version = xbps_pkg_version(pkgver);
588 const char *revertver = NULL;
589
590 assert(pkg);
591 assert(pkgver);
592
593 if ((reverts = xbps_dictionary_get(pkg, "reverts")) == NULL)
594 return false;
595
596 for (i = 0; i < xbps_array_count(reverts); i++) {
597 xbps_array_get_cstring_nocopy(reverts, i, &revertver);
598 if (strcmp(version, revertver) == 0) {
599 return true;
600 }
601 }
602
603 return false;
604}
605
606char *
607xbps_sanitize_path(const char *src)
608{
609 const char *s = src;
610 char *d, *dest;
611 size_t len;
612
613 assert(src);
614 len = strlen(src);
615 assert(len != 0);
616
617 dest = malloc(len+1);
618 assert(dest);
619 d = dest;
620
621 while ((*d = *s)) {
622 if (*s == '/' && *(s+1) == '/') {
623 s++;
624 continue;
625 }
626 d++, s++;
627 }
628 *d = '\0';
629
630 return dest;
631}
632
633char *
634xbps_symlink_target(struct xbps_handle *xhp, const char *path, const char *tgt)
635{
636 struct stat sb;
637 char *res = NULL, *lnk = NULL, *p = NULL, *p1 = NULL, *dname = NULL;
638 char *rootdir = NULL;
639 ssize_t r;
640
641 assert(xhp);
642 assert(path);
643 assert(tgt);
644
645 if (lstat(path, &sb) == -1)
646 return NULL;
647
648 lnk = malloc(sb.st_size + 1);
649 assert(lnk);
650
651 r = readlink(path, lnk, sb.st_size + 1);
652 if (r < 0 || r > sb.st_size) {
653 free(lnk);
654 return NULL;
655 }
656 lnk[sb.st_size] = '\0';
657
658 if (tgt[0] != '/') {
659 /*
660 * target file is relative and wasn't converted to absolute by
661 * xbps-create(8), just compare it as is.
662 */
663 return lnk;
664 }
665
666 rootdir = realpath(xhp->rootdir, NULL);
667 if (rootdir == NULL) {
668 free(lnk);
669 return NULL;
670 }
671
672 if (strstr(lnk, "./")) {
673 /* contains references to relative paths */
674 p = realpath(path, NULL);
675 if (p == NULL) {
676 /* dangling symlink, use target */
677 free(rootdir);
678 free(lnk);
679 return strdup(tgt);
680 }
681 if (strcmp(rootdir, "/") == 0) {
682 res = strdup(p);
683 } else {
684 p1 = strdup(p + strlen(rootdir));
685 assert(p1);
686 res = xbps_sanitize_path(p1);
687 free(p1);
688 }
689 free(lnk);
690 free(p);
691 } else if (lnk[0] != '/') {
692 /* relative path */
693 p = strdup(path);
694 assert(p);
695 dname = dirname(p);
696 assert(dname);
697 if (strcmp(rootdir, "/") == 0) {
698 p1 = xbps_xasprintf("%s/%s", dname, lnk);
699 assert(p1);
700 res = xbps_sanitize_path(p1);
701 free(p1);
702 free(p);
703 } else {
704 p1 = strdup(dname + strlen(rootdir));
705 assert(p1);
706 free(p);
707 p = xbps_xasprintf("%s/%s", p1, lnk);
708 free(p1);
709 res = xbps_sanitize_path(p);
710 free(p);
711 }
712 free(lnk);
713 } else {
714 /* absolute */
715 res = lnk;
716 }
717 assert(res);
718 free(rootdir);
719
720 return res;
721}
722
723bool
724xbps_patterns_match(xbps_array_t patterns, const char *path)
725{
726 bool match = false;
727
728 assert(path);
729
730 if (patterns == NULL)
731 return false;
732
733 for (unsigned int i = 0; i < xbps_array_count(patterns); i++) {
734 const char *pattern = NULL;
735 bool negate = false;
736 if (!xbps_array_get_cstring_nocopy(patterns, i, &pattern))
737 continue;
738 if (pattern == NULL)
739 continue;
740 if ((negate = *pattern == '!') || *pattern == '\\')
741 pattern++;
742 if (fnmatch(pattern, path, 0) == 0)
743 match = !negate;
744 }
745
746 return match;
747}
char rootdir[XBPS_MAXPATH]
Definition xbps.h:664
const char * target_arch
Definition xbps.h:645
char native_arch[64]
Definition xbps.h:685
char cachedir[XBPS_MAXPATH]
Definition xbps.h:671
Generic XBPS structure handler for initialization.
Definition xbps.h:560
xbps_dictionary_t xbps_pkgdb_get_virtualpkg(struct xbps_handle *xhp, const char *pkg)
Definition pkgdb.c:422
xbps_dictionary_t xbps_pkgdb_get_pkg(struct xbps_handle *xhp, const char *pkg)
Definition pkgdb.c:408
pkg_state_t
Definition xbps.h:1821
int xbps_pkg_state_dictionary(xbps_dictionary_t dict, pkg_state_t *state)
bool xbps_match_string_in_array(xbps_array_t array, const char *val)
char * xbps_xasprintf(const char *fmt,...) __attribute__((format(printf
int xbps_humanize_number(char *buf, int64_t bytes)
Definition util.c:553
const char * xbps_pkgpattern_version(const char *pkg)
Definition util.c:313
bool xbps_pkg_name(char *dst, size_t len, const char *pkg)
Definition util.c:249
char * xbps_sanitize_path(const char *src)
Definition util.c:607
bool xbps_patterns_match(xbps_array_t patterns, const char *path)
Definition util.c:724
bool xbps_pkg_is_ignored(struct xbps_handle *xhp, const char *pkg)
Definition util.c:99
ssize_t xbps_pkg_url(struct xbps_handle *xhp, char *dst, size_t dstsz, xbps_dictionary_t pkgd)
char * xbps_binpkg_pkgver(const char *pkg)
Definition util.c:146
size_t xbps_strlcpy(char *dest, const char *src, size_t siz)
Definition util.c:571
bool xbps_pkg_reverts(xbps_dictionary_t pkg, const char *pkgver)
Definition util.c:583
bool xbps_remote_binpkg_exists(struct xbps_handle *xhp, xbps_dictionary_t pkgd)
Definition util.c:451
ssize_t xbps_pkg_path(struct xbps_handle *xhp, char *dst, size_t dstsz, xbps_dictionary_t pkgd)
Definition util.c:321
ssize_t xbps_pkg_path_or_url(struct xbps_handle *xhp, char *dst, size_t dstsz, xbps_dictionary_t pkgd)
int xbps_pkg_is_installed(struct xbps_handle *xhp, const char *pkg)
Definition util.c:75
char * xbps_binpkg_arch(const char *pkg)
Definition util.c:188
int xbps_pkgpattern_match(const char *pkg, const char *pattern)
Definition util.c:526
const char * xbps_pkg_revision(const char *pkg)
Definition util.c:223
const char * xbps_pkg_version(const char *pkg)
Definition util.c:120
bool xbps_repository_is_remote(const char *uri)
Definition util.c:62
bool xbps_pkgpattern_name(char *dst, size_t len, const char *pkg)
Definition util.c:285
bool xbps_binpkg_exists(struct xbps_handle *xhp, xbps_dictionary_t pkgd)
Definition util.c:425
bool xbps_pkg_arch_match(struct xbps_handle *xhp, const char *orig, const char *target)
Definition util.c:480
char * xbps_symlink_target(struct xbps_handle *xhp, const char *path, const char *tgt)
Definition util.c:634
size_t xbps_strlcat(char *dest, const char *src, size_t siz)
Definition util.c:562
char * xbps_repository_pkg_path(struct xbps_handle *xhp, xbps_dictionary_t pkg_repod)
Definition util.c:389