X-Git-Url: https://git.distorted.org.uk/u/mdw/catacomb/blobdiff_plain/78ec50faca2fd89e24cb0ac654fcb3d99c6462ab..df82bc85db06b9cd8917aec33aadaf151d9d4a46:/key-data.c diff --git a/key-data.c b/key-data.c index c77b6a4..69795fe 100644 --- a/key-data.c +++ b/key-data.c @@ -210,7 +210,7 @@ key_data *key_newencrypted(unsigned e, const void *p, size_t sz) return (k); } -/* --- @key_mewmp@ --- * +/* --- @key_newmp@ --- * * * Arguments: @unsigned e@ = other encoding flags * @mp *m@ = pointer to the value to set @@ -350,6 +350,7 @@ static void structset(key_data *k, int stealp, unsigned f; assert(((void)"Key is not structured", k->e == KENC_STRUCT)); + assert(((void)"Key has multiple references", k->ref == 1)); if (!kd) { ks = sym_find(&k->u.s, tag, -1, 0, 0); if (ks) sym_remove(&k->u.s, ks); @@ -410,4 +411,59 @@ int key_do(key_data *k, const key_filter *kf, dstr *d, } } +/* --- @key_copydata@ --- * + * + * Arguments: @key_data *k@ = key data to copy + * @const key_filter *kf@ = pointer to filter block + * + * Returns: Pointer to a copy of the data, or null if the root subkey + * didn't match the filter. + * + * Use: Copies a chunk of key data. Subkeys, whether they're + * structured or leaves, which don't match the filter aren't + * copied. The copy may or may not have structure in common + * with the original. + */ + +static int structmatchp(key_data *k, const key_filter *kf) +{ + key_subkeyiter i; + + if (!KEY_MATCH(k, kf)) return (0); + else if ((k->e & KF_ENCMASK) == KENC_STRUCT) return (1); + else { + for (key_mksubkeyiter(&i, k); key_nextsubkey(&i, 0, &k); ) + if (!structmatchp(k, kf)) return (0); + return (1); + } +} + +key_data *key_copydata(key_data *k, const key_filter *kf) +{ + key_subkeyiter i; + const char *tag; + key_data *kd, *kkd; + + /* --- Trivial cases --- */ + + if (!KEY_MATCH(k, kf)) + return (0); + else if (structmatchp(k, kf)) { + key_incref(k); + return (k); + } + + /* --- Copy a structured key recursively --- */ + + kkd = key_newstruct(); + for (key_mksubkeyiter(&i, k); key_nextsubkey(&i, &tag, &kd); ) { + if ((kd = key_copydata(kd, kf)) != 0) + key_structsteal(kkd, tag, kd); + } + + /* --- Done --- */ + + return (kkd); +} + /*----- That's all, folks -------------------------------------------------*/