1
/* Copyright (c) 2007-2012 Dovecot authors, see the included COPYING file */
1
/* Copyright (c) 2007-2013 Dovecot authors, see the included COPYING file */
6
8
#include "mkdir-parents.h"
7
9
#include "unlink-old-files.h"
31
dbox_alt_path_has_changed(const char *root_dir,
32
const char *alt_path, const char *alt_symlink_path)
33
dbox_alt_path_has_changed(const char *root_dir, const char *alt_path,
34
const char *alt_path2, const char *alt_symlink_path)
37
ret = readlink(alt_symlink_path, buf, sizeof(buf)-1);
38
if (t_readlink(alt_symlink_path, &linkpath) < 0) {
39
39
if (errno == ENOENT)
40
40
return alt_path != NULL;
41
41
i_error("readlink(%s) failed: %m", alt_symlink_path);
46
45
if (alt_path == NULL) {
47
46
i_warning("dbox %s: Original ALT=%s, "
48
"but currently no ALT path set", root_dir, buf);
47
"but currently no ALT path set", root_dir, linkpath);
50
} else if (strcmp(buf, alt_path) != 0) {
49
} else if (strcmp(linkpath, alt_path) != 0) {
50
if (strcmp(linkpath, alt_path2) == 0) {
51
/* FIXME: for backwards compatibility. old versions
52
created the symlink to mailboxes/ directory, which
53
was fine with sdbox, but didn't even exist with
54
mdbox. we'll silently replace the symlink. */
51
57
i_warning("dbox %s: Original ALT=%s, "
52
"but currently ALT=%s", root_dir, buf, alt_path);
58
"but currently ALT=%s", root_dir, linkpath, alt_path);
58
64
static void dbox_verify_alt_path(struct mailbox_list *list)
60
const char *root_dir, *alt_symlink_path, *alt_path;
66
const char *root_dir, *alt_symlink_path, *alt_path, *alt_path2;
62
root_dir = mailbox_list_get_path(list, NULL,
63
MAILBOX_LIST_PATH_TYPE_DIR);
68
root_dir = mailbox_list_get_root_forced(list, MAILBOX_LIST_PATH_TYPE_DIR);
65
70
t_strconcat(root_dir, "/"DBOX_ALT_SYMLINK_NAME, NULL);
66
alt_path = mailbox_list_get_path(list, NULL,
67
MAILBOX_LIST_PATH_TYPE_ALT_MAILBOX);
68
if (!dbox_alt_path_has_changed(root_dir, alt_path, alt_symlink_path))
71
(void)mailbox_list_get_root_path(list, MAILBOX_LIST_PATH_TYPE_ALT_DIR,
73
(void)mailbox_list_get_root_path(list, MAILBOX_LIST_PATH_TYPE_ALT_MAILBOX,
75
if (!dbox_alt_path_has_changed(root_dir, alt_path, alt_path2,
71
79
/* unlink/create the current alt path symlink */
83
91
int dbox_storage_create(struct mail_storage *_storage,
84
92
struct mail_namespace *ns,
85
const char **error_r ATTR_UNUSED)
87
95
struct dbox_storage *storage = (struct dbox_storage *)_storage;
88
96
const struct mail_storage_settings *set = _storage->set;
89
struct fs_settings fs_set;
91
memset(&fs_set, 0, sizeof(fs_set));
92
fs_set.temp_file_prefix = mailbox_list_get_global_temp_prefix(ns->list);
94
if (*set->mail_attachment_fs != '\0') T_BEGIN {
99
if (*set->mail_attachment_fs != '\0') {
95
100
const char *name, *args, *dir;
97
102
args = strchr(set->mail_attachment_fs, ' ');
102
107
name = t_strdup_until(set->mail_attachment_fs, args++);
109
if (strcmp(name, "sis-queue") == 0 &&
110
(_storage->class_flags & MAIL_STORAGE_CLASS_FLAG_FILE_PER_MSG) != 0) {
111
/* FIXME: the deduplication part doesn't work, because
112
sdbox renames the files.. */
113
*error_r = "mail_attachment_fs: "
114
"sis-queue not currently supported by sdbox";
104
117
dir = mail_user_home_expand(_storage->user,
105
118
set->mail_attachment_dir);
106
119
storage->attachment_dir = p_strdup(_storage->pool, dir);
107
storage->attachment_fs = fs_init(name, args, &fs_set);
110
dbox_verify_alt_path(ns->list);
121
if (mailbox_list_init_fs(ns->list, name, args,
122
storage->attachment_dir,
123
&storage->attachment_fs, &error) < 0) {
124
*error_r = t_strdup_printf("mail_attachment_fs: %s",
130
if (!ns->list->set.alt_dir_nocheck)
131
dbox_verify_alt_path(ns->list);
118
139
if (storage->attachment_fs != NULL)
119
140
fs_deinit(&storage->attachment_fs);
141
index_storage_destroy(_storage);
122
144
uint32_t dbox_get_uidvalidity_next(struct mailbox_list *list)
124
146
const char *path;
126
path = mailbox_list_get_path(list, NULL,
127
MAILBOX_LIST_PATH_TYPE_CONTROL);
148
path = mailbox_list_get_root_forced(list, MAILBOX_LIST_PATH_TYPE_CONTROL);
128
149
path = t_strconcat(path, "/"DBOX_UIDVALIDITY_FILE_NAME, NULL);
129
150
return mailbox_uidvalidity_next(list, path);
136
157
if (box->notify_callback == NULL)
137
158
index_mailbox_check_remove_all(box);
139
dir = mailbox_list_get_path(box->list, box->name,
140
MAILBOX_LIST_PATH_TYPE_INDEX);
141
path = t_strdup_printf("%s/"DBOX_INDEX_PREFIX".log", dir);
160
if (mailbox_get_path_to(box, MAILBOX_LIST_PATH_TYPE_INDEX,
163
path = t_strdup_printf("%s/"MAIL_INDEX_PREFIX".log", dir);
142
164
index_mailbox_check_add(box, path);
158
180
} else if (st.st_atime > st.st_ctime + DBOX_TMP_DELETE_SECS) {
159
181
/* there haven't been any changes to this directory since we
160
182
last checked it. */
161
} else if (st.st_atime < ioloop_time - interval) {
183
} else if (st.st_atime < ioloop_time - (time_t)interval) {
162
184
/* time to scan */
163
185
const char *prefix =
164
186
mailbox_list_get_global_temp_prefix(list);
178
200
else if (errno == ENOENT || errno == ENAMETOOLONG) {
179
201
mail_storage_set_error(box->storage, MAIL_ERROR_NOTFOUND,
180
T_MAIL_ERR_MAILBOX_NOT_FOUND(box->name));
202
T_MAIL_ERR_MAILBOX_NOT_FOUND(box->vname));
182
204
} else if (errno == EACCES) {
183
205
mail_storage_set_critical(box->storage, "%s",
194
216
mail_index_set_fsync_mode(box->index,
195
217
box->storage->set->parsed_fsync_mode,
196
MAIL_INDEX_SYNC_TYPE_APPEND |
197
MAIL_INDEX_SYNC_TYPE_EXPUNGE);
218
MAIL_INDEX_FSYNC_MASK_APPENDS |
219
MAIL_INDEX_FSYNC_MASK_EXPUNGES);
244
(box->list->props & MAILBOX_LIST_PROP_NO_NOSELECT) == 0)
265
if ((ret = index_storage_mailbox_create(box, directory)) <= 0)
247
267
if (mailbox_open(box) < 0)
270
if (mail_index_get_header(box->view)->uid_validity != 0) {
271
mail_storage_set_error(box->storage, MAIL_ERROR_EXISTS,
272
"Mailbox already exists");
250
276
/* if alt path already exists and contains files, rebuild storage so
251
277
that we don't start overwriting files. */
252
alt_path = mailbox_list_get_path(box->list, box->name,
253
MAILBOX_LIST_PATH_TYPE_ALT_MAILBOX);
254
if (alt_path != NULL && stat(alt_path, &st) == 0) {
278
ret = mailbox_get_path_to(box, MAILBOX_LIST_PATH_TYPE_ALT_MAILBOX, &alt_path);
279
if (ret > 0 && stat(alt_path, &st) == 0) {
255
280
ret = dir_is_empty(box->storage, alt_path);
270
295
ret = mail_index_sync_begin(box->index, &sync_ctx, &view, &trans, 0);
272
297
i_assert(ret != 0);
273
mail_storage_set_index_error(box);
298
mailbox_set_index_error(box);
284
309
return mail_index_sync_commit(&sync_ctx);
312
int dbox_verify_alt_storage(struct mailbox_list *list)
314
const char *alt_path;
317
if (!mailbox_list_get_root_path(list, MAILBOX_LIST_PATH_TYPE_ALT_DIR,
321
/* make sure alt storage is mounted. if it's not, abort the rebuild. */
322
if (stat(alt_path, &st) == 0)
324
if (errno != ENOENT) {
325
i_error("stat(%s) failed: %m", alt_path);
329
/* try to create the alt directory. if it fails, it means alt
330
storage isn't mounted. */
331
if (mailbox_list_mkdir_root(list, alt_path,
332
MAILBOX_LIST_PATH_TYPE_ALT_DIR) < 0)
337
bool dbox_header_have_flag(struct mailbox *box, uint32_t ext_id,
338
unsigned int flags_offset, uint8_t flag)
344
mail_index_get_header_ext(box->view, ext_id, &data, &data_size);
345
if (flags_offset < data_size)
346
flags = *((const uint8_t *)data + flags_offset);
347
return (flags & flag) != 0;