From 100ded9e8b058873897806207afb9f93985664ae Mon Sep 17 00:00:00 2001 From: claudio Date: Tue, 11 Jan 2022 13:06:07 +0000 Subject: [PATCH] Change the way the parser accesses files. It now builds the file path based on information from the repository, a local path and the filename. This simplifies some code both in the main process and the parser. For this to work repositories are passed to the parser before any other entity of this repository is passed. Struct entity is extended to include the repoid and the path along the file(name). Input and OK tb@ & job@ --- usr.sbin/rpki-client/extern.h | 17 ++-- usr.sbin/rpki-client/main.c | 144 +++++++++++++++++++++------------- usr.sbin/rpki-client/mft.c | 39 +++++---- usr.sbin/rpki-client/parser.c | 111 +++++++++++++++++++++++--- usr.sbin/rpki-client/repo.c | 86 +++++++++++++------- 5 files changed, 273 insertions(+), 124 deletions(-) diff --git a/usr.sbin/rpki-client/extern.h b/usr.sbin/rpki-client/extern.h index 47fc57cb173..737aa4588a0 100644 --- a/usr.sbin/rpki-client/extern.h +++ b/usr.sbin/rpki-client/extern.h @@ -1,4 +1,4 @@ -/* $OpenBSD: extern.h,v 1.100 2021/12/29 11:37:57 claudio Exp $ */ +/* $OpenBSD: extern.h,v 1.101 2022/01/11 13:06:07 claudio Exp $ */ /* * Copyright (c) 2019 Kristaps Dzonsons * @@ -162,14 +162,15 @@ struct mftfile { * manifest file. */ struct mft { - char *file; /* full path of MFT file */ + char *path; /* relative path to directory of the MFT */ struct mftfile *files; /* file and hash */ size_t filesz; /* number of filenames */ - int stale; /* if a stale manifest */ char *seqnum; /* manifestNumber */ char *aia; /* AIA */ char *aki; /* AKI */ char *ski; /* SKI */ + unsigned int repoid; + int stale; /* if a stale manifest */ }; /* @@ -292,6 +293,7 @@ enum rtype { RTYPE_CER, RTYPE_CRL, RTYPE_GBR, + RTYPE_REPO, }; enum http_result { @@ -337,9 +339,11 @@ enum publish_type { */ struct entity { TAILQ_ENTRY(entity) entries; - char *file; /* local path to file */ + char *path; /* path relative to repository */ + char *file; /* filename */ unsigned char *data; /* optional data blob */ size_t datasz; /* length of optional data blob */ + unsigned int repoid; /* repository identifier */ int talid; /* tal identifier */ enum rtype type; /* type of entity (not RTYPE_EOF) */ }; @@ -500,9 +504,12 @@ int filepath_add(struct filepath_tree *, char *); void rrdp_save_state(unsigned int, struct rrdp_session *); int rrdp_handle_file(unsigned int, enum publish_type, char *, char *, size_t, char *, size_t); -char *repo_filename(const struct repo *, const char *); +char *repo_basedir(const struct repo *); +unsigned int repo_id(const struct repo *); +const char *repo_uri(const struct repo *); struct repo *ta_lookup(int, struct tal *); struct repo *repo_lookup(int, const char *, const char *); +struct repo *repo_byid(unsigned int); int repo_queued(struct repo *, struct entity *); void repo_cleanup(struct filepath_tree *); void repo_free(void); diff --git a/usr.sbin/rpki-client/main.c b/usr.sbin/rpki-client/main.c index ce7abda7d12..fa8d2841330 100644 --- a/usr.sbin/rpki-client/main.c +++ b/usr.sbin/rpki-client/main.c @@ -1,4 +1,4 @@ -/* $OpenBSD: main.c,v 1.172 2022/01/06 16:06:30 claudio Exp $ */ +/* $OpenBSD: main.c,v 1.173 2022/01/11 13:06:07 claudio Exp $ */ /* * Copyright (c) 2021 Claudio Jeker * Copyright (c) 2019 Kristaps Dzonsons @@ -104,8 +104,9 @@ entity_free(struct entity *ent) if (ent == NULL) return; - free(ent->data); + free(ent->path); free(ent->file); + free(ent->data); free(ent); } @@ -118,7 +119,9 @@ void entity_read_req(struct ibuf *b, struct entity *ent) { io_read_buf(b, &ent->type, sizeof(ent->type)); + io_read_buf(b, &ent->repoid, sizeof(ent->repoid)); io_read_buf(b, &ent->talid, sizeof(ent->talid)); + io_read_str(b, &ent->path); io_read_str(b, &ent->file); io_read_buf_alloc(b, (void **)&ent->data, &ent->datasz); } @@ -134,12 +137,36 @@ entity_write_req(const struct entity *ent) b = io_new_buffer(); io_simple_buffer(b, &ent->type, sizeof(ent->type)); + io_simple_buffer(b, &ent->repoid, sizeof(ent->repoid)); io_simple_buffer(b, &ent->talid, sizeof(ent->talid)); + io_str_buffer(b, ent->path); io_str_buffer(b, ent->file); io_buf_buffer(b, ent->data, ent->datasz); io_close_buffer(&procq, b); } +static void +entity_write_repo(struct repo *rp) +{ + struct ibuf *b; + enum rtype type = RTYPE_REPO; + unsigned int repoid; + char *path; + int talid = 0; + + repoid = repo_id(rp); + path = repo_basedir(rp); + b = io_new_buffer(); + io_simple_buffer(b, &type, sizeof(type)); + io_simple_buffer(b, &repoid, sizeof(repoid)); + io_simple_buffer(b, &talid, sizeof(talid)); + io_str_buffer(b, path); + io_str_buffer(b, NULL); + io_buf_buffer(b, NULL, 0); + io_close_buffer(&procq, b); + free(path); +} + /* * Scan through all queued requests and see which ones are in the given * repo, then flush those into the parser process. @@ -149,20 +176,9 @@ entityq_flush(struct entityq *q, struct repo *rp) { struct entity *p, *np; - TAILQ_FOREACH_SAFE(p, q, entries, np) { - char *file = p->file; - - /* - * XXX fixup path here since the repo may change - * during load because of fallback. In that case - * the file path changes as well since RRDP and RSYNC - * can not share a common repo. - */ - p->file = repo_filename(rp, file); - if (p->file == NULL) - err(1, "can't construct repo filename"); - free(file); + entity_write_repo(rp); + TAILQ_FOREACH_SAFE(p, q, entries, np) { entity_write_req(p); TAILQ_REMOVE(q, p, entries); entity_free(p); @@ -173,7 +189,7 @@ entityq_flush(struct entityq *q, struct repo *rp) * Add the heap-allocated file to the queue for processing. */ static void -entityq_add(char *file, enum rtype type, struct repo *rp, +entityq_add(char *path, char *file, enum rtype type, struct repo *rp, unsigned char *data, size_t datasz, int talid) { struct entity *p; @@ -183,6 +199,9 @@ entityq_add(char *file, enum rtype type, struct repo *rp, p->type = type; p->talid = talid; + p->path = path; + if (rp != NULL) + p->repoid = repo_id(rp); p->file = file; p->data = data; p->datasz = (data != NULL) ? datasz : 0; @@ -195,20 +214,6 @@ entityq_add(char *file, enum rtype type, struct repo *rp, */ if (rp == NULL || !repo_queued(rp, p)) { - /* - * XXX fixup path here since for repo path the - * file path has not yet been fixed here. - * This is a quick way to make this work but in - * the long run repos need to be passed to the parser. - */ - if (rp != NULL) { - file = p->file; - p->file = repo_filename(rp, file); - if (p->file == NULL) - err(1, "can't construct repo filename from %s", - file); - free(file); - } entity_write_req(p); entity_free(p); } @@ -320,23 +325,18 @@ rrdp_http_done(unsigned int id, enum http_result res, const char *last_mod) * These are always relative to the directory in which "mft" sits. */ static void -queue_add_from_mft(const char *mft, const struct mftfile *file, enum rtype type) +queue_add_from_mft(const char *path, const struct mftfile *file, + enum rtype type, struct repo *rp) { - char *cp, *nfile; + char *nfile, *npath = NULL; - /* Construct local path from filename. */ - cp = strrchr(mft, '/'); - assert(cp != NULL); - assert(cp - mft < INT_MAX); - if (asprintf(&nfile, "%.*s/%s", (int)(cp - mft), mft, file->file) == -1) + if (path != NULL) + if ((npath = strdup(path)) == NULL) + err(1, NULL); + if ((nfile = strdup(file->file)) == NULL) err(1, NULL); - /* - * Since we're from the same directory as the MFT file, we know - * that the repository has already been loaded. - */ - - entityq_add(nfile, type, NULL, NULL, 0, -1); + entityq_add(npath, nfile, type, rp, NULL, 0, -1); } /* @@ -348,7 +348,7 @@ queue_add_from_mft(const char *mft, const struct mftfile *file, enum rtype type) * check the suffix anyway). */ static void -queue_add_from_mft_set(const struct mft *mft) +queue_add_from_mft_set(const struct mft *mft, const char *name, struct repo *rp) { size_t i, sz; const struct mftfile *f; @@ -359,7 +359,7 @@ queue_add_from_mft_set(const struct mft *mft) assert(sz > 4); if (strcasecmp(f->file + sz - 4, ".crl") != 0) continue; - queue_add_from_mft(mft->file, f, RTYPE_CRL); + queue_add_from_mft(mft->path, f, RTYPE_CRL, rp); } for (i = 0; i < mft->filesz; i++) { @@ -369,13 +369,13 @@ queue_add_from_mft_set(const struct mft *mft) if (strcasecmp(f->file + sz - 4, ".crl") == 0) continue; else if (strcasecmp(f->file + sz - 4, ".cer") == 0) - queue_add_from_mft(mft->file, f, RTYPE_CER); + queue_add_from_mft(mft->path, f, RTYPE_CER, rp); else if (strcasecmp(f->file + sz - 4, ".roa") == 0) - queue_add_from_mft(mft->file, f, RTYPE_ROA); + queue_add_from_mft(mft->path, f, RTYPE_ROA, rp); else if (strcasecmp(f->file + sz - 4, ".gbr") == 0) - queue_add_from_mft(mft->file, f, RTYPE_GBR); + queue_add_from_mft(mft->path, f, RTYPE_GBR, rp); else - logx("%s: unsupported file type: %s", mft->file, + logx("%s: unsupported file type: %s", name, f->file); } } @@ -399,7 +399,7 @@ queue_add_tal(const char *file, int talid) if ((nfile = strdup(file)) == NULL) err(1, NULL); /* Not in a repository, so directly add to queue. */ - entityq_add(nfile, RTYPE_TAL, NULL, buf, len, talid); + entityq_add(NULL, nfile, RTYPE_TAL, NULL, buf, len, talid); } /* @@ -410,12 +410,19 @@ queue_add_from_tal(struct tal *tal) { struct repo *repo; unsigned char *data; + char *nfile; assert(tal->urisz); if ((taldescs[tal->id] = strdup(tal->descr)) == NULL) err(1, NULL); + /* figure out the TA filename, must be done before repo lookup */ + nfile = strrchr(tal->uri[0], '/'); + assert(nfile != NULL); + if ((nfile = strdup(nfile + 1)) == NULL) + err(1, NULL); + /* Look up the repository. */ repo = ta_lookup(tal->id, tal); if (repo == NULL) @@ -424,7 +431,7 @@ queue_add_from_tal(struct tal *tal) /* steal the pkey from the tal structure */ data = tal->pkey; tal->pkey = NULL; - entityq_add(NULL, RTYPE_CER, repo, data, tal->pkeysz, tal->id); + entityq_add(NULL, nfile, RTYPE_CER, repo, data, tal->pkeysz, tal->id); } /* @@ -434,16 +441,40 @@ static void queue_add_from_cert(const struct cert *cert) { struct repo *repo; - char *nfile; + char *nfile, *npath; + const char *uri, *repouri, *file; + size_t repourisz; repo = repo_lookup(cert->talid, cert->repo, rrdpon ? cert->notify : NULL); if (repo == NULL) return; - if ((nfile = strdup(cert->mft)) == NULL) - err(1, NULL); - entityq_add(nfile, RTYPE_MFT, repo, NULL, 0, -1); + /* + * Figure out the cert filename and path by chopping up the + * MFT URI in the cert based on the repo base URI. + */ + uri = cert->mft; + repouri = repo_uri(repo); + repourisz = strlen(repouri); + if (strncmp(repouri, cert->mft, repourisz) != 0) { + warnx("%s: URI %s outside of repository", repouri, uri); + return; + } + uri += repourisz + 1; /* skip base and '/' */ + file = strrchr(uri, '/'); + if (file == NULL) { + npath = NULL; + if ((nfile = strdup(uri)) == NULL) + err(1, NULL); + } else { + if ((npath = strndup(uri, file - uri)) == NULL) + err(1, NULL); + if ((nfile = strdup(file + 1)) == NULL) + err(1, NULL); + } + + entityq_add(npath, nfile, RTYPE_MFT, repo, NULL, 0, -1); } /* @@ -519,7 +550,8 @@ entity_process(struct ibuf *b, struct stats *st, struct vrp_tree *tree, } mft = mft_read(b); if (!mft->stale) - queue_add_from_mft_set(mft); + queue_add_from_mft_set(mft, file, + repo_byid(mft->repoid)); else st->mfts_stale++; mft_free(mft); diff --git a/usr.sbin/rpki-client/mft.c b/usr.sbin/rpki-client/mft.c index 3c30d5f4cf9..d9268fda7d6 100644 --- a/usr.sbin/rpki-client/mft.c +++ b/usr.sbin/rpki-client/mft.c @@ -1,4 +1,4 @@ -/* $OpenBSD: mft.c,v 1.43 2022/01/06 16:06:30 claudio Exp $ */ +/* $OpenBSD: mft.c,v 1.44 2022/01/11 13:06:07 claudio Exp $ */ /* * Copyright (c) 2019 Kristaps Dzonsons * @@ -433,8 +433,6 @@ mft_parse(X509 **x509, const char *fn, const unsigned char *der, size_t len) if ((p.res = calloc(1, sizeof(struct mft))) == NULL) err(1, NULL); - if ((p.res->file = strdup(fn)) == NULL) - err(1, NULL); p.res->aia = x509_get_aia(*x509, fn); p.res->aki = x509_get_aki(*x509, 0, fn); @@ -517,7 +515,7 @@ mft_free(struct mft *p) free(p->aia); free(p->aki); free(p->ski); - free(p->file); + free(p->path); free(p->files); free(p->seqnum); free(p); @@ -532,18 +530,19 @@ mft_buffer(struct ibuf *b, const struct mft *p) { size_t i; - io_simple_buffer(b, &p->stale, sizeof(int)); - io_str_buffer(b, p->file); - io_simple_buffer(b, &p->filesz, sizeof(size_t)); + io_simple_buffer(b, &p->stale, sizeof(p->stale)); + io_simple_buffer(b, &p->repoid, sizeof(p->repoid)); + io_str_buffer(b, p->path); + + io_str_buffer(b, p->aia); + io_str_buffer(b, p->aki); + io_str_buffer(b, p->ski); + io_simple_buffer(b, &p->filesz, sizeof(size_t)); for (i = 0; i < p->filesz; i++) { io_str_buffer(b, p->files[i].file); io_simple_buffer(b, p->files[i].hash, SHA256_DIGEST_LENGTH); } - - io_str_buffer(b, p->aia); - io_str_buffer(b, p->aki); - io_str_buffer(b, p->ski); } /* @@ -559,11 +558,16 @@ mft_read(struct ibuf *b) if ((p = calloc(1, sizeof(struct mft))) == NULL) err(1, NULL); - io_read_buf(b, &p->stale, sizeof(int)); - io_read_str(b, &p->file); - io_read_buf(b, &p->filesz, sizeof(size_t)); + io_read_buf(b, &p->stale, sizeof(p->stale)); + io_read_buf(b, &p->repoid, sizeof(p->repoid)); + io_read_str(b, &p->path); - assert(p->file); + io_read_str(b, &p->aia); + io_read_str(b, &p->aki); + io_read_str(b, &p->ski); + assert(p->aia && p->aki && p->ski); + + io_read_buf(b, &p->filesz, sizeof(size_t)); if ((p->files = calloc(p->filesz, sizeof(struct mftfile))) == NULL) err(1, NULL); @@ -572,10 +576,5 @@ mft_read(struct ibuf *b) io_read_buf(b, p->files[i].hash, SHA256_DIGEST_LENGTH); } - io_read_str(b, &p->aia); - io_read_str(b, &p->aki); - io_read_str(b, &p->ski); - assert(p->aia && p->aki && p->ski); - return p; } diff --git a/usr.sbin/rpki-client/parser.c b/usr.sbin/rpki-client/parser.c index cc3b259804b..782b80aa5bc 100644 --- a/usr.sbin/rpki-client/parser.c +++ b/usr.sbin/rpki-client/parser.c @@ -1,4 +1,4 @@ -/* $OpenBSD: parser.c,v 1.33 2022/01/05 11:07:35 claudio Exp $ */ +/* $OpenBSD: parser.c,v 1.34 2022/01/11 13:06:07 claudio Exp $ */ /* * Copyright (c) 2019 Claudio Jeker * Copyright (c) 2019 Kristaps Dzonsons @@ -46,6 +46,45 @@ static X509_STORE_CTX *ctx; static struct auth_tree auths = RB_INITIALIZER(&auths); static struct crl_tree crlt = RB_INITIALIZER(&crlt); +struct parse_repo { + RB_ENTRY(parse_repo) entry; + char *path; + unsigned int id; +}; + +static RB_HEAD(repo_tree, parse_repo) repos = RB_INITIALIZER(&repos); + +static inline int +repocmp(struct parse_repo *a, struct parse_repo *b) +{ + return a->id - b->id; +} + +RB_GENERATE_STATIC(repo_tree, parse_repo, entry, repocmp); + +static struct parse_repo * +repo_get(unsigned int id) +{ + struct parse_repo needle = { .id = id }; + + return RB_FIND(repo_tree, &repos, &needle); +} + +static void +repo_add(unsigned int id, char *path) +{ + struct parse_repo *rp; + + if ((rp = malloc(sizeof(*rp))) == NULL) + err(1, NULL); + rp->id = id; + if ((rp->path = strdup(path)) == NULL) + err(1, NULL); + + if (RB_INSERT(repo_tree, &repos, rp) != NULL) + errx(1, "repository already added: id %d, %s", id, path); +} + static int verify_cb(int ok, X509_STORE_CTX *store_ctx) { @@ -192,7 +231,8 @@ proc_parser_roa(char *file, const unsigned char *der, size_t len) * Return the mft on success or NULL on failure. */ static struct mft * -proc_parser_mft(char *file, const unsigned char *der, size_t len) +proc_parser_mft(char *file, const unsigned char *der, size_t len, + const char *path, unsigned int repoid) { struct mft *mft; X509 *x509; @@ -235,6 +275,10 @@ proc_parser_mft(char *file, const unsigned char *der, size_t len) return NULL; } + if (path != NULL) + if ((mft->path = strdup(path)) == NULL) + err(1, NULL); + mft->repoid = repoid; return mft; } @@ -544,6 +588,37 @@ build_crls(const struct crl *crl, STACK_OF(X509_CRL) **crls) err(1, "sk_X509_CRL_push"); } +static char * +parse_filepath(struct entity *entp) +{ + struct parse_repo *rp; + char *file; + + /* build file path based on repoid, entity path and filename */ + rp = repo_get(entp->repoid); + if (rp == NULL) { + if (entp->path == NULL) { + if ((file = strdup(entp->file)) == NULL) + err(1, NULL); + } else { + if (asprintf(&file, "%s/%s", entp->path, + entp->file) == -1) + err(1, NULL); + } + } else { + if (entp->path == NULL) { + if (asprintf(&file, "%s/%s", rp->path, + entp->file) == -1) + err(1, NULL); + } else { + if (asprintf(&file, "%s/%s/%s", rp->path, + entp->path, entp->file) == -1) + err(1, NULL); + } + } + return file; +} + static void parse_entity(struct entityq *q, struct msgbuf *msgq) { @@ -555,23 +630,31 @@ parse_entity(struct entityq *q, struct msgbuf *msgq) struct ibuf *b; unsigned char *f; size_t flen; + char *file; int c; while ((entp = TAILQ_FIRST(q)) != NULL) { TAILQ_REMOVE(q, entp, entries); - b = io_new_buffer(); + /* handle RTYPE_REPO first */ + if (entp->type == RTYPE_REPO) { + repo_add(entp->repoid, entp->path); + entity_free(entp); + continue; + } f = NULL; + file = parse_filepath(entp); if (entp->type != RTYPE_TAL) { - f = load_file(entp->file, &flen); + f = load_file(file, &flen); if (f == NULL) - warn("%s", entp->file); + warn("%s", file); } /* pass back at least type and filename */ + b = io_new_buffer(); io_simple_buffer(b, &entp->type, sizeof(entp->type)); - io_str_buffer(b, entp->file); + io_str_buffer(b, file); switch (entp->type) { case RTYPE_TAL: @@ -585,11 +668,11 @@ parse_entity(struct entityq *q, struct msgbuf *msgq) break; case RTYPE_CER: if (entp->data != NULL) - cert = proc_parser_root_cert(entp->file, + cert = proc_parser_root_cert(file, f, flen, entp->data, entp->datasz, entp->talid); else - cert = proc_parser_cert(entp->file, f, flen); + cert = proc_parser_cert(file, f, flen); c = (cert != NULL); io_simple_buffer(b, &c, sizeof(int)); if (cert != NULL) @@ -601,10 +684,11 @@ parse_entity(struct entityq *q, struct msgbuf *msgq) */ break; case RTYPE_CRL: - proc_parser_crl(entp->file, f, flen); + proc_parser_crl(file, f, flen); break; case RTYPE_MFT: - mft = proc_parser_mft(entp->file, f, flen); + mft = proc_parser_mft(file, f, flen, + entp->path, entp->repoid); c = (mft != NULL); io_simple_buffer(b, &c, sizeof(int)); if (mft != NULL) @@ -612,7 +696,7 @@ parse_entity(struct entityq *q, struct msgbuf *msgq) mft_free(mft); break; case RTYPE_ROA: - roa = proc_parser_roa(entp->file, f, flen); + roa = proc_parser_roa(file, f, flen); c = (roa != NULL); io_simple_buffer(b, &c, sizeof(int)); if (roa != NULL) @@ -620,13 +704,14 @@ parse_entity(struct entityq *q, struct msgbuf *msgq) roa_free(roa); break; case RTYPE_GBR: - proc_parser_gbr(entp->file, f, flen); + proc_parser_gbr(file, f, flen); break; default: - abort(); + errx(1, "unhandled entity type %d", entp->type); } free(f); + free(file); io_close_buffer(msgq, b); entity_free(entp); } diff --git a/usr.sbin/rpki-client/repo.c b/usr.sbin/rpki-client/repo.c index 3edb098bd86..1d4c5c4ded9 100644 --- a/usr.sbin/rpki-client/repo.c +++ b/usr.sbin/rpki-client/repo.c @@ -1,4 +1,4 @@ -/* $OpenBSD: repo.c,v 1.19 2022/01/04 18:16:09 claudio Exp $ */ +/* $OpenBSD: repo.c,v 1.20 2022/01/11 13:06:07 claudio Exp $ */ /* * Copyright (c) 2021 Claudio Jeker * Copyright (c) 2019 Kristaps Dzonsons @@ -64,7 +64,7 @@ struct rrdprepo { unsigned int id; enum repo_state state; }; -SLIST_HEAD(, rrdprepo) rrdprepos = SLIST_HEAD_INITIALIZER(rrdprepos); +static SLIST_HEAD(, rrdprepo) rrdprepos = SLIST_HEAD_INITIALIZER(rrdprepos); struct rsyncrepo { SLIST_ENTRY(rsyncrepo) entry; @@ -73,7 +73,7 @@ struct rsyncrepo { unsigned int id; enum repo_state state; }; -SLIST_HEAD(, rsyncrepo) rsyncrepos = SLIST_HEAD_INITIALIZER(rsyncrepos); +static SLIST_HEAD(, rsyncrepo) rsyncrepos = SLIST_HEAD_INITIALIZER(rsyncrepos); struct tarepo { SLIST_ENTRY(tarepo) entry; @@ -86,7 +86,7 @@ struct tarepo { unsigned int id; enum repo_state state; }; -SLIST_HEAD(, tarepo) tarepos = SLIST_HEAD_INITIALIZER(tarepos); +static SLIST_HEAD(, tarepo) tarepos = SLIST_HEAD_INITIALIZER(tarepos); struct repo { SLIST_ENTRY(repo) entry; @@ -100,7 +100,7 @@ struct repo { int talid; unsigned int id; /* identifier */ }; -SLIST_HEAD(, repo) repos = SLIST_HEAD_INITIALIZER(repos); +static SLIST_HEAD(, repo) repos = SLIST_HEAD_INITIALIZER(repos); /* counter for unique repo id */ unsigned int repoid; @@ -152,9 +152,8 @@ filepath_add(struct filepath_tree *tree, char *file) static struct filepath * filepath_find(struct filepath_tree *tree, char *file) { - struct filepath needle; + struct filepath needle = { .file = file }; - needle.file = file; return RB_FIND(filepath_tree, tree, &needle); } @@ -1146,39 +1145,66 @@ repo_lookup(int talid, const char *uri, const char *notify) if (rp->rrdp == NULL) rp->rsync = rsync_get(uri, nofetch); + if (repo_state(rp) != REPO_LOADING) + entityq_flush(&rp->queue, rp); + return rp; } /* - * Build local file name base on the URI and the repo info. + * Find repository by identifier. */ -char * -repo_filename(const struct repo *rp, const char *uri) +struct repo * +repo_byid(unsigned int id) { - char *nfile; - char *dir, *repouri; + struct repo *rp; - if (uri == NULL && rp->ta) - return ta_filename(rp->ta, 0); + SLIST_FOREACH(rp, &repos, entry) { + if (rp->id == id) + return rp; + } + return NULL; +} - assert(uri != NULL); - if (rp->rrdp) - return rrdp_filename(rp->rrdp, uri, 0); +/* + * Return the repository base directory. + * Returned string must be freed by caller. + */ +char * +repo_basedir(const struct repo *rp) +{ + char *path; - /* must be rsync */ - dir = rp->rsync->basedir; - repouri = rp->rsync->repouri; + if (rp->ta) { + if ((path = strdup(rp->ta->basedir)) == NULL) + err(1, NULL); + } else if (rp->rsync) { + if ((path = strdup(rp->rsync->basedir)) == NULL) + err(1, NULL); + } else if (rp->rrdp) { + path = rrdp_filename(rp->rrdp, rp->repouri, 0); + } else + errx(1, "%s: bad repo", rp->repouri); - if (strstr(uri, repouri) != uri) { - warnx("%s: URI %s outside of repository", repouri, uri); - return NULL; - } + return path; +} - uri += strlen(repouri) + 1; /* skip base and '/' */ +/* + * Return the repository identifier. + */ +unsigned int +repo_id(const struct repo *rp) +{ + return rp->id; +} - if (asprintf(&nfile, "%s/%s", dir, uri) == -1) - err(1, NULL); - return nfile; +/* + * Return the repository URI. + */ +const char * +repo_uri(const struct repo *rp) +{ + return rp->repouri; } int @@ -1220,10 +1246,10 @@ repo_fail(struct repo *rp) if (rp->ta) http_finish(rp->ta->id, HTTP_FAILED, NULL); - else if (rp->rrdp) - rrdp_finish(rp->rrdp->id, 0); else if (rp->rsync) rsync_finish(rp->rsync->id, 0); + else if (rp->rrdp) + rrdp_finish(rp->rrdp->id, 0); else errx(1, "%s: bad repo", rp->repouri); } -- 2.20.1