35#include <archive_entry.h>
37#include <openssl/err.h>
38#include <openssl/sha.h>
39#include <openssl/rsa.h>
40#include <openssl/ssl.h>
41#include <openssl/pem.h>
43#include "xbps_api_impl.h"
61 assert(strcmp(name,
"repodata") == 0 || strcmp(name,
"stagedata") == 0);
67static xbps_dictionary_t
70 struct archive_entry *entry;
76 rv = archive_read_next_header(repo->ar, &entry);
77 if (rv != ARCHIVE_OK) {
78 xbps_dbg_printf(
"%s: read_next_header %s\n", repo->
uri,
79 archive_error_string(repo->ar));
82 return xbps_archive_get_dictionary(repo->ar, entry);
87 int *lockfd,
char **lockfname)
89 char *repofile, *lockfile;
103 fd = open(lockfile, O_WRONLY|O_CREAT|O_EXCL|O_CLOEXEC, 0660);
108 xbps_dbg_printf(
"[repo] `%s' failed to "
109 "create lock file %s\n", lockfile, strerror(rv));
113 xbps_dbg_printf(
"[repo] `%s' lock file exists,"
114 "waiting for 1s...\n", lockfile);
118 *lockfname = lockfile;
136repo_open_local(
struct xbps_repo *repo,
const char *repofile)
140 if (fstat(repo->fd, &st) == -1) {
141 xbps_dbg_printf(
"[repo] `%s' fstat repodata %s\n",
142 repofile, strerror(errno));
146 repo->ar = archive_read_new();
148 archive_read_support_filter_gzip(repo->ar);
149 archive_read_support_filter_bzip2(repo->ar);
150 archive_read_support_filter_xz(repo->ar);
151 archive_read_support_filter_lz4(repo->ar);
152 archive_read_support_filter_zstd(repo->ar);
153 archive_read_support_format_tar(repo->ar);
155 if (archive_read_open_fd(repo->ar, repo->fd, st.st_blksize) == ARCHIVE_FATAL) {
156 xbps_dbg_printf(
"[repo] `%s' failed to open repodata archive %s\n",
157 repofile, archive_error_string(repo->ar));
160 if ((repo->
idx = repo_get_dict(repo)) == NULL) {
161 xbps_dbg_printf(
"[repo] `%s' failed to internalize "
162 " index on archive, removing file.\n", repofile);
164 (void)unlink(repofile);
167 xbps_dictionary_make_immutable(repo->
idx);
168 repo->
idxmeta = repo_get_dict(repo);
171 xbps_dictionary_make_immutable(repo->
idxmeta);
192 xbps_dbg_printf(
"[repo] `%s' used remotely (kept in memory).\n", repo->
uri);
200repo_open_with_type(
struct xbps_handle *
xhp,
const char *url,
const char *name)
204 char *repofile = NULL;
214 repo = calloc(1,
sizeof(
struct xbps_repo));
224 if ((rpath = xbps_get_remote_repo_string(url)) == NULL) {
238 if (repo_open_remote(repo)) {
247 repo->fd = open(repofile, O_RDONLY|O_CLOEXEC);
248 if (repo->fd == -1) {
250 xbps_dbg_printf(
"[repo] `%s' open %s %s\n",
251 repofile, name, strerror(rv));
252 xbps_error_printf(
"%s: %s\n", strerror(rv), repofile);
255 if (repo_open_local(repo, repofile)) {
282 if (repo[0] !=
'/' && repo[0] !=
'\0') {
283 if ((url = realpath(repo, NULL)) == NULL)
284 xbps_dbg_printf(
"[repo] %s: realpath %s\n", __func__, repo);
288 xbps_dbg_printf(
"[repo] `%s' already stored\n", url ? url : repo);
294 xbps_dbg_printf(
"[repo] `%s' stored successfully\n", url ? url : repo);
320 xbps_dbg_printf(
"[repo] `%s' removed\n", url);
331 return repo_open_with_type(
xhp, url,
"stagedata");
336 return repo_open_with_type(
xhp, url,
"repodata");
344 xbps_dictionary_t
idx;
346 xbps_object_t keysym;
347 xbps_object_iterator_t iter;
355 idx = xbps_dictionary_copy_mutable(repo->
idx);
356 iter = xbps_dictionary_iterator(stage->
idx);
357 while ((keysym = xbps_object_iterator_next(iter))) {
358 pkgname = xbps_dictionary_keysym_cstring_nocopy(keysym);
359 xbps_dictionary_set(
idx, pkgname,
360 xbps_dictionary_get_keysym(stage->
idx, keysym));
362 xbps_object_iterator_release(iter);
363 xbps_object_release(repo->
idx);
377 if (repo->ar != NULL) {
378 archive_read_free(repo->ar);
381 if (repo->fd != -1) {
395 if (repo->
idx != NULL) {
396 xbps_object_release(repo->
idx);
400 xbps_object_release(repo->
idxmeta);
409 xbps_dictionary_t pkgd;
411 char pkgname[XBPS_NAME_SIZE] = {0};
413 if (!repo || !repo->
idx || !pkg) {
416 pkgd = xbps_find_virtualpkg_in_dict(repo->
xhp, repo->
idx, pkg);
420 if (xbps_dictionary_get(pkgd,
"repository") && xbps_dictionary_get(pkgd,
"pkgname")) {
423 if (!xbps_dictionary_set_cstring_nocopy(pkgd,
"repository", repo->
uri)) {
426 if (!xbps_dictionary_get_cstring_nocopy(pkgd,
"pkgver", &pkgver)) {
432 if (!xbps_dictionary_set_cstring(pkgd,
"pkgname", pkgname)) {
435 xbps_dbg_printf(
"%s: found %s\n", __func__, pkgver);
443 xbps_dictionary_t pkgd = NULL;
445 char pkgname[XBPS_NAME_SIZE] = {0};
447 if (!repo || !repo->
idx || !pkg) {
451 if ((pkgd = xbps_find_virtualpkg_in_conf(repo->
xhp, repo->
idx, pkg))) {
455 if ((pkgd = xbps_find_pkg_in_dict(repo->
idx, pkg))) {
460 if (xbps_dictionary_get(pkgd,
"repository") && xbps_dictionary_get(pkgd,
"pkgname")) {
463 if (!xbps_dictionary_set_cstring_nocopy(pkgd,
"repository", repo->
uri)) {
466 if (!xbps_dictionary_get_cstring_nocopy(pkgd,
"pkgver", &pkgver)) {
472 if (!xbps_dictionary_set_cstring(pkgd,
"pkgname", pkgname)) {
475 xbps_dbg_printf(
"%s: found %s\n", __func__, pkgver);
480revdeps_match(
struct xbps_repo *repo, xbps_dictionary_t tpkgd,
const char *str)
482 xbps_dictionary_t pkgd;
483 xbps_array_t revdeps = NULL, pkgdeps, provides;
484 xbps_object_iterator_t iter;
486 const char *pkgver = NULL, *tpkgver = NULL, *arch = NULL, *vpkg = NULL;
488 iter = xbps_dictionary_iterator(repo->
idx);
491 while ((obj = xbps_object_iterator_next(iter))) {
492 pkgd = xbps_dictionary_get_keysym(repo->
idx, obj);
493 if (xbps_dictionary_equals(pkgd, tpkgd))
496 pkgdeps = xbps_dictionary_get(pkgd,
"run_depends");
497 if (!xbps_array_count(pkgdeps))
505 xbps_dictionary_get_cstring_nocopy(pkgd,
506 "architecture", &arch);
510 xbps_dictionary_get_cstring_nocopy(pkgd,
514 revdeps = xbps_array_create();
517 xbps_array_add_cstring_nocopy(revdeps, tpkgver);
524 provides = xbps_dictionary_get(tpkgd,
"provides");
525 for (
unsigned int i = 0; i < xbps_array_count(provides); i++) {
526 xbps_array_get_cstring_nocopy(provides, i, &vpkg);
530 xbps_dictionary_get_cstring_nocopy(pkgd,
531 "architecture", &arch);
535 xbps_dictionary_get_cstring_nocopy(pkgd,
"pkgver",
539 revdeps = xbps_array_create();
542 xbps_array_add_cstring_nocopy(revdeps, tpkgver);
547 xbps_dictionary_get_cstring_nocopy(tpkgd,
"pkgver", &pkgver);
551 xbps_dictionary_get_cstring_nocopy(pkgd,
552 "architecture", &arch);
556 xbps_dictionary_get_cstring_nocopy(pkgd,
"pkgver", &tpkgver);
559 revdeps = xbps_array_create();
562 xbps_array_add_cstring_nocopy(revdeps, tpkgver);
564 xbps_object_iterator_release(iter);
571 xbps_array_t revdeps = NULL, vdeps = NULL;
572 xbps_dictionary_t pkgd;
576 if (repo->
idx == NULL)
587 if ((vdeps = xbps_dictionary_get(pkgd,
"provides"))) {
588 for (
unsigned int i = 0; i < xbps_array_count(vdeps); i++) {
589 char vpkgn[XBPS_NAME_SIZE];
591 xbps_array_get_cstring_nocopy(vdeps, i, &vpkg);
595 if (strcmp(vpkgn, pkg) == 0) {
602 revdeps = revdeps_match(repo, pkgd, vpkg);
605 revdeps = revdeps_match(repo, pkgd, NULL);
613 xbps_dictionary_t repokeyd = NULL;
614 xbps_data_t pubkey = NULL;
615 uint16_t pubkey_size = 0;
616 const char *signedby = NULL;
618 char *p, *dbkeyd, *rkeyfile = NULL;
625 if (!xbps_dictionary_count(repo->
idxmeta)) {
626 xbps_dbg_printf(
"[repo] `%s' unsigned repository!\n", repo->
uri);
635 xbps_dictionary_get_cstring_nocopy(repo->
idxmeta,
"signature-by", &signedby);
636 xbps_dictionary_get_uint16(repo->
idxmeta,
"public-key-size", &pubkey_size);
637 pubkey = xbps_dictionary_get(repo->
idxmeta,
"public-key");
639 if (signedby == NULL || pubkey_size == 0 ||
640 xbps_object_type(pubkey) != XBPS_TYPE_DATA) {
641 xbps_dbg_printf(
"[repo] `%s': incomplete signed repository "
642 "(missing objs)\n", repo->
uri);
656 if (xbps_object_type(repokeyd) == XBPS_TYPE_DICTIONARY) {
657 xbps_dbg_printf(
"[repo] `%s' public key already stored.\n", repo->
uri);
665 import = xbps_set_cb_state(repo->xhp, XBPS_STATE_REPO_KEY_IMPORT, 0,
666 hexfp, "`%s' repository has been RSA signed by \"%s\
"",
667 repo->
uri, signedby);
673 p = strdup(rkeyfile);
676 if (access(dbkeyd, R_OK|W_OK) == -1) {
682 xbps_dbg_printf(
"[repo] `%s' cannot create %s: %s\n",
683 repo->
uri, dbkeyd, strerror(errno));
690 repokeyd = xbps_dictionary_create();
691 xbps_dictionary_set(repokeyd,
"public-key", pubkey);
692 xbps_dictionary_set_uint16(repokeyd,
"public-key-size", pubkey_size);
693 xbps_dictionary_set_cstring_nocopy(repokeyd,
"signature-by", signedby);
695 if (!xbps_dictionary_externalize_to_file(repokeyd, rkeyfile)) {
697 xbps_dbg_printf(
"[repo] `%s' failed to externalize %s: %s\n",
698 repo->
uri, rkeyfile, strerror(rv));
705 xbps_object_release(repokeyd);
char metadir[XBPS_MAXPATH+sizeof(XBPS_META_PATH)]
xbps_array_t repositories
int(* state_cb)(const struct xbps_state_cb_data *, void *)
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)
struct xbps_repo * xbps_repo_stage_open(struct xbps_handle *xhp, const char *url)
void xbps_repo_release(struct xbps_repo *repo)
bool xbps_repo_remove(struct xbps_handle *xhp, const char *repo)
int xbps_repo_key_import(struct xbps_repo *repo)
struct xbps_repo * xbps_repo_public_open(struct xbps_handle *xhp, const char *url)
void xbps_repo_close(struct xbps_repo *repo)
char * xbps_repo_path(struct xbps_handle *xhp, const char *url)
xbps_dictionary_t xbps_repo_get_virtualpkg(struct xbps_repo *repo, const char *pkg)
bool xbps_repo_fetch_remote(struct xbps_repo *repo, const char *url)
bool xbps_repo_lock(struct xbps_handle *xhp, const char *repodir, int *lockfd, char **lockfname)
xbps_array_t xbps_repo_get_pkg_revdeps(struct xbps_repo *repo, const char *pkg)
void xbps_repo_unlock(int lockfd, char *lockfname)
char * xbps_repo_path_with_name(struct xbps_handle *xhp, const char *url, const char *name)
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)