38#include <archive_entry.h>
40#include "xbps_api_impl.h"
58 r = snprintf(path,
sizeof(path),
"%s/%s-repodata.lock", repodir, arch);
59 if (r < 0 || (
size_t)r >
sizeof(path)) {
63 fd = open(path, O_WRONLY|O_CREAT|O_CLOEXEC, 0660);
67 if (flock(fd, LOCK_EX|LOCK_NB) == 0)
69 if (errno != EWOULDBLOCK) {
76 if (flock(fd, LOCK_EX) == -1) {
94 r = snprintf(path,
sizeof(path),
"%s/%s-repodata.lock", repodir, arch);
95 if (r < 0 || (
size_t)r >
sizeof(path))
101repo_read_next(
struct xbps_repo *repo,
struct archive *ar,
struct archive_entry **entry)
105 r = archive_read_next_header(ar, entry);
106 if (r == ARCHIVE_FATAL) {
108 repo->
uri, archive_error_string(ar));
109 return -xbps_archive_errno(ar);
110 }
else if (r == ARCHIVE_WARN) {
112 repo->
uri, archive_error_string(ar));
114 }
else if (r == ARCHIVE_EOF) {
121repo_read_index(
struct xbps_repo *repo,
struct archive *ar)
123 struct archive_entry *entry;
128 r = repo_read_next(repo, ar, &entry);
133 pname = archive_entry_pathname(entry);
136 if (strcmp(pname, XBPS_REPODATA_INDEX) != 0) {
137 xbps_error_printf(
"failed to read repository index: %s: unexpected archive entry\n",
143 if (archive_entry_size(entry) == 0) {
144 r = archive_read_data_skip(ar);
145 if (r == ARCHIVE_FATAL) {
147 repo->
uri, archive_error_string(ar));
148 return -xbps_archive_errno(ar);
150 repo->
index = xbps_dictionary_create();
154 buf = xbps_archive_get_file(ar, entry);
158 "failed to open repository: %s: failed to read index: %s\n",
159 repo->
uri, strerror(-r));
162 repo->
index = xbps_dictionary_internalize(buf);
169 "failed to open repository: %s: failed to parse index: %s\n",
170 repo->
uri, strerror(-r));
174 xbps_dictionary_make_immutable(repo->
index);
179repo_read_meta(
struct xbps_repo *repo,
struct archive *ar)
181 struct archive_entry *entry;
186 r = repo_read_next(repo, ar, &entry);
190 pname = archive_entry_pathname(entry);
193 if (strcmp(pname, XBPS_REPODATA_META) != 0) {
194 xbps_error_printf(
"failed to read repository metadata: %s: unexpected archive entry\n",
199 if (archive_entry_size(entry) == 0) {
200 r = archive_read_data_skip(ar);
201 if (r == ARCHIVE_FATAL) {
203 repo->
uri, archive_error_string(ar));
204 return -xbps_archive_errno(ar);
210 buf = xbps_archive_get_file(ar, entry);
214 "failed to read repository metadata: %s: failed to read "
216 repo->
uri, strerror(-r));
220 if (strcmp(buf,
"DEADBEEF") == 0) {
226 repo->
idxmeta = xbps_dictionary_internalize(buf);
233 "failed to read repository metadata: %s: failed to parse "
235 repo->
uri, strerror(-r));
240 xbps_dictionary_make_immutable(repo->
idxmeta);
245repo_read_stage(
struct xbps_repo *repo,
struct archive *ar)
247 struct archive_entry *entry;
251 r = repo_read_next(repo, ar, &entry);
255 repo->stage = xbps_dictionary_create();
261 pname = archive_entry_pathname(entry);
264 if (strcmp(pname, XBPS_REPODATA_STAGE) != 0) {
265 xbps_error_printf(
"failed to read repository stage: %s: unexpected archive entry\n",
270 if (archive_entry_size(entry) == 0) {
271 repo->stage = xbps_dictionary_create();
275 repo->stage = xbps_archive_get_dictionary(ar, entry);
278 repo->
uri, archive_error_string(ar));
281 xbps_dictionary_make_immutable(repo->stage);
286repo_read(
struct xbps_repo *repo,
struct archive *ar)
290 r = repo_read_index(repo, ar);
293 r = repo_read_meta(repo, ar);
296 r = repo_read_stage(repo, ar);
304repo_open_local(
struct xbps_repo *repo,
struct archive *ar)
311 cachedir = xbps_get_remote_repo_string(repo->
uri);
318 r = snprintf(path,
sizeof(path),
"%s/%s/%s-repodata",
322 r = snprintf(path,
sizeof(path),
"%s/%s-repodata", repo->
uri, repo->
arch);
324 if (r < 0 || (
size_t)r >=
sizeof(path)) {
331 r = xbps_archive_read_open(ar, path);
346repo_open_remote(
struct xbps_repo *repo,
struct archive *ar)
351 r = snprintf(url,
sizeof(url),
"%s/%s-repodata", repo->
uri, repo->
arch);
352 if (r < 0 || (
size_t)r >=
sizeof(url)) {
355 return -ENAMETOOLONG;
358 r = xbps_archive_read_open_remote(ar, url);
373 ar = xbps_archive_read_new();
381 r = repo_open_remote(repo, ar);
383 r = repo_open_local(repo, ar);
387 r = repo_read(repo, ar);
391 r = archive_read_close(ar);
394 repo->
uri, archive_error_string(ar));
398 archive_read_free(ar);
401 archive_read_free(ar);
421 if (repo[0] !=
'/' && repo[0] !=
'\0') {
422 if ((url = realpath(repo, NULL)) == NULL)
432 if (xbps_array_add_cstring(xhp->
repositories, url ? url : repo)) {
433 xbps_dbg_printf(
"[repo] `%s' stored successfully\n", url ? url : repo);
470 xbps_dictionary_t idx;
471 xbps_object_t keysym;
472 xbps_object_iterator_t iter;
475 idx = xbps_dictionary_copy_mutable(repo->
index);
479 iter = xbps_dictionary_iterator(repo->stage);
485 while ((keysym = xbps_object_iterator_next(iter))) {
486 const char *pkgname = xbps_dictionary_keysym_cstring_nocopy(keysym);
487 xbps_dictionary_t pkgd = xbps_dictionary_get_keysym(repo->stage, keysym);
488 if (!xbps_dictionary_set(idx, pkgname, pkgd)) {
494 xbps_object_iterator_release(iter);
498 xbps_object_iterator_release(iter);
500 xbps_object_release(idx);
510 repo = calloc(1,
sizeof(*repo));
522 r = repo_open(
xhp, repo);
529 if (xbps_dictionary_count(repo->stage) == 0 ||
532 xbps_object_retain(repo->
idx);
536 r = repo_merge_stage(repo);
539 "failed to open repository: %s: could not merge stage: %s\n",
557 xbps_object_release(repo->
idx);
561 xbps_object_release(repo->
index);
565 xbps_object_release(repo->stage);
569 xbps_object_release(repo->
idxmeta);
578 xbps_dictionary_t pkgd;
580 char pkgname[XBPS_NAME_SIZE] = {0};
582 if (!repo || !repo->
idx || !pkg) {
585 pkgd = xbps_find_virtualpkg_in_dict(repo->
xhp, repo->
idx, pkg);
589 if (xbps_dictionary_get(pkgd,
"repository") && xbps_dictionary_get(pkgd,
"pkgname")) {
592 if (!xbps_dictionary_set_cstring_nocopy(pkgd,
"repository", repo->
uri)) {
595 if (!xbps_dictionary_get_cstring_nocopy(pkgd,
"pkgver", &pkgver)) {
601 if (!xbps_dictionary_set_cstring(pkgd,
"pkgname", pkgname)) {
612 xbps_dictionary_t pkgd = NULL;
614 char pkgname[XBPS_NAME_SIZE] = {0};
616 if (!repo || !repo->
idx || !pkg) {
620 if ((pkgd = xbps_find_virtualpkg_in_conf(repo->
xhp, repo->
idx, pkg))) {
624 if ((pkgd = xbps_find_pkg_in_dict(repo->
idx, pkg))) {
629 if (xbps_dictionary_get(pkgd,
"repository") && xbps_dictionary_get(pkgd,
"pkgname")) {
632 if (!xbps_dictionary_set_cstring_nocopy(pkgd,
"repository", repo->
uri)) {
635 if (!xbps_dictionary_get_cstring_nocopy(pkgd,
"pkgver", &pkgver)) {
641 if (!xbps_dictionary_set_cstring(pkgd,
"pkgname", pkgname)) {
649revdeps_match(
struct xbps_repo *repo, xbps_dictionary_t tpkgd,
const char *str)
651 xbps_dictionary_t pkgd;
652 xbps_array_t revdeps = NULL, pkgdeps, provides;
653 xbps_object_iterator_t iter;
655 const char *pkgver = NULL, *tpkgver = NULL, *
arch = NULL, *vpkg = NULL;
657 iter = xbps_dictionary_iterator(repo->
idx);
660 while ((obj = xbps_object_iterator_next(iter))) {
661 pkgd = xbps_dictionary_get_keysym(repo->
idx, obj);
662 if (xbps_dictionary_equals(pkgd, tpkgd))
665 pkgdeps = xbps_dictionary_get(pkgd,
"run_depends");
666 if (!xbps_array_count(pkgdeps))
674 xbps_dictionary_get_cstring_nocopy(pkgd,
675 "architecture", &
arch);
679 xbps_dictionary_get_cstring_nocopy(pkgd,
683 revdeps = xbps_array_create();
686 xbps_array_add_cstring_nocopy(revdeps, tpkgver);
693 provides = xbps_dictionary_get(tpkgd,
"provides");
694 for (
unsigned int i = 0; i < xbps_array_count(provides); i++) {
695 xbps_array_get_cstring_nocopy(provides, i, &vpkg);
699 xbps_dictionary_get_cstring_nocopy(pkgd,
700 "architecture", &
arch);
704 xbps_dictionary_get_cstring_nocopy(pkgd,
"pkgver",
708 revdeps = xbps_array_create();
711 xbps_array_add_cstring_nocopy(revdeps, tpkgver);
716 xbps_dictionary_get_cstring_nocopy(tpkgd,
"pkgver", &pkgver);
720 xbps_dictionary_get_cstring_nocopy(pkgd,
721 "architecture", &
arch);
725 xbps_dictionary_get_cstring_nocopy(pkgd,
"pkgver", &tpkgver);
728 revdeps = xbps_array_create();
731 xbps_array_add_cstring_nocopy(revdeps, tpkgver);
733 xbps_object_iterator_release(iter);
740 xbps_array_t revdeps = NULL, vdeps = NULL;
741 xbps_dictionary_t pkgd;
745 if (repo->
idx == NULL)
756 if ((vdeps = xbps_dictionary_get(pkgd,
"provides"))) {
757 for (
unsigned int i = 0; i < xbps_array_count(vdeps); i++) {
758 char vpkgn[XBPS_NAME_SIZE];
760 xbps_array_get_cstring_nocopy(vdeps, i, &vpkg);
764 if (strcmp(vpkgn, pkg) == 0) {
771 revdeps = revdeps_match(repo, pkgd, vpkg);
774 revdeps = revdeps_match(repo, pkgd, NULL);
782 xbps_dictionary_t repokeyd = NULL;
783 xbps_data_t pubkey = NULL;
784 uint16_t pubkey_size = 0;
785 const char *signedby = NULL;
787 char *p, *dbkeyd, *rkeyfile = NULL;
794 if (!xbps_dictionary_count(repo->
idxmeta)) {
804 xbps_dictionary_get_cstring_nocopy(repo->
idxmeta,
"signature-by", &signedby);
805 xbps_dictionary_get_uint16(repo->
idxmeta,
"public-key-size", &pubkey_size);
806 pubkey = xbps_dictionary_get(repo->
idxmeta,
"public-key");
808 if (signedby == NULL || pubkey_size == 0 ||
809 xbps_object_type(pubkey) != XBPS_TYPE_DATA) {
811 "(missing objs)\n", repo->
uri);
825 if (xbps_object_type(repokeyd) == XBPS_TYPE_DICTIONARY) {
834 import = xbps_set_cb_state(repo->xhp, XBPS_STATE_REPO_KEY_IMPORT, 0,
835 hexfp, "`%s' repository has been RSA signed by \"%s\
"",
836 repo->
uri, signedby);
842 p = strdup(rkeyfile);
845 if (access(dbkeyd, R_OK|W_OK) == -1) {
852 repo->
uri, dbkeyd, strerror(errno));
859 repokeyd = xbps_dictionary_create();
860 xbps_dictionary_set(repokeyd,
"public-key", pubkey);
861 xbps_dictionary_set_uint16(repokeyd,
"public-key-size", pubkey_size);
862 xbps_dictionary_set_cstring_nocopy(repokeyd,
"signature-by", signedby);
864 if (!xbps_dictionary_externalize_to_file(repokeyd, rkeyfile)) {
867 repo->
uri, rkeyfile, strerror(rv));
874 xbps_object_release(repokeyd);
xbps_array_t repositories
char metadir[XBPS_MAXPATH]
Generic XBPS structure handler for initialization.
#define xbps_unreachable()
Log and abort for code that should be unreachable.
void xbps_error_printf(const char *fmt,...)
Prints error messages to stderr.
void xbps_dbg_printf(const char *fmt,...)
Prints debug messages to stderr.
void xbps_warn_printf(const char *fmt,...)
Prints warning messages to stderr.
bool xbps_match_pkgdep_in_array(xbps_array_t array, const char *pkgver)
bool xbps_match_string_in_array(xbps_array_t array, const char *val)
xbps_dictionary_t xbps_repo_get_pkg(struct xbps_repo *repo, const char *pkg)
struct xbps_repo * xbps_repo_open(struct xbps_handle *xhp, const char *url)
void xbps_repo_release(struct xbps_repo *repo)
int xbps_repo_lock(const char *repodir, const char *arch)
bool xbps_repo_remove(struct xbps_handle *xhp, const char *repo)
int xbps_repo_key_import(struct xbps_repo *repo)
xbps_dictionary_t xbps_repo_get_virtualpkg(struct xbps_repo *repo, const char *pkg)
xbps_array_t xbps_repo_get_pkg_revdeps(struct xbps_repo *repo, const char *pkg)
void xbps_repo_unlock(const char *repodir, const char *arch, int fd)
bool xbps_repo_store(struct xbps_handle *xhp, const char *repo)
xbps_dictionary_t idxmeta
xbps_dictionary_t xbps_plist_dictionary_from_file(const char *path)
char * xbps_pubkey2fp(xbps_data_t pubkey)
char * xbps_xasprintf(const char *fmt,...) __attribute__((format(printf
bool xbps_pkg_name(char *dst, size_t len, const char *pkg)
int xbps_mkpath(const char *path, mode_t mode)
bool xbps_remove_string_from_array(xbps_array_t array, const char *str)
bool xbps_repository_is_remote(const char *uri)
bool xbps_pkg_arch_match(struct xbps_handle *xhp, const char *orig, const char *target)