]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
lib-dict: Change dict_vfuncs.lookup() to support multiple values
authorTimo Sirainen <timo.sirainen@open-xchange.com>
Thu, 25 Nov 2021 10:53:26 +0000 (12:53 +0200)
committerAki Tuomi <aki.tuomi@open-xchange.com>
Mon, 17 Jan 2022 11:52:09 +0000 (13:52 +0200)
12 files changed:
src/lib-dict-backend/dict-cdb.c
src/lib-dict-backend/dict-ldap.c
src/lib-dict-backend/dict-sql.c
src/lib-dict-extra/dict-fs.c
src/lib-dict/dict-client.c
src/lib-dict/dict-fail.c
src/lib-dict/dict-file.c
src/lib-dict/dict-memcached-ascii.c
src/lib-dict/dict-memcached.c
src/lib-dict/dict-private.h
src/lib-dict/dict-redis.c
src/lib-dict/dict.c

index c6fad305018f9aecd06e109447a6d554cab15c6b..5c4734a124cad7601f9f7609de31adafacedef57 100644 (file)
@@ -87,7 +87,7 @@ static int
 cdb_dict_lookup(struct dict *_dict,
                const struct dict_op_settings *set ATTR_UNUSED,
                pool_t pool,
-               const char *key, const char **value_r,
+               const char *key, const char *const **values_r,
                const char **error_r)
 {
        struct cdb_dict *dict = (struct cdb_dict *)_dict;
@@ -110,7 +110,6 @@ cdb_dict_lookup(struct dict *_dict,
        }
 
        if (ret <= 0) {
-               *value_r = NULL;
                /* something bad with db */
                if (ret < 0) {
                        *error_r = t_strdup_printf("cdb_find(%s) failed: %m", dict->path);
@@ -126,7 +125,9 @@ cdb_dict_lookup(struct dict *_dict,
                *error_r = t_strdup_printf("cdb_read(%s) failed: %m", dict->path);
                return -1;
        }
-       *value_r = data;
+       const char **values = p_new(pool, const char *, 2);
+       values[0] = data;
+       *values_r = values;
        return 1;
 }
 
index 433871b98073ba5aa6f5cb5b6bdce5e1616f260f..435ef15569a0a318f5ae03d6bd3d2f4cf5f101a2 100644 (file)
@@ -355,7 +355,7 @@ ldap_dict_lookup_callback(struct ldap_result *result, struct dict_ldap_op *op)
 static int
 ldap_dict_lookup(struct dict *dict, const struct dict_op_settings *set,
                 pool_t pool, const char *key,
-                const char **value_r, const char **error_r)
+                const char *const **values_r, const char **error_r)
 {
        struct dict_lookup_result res;
 
@@ -367,7 +367,7 @@ ldap_dict_lookup(struct dict *dict, const struct dict_op_settings *set,
                return -1;
        }
        if (res.ret > 0)
-               *value_r = p_strdup(pool, res.value);
+               *values_r = p_strarray_dup(pool, res.values);
        return res.ret;
 }
 
index 7935b9351b71a197f7ce2a7d4e7f53347885dae1..ffcd1d6fb640c42865e811782d6265cb642aab71 100644 (file)
@@ -492,13 +492,6 @@ sql_dict_result_unescape(enum dict_sql_type type, pool_t pool,
        return str_c(str);
 }
 
-static const char *
-sql_dict_result_unescape_value(const struct dict_sql_map *map, pool_t pool,
-                              struct sql_result *result)
-{
-       return sql_dict_result_unescape(map->value_types[0], pool, result, 0);
-}
-
 static const char *const *
 sql_dict_result_unescape_values(const struct dict_sql_map *map, pool_t pool,
                                struct sql_result *result)
@@ -528,7 +521,7 @@ sql_dict_result_unescape_field(const struct dict_sql_map *map, pool_t pool,
 
 static int sql_dict_lookup(struct dict *_dict, const struct dict_op_settings *set,
                           pool_t pool, const char *key,
-                          const char **value_r, const char **error_r)
+                          const char *const **values_r, const char **error_r)
 {
        struct sql_dict *dict = (struct sql_dict *)_dict;
        const struct dict_sql_map *map;
@@ -536,8 +529,6 @@ static int sql_dict_lookup(struct dict *_dict, const struct dict_op_settings *se
        struct sql_result *result = NULL;
        int ret;
 
-       *value_r = NULL;
-
        if (sql_lookup_get_query(dict, set, key, &map, &stmt, error_r) < 0)
                return -1;
 
@@ -547,7 +538,7 @@ static int sql_dict_lookup(struct dict *_dict, const struct dict_op_settings *se
                *error_r = t_strdup_printf("dict sql lookup failed: %s",
                                           sql_result_get_error(result));
        } else if (ret > 0) {
-               *value_r = sql_dict_result_unescape_value(map, pool, result);
+               *values_r = sql_dict_result_unescape_values(map, pool, result);
        }
 
        sql_result_unref(result);
index 4c173e3f749c874b4784877f02c732995544e991..7bd0b82dd6f4f3a12392962c1a3d4b0ca2661712 100644 (file)
@@ -19,7 +19,7 @@ struct fs_dict_iterate_context {
        enum dict_iterate_flags flags;
        pool_t value_pool;
        struct fs_iter *fs_iter;
-       const char *values[2];
+       const char *const *values;
        char *error;
 };
 
@@ -106,7 +106,7 @@ static const char *fs_dict_get_full_key(const char *username, const char *key)
 
 static int fs_dict_lookup(struct dict *_dict, const struct dict_op_settings *set,
                          pool_t pool, const char *key,
-                         const char **value_r, const char **error_r)
+                         const char *const **values_r, const char **error_r)
 {
        struct fs_dict *dict = (struct fs_dict *)_dict;
        struct fs_file *file;
@@ -130,10 +130,11 @@ static int fs_dict_lookup(struct dict *_dict, const struct dict_op_settings *set
        i_assert(ret == -1);
 
        if (input->stream_errno == 0) {
-               *value_r = str_c(str);
+               const char **values = p_new(pool, const char *, 2);
+               values[0] = str_c(str);
+               *values_r = values;
                ret = 1;
        } else {
-               *value_r = NULL;
                if (input->stream_errno == ENOENT)
                        ret = 0;
                else {
@@ -196,7 +197,6 @@ static bool fs_dict_iterate(struct dict_iterate_context *ctx,
        }
        path = t_strconcat(iter->path, *key_r, NULL);
        if ((iter->flags & DICT_ITERATE_FLAG_NO_VALUE) != 0) {
-               iter->values[0] = NULL;
                *key_r = path;
                return TRUE;
        }
@@ -205,7 +205,7 @@ static bool fs_dict_iterate(struct dict_iterate_context *ctx,
                .username = ctx->set.username,
        };
        ret = fs_dict_lookup(ctx->dict, &set, iter->value_pool, path,
-                            &iter->values[0], &error);
+                            &iter->values, &error);
        if (ret < 0) {
                /* I/O error */
                iter->error = i_strdup(error);
index 32b2da1108104c98ebf30ed1bfc833f2009f0854..f18ae6b3ab96a2e5c65e2b1a23134b6f20996984 100644 (file)
@@ -988,7 +988,7 @@ client_dict_lookup_async(struct dict *_dict, const struct dict_op_settings *set,
 
 struct client_dict_sync_lookup {
        char *error;
-       char *value;
+       const char **values;
        int ret;
 };
 
@@ -998,14 +998,19 @@ static void client_dict_lookup_callback(const struct dict_lookup_result *result,
        lookup->ret = result->ret;
        if (result->ret == -1)
                lookup->error = i_strdup(result->error);
-       else if (result->ret == 1)
-               lookup->value = i_strdup(result->value);
+       else if (result->ret == 1) {
+               /* The caller's pool could point to data stack. We can't
+                  allocate from there, since we're in a different data stack
+                  frame. */
+               lookup->values = p_strarray_dup(default_pool, result->values);
+       }
 }
 
 static int client_dict_lookup(struct dict *_dict,
                              const struct dict_op_settings *set,
                              pool_t pool, const char *key,
-                             const char **value_r, const char **error_r)
+                             const char *const **values_r,
+                             const char **error_r)
 {
        struct client_dict_sync_lookup lookup;
 
@@ -1022,12 +1027,11 @@ static int client_dict_lookup(struct dict *_dict,
                i_free(lookup.error);
                return -1;
        case 0:
-               i_assert(lookup.value == NULL);
-               *value_r = NULL;
+               i_assert(lookup.values == NULL);
                return 0;
        case 1:
-               *value_r = p_strdup(pool, lookup.value);
-               i_free(lookup.value);
+               *values_r = p_strarray_dup(pool, lookup.values);
+               i_free(lookup.values);
                return 1;
        }
        i_unreached();
index 101750b92479f9d91fcc0650d520acc020a789c7..65c35c5cec9e67648bb1553daabbffdd1a692713 100644 (file)
@@ -34,7 +34,8 @@ static void dict_fail_wait(struct dict *dict ATTR_UNUSED)
 static int dict_fail_lookup(struct dict *dict ATTR_UNUSED,
                            const struct dict_op_settings *set ATTR_UNUSED,
                            pool_t pool ATTR_UNUSED,
-                           const char *key ATTR_UNUSED, const char **value_r ATTR_UNUSED,
+                           const char *key ATTR_UNUSED,
+                           const char *const **values_r ATTR_UNUSED,
                            const char **error_r)
 {
        *error_r = "Unsupported operation (dict does not support this feature)";
index c9228a865a442a68e86a85a07d9a25b5dbaf0805..3a5b2f5f15d81e770f64750e7a090917f47f724f 100644 (file)
@@ -224,9 +224,10 @@ static int file_dict_refresh(struct file_dict *dict, const char **error_r)
 static int file_dict_lookup(struct dict *_dict,
                            const struct dict_op_settings *set,
                            pool_t pool, const char *key,
-                           const char **value_r, const char **error_r)
+                           const char *const **values_r, const char **error_r)
 {
        struct file_dict *dict = (struct file_dict *)_dict;
+       const char *value;
 
        if (file_dict_ensure_path_home_dir(dict, set->home_dir, error_r) < 0)
                return -1;
@@ -234,8 +235,14 @@ static int file_dict_lookup(struct dict *_dict,
        if (file_dict_refresh(dict, error_r) < 0)
                return -1;
 
-       *value_r = p_strdup(pool, hash_table_lookup(dict->hash, key));
-       return *value_r == NULL ? 0 : 1;
+       value = hash_table_lookup(dict->hash, key);
+       if (value == NULL)
+               return 0;
+
+       const char **values = p_new(pool, const char *, 2);
+       values[0] = p_strdup(pool, value);
+       *values_r = values;
+       return 1;
 }
 
 static struct dict_iterate_context *
index 6ae5443bbf45c929c32daef0e8fffefac6642274..056a586811de3176f358707f1e9023a76ca57905 100644 (file)
@@ -520,7 +520,8 @@ memcached_ascii_dict_get_full_key(struct memcached_ascii_dict *dict,
 static int
 memcached_ascii_dict_lookup(struct dict *_dict,
                            const struct dict_op_settings *set,
-                           pool_t pool, const char *key, const char **value_r,
+                           pool_t pool, const char *key,
+                           const char *const **values_r,
                            const char **error_r)
 {
        struct memcached_ascii_dict *dict = (struct memcached_ascii_dict *)_dict;
@@ -541,7 +542,9 @@ memcached_ascii_dict_lookup(struct dict *_dict,
        if (memcached_ascii_wait(dict, error_r) < 0)
                return -1;
 
-       *value_r = p_strdup(pool, str_c(dict->conn.reply_str));
+       const char **values = p_new(pool, const char *, 2);
+       values[0] = p_strdup(pool, str_c(dict->conn.reply_str));
+       *values_r = values;
        return dict->conn.value_received ? 1 : 0;
 }
 
index c5b7ce63faf001fe8c1a978a4288b15d88f2ea25..a09476fd2ad32dafb74e0d1fd90fda567f1e06c7 100644 (file)
@@ -274,7 +274,8 @@ static void memcached_add_header(buffer_t *buf, unsigned int key_len)
 
 static int
 memcached_dict_lookup(struct dict *_dict, const struct dict_op_settings *set ATTR_UNUSED,
-                     pool_t pool, const char *key, const char **value_r,
+                     pool_t pool, const char *key,
+                     const char *const **values_r,
                      const char **error_r)
 {
        struct memcached_dict *dict = (struct memcached_dict *)_dict;
@@ -341,10 +342,13 @@ memcached_dict_lookup(struct dict *_dict, const struct dict_op_settings *set ATT
                return -1;
        }
        switch (dict->conn.reply.status) {
-       case MEMCACHED_RESPONSE_OK:
-               *value_r = p_strndup(pool, dict->conn.reply.value,
-                                    dict->conn.reply.value_len);
+       case MEMCACHED_RESPONSE_OK: {
+               const char **values = p_new(pool, const char *, 2);
+               values[0] = p_strndup(pool, dict->conn.reply.value,
+                                     dict->conn.reply.value_len);
+               *values_r = values;
                return 1;
+       }
        case MEMCACHED_RESPONSE_NOTFOUND:
                return 0;
        case MEMCACHED_RESPONSE_INTERNALERROR:
index e5ec5e3d64f36f68af0a264aead108300300ed3c..780ce07ce9ba1e75a6c8e16aa9c5e29a1bf109c6 100644 (file)
@@ -1,3 +1,4 @@
+
 #ifndef DICT_PRIVATE_H
 #define DICT_PRIVATE_H
 
@@ -14,7 +15,7 @@ struct dict_vfuncs {
        void (*wait)(struct dict *dict);
 
        int (*lookup)(struct dict *dict, const struct dict_op_settings *set,
-                     pool_t pool, const char *key, const char **value_r,
+                     pool_t pool, const char *key, const char *const **values_r,
                      const char **error_r);
 
        struct dict_iterate_context *
index 01ec7b0d401ce3e7b69222540e13c1fdbc1c9c1b..57fe333715636d455b25072c9fffc977daedc133 100644 (file)
@@ -538,7 +538,7 @@ static void redis_dict_select_db(struct redis_dict *dict)
 static int redis_dict_lookup(struct dict *_dict,
                             const struct dict_op_settings *set,
                             pool_t pool, const char *key,
-                            const char **value_r, const char **error_r)
+                            const char *const **values_r, const char **error_r)
 {
        struct redis_dict *dict = (struct redis_dict *)_dict;
        struct timeout *to;
@@ -600,7 +600,9 @@ static int redis_dict_lookup(struct dict *_dict,
        if (dict->conn.value_not_found)
                return 0;
 
-       *value_r = p_strdup(pool, str_c(dict->conn.last_reply));
+       const char **values = p_new(pool, const char *, 2);
+       values[0] = p_strdup(pool, str_c(dict->conn.last_reply));
+       *values_r = values;
        return 1;
 }
 
index 063a28d9908e7196a9df4d3e01ff870f0a70773a..a5e523adf353dafa8e0d56daf6d070534ad24f76 100644 (file)
@@ -323,12 +323,17 @@ int dict_lookup(struct dict *dict, const struct dict_op_settings *set,
                const char **value_r, const char **error_r)
 {
        struct event *event = dict_event_create(dict, set);
+       const char *const *values;
        int ret;
        i_assert(dict_key_prefix_is_valid(key, set->username));
 
        e_debug(event, "Looking up '%s'", key);
        event_add_str(event, "key", key);
-       ret = dict->v.lookup(dict, set, pool, key, value_r, error_r);
+       ret = dict->v.lookup(dict, set, pool, key, &values, error_r);
+       if (ret > 0)
+               *value_r = values[0];
+       else if (ret == 0)
+               *value_r = NULL;
        dict_lookup_finished(event, ret, *error_r);
        event_unref(&event);
        return ret;