From 016bb32b8939911e9fc85b8a1ed3d3979332ebff Mon Sep 17 00:00:00 2001 From: Andrew Bettison Date: Mon, 16 Mar 2015 22:36:38 +1030 Subject: [PATCH] Add rhizome_manifest_overwrite() function --- rhizome.h | 1 + rhizome_bundle.c | 149 +++++++++++++++++++++++++++++++++++++---------- 2 files changed, 119 insertions(+), 31 deletions(-) diff --git a/rhizome.h b/rhizome.h index 511c82a6..b133bd25 100644 --- a/rhizome.h +++ b/rhizome.h @@ -305,6 +305,7 @@ enum rhizome_manifest_parse_status { RHIZOME_MANIFEST_OVERFLOW = 5, // maximum field count exceeded }; +int rhizome_manifest_overwrite(rhizome_manifest *m, const rhizome_manifest *srcm); int rhizome_manifest_field_label_is_valid(const char *field_label, size_t field_label_len); int rhizome_manifest_field_value_is_valid(const char *field_value, size_t field_value_len); enum rhizome_manifest_parse_status diff --git a/rhizome_bundle.c b/rhizome_bundle.c index 9091b40c..b91c75c9 100644 --- a/rhizome_bundle.c +++ b/rhizome_bundle.c @@ -664,11 +664,12 @@ int rhizome_manifest_parse(rhizome_manifest *m) OUT(); } -typedef int MANIFEST_FIELD_TESTER(rhizome_manifest *); +typedef int MANIFEST_FIELD_TESTER(const rhizome_manifest *); typedef void MANIFEST_FIELD_UNSETTER(rhizome_manifest *); +typedef void MANIFEST_FIELD_COPIER(rhizome_manifest *, const rhizome_manifest *); typedef int MANIFEST_FIELD_PARSER(rhizome_manifest *, const char *); -static int _rhizome_manifest_test_id(rhizome_manifest *m) +static int _rhizome_manifest_test_id(const rhizome_manifest *m) { return m->has_id; } @@ -676,6 +677,10 @@ static void _rhizome_manifest_unset_id(rhizome_manifest *m) { rhizome_manifest_set_id(m, NULL); } +static void _rhizome_manifest_copy_id(rhizome_manifest *m, const rhizome_manifest *srcm) +{ + rhizome_manifest_set_id(m, srcm->has_id ? &srcm->cryptoSignPublic : NULL); +} static int _rhizome_manifest_parse_id(rhizome_manifest *m, const char *text) { rhizome_bid_t bid; @@ -685,7 +690,7 @@ static int _rhizome_manifest_parse_id(rhizome_manifest *m, const char *text) return 1; } -static int _rhizome_manifest_test_version(rhizome_manifest *m) +static int _rhizome_manifest_test_version(const rhizome_manifest *m) { return m->version != 0; } @@ -693,6 +698,10 @@ static void _rhizome_manifest_unset_version(rhizome_manifest *m) { m->version = 0; } +static void _rhizome_manifest_copy_version(rhizome_manifest *m, const rhizome_manifest *srcm) +{ + rhizome_manifest_set_version(m, srcm->version); +} static int _rhizome_manifest_parse_version(rhizome_manifest *m, const char *text) { uint64_t version; @@ -702,7 +711,7 @@ static int _rhizome_manifest_parse_version(rhizome_manifest *m, const char *text return 1; } -static int _rhizome_manifest_test_filehash(rhizome_manifest *m) +static int _rhizome_manifest_test_filehash(const rhizome_manifest *m) { return m->has_filehash; } @@ -710,6 +719,10 @@ static void _rhizome_manifest_unset_filehash(rhizome_manifest *m) { rhizome_manifest_set_filehash(m, NULL); } +static void _rhizome_manifest_copy_filehash(rhizome_manifest *m, const rhizome_manifest *srcm) +{ + rhizome_manifest_set_filehash(m, srcm->has_filehash ? &srcm->filehash : NULL); +} static int _rhizome_manifest_parse_filehash(rhizome_manifest *m, const char *text) { rhizome_filehash_t hash; @@ -719,7 +732,7 @@ static int _rhizome_manifest_parse_filehash(rhizome_manifest *m, const char *tex return 1; } -static int _rhizome_manifest_test_filesize(rhizome_manifest *m) +static int _rhizome_manifest_test_filesize(const rhizome_manifest *m) { return m->filesize != RHIZOME_SIZE_UNSET; } @@ -727,6 +740,10 @@ static void _rhizome_manifest_unset_filesize(rhizome_manifest *m) { rhizome_manifest_set_filesize(m, RHIZOME_SIZE_UNSET); } +static void _rhizome_manifest_copy_filesize(rhizome_manifest *m, const rhizome_manifest *srcm) +{ + rhizome_manifest_set_filesize(m, srcm->filesize); +} static int _rhizome_manifest_parse_filesize(rhizome_manifest *m, const char *text) { uint64_t size; @@ -736,7 +753,7 @@ static int _rhizome_manifest_parse_filesize(rhizome_manifest *m, const char *tex return 1; } -static int _rhizome_manifest_test_tail(rhizome_manifest *m) +static int _rhizome_manifest_test_tail(const rhizome_manifest *m) { return m->is_journal; } @@ -744,6 +761,10 @@ static void _rhizome_manifest_unset_tail(rhizome_manifest *m) { rhizome_manifest_set_tail(m, RHIZOME_SIZE_UNSET); } +static void _rhizome_manifest_copy_tail(rhizome_manifest *m, const rhizome_manifest *srcm) +{ + rhizome_manifest_set_tail(m, srcm->tail); +} static int _rhizome_manifest_parse_tail(rhizome_manifest *m, const char *text) { uint64_t tail; @@ -753,7 +774,7 @@ static int _rhizome_manifest_parse_tail(rhizome_manifest *m, const char *text) return 1; } -static int _rhizome_manifest_test_BK(rhizome_manifest *m) +static int _rhizome_manifest_test_BK(const rhizome_manifest *m) { return m->has_bundle_key; } @@ -761,6 +782,10 @@ static void _rhizome_manifest_unset_BK(rhizome_manifest *m) { m->has_bundle_key = 0; } +static void _rhizome_manifest_copy_BK(rhizome_manifest *m, const rhizome_manifest *srcm) +{ + rhizome_manifest_set_bundle_key(m, srcm->has_bundle_key ? &srcm->bundle_key : NULL); +} static int _rhizome_manifest_parse_BK(rhizome_manifest *m, const char *text) { rhizome_bk_t bk; @@ -770,7 +795,7 @@ static int _rhizome_manifest_parse_BK(rhizome_manifest *m, const char *text) return 1; } -static int _rhizome_manifest_test_service(rhizome_manifest *m) +static int _rhizome_manifest_test_service(const rhizome_manifest *m) { return m->service != NULL; } @@ -778,6 +803,10 @@ static void _rhizome_manifest_unset_service(rhizome_manifest *m) { rhizome_manifest_del_service(m); } +static void _rhizome_manifest_copy_service(rhizome_manifest *m, const rhizome_manifest *srcm) +{ + rhizome_manifest_set_service(m, srcm->service); +} static int _rhizome_manifest_parse_service(rhizome_manifest *m, const char *text) { if (!rhizome_str_is_manifest_service(text)) @@ -786,7 +815,7 @@ static int _rhizome_manifest_parse_service(rhizome_manifest *m, const char *text return 1; } -static int _rhizome_manifest_test_date(rhizome_manifest *m) +static int _rhizome_manifest_test_date(const rhizome_manifest *m) { return m->has_date; } @@ -794,6 +823,13 @@ static void _rhizome_manifest_unset_date(rhizome_manifest *m) { rhizome_manifest_del_date(m); } +static void _rhizome_manifest_copy_date(rhizome_manifest *m, const rhizome_manifest *srcm) +{ + if (srcm->has_date) + rhizome_manifest_set_date(m, srcm->date); + else + rhizome_manifest_del_date(m); +} static int _rhizome_manifest_parse_date(rhizome_manifest *m, const char *text) { int64_t date; @@ -803,7 +839,7 @@ static int _rhizome_manifest_parse_date(rhizome_manifest *m, const char *text) return 1; } -static int _rhizome_manifest_test_sender(rhizome_manifest *m) +static int _rhizome_manifest_test_sender(const rhizome_manifest *m) { return m->has_sender; } @@ -811,6 +847,10 @@ static void _rhizome_manifest_unset_sender(rhizome_manifest *m) { rhizome_manifest_set_sender(m, NULL); } +static void _rhizome_manifest_copy_sender(rhizome_manifest *m, const rhizome_manifest *srcm) +{ + rhizome_manifest_set_sender(m, srcm->has_sender ? &srcm->sender : NULL); +} static int _rhizome_manifest_parse_sender(rhizome_manifest *m, const char *text) { sid_t sid; @@ -820,7 +860,7 @@ static int _rhizome_manifest_parse_sender(rhizome_manifest *m, const char *text) return 1; } -static int _rhizome_manifest_test_recipient(rhizome_manifest *m) +static int _rhizome_manifest_test_recipient(const rhizome_manifest *m) { return m->has_recipient; } @@ -828,6 +868,10 @@ static void _rhizome_manifest_unset_recipient(rhizome_manifest *m) { rhizome_manifest_set_recipient(m, NULL); } +static void _rhizome_manifest_copy_recipient(rhizome_manifest *m, const rhizome_manifest *srcm) +{ + rhizome_manifest_set_recipient(m, srcm->has_recipient ? &srcm->recipient : NULL); +} static int _rhizome_manifest_parse_recipient(rhizome_manifest *m, const char *text) { sid_t sid; @@ -837,7 +881,7 @@ static int _rhizome_manifest_parse_recipient(rhizome_manifest *m, const char *te return 1; } -static int _rhizome_manifest_test_name(rhizome_manifest *m) +static int _rhizome_manifest_test_name(const rhizome_manifest *m) { return m->name != NULL; } @@ -845,13 +889,17 @@ static void _rhizome_manifest_unset_name(rhizome_manifest *m) { rhizome_manifest_del_name(m); } +static void _rhizome_manifest_copy_name(rhizome_manifest *m, const rhizome_manifest *srcm) +{ + rhizome_manifest_set_name(m, srcm->name); +} static int _rhizome_manifest_parse_name(rhizome_manifest *m, const char *text) { rhizome_manifest_set_name(m, text); return 1; } -static int _rhizome_manifest_test_crypt(rhizome_manifest *m) +static int _rhizome_manifest_test_crypt(const rhizome_manifest *m) { return m->payloadEncryption != PAYLOAD_CRYPT_UNKNOWN; } @@ -859,6 +907,10 @@ static void _rhizome_manifest_unset_crypt(rhizome_manifest *m) { rhizome_manifest_set_crypt(m, PAYLOAD_CRYPT_UNKNOWN); } +static void _rhizome_manifest_copy_crypt(rhizome_manifest *m, const rhizome_manifest *srcm) +{ + rhizome_manifest_set_crypt(m, srcm->payloadEncryption); +} static int _rhizome_manifest_parse_crypt(rhizome_manifest *m, const char *text) { if (!(strcmp(text, "0") == 0 || strcmp(text, "1") == 0)) @@ -872,23 +924,62 @@ static struct rhizome_manifest_field_descriptor { int core; MANIFEST_FIELD_TESTER *test; MANIFEST_FIELD_UNSETTER *unset; + MANIFEST_FIELD_COPIER *copy; MANIFEST_FIELD_PARSER *parse; } rhizome_manifest_fields[] = { - { "id", 1, _rhizome_manifest_test_id, _rhizome_manifest_unset_id, _rhizome_manifest_parse_id }, - { "version", 1, _rhizome_manifest_test_version, _rhizome_manifest_unset_version, _rhizome_manifest_parse_version }, - { "filehash", 1, _rhizome_manifest_test_filehash, _rhizome_manifest_unset_filehash, _rhizome_manifest_parse_filehash }, - { "filesize", 1, _rhizome_manifest_test_filesize, _rhizome_manifest_unset_filesize, _rhizome_manifest_parse_filesize }, - { "tail", 1, _rhizome_manifest_test_tail, _rhizome_manifest_unset_tail, _rhizome_manifest_parse_tail }, - { "BK", 0, _rhizome_manifest_test_BK, _rhizome_manifest_unset_BK, _rhizome_manifest_parse_BK }, - { "service", 0, _rhizome_manifest_test_service, _rhizome_manifest_unset_service, _rhizome_manifest_parse_service }, - { "date", 0, _rhizome_manifest_test_date, _rhizome_manifest_unset_date, _rhizome_manifest_parse_date }, - { "sender", 0, _rhizome_manifest_test_sender, _rhizome_manifest_unset_sender, _rhizome_manifest_parse_sender }, - { "recipient", 0, _rhizome_manifest_test_recipient, _rhizome_manifest_unset_recipient, _rhizome_manifest_parse_recipient }, - { "name", 0, _rhizome_manifest_test_name, _rhizome_manifest_unset_name, _rhizome_manifest_parse_name }, - { "crypt", 0, _rhizome_manifest_test_crypt, _rhizome_manifest_unset_crypt, _rhizome_manifest_parse_crypt }, +#define FIELD(CORE, NAME) \ + { #NAME, CORE, _rhizome_manifest_test_ ## NAME, _rhizome_manifest_unset_ ## NAME, _rhizome_manifest_copy_ ## NAME, _rhizome_manifest_parse_ ## NAME } + FIELD(1, id), + FIELD(1, version), + FIELD(1, filehash), + FIELD(1, filesize), + FIELD(1, tail), + FIELD(0, BK), + FIELD(0, service), + FIELD(0, date), + FIELD(0, sender), + FIELD(0, recipient), + FIELD(0, name), + FIELD(0, crypt), +#undef FIELD }; +static struct rhizome_manifest_field_descriptor *get_rhizome_manifest_field_descriptor(const char *label) +{ + unsigned i; + for (i = 0; i < NELS(rhizome_manifest_fields); ++i) + if (strcasecmp(label, rhizome_manifest_fields[i].label) == 0) + return &rhizome_manifest_fields[i]; + return NULL; +} + +/* Overwrite a Rhizome manifest with fields from another. Used in the "add bundle" application API + * when the application supplies a partial manifest to override or add to existing manifest fields. + * + * Returns -1 if a field in the destination manifest cannot be overwritten for an unrecoverable + * reason, eg, out of memory or too many variables, leaving the destination manifest in an undefined + * state. + * + * @author Andrew Bettison + */ +int rhizome_manifest_overwrite(rhizome_manifest *m, const rhizome_manifest *srcm) +{ + unsigned i; + for (i = 0; i < NELS(rhizome_manifest_fields); ++i) { + struct rhizome_manifest_field_descriptor *desc = &rhizome_manifest_fields[i]; + if (desc->test(srcm)) + desc->copy(m, srcm); + } + for (i = 0; i < srcm->var_count; ++i) { + struct rhizome_manifest_field_descriptor *desc = get_rhizome_manifest_field_descriptor(srcm->vars[i]); + if (!desc) + if (rhizome_manifest_set(m, srcm->vars[i], srcm->values[i]) == NULL) + return -1; + } + return 0; +} + int rhizome_manifest_field_label_is_valid(const char *field_label, size_t field_label_len) { if (field_label_len == 0 || field_label_len > MAX_MANIFEST_FIELD_LABEL_LEN) @@ -959,11 +1050,7 @@ rhizome_manifest_parse_field(rhizome_manifest *m, const char *field_label, size_ return RHIZOME_MANIFEST_SYNTAX_ERROR; } const char *value = alloca_strndup(field_value, field_value_len); - struct rhizome_manifest_field_descriptor *desc = NULL; - unsigned i; - for (i = 0; desc == NULL && i < NELS(rhizome_manifest_fields); ++i) - if (strcasecmp(label, rhizome_manifest_fields[i].label) == 0) - desc = &rhizome_manifest_fields[i]; + struct rhizome_manifest_field_descriptor *desc = get_rhizome_manifest_field_descriptor(label); enum rhizome_manifest_parse_status status = RHIZOME_MANIFEST_OK; assert(m->var_count <= NELS(m->vars)); if (desc ? desc->test(m) : rhizome_manifest_get(m, label) != NULL) { @@ -980,7 +1067,7 @@ rhizome_manifest_parse_field(rhizome_manifest *m, const char *field_label, size_ DEBUGF("Manifest field parse failed at %s=%s", label, alloca_toprint(100, field_value, field_value_len)); status = desc->core ? RHIZOME_MANIFEST_INVALID : RHIZOME_MANIFEST_MALFORMED; } - } else if ((rhizome_manifest_set(m, label, value)) == NULL) + } else if (rhizome_manifest_set(m, label, value) == NULL) status = RHIZOME_MANIFEST_ERROR; if (status != RHIZOME_MANIFEST_OK) { if (config.debug.rhizome_manifest)