Change the way the parser accesses files. It now builds the file path
authorclaudio <claudio@openbsd.org>
Tue, 11 Jan 2022 13:06:07 +0000 (13:06 +0000)
committerclaudio <claudio@openbsd.org>
Tue, 11 Jan 2022 13:06:07 +0000 (13:06 +0000)
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
usr.sbin/rpki-client/main.c
usr.sbin/rpki-client/mft.c
usr.sbin/rpki-client/parser.c
usr.sbin/rpki-client/repo.c

index 47fc57c..737aa45 100644 (file)
@@ -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 <kristaps@bsd.lv>
  *
@@ -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);
index ce7abda..fa8d284 100644 (file)
@@ -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 <claudio@openbsd.org>
  * Copyright (c) 2019 Kristaps Dzonsons <kristaps@bsd.lv>
@@ -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);
index 3c30d5f..d9268fd 100644 (file)
@@ -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 <kristaps@bsd.lv>
  *
@@ -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;
 }
index cc3b259..782b80a 100644 (file)
@@ -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 <claudio@openbsd.org>
  * Copyright (c) 2019 Kristaps Dzonsons <kristaps@bsd.lv>
@@ -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);
        }
index 3edb098..1d4c5c4 100644 (file)
@@ -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 <claudio@openbsd.org>
  * Copyright (c) 2019 Kristaps Dzonsons <kristaps@bsd.lv>
@@ -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);
 }