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) {
75 xbps_warn_printf(
"repository locked: %s: waiting...", repodir);
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) {
107 xbps_error_printf(
"failed to read repository: %s: %s\n",
108 repo->
uri, archive_error_string(ar));
109 return -archive_errno(ar);
110 }
else if (r == ARCHIVE_WARN) {
111 xbps_warn_printf(
"reading repository: %s: %s\n",
112 repo->
uri, archive_error_string(ar));
114 }
else if (r == ARCHIVE_EOF) {
122repo_read_index(
struct xbps_repo *repo,
struct archive *ar)
124 struct archive_entry *entry;
128 r = repo_read_next(repo, ar, &entry);
133 if (strcmp(archive_entry_pathname(entry), XBPS_REPODATA_INDEX) != 0) {
134 xbps_error_printf(
"failed to read repository index: %s: unexpected archive entry\n",
140 if (archive_entry_size(entry) == 0) {
141 r = archive_read_data_skip(ar);
142 if (r == ARCHIVE_FATAL) {
143 xbps_error_printf(
"failed to read repository: %s: archive error: %s\n",
144 repo->
uri, archive_error_string(ar));
145 return -archive_errno(ar);
147 repo->
index = xbps_dictionary_create();
151 buf = xbps_archive_get_file(ar, entry);
154 repo->
index = xbps_dictionary_internalize(buf);
158 xbps_error_printf(
"failed to open repository: %s: reading index: %s\n",
159 repo->
uri, strerror(-r));
163 xbps_dictionary_make_immutable(repo->
index);
168repo_read_meta(
struct xbps_repo *repo,
struct archive *ar)
170 struct archive_entry *entry;
174 r = repo_read_next(repo, ar, &entry);
178 if (strcmp(archive_entry_pathname(entry), XBPS_REPODATA_META) != 0) {
179 xbps_error_printf(
"failed to read repository metadata: %s: unexpected archive entry\n",
184 if (archive_entry_size(entry) == 0) {
185 r = archive_read_data_skip(ar);
186 if (r == ARCHIVE_FATAL) {
187 xbps_error_printf(
"failed to read repository: %s: archive error: %s\n",
188 repo->
uri, archive_error_string(ar));
189 return -archive_errno(ar);
191 repo->
idxmeta = xbps_dictionary_create();
195 buf = xbps_archive_get_file(ar, entry);
198 xbps_error_printf(
"failed to read repository metadata: %s: %s\n",
199 repo->
uri, strerror(-r));
203 if (strcmp(buf,
"DEADBEEF") == 0) {
209 repo->
idxmeta = xbps_dictionary_internalize(buf);
216 xbps_error_printf(
"failed to read repository metadata: %s: invalid dictionary\n",
220 xbps_error_printf(
"failed to read repository metadata: %s: %s\n",
221 repo->
uri, strerror(-r));
225 xbps_dictionary_make_immutable(repo->
idxmeta);
230repo_read_stage(
struct xbps_repo *repo,
struct archive *ar)
232 struct archive_entry *entry;
235 r = repo_read_next(repo, ar, &entry);
239 repo->stage = xbps_dictionary_create();
245 if (strcmp(archive_entry_pathname(entry), XBPS_REPODATA_STAGE) != 0) {
246 xbps_error_printf(
"failed to read repository stage: %s: unexpected archive entry\n",
251 if (archive_entry_size(entry) == 0) {
252 repo->stage = xbps_dictionary_create();
256 repo->stage = xbps_archive_get_dictionary(ar, entry);
258 xbps_error_printf(
"failed to open repository: %s: reading stage: %s\n",
259 repo->
uri, archive_error_string(ar));
262 xbps_dictionary_make_immutable(repo->stage);
267repo_read(
struct xbps_repo *repo,
struct archive *ar)
271 r = repo_read_index(repo, ar);
274 r = repo_read_meta(repo, ar);
277 r = repo_read_stage(repo, ar);
285repo_open_local(
struct xbps_repo *repo,
struct archive *ar)
292 cachedir = xbps_get_remote_repo_string(repo->
uri);
295 xbps_error_printf(
"failed to open repository: %s: invalid repository url\n",
299 r = snprintf(path,
sizeof(path),
"%s/%s/%s-repodata",
303 r = snprintf(path,
sizeof(path),
"%s/%s-repodata", repo->
uri, repo->
arch);
305 if (r < 0 || (
size_t)r >=
sizeof(path)) {
307 xbps_error_printf(
"failed to open repository: %s: repository path too long\n",
312 r = xbps_archive_read_open(ar, path);
315 xbps_error_printf(
"failed to open repodata: %s: %s\n",
327repo_open_remote(
struct xbps_repo *repo,
struct archive *ar)
332 r = snprintf(url,
sizeof(url),
"%s/%s-repodata", repo->
uri, repo->
arch);
333 if (r < 0 || (
size_t)r >=
sizeof(url)) {
334 xbps_error_printf(
"failed to open repository: %s: repository url too long\n",
336 return -ENAMETOOLONG;
339 r = xbps_archive_read_open_remote(ar, url);
341 xbps_error_printf(
"failed to open repository: %s: %s\n", repo->
uri, strerror(-r));
342 archive_read_free(ar);
355 ar = xbps_archive_read_new();
358 xbps_error_printf(
"failed to open repo: %s\n", strerror(-r));
363 r = repo_open_remote(repo, ar);
365 r = repo_open_local(repo, ar);
369 r = repo_read(repo, ar);
373 r = archive_read_close(ar);
375 xbps_error_printf(
"failed to open repository: %s: closing archive: %s\n",
376 repo->
uri, archive_error_string(ar));
380 archive_read_free(ar);
383 archive_read_free(ar);
403 if (repo[0] !=
'/' && repo[0] !=
'\0') {
404 if ((url = realpath(repo, NULL)) == NULL)
405 xbps_dbg_printf(
"[repo] %s: realpath %s\n", __func__, repo);
409 xbps_dbg_printf(
"[repo] `%s' already stored\n", url ? url : repo);
414 if (xbps_array_add_cstring(xhp->
repositories, url ? url : repo)) {
415 xbps_dbg_printf(
"[repo] `%s' stored successfully\n", url ? url : repo);
441 xbps_dbg_printf(
"[repo] `%s' removed\n", url);
452 xbps_dictionary_t idx;
453 xbps_object_t keysym;
454 xbps_object_iterator_t iter;
457 idx = xbps_dictionary_copy_mutable(repo->
index);
461 iter = xbps_dictionary_iterator(repo->stage);
467 while ((keysym = xbps_object_iterator_next(iter))) {
468 const char *pkgname = xbps_dictionary_keysym_cstring_nocopy(keysym);
469 xbps_dictionary_t pkgd = xbps_dictionary_get_keysym(repo->stage, keysym);
470 if (!xbps_dictionary_set(idx, pkgname, pkgd)) {
476 xbps_object_iterator_release(iter);
480 xbps_object_iterator_release(iter);
482 xbps_object_release(idx);
492 repo = calloc(1,
sizeof(*repo));
495 xbps_error_printf(
"failed to open repository: %s\n", strerror(-r));
504 r = repo_open(
xhp, repo);
511 if (xbps_dictionary_count(repo->stage) == 0 ||
514 xbps_object_retain(repo->
idx);
518 r = repo_merge_stage(repo);
521 "failed to open repository: %s: could not merge stage: %s\n",
539 xbps_object_release(repo->
idx);
543 xbps_object_release(repo->
index);
547 xbps_object_release(repo->stage);
551 xbps_object_release(repo->
idxmeta);
560 xbps_dictionary_t pkgd;
562 char pkgname[XBPS_NAME_SIZE] = {0};
564 if (!repo || !repo->
idx || !pkg) {
567 pkgd = xbps_find_virtualpkg_in_dict(repo->
xhp, repo->
idx, pkg);
571 if (xbps_dictionary_get(pkgd,
"repository") && xbps_dictionary_get(pkgd,
"pkgname")) {
574 if (!xbps_dictionary_set_cstring_nocopy(pkgd,
"repository", repo->
uri)) {
577 if (!xbps_dictionary_get_cstring_nocopy(pkgd,
"pkgver", &pkgver)) {
583 if (!xbps_dictionary_set_cstring(pkgd,
"pkgname", pkgname)) {
586 xbps_dbg_printf(
"%s: found %s\n", __func__, pkgver);
594 xbps_dictionary_t pkgd = NULL;
596 char pkgname[XBPS_NAME_SIZE] = {0};
598 if (!repo || !repo->
idx || !pkg) {
602 if ((pkgd = xbps_find_virtualpkg_in_conf(repo->
xhp, repo->
idx, pkg))) {
606 if ((pkgd = xbps_find_pkg_in_dict(repo->
idx, pkg))) {
611 if (xbps_dictionary_get(pkgd,
"repository") && xbps_dictionary_get(pkgd,
"pkgname")) {
614 if (!xbps_dictionary_set_cstring_nocopy(pkgd,
"repository", repo->
uri)) {
617 if (!xbps_dictionary_get_cstring_nocopy(pkgd,
"pkgver", &pkgver)) {
623 if (!xbps_dictionary_set_cstring(pkgd,
"pkgname", pkgname)) {
626 xbps_dbg_printf(
"%s: found %s\n", __func__, pkgver);
631revdeps_match(
struct xbps_repo *repo, xbps_dictionary_t tpkgd,
const char *str)
633 xbps_dictionary_t pkgd;
634 xbps_array_t revdeps = NULL, pkgdeps, provides;
635 xbps_object_iterator_t iter;
637 const char *pkgver = NULL, *tpkgver = NULL, *
arch = NULL, *vpkg = NULL;
639 iter = xbps_dictionary_iterator(repo->
idx);
642 while ((obj = xbps_object_iterator_next(iter))) {
643 pkgd = xbps_dictionary_get_keysym(repo->
idx, obj);
644 if (xbps_dictionary_equals(pkgd, tpkgd))
647 pkgdeps = xbps_dictionary_get(pkgd,
"run_depends");
648 if (!xbps_array_count(pkgdeps))
656 xbps_dictionary_get_cstring_nocopy(pkgd,
657 "architecture", &
arch);
661 xbps_dictionary_get_cstring_nocopy(pkgd,
665 revdeps = xbps_array_create();
668 xbps_array_add_cstring_nocopy(revdeps, tpkgver);
675 provides = xbps_dictionary_get(tpkgd,
"provides");
676 for (
unsigned int i = 0; i < xbps_array_count(provides); i++) {
677 xbps_array_get_cstring_nocopy(provides, i, &vpkg);
681 xbps_dictionary_get_cstring_nocopy(pkgd,
682 "architecture", &
arch);
686 xbps_dictionary_get_cstring_nocopy(pkgd,
"pkgver",
690 revdeps = xbps_array_create();
693 xbps_array_add_cstring_nocopy(revdeps, tpkgver);
698 xbps_dictionary_get_cstring_nocopy(tpkgd,
"pkgver", &pkgver);
702 xbps_dictionary_get_cstring_nocopy(pkgd,
703 "architecture", &
arch);
707 xbps_dictionary_get_cstring_nocopy(pkgd,
"pkgver", &tpkgver);
710 revdeps = xbps_array_create();
713 xbps_array_add_cstring_nocopy(revdeps, tpkgver);
715 xbps_object_iterator_release(iter);
722 xbps_array_t revdeps = NULL, vdeps = NULL;
723 xbps_dictionary_t pkgd;
727 if (repo->
idx == NULL)
738 if ((vdeps = xbps_dictionary_get(pkgd,
"provides"))) {
739 for (
unsigned int i = 0; i < xbps_array_count(vdeps); i++) {
740 char vpkgn[XBPS_NAME_SIZE];
742 xbps_array_get_cstring_nocopy(vdeps, i, &vpkg);
746 if (strcmp(vpkgn, pkg) == 0) {
753 revdeps = revdeps_match(repo, pkgd, vpkg);
756 revdeps = revdeps_match(repo, pkgd, NULL);
764 xbps_dictionary_t repokeyd = NULL;
765 xbps_data_t pubkey = NULL;
766 uint16_t pubkey_size = 0;
767 const char *signedby = NULL;
769 char *p, *dbkeyd, *rkeyfile = NULL;
776 if (!xbps_dictionary_count(repo->
idxmeta)) {
777 xbps_dbg_printf(
"[repo] `%s' unsigned repository!\n", repo->
uri);
786 xbps_dictionary_get_cstring_nocopy(repo->
idxmeta,
"signature-by", &signedby);
787 xbps_dictionary_get_uint16(repo->
idxmeta,
"public-key-size", &pubkey_size);
788 pubkey = xbps_dictionary_get(repo->
idxmeta,
"public-key");
790 if (signedby == NULL || pubkey_size == 0 ||
791 xbps_object_type(pubkey) != XBPS_TYPE_DATA) {
792 xbps_dbg_printf(
"[repo] `%s': incomplete signed repository "
793 "(missing objs)\n", repo->
uri);
807 if (xbps_object_type(repokeyd) == XBPS_TYPE_DICTIONARY) {
808 xbps_dbg_printf(
"[repo] `%s' public key already stored.\n", repo->
uri);
816 import = xbps_set_cb_state(repo->xhp, XBPS_STATE_REPO_KEY_IMPORT, 0,
817 hexfp, "`%s' repository has been RSA signed by \"%s\
"",
818 repo->
uri, signedby);
824 p = strdup(rkeyfile);
827 if (access(dbkeyd, R_OK|W_OK) == -1) {
833 xbps_dbg_printf(
"[repo] `%s' cannot create %s: %s\n",
834 repo->
uri, dbkeyd, strerror(errno));
841 repokeyd = xbps_dictionary_create();
842 xbps_dictionary_set(repokeyd,
"public-key", pubkey);
843 xbps_dictionary_set_uint16(repokeyd,
"public-key-size", pubkey_size);
844 xbps_dictionary_set_cstring_nocopy(repokeyd,
"signature-by", signedby);
846 if (!xbps_dictionary_externalize_to_file(repokeyd, rkeyfile)) {
848 xbps_dbg_printf(
"[repo] `%s' failed to externalize %s: %s\n",
849 repo->
uri, rkeyfile, strerror(rv));
856 xbps_object_release(repokeyd);
xbps_array_t repositories
char metadir[XBPS_MAXPATH]
Generic XBPS structure handler for initialization.
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)