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