This diff changes the way the parser figures out which file to work on.
Until now the parent process sent a full path to the parser but that does
not work well with the idea of splitting the repo up into validated, rsync
and rrdp parts.
So this diff changes the way the parser opens a file. There are now three
bits of information passed in struct entity.
- repoid: id of the repository to use, can be zero to indicate no repo.
- path: relative path from the base repo to the working directory where
file lives. Again this is optional and can be NULL.
- file: filename of the object to work on. This value has to be set.
To make this work struct mft needs to pass the path and repoid back to the
parent so that the parent can build the next round of files to parse based
on that information.
Right now the code should behave exactly the same as -current.
--
:wq Claudio
Index: extern.h
===================================================================
RCS file: /cvs/src/usr.sbin/rpki-client/extern.h,v
retrieving revision 1.100
diff -u -p -r1.100 extern.h
--- extern.h 29 Dec 2021 11:37:57 -0000 1.100
+++ extern.h 7 Jan 2022 14:37:05 -0000
@@ -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
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: main.c
===================================================================
RCS file: /cvs/src/usr.sbin/rpki-client/main.c,v
retrieving revision 1.172
diff -u -p -r1.172 main.c
--- main.c 6 Jan 2022 16:06:30 -0000 1.172
+++ main.c 10 Jan 2022 10:30:53 -0000
@@ -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 *en
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
{
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
* 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,
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,
*/
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 htt
* 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, cons
* 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
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
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 tali
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 st
}
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: mft.c
===================================================================
RCS file: /cvs/src/usr.sbin/rpki-client/mft.c,v
retrieving revision 1.43
diff -u -p -r1.43 mft.c
--- mft.c 6 Jan 2022 16:06:30 -0000 1.43
+++ mft.c 7 Jan 2022 15:02:56 -0000
@@ -433,8 +433,6 @@ mft_parse(X509 **x509, const char *fn, c
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
{
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);
@@ -571,11 +575,6 @@ mft_read(struct ibuf *b)
io_read_str(b, &p->files[i].file);
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: parser.c
===================================================================
RCS file: /cvs/src/usr.sbin/rpki-client/parser.c,v
retrieving revision 1.33
diff -u -p -r1.33 parser.c
--- parser.c 5 Jan 2022 11:07:35 -0000 1.33
+++ parser.c 10 Jan 2022 11:11:18 -0000
@@ -46,6 +46,46 @@ 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 to repo tree %d, %s", id,
path);
+ warnx("repository added to repo tree %d, %s", id, path);
+}
+
static int
verify_cb(int ok, X509_STORE_CTX *store_ctx)
{
@@ -192,7 +232,8 @@ proc_parser_roa(char *file, const unsign
* 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 +276,10 @@ proc_parser_mft(char *file, const unsign
return NULL;
}
+ if (path != NULL)
+ if ((mft->path = strdup(path)) == NULL)
+ err(1, NULL);
+ mft->repoid = repoid;
return mft;
}
@@ -544,6 +589,37 @@ build_crls(const struct crl *crl, STACK_
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 +631,31 @@ parse_entity(struct entityq *q, struct m
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 +669,11 @@ parse_entity(struct entityq *q, struct m
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 +685,11 @@ parse_entity(struct entityq *q, struct m
*/
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 +697,7 @@ parse_entity(struct entityq *q, struct m
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 +705,14 @@ parse_entity(struct entityq *q, struct m
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: repo.c
===================================================================
RCS file: /cvs/src/usr.sbin/rpki-client/repo.c,v
retrieving revision 1.19
diff -u -p -r1.19 repo.c
--- repo.c 4 Jan 2022 18:16:09 -0000 1.19
+++ repo.c 7 Jan 2022 14:41:47 -0000
@@ -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,
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,
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);
}