"Fossies" - the Fresh Open Source Software Archive  

Source code changes of the file "src/lib-dict-extra/dict-fs.c" between
dovecot-2.3.16.tar.gz and dovecot-2.3.17.tar.gz

About: Dovecot is an IMAP and POP3 server, written with security primarily in mind.

dict-fs.c  (dovecot-2.3.16):dict-fs.c  (dovecot-2.3.17)
skipping to change at line 14 skipping to change at line 14
#include "array.h" #include "array.h"
#include "fs-api.h" #include "fs-api.h"
#include "istream.h" #include "istream.h"
#include "str.h" #include "str.h"
#include "dict-transaction-memory.h" #include "dict-transaction-memory.h"
#include "dict-private.h" #include "dict-private.h"
struct fs_dict { struct fs_dict {
struct dict dict; struct dict dict;
struct fs *fs; struct fs *fs;
char *username;
}; };
struct fs_dict_iterate_context { struct fs_dict_iterate_context {
struct dict_iterate_context ctx; struct dict_iterate_context ctx;
const char **paths; char *path;
unsigned int path_idx;
enum dict_iterate_flags flags; enum dict_iterate_flags flags;
pool_t value_pool; pool_t value_pool;
struct fs_iter *fs_iter; struct fs_iter *fs_iter;
const char *values[2]; const char *values[2];
char *error; char *error;
}; };
static int static int
fs_dict_init(struct dict *driver, const char *uri, fs_dict_init(struct dict *driver, const char *uri,
const struct dict_settings *set, const struct dict_settings *set,
skipping to change at line 48 skipping to change at line 46
p = strchr(uri, ':'); p = strchr(uri, ':');
if (p == NULL) { if (p == NULL) {
fs_driver = uri; fs_driver = uri;
fs_args = ""; fs_args = "";
} else { } else {
fs_driver = t_strdup_until(uri, p); fs_driver = t_strdup_until(uri, p);
fs_args = p+1; fs_args = p+1;
} }
i_zero(&fs_set); i_zero(&fs_set);
fs_set.username = set->username;
fs_set.base_dir = set->base_dir; fs_set.base_dir = set->base_dir;
if (fs_init(fs_driver, fs_args, &fs_set, &fs, error_r) < 0) if (fs_init(fs_driver, fs_args, &fs_set, &fs, error_r) < 0)
return -1; return -1;
dict = i_new(struct fs_dict, 1); dict = i_new(struct fs_dict, 1);
dict->dict = *driver; dict->dict = *driver;
dict->fs = fs; dict->fs = fs;
dict->username = i_strdup(set->username);
*dict_r = &dict->dict; *dict_r = &dict->dict;
return 0; return 0;
} }
static void fs_dict_deinit(struct dict *_dict) static void fs_dict_deinit(struct dict *_dict)
{ {
struct fs_dict *dict = (struct fs_dict *)_dict; struct fs_dict *dict = (struct fs_dict *)_dict;
fs_deinit(&dict->fs); fs_deinit(&dict->fs);
i_free(dict->username);
i_free(dict); i_free(dict);
} }
/* Remove unsafe paths */ /* Remove unsafe paths */
static const char *fs_dict_escape_key(const char *key) static const char *fs_dict_escape_key(const char *key)
{ {
const char *ptr; const char *ptr;
string_t *new_key = NULL; string_t *new_key = NULL;
/* we take the slow path always if we see potential /* we take the slow path always if we see potential
need for escaping */ need for escaping */
skipping to change at line 99 skipping to change at line 94
else else
str_append(new_key, "/."); str_append(new_key, "/.");
key = ptr + 2; key = ptr + 2;
} }
if (new_key == NULL) if (new_key == NULL)
return key; return key;
str_append(new_key, key); str_append(new_key, key);
return str_c(new_key); return str_c(new_key);
} }
static const char *fs_dict_get_full_key(struct fs_dict *dict, const char *key) static const char *fs_dict_get_full_key(const char *username, const char *key)
{ {
key = fs_dict_escape_key(key); key = fs_dict_escape_key(key);
if (str_begins(key, DICT_PATH_SHARED)) if (str_begins(key, DICT_PATH_SHARED))
return key + strlen(DICT_PATH_SHARED); return key + strlen(DICT_PATH_SHARED);
else if (str_begins(key, DICT_PATH_PRIVATE)) { else if (str_begins(key, DICT_PATH_PRIVATE)) {
return t_strdup_printf("%s/%s", dict->username, return t_strdup_printf("%s/%s", username,
key + strlen(DICT_PATH_PRIVATE)); key + strlen(DICT_PATH_PRIVATE));
} else { } else {
i_unreached(); i_unreached();
} }
} }
static int fs_dict_lookup(struct dict *_dict, pool_t pool, 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 **value_r, const char **error_r)
{ {
struct fs_dict *dict = (struct fs_dict *)_dict; struct fs_dict *dict = (struct fs_dict *)_dict;
struct fs_file *file; struct fs_file *file;
struct istream *input; struct istream *input;
const unsigned char *data; const unsigned char *data;
size_t size; size_t size;
const char *path; const char *path;
string_t *str; string_t *str;
int ret; int ret;
path = fs_dict_get_full_key(dict, key); path = fs_dict_get_full_key(set->username, key);
file = fs_file_init(dict->fs, path, FS_OPEN_MODE_READONLY); file = fs_file_init(dict->fs, path, FS_OPEN_MODE_READONLY);
input = fs_read_stream(file, IO_BLOCK_SIZE); input = fs_read_stream(file, IO_BLOCK_SIZE);
(void)i_stream_read(input); (void)i_stream_read(input);
str = str_new(pool, i_stream_get_data_size(input)+1); str = str_new(pool, i_stream_get_data_size(input)+1);
while ((ret = i_stream_read_more(input, &data, &size)) > 0) { while ((ret = i_stream_read_more(input, &data, &size)) > 0) {
str_append_data(str, data, size); str_append_data(str, data, size);
i_stream_skip(input, size); i_stream_skip(input, size);
} }
i_assert(ret == -1); i_assert(ret == -1);
skipping to change at line 155 skipping to change at line 151
path, i_stream_get_error(input)); path, i_stream_get_error(input));
} }
} }
i_stream_unref(&input); i_stream_unref(&input);
fs_file_deinit(&file); fs_file_deinit(&file);
return ret; return ret;
} }
static struct dict_iterate_context * static struct dict_iterate_context *
fs_dict_iterate_init(struct dict *_dict, const char *const *paths, fs_dict_iterate_init(struct dict *_dict, const struct dict_op_settings *set,
enum dict_iterate_flags flags) const char *path, enum dict_iterate_flags flags)
{ {
struct fs_dict *dict = (struct fs_dict *)_dict; struct fs_dict *dict = (struct fs_dict *)_dict;
struct fs_dict_iterate_context *iter; struct fs_dict_iterate_context *iter;
/* these flags are not supported for now */ /* these flags are not supported for now */
i_assert((flags & DICT_ITERATE_FLAG_RECURSE) == 0); i_assert((flags & DICT_ITERATE_FLAG_RECURSE) == 0);
i_assert((flags & DICT_ITERATE_FLAG_EXACT_KEY) == 0); i_assert((flags & DICT_ITERATE_FLAG_EXACT_KEY) == 0);
i_assert((flags & (DICT_ITERATE_FLAG_SORT_BY_KEY | i_assert((flags & (DICT_ITERATE_FLAG_SORT_BY_KEY |
DICT_ITERATE_FLAG_SORT_BY_VALUE)) == 0); DICT_ITERATE_FLAG_SORT_BY_VALUE)) == 0);
iter = i_new(struct fs_dict_iterate_context, 1); iter = i_new(struct fs_dict_iterate_context, 1);
iter->ctx.dict = _dict; iter->ctx.dict = _dict;
iter->paths = p_strarray_dup(default_pool, paths); iter->path = i_strdup(path);
iter->flags = flags; iter->flags = flags;
iter->value_pool = pool_alloconly_create("iterate value pool", 128); iter->value_pool = pool_alloconly_create("iterate value pool", 128);
iter->fs_iter = fs_iter_init(dict->fs, iter->fs_iter = fs_iter_init(dict->fs,
fs_dict_get_full_key(dict, paths[0]), 0); fs_dict_get_full_key(set->username, path), 0 );
return &iter->ctx; return &iter->ctx;
} }
static bool fs_dict_iterate(struct dict_iterate_context *ctx, static bool fs_dict_iterate(struct dict_iterate_context *ctx,
const char **key_r, const char *const **values_r) const char **key_r, const char *const **values_r)
{ {
struct fs_dict_iterate_context *iter = struct fs_dict_iterate_context *iter =
(struct fs_dict_iterate_context *)ctx; (struct fs_dict_iterate_context *)ctx;
struct fs_dict *dict = (struct fs_dict *)ctx->dict; struct fs_dict *dict = (struct fs_dict *)ctx->dict;
const char *path, *error; const char *path, *error;
skipping to change at line 195 skipping to change at line 191
if (iter->error != NULL) if (iter->error != NULL)
return FALSE; return FALSE;
*key_r = fs_iter_next(iter->fs_iter); *key_r = fs_iter_next(iter->fs_iter);
if (*key_r == NULL) { if (*key_r == NULL) {
if (fs_iter_deinit(&iter->fs_iter, &error) < 0) { if (fs_iter_deinit(&iter->fs_iter, &error) < 0) {
iter->error = i_strdup(error); iter->error = i_strdup(error);
return FALSE; return FALSE;
} }
if (iter->paths[++iter->path_idx] == NULL) if (iter->path == NULL)
return FALSE; return FALSE;
path = fs_dict_get_full_key(dict, iter->paths[iter->path_idx]); path = fs_dict_get_full_key(ctx->set.username, iter->path);
iter->fs_iter = fs_iter_init(dict->fs, path, 0); iter->fs_iter = fs_iter_init(dict->fs, path, 0);
return fs_dict_iterate(ctx, key_r, values_r); return fs_dict_iterate(ctx, key_r, values_r);
} }
path = t_strconcat(iter->paths[iter->path_idx], *key_r, NULL); path = t_strconcat(iter->path, *key_r, NULL);
if ((iter->flags & DICT_ITERATE_FLAG_NO_VALUE) != 0) { if ((iter->flags & DICT_ITERATE_FLAG_NO_VALUE) != 0) {
iter->values[0] = NULL; iter->values[0] = NULL;
*key_r = path; *key_r = path;
return TRUE; return TRUE;
} }
p_clear(iter->value_pool); p_clear(iter->value_pool);
ret = fs_dict_lookup(ctx->dict, iter->value_pool, path, struct dict_op_settings set = {
.username = ctx->set.username,
};
ret = fs_dict_lookup(ctx->dict, &set, iter->value_pool, path,
&iter->values[0], &error); &iter->values[0], &error);
if (ret < 0) { if (ret < 0) {
/* I/O error */ /* I/O error */
iter->error = i_strdup(error); iter->error = i_strdup(error);
return FALSE; return FALSE;
} else if (ret == 0) { } else if (ret == 0) {
/* file was just deleted, just skip to next one */ /* file was just deleted, just skip to next one */
return fs_dict_iterate(ctx, key_r, values_r); return fs_dict_iterate(ctx, key_r, values_r);
} }
*key_r = path; *key_r = path;
skipping to change at line 238 skipping to change at line 237
const char *error; const char *error;
int ret; int ret;
if (fs_iter_deinit(&iter->fs_iter, &error) < 0 && iter->error == NULL) if (fs_iter_deinit(&iter->fs_iter, &error) < 0 && iter->error == NULL)
iter->error = i_strdup(error); iter->error = i_strdup(error);
ret = iter->error != NULL ? -1 : 0; ret = iter->error != NULL ? -1 : 0;
*error_r = t_strdup(iter->error); *error_r = t_strdup(iter->error);
pool_unref(&iter->value_pool); pool_unref(&iter->value_pool);
i_free(iter->paths); i_free(iter->path);
i_free(iter->error); i_free(iter->error);
i_free(iter); i_free(iter);
return ret; return ret;
} }
static struct dict_transaction_context * static struct dict_transaction_context *
fs_dict_transaction_init(struct dict *_dict) fs_dict_transaction_init(struct dict *_dict)
{ {
struct dict_transaction_memory_context *ctx; struct dict_transaction_memory_context *ctx;
pool_t pool; pool_t pool;
skipping to change at line 266 skipping to change at line 265
static int fs_dict_write_changes(struct dict_transaction_memory_context *ctx, static int fs_dict_write_changes(struct dict_transaction_memory_context *ctx,
const char **error_r) const char **error_r)
{ {
struct fs_dict *dict = (struct fs_dict *)ctx->ctx.dict; struct fs_dict *dict = (struct fs_dict *)ctx->ctx.dict;
struct fs_file *file; struct fs_file *file;
const struct dict_transaction_memory_change *change; const struct dict_transaction_memory_change *change;
const char *key; const char *key;
int ret = 0; int ret = 0;
array_foreach(&ctx->changes, change) { array_foreach(&ctx->changes, change) {
key = fs_dict_get_full_key(dict, change->key); key = fs_dict_get_full_key(ctx->ctx.set.username, change->key);
switch (change->type) { switch (change->type) {
case DICT_CHANGE_TYPE_SET: case DICT_CHANGE_TYPE_SET:
file = fs_file_init(dict->fs, key, file = fs_file_init(dict->fs, key,
FS_OPEN_MODE_REPLACE); FS_OPEN_MODE_REPLACE);
if (fs_write(file, change->value.str, strlen(change->valu e.str)) < 0) { if (fs_write(file, change->value.str, strlen(change->valu e.str)) < 0) {
*error_r = t_strdup_printf( *error_r = t_strdup_printf(
"fs_write(%s) failed: %s", key, "fs_write(%s) failed: %s", key,
fs_file_last_error(file)); fs_file_last_error(file));
ret = -1; ret = -1;
} }
 End of changes. 18 change blocks. 
20 lines changed or deleted 20 lines changed or added

Home  |  About  |  Features  |  All  |  Newest  |  Dox  |  Diffs  |  RSS Feeds  |  Screenshots  |  Comments  |  Imprint  |  Privacy  |  HTTP(S)