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;
}
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);
*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;
}
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;
return -1;
}
if (res.ret > 0)
- *value_r = p_strdup(pool, res.value);
+ *values_r = p_strarray_dup(pool, res.values);
return res.ret;
}
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)
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;
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;
*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);
enum dict_iterate_flags flags;
pool_t value_pool;
struct fs_iter *fs_iter;
- const char *values[2];
+ const char *const *values;
char *error;
};
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;
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 {
}
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;
}
.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);
struct client_dict_sync_lookup {
char *error;
- char *value;
+ const char **values;
int ret;
};
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;
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();
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)";
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;
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 *
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;
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;
}
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;
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:
+
#ifndef DICT_PRIVATE_H
#define DICT_PRIVATE_H
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 *
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;
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;
}
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;