dovecot-2.1: mdbox: Make sure m.* files aren't overwritten when ...
dovecot at dovecot.org
dovecot at dovecot.org
Fri Dec 9 16:26:49 EET 2011
details: http://hg.dovecot.org/dovecot-2.1/rev/31825aab83f6
changeset: 13831:31825aab83f6
user: Timo Sirainen <tss at iki.fi>
date: Fri Dec 09 16:26:39 2011 +0200
description:
mdbox: Make sure m.* files aren't overwritten when storage index isn't found.
This mainly helps to avoid situations where m.1 is replaced by mail delivery
when index directory has been (wrongly) changed.
diffstat:
src/lib-storage/index/dbox-multi/mdbox-map-private.h | 2 +
src/lib-storage/index/dbox-multi/mdbox-map.c | 66 +++++++++++++++++--
2 files changed, 61 insertions(+), 7 deletions(-)
diffs (138 lines):
diff -r ec3714f01ef2 -r 31825aab83f6 src/lib-storage/index/dbox-multi/mdbox-map-private.h
--- a/src/lib-storage/index/dbox-multi/mdbox-map-private.h Thu Dec 08 18:56:48 2011 +0200
+++ b/src/lib-storage/index/dbox-multi/mdbox-map-private.h Fri Dec 09 16:26:39 2011 +0200
@@ -23,6 +23,8 @@
mode_t create_mode;
gid_t create_gid;
const char *create_gid_origin;
+
+ unsigned int verify_existing_file_ids:1;
};
struct mdbox_map_append {
diff -r ec3714f01ef2 -r 31825aab83f6 src/lib-storage/index/dbox-multi/mdbox-map.c
--- a/src/lib-storage/index/dbox-multi/mdbox-map.c Thu Dec 08 18:56:48 2011 +0200
+++ b/src/lib-storage/index/dbox-multi/mdbox-map.c Fri Dec 09 16:26:39 2011 +0200
@@ -108,7 +108,7 @@
struct stat st;
if (stat(path, &st) == 0)
- return 0;
+ return 1;
if (mailbox_list_mkdir(map->root_list, NULL, path) < 0) {
mail_storage_copy_list_error(MAP_STORAGE(map), map->root_list);
@@ -119,14 +119,16 @@
static int mdbox_map_mkdir_storage(struct mdbox_map *map)
{
- if (mdbox_map_mkdir_storage_path(map, map->path) < 0)
+ int ret;
+
+ if ((ret = mdbox_map_mkdir_storage_path(map, map->path)) < 0)
return -1;
if (strcmp(map->path, map->index_path) != 0) {
if (mdbox_map_mkdir_storage_path(map, map->index_path) < 0)
return -1;
}
- return 0;
+ return ret;
}
static void mdbox_map_cleanup(struct mdbox_map *map)
@@ -150,7 +152,7 @@
static int mdbox_map_open_internal(struct mdbox_map *map, bool create_missing)
{
enum mail_index_open_flags open_flags;
- int ret;
+ int ret = 0;
if (map->view != NULL) {
/* already opened */
@@ -160,11 +162,24 @@
open_flags = MAIL_INDEX_OPEN_FLAG_NEVER_IN_MEMORY |
mail_storage_settings_to_index_flags(MAP_STORAGE(map)->set);
if (create_missing) {
- open_flags |= MAIL_INDEX_OPEN_FLAG_CREATE;
- if (mdbox_map_mkdir_storage(map) < 0)
+ if ((ret = mdbox_map_mkdir_storage(map)) < 0)
return -1;
+ if (ret > 0) {
+ /* storage/ directory already existed.
+ the index should exist also. */
+ } else {
+ open_flags |= MAIL_INDEX_OPEN_FLAG_CREATE;
+ }
}
ret = mail_index_open(map->index, open_flags);
+ if (ret == 0 && create_missing) {
+ /* storage/ already existed, but indexes didn't. we'll need to
+ take extra steps to make sure we won't overwrite any m.*
+ files that may already exist. */
+ map->verify_existing_file_ids = TRUE;
+ open_flags |= MAIL_INDEX_OPEN_FLAG_CREATE;
+ ret = mail_index_open(map->index, open_flags);
+ }
if (ret < 0) {
mail_storage_set_internal_error(MAP_STORAGE(map));
mail_index_reset_error(map->index);
@@ -1147,13 +1162,39 @@
array_delete(&ctx->appends, count-1, 1);
}
+static int
+mdbox_find_highest_file_id(struct mdbox_map *map, uint32_t *file_id_r)
+{
+ const unsigned int prefix_len = strlen(MDBOX_MAIL_FILE_PREFIX);
+ DIR *dir;
+ struct dirent *d;
+ unsigned int id, highest_id = 0;
+
+ dir = opendir(map->path);
+ if (dir == NULL) {
+ i_error("opendir(%s) failed: %m", map->path);
+ return -1;
+ }
+ while ((d = readdir(dir)) != NULL) {
+ if (strncmp(d->d_name, MDBOX_MAIL_FILE_PREFIX, prefix_len) == 0 &&
+ str_to_uint(d->d_name + prefix_len, &id) == 0) {
+ if (highest_id < id)
+ highest_id = id;
+ }
+ }
+ (void)closedir(dir);
+
+ *file_id_r = highest_id;
+ return 0;
+}
+
static int mdbox_map_assign_file_ids(struct mdbox_map_append_context *ctx,
bool separate_transaction)
{
struct dbox_file_append_context *const *file_appends;
unsigned int i, count;
struct mdbox_map_mail_index_header hdr;
- uint32_t first_file_id, file_id;
+ uint32_t first_file_id, file_id, existing_id;
/* start the syncing. we'll need it even if there are no file ids to
be assigned. */
@@ -1163,6 +1204,17 @@
mdbox_map_get_ext_hdr(ctx->map, ctx->atomic->sync_view, &hdr);
file_id = hdr.highest_file_id + 1;
+ if (ctx->map->verify_existing_file_ids) {
+ /* storage/ directory had been already created but
+ without indexes. scan to see if there exists a higher
+ m.* file id than what is in header, so we won't
+ accidentally overwrite any existing files. */
+ if (mdbox_find_highest_file_id(ctx->map, &existing_id) < 0)
+ return -1;
+ if (file_id < existing_id+1)
+ file_id = existing_id+1;
+ }
+
/* assign file_ids for newly created files */
first_file_id = file_id;
file_appends = array_get(&ctx->file_appends, &count);
More information about the dovecot-cvs
mailing list