1 /* Copyright (c) 2002-2018 Dovecot authors, see the included COPYING file */
2
3 #include "lib.h"
4 #include "ioloop.h"
5 #include "array.h"
6 #include "llist.h"
7 #include "mail-storage.h"
8 #include "str.h"
9 #include "str-sanitize.h"
10 #include "sha1.h"
11 #include "unichar.h"
12 #include "hex-binary.h"
13 #include "fs-api.h"
14 #include "iostream-ssl.h"
15 #include "file-dotlock.h"
16 #include "file-create-locked.h"
17 #include "istream.h"
18 #include "eacces-error.h"
19 #include "mkdir-parents.h"
20 #include "time-util.h"
21 #include "var-expand.h"
22 #include "dsasl-client.h"
23 #include "imap-date.h"
24 #include "settings-parser.h"
25 #include "mail-index-private.h"
26 #include "mail-index-alloc-cache.h"
27 #include "mailbox-tree.h"
28 #include "mailbox-list-private.h"
29 #include "mail-storage-private.h"
30 #include "mail-storage-settings.h"
31 #include "mail-namespace.h"
32 #include "mail-search.h"
33 #include "mail-search-register.h"
34 #include "mail-search-mime-register.h"
35 #include "mailbox-search-result-private.h"
36 #include "mailbox-guid-cache.h"
37 #include "mail-cache.h"
38
39 #include <ctype.h>
40
41 #define MAILBOX_DELETE_RETRY_SECS 30
42 #define MAILBOX_MAX_HIERARCHY_NAME_LENGTH 255
43
44 extern struct mail_search_register *mail_search_register_imap;
45 extern struct mail_search_register *mail_search_register_human;
46
47 struct event_category event_category_storage = {
48 .name = "storage",
49 };
50 struct event_category event_category_mailbox = {
51 .parent = &event_category_storage,
52 .name = "mailbox",
53 };
54 struct event_category event_category_mail = {
55 .parent = &event_category_mailbox,
56 .name = "mail",
57 };
58
59 struct mail_storage_module_register mail_storage_module_register = { 0 };
60 struct mail_module_register mail_module_register = { 0 };
61
62 struct mail_storage_mail_index_module mail_storage_mail_index_module =
63 MODULE_CONTEXT_INIT(&mail_index_module_register);
64 ARRAY_TYPE(mail_storage) mail_storage_classes;
65
66 static int mail_storage_init_refcount = 0;
67
mail_storage_init(void)68 void mail_storage_init(void)
69 {
70 if (mail_storage_init_refcount++ > 0)
71 return;
72 dsasl_clients_init();
73 mailbox_attributes_init();
74 mailbox_lists_init();
75 mail_storage_hooks_init();
76 i_array_init(&mail_storage_classes, 8);
77 mail_storage_register_all();
78 mailbox_list_register_all();
79 }
80
mail_storage_deinit(void)81 void mail_storage_deinit(void)
82 {
83 i_assert(mail_storage_init_refcount > 0);
84 if (--mail_storage_init_refcount > 0)
85 return;
86 if (mail_search_register_human != NULL)
87 mail_search_register_deinit(&mail_search_register_human);
88 if (mail_search_register_imap != NULL)
89 mail_search_register_deinit(&mail_search_register_imap);
90 mail_search_mime_register_deinit();
91 if (array_is_created(&mail_storage_classes))
92 array_free(&mail_storage_classes);
93 mail_storage_hooks_deinit();
94 mailbox_lists_deinit();
95 mailbox_attributes_deinit();
96 dsasl_clients_deinit();
97 }
98
mail_storage_class_register(struct mail_storage * storage_class)99 void mail_storage_class_register(struct mail_storage *storage_class)
100 {
101 i_assert(mail_storage_find_class(storage_class->name) == NULL);
102
103 /* append it after the list, so the autodetection order is correct */
104 array_push_back(&mail_storage_classes, &storage_class);
105 }
106
mail_storage_class_unregister(struct mail_storage * storage_class)107 void mail_storage_class_unregister(struct mail_storage *storage_class)
108 {
109 struct mail_storage *const *classes;
110 unsigned int i, count;
111
112 classes = array_get(&mail_storage_classes, &count);
113 for (i = 0; i < count; i++) {
114 if (classes[i] == storage_class) {
115 array_delete(&mail_storage_classes, i, 1);
116 break;
117 }
118 }
119 }
120
mail_storage_find_class(const char * name)121 struct mail_storage *mail_storage_find_class(const char *name)
122 {
123 struct mail_storage *const *classes;
124 unsigned int i, count;
125
126 i_assert(name != NULL);
127
128 classes = array_get(&mail_storage_classes, &count);
129 for (i = 0; i < count; i++) {
130 if (strcasecmp(classes[i]->name, name) == 0)
131 return classes[i];
132 }
133 return NULL;
134 }
135
136 static struct mail_storage *
mail_storage_autodetect(const struct mail_namespace * ns,struct mailbox_list_settings * set)137 mail_storage_autodetect(const struct mail_namespace *ns,
138 struct mailbox_list_settings *set)
139 {
140 struct mail_storage *const *classes;
141 unsigned int i, count;
142
143 classes = array_get(&mail_storage_classes, &count);
144 for (i = 0; i < count; i++) {
145 if (classes[i]->v.autodetect != NULL) {
146 if (classes[i]->v.autodetect(ns, set))
147 return classes[i];
148 }
149 }
150 return NULL;
151 }
152
153 static void
mail_storage_set_autodetection(const char ** data,const char ** driver)154 mail_storage_set_autodetection(const char **data, const char **driver)
155 {
156 const char *p;
157
158 /* check if data is in driver:data format (eg. mbox:~/mail) */
159 p = *data;
160 while (i_isalnum(*p) || *p == '_') p++;
161
162 if (*p == ':' && p != *data) {
163 /* no autodetection if the storage driver is given. */
164 *driver = t_strdup_until(*data, p);
165 *data = p + 1;
166 }
167 }
168
169 static struct mail_storage *
mail_storage_get_class(struct mail_namespace * ns,const char * driver,struct mailbox_list_settings * list_set,enum mail_storage_flags flags,const char ** error_r)170 mail_storage_get_class(struct mail_namespace *ns, const char *driver,
171 struct mailbox_list_settings *list_set,
172 enum mail_storage_flags flags, const char **error_r)
173 {
174 struct mail_storage *storage_class = NULL;
175 const char *home;
176
177 if (driver == NULL) {
178 /* no mail_location, autodetect */
179 } else if (strcmp(driver, "auto") == 0) {
180 /* explicit autodetection with "auto" driver. */
181 if (list_set->root_dir != NULL &&
182 *list_set->root_dir == '\0') {
183 /* handle the same as with driver=NULL */
184 list_set->root_dir = NULL;
185 }
186 } else {
187 storage_class = mail_user_get_storage_class(ns->user, driver);
188 if (storage_class == NULL) {
189 *error_r = t_strdup_printf(
190 "Unknown mail storage driver %s", driver);
191 return NULL;
192 }
193 }
194
195 if (list_set->root_dir == NULL || *list_set->root_dir == '\0') {
196 /* no root directory given. is this allowed? */
197 const struct mailbox_list *list;
198
199 list = list_set->layout == NULL ? NULL :
200 mailbox_list_find_class(list_set->layout);
201 if (storage_class == NULL &&
202 (flags & MAIL_STORAGE_FLAG_NO_AUTODETECTION) == 0) {
203 /* autodetection should take care of this */
204 } else if (storage_class != NULL &&
205 (storage_class->class_flags & MAIL_STORAGE_CLASS_FLAG_NO_ROOT) != 0) {
206 /* root not required for this storage */
207 } else if (list != NULL &&
208 (list->props & MAILBOX_LIST_PROP_NO_ROOT) != 0) {
209 /* root not required for this layout */
210 } else {
211 *error_r = "Root mail directory not given";
212 return NULL;
213 }
214 }
215
216 if (storage_class != NULL) {
217 storage_class->v.get_list_settings(ns, list_set);
218 return storage_class;
219 }
220
221 storage_class = mail_storage_autodetect(ns, list_set);
222 if (storage_class != NULL)
223 return storage_class;
224
225 (void)mail_user_get_home(ns->user, &home);
226 if (home == NULL || *home == '\0') home = "(not set)";
227
228 if (ns->set->location == NULL || *ns->set->location == '\0') {
229 *error_r = t_strdup_printf(
230 "Mail storage autodetection failed with home=%s", home);
231 } else if (str_begins(ns->set->location, "auto:")) {
232 *error_r = t_strdup_printf(
233 "Autodetection failed for %s (home=%s)",
234 ns->set->location, home);
235 } else {
236 *error_r = t_strdup_printf(
237 "Ambiguous mail location setting, "
238 "don't know what to do with it: %s "
239 "(try prefixing it with mbox: or maildir:)",
240 ns->set->location);
241 }
242 return NULL;
243 }
244
245 static int
mail_storage_verify_root(const char * root_dir,const char * dir_type,const char ** error_r)246 mail_storage_verify_root(const char *root_dir, const char *dir_type,
247 const char **error_r)
248 {
249 struct stat st;
250
251 if (stat(root_dir, &st) == 0) {
252 /* exists */
253 if (S_ISDIR(st.st_mode))
254 return 0;
255 *error_r = t_strdup_printf(
256 "Root mail directory is a file: %s", root_dir);
257 return -1;
258 } else if (errno == EACCES) {
259 *error_r = mail_error_eacces_msg("stat", root_dir);
260 return -1;
261 } else if (errno != ENOENT) {
262 *error_r = t_strdup_printf("stat(%s) failed: %m", root_dir);
263 return -1;
264 } else {
265 *error_r = t_strdup_printf(
266 "Root %s directory doesn't exist: %s", dir_type, root_dir);
267 return -1;
268 }
269 }
270
271 static int
mail_storage_create_root(struct mailbox_list * list,enum mail_storage_flags flags,const char ** error_r)272 mail_storage_create_root(struct mailbox_list *list,
273 enum mail_storage_flags flags, const char **error_r)
274 {
275 const char *root_dir, *type_name, *error;
276 enum mailbox_list_path_type type;
277
278 if (list->set.iter_from_index_dir) {
279 type = MAILBOX_LIST_PATH_TYPE_INDEX;
280 type_name = "index";
281 } else {
282 type = MAILBOX_LIST_PATH_TYPE_MAILBOX;
283 type_name = "mail";
284 }
285 if (!mailbox_list_get_root_path(list, type, &root_dir)) {
286 /* storage doesn't use directories (e.g. shared root) */
287 return 0;
288 }
289
290 if ((flags & MAIL_STORAGE_FLAG_NO_AUTOVERIFY) != 0) {
291 if (!event_want_debug_log(list->ns->user->event))
292 return 0;
293
294 /* we don't need to verify, but since debugging is
295 enabled, check and log if the root doesn't exist */
296 if (mail_storage_verify_root(root_dir, type_name, &error) < 0) {
297 e_debug(list->ns->user->event,
298 "Namespace %s: Creating storage despite: %s",
299 list->ns->prefix, error);
300 }
301 return 0;
302 }
303
304 if ((flags & MAIL_STORAGE_FLAG_NO_AUTOCREATE) == 0) {
305 /* If the directories don't exist, we'll just autocreate them
306 later. */
307 return 0;
308 }
309 return mail_storage_verify_root(root_dir, type_name, error_r);
310 }
311
312 static bool
mail_storage_match_class(struct mail_storage * storage,const struct mail_storage * storage_class,const struct mailbox_list_settings * set)313 mail_storage_match_class(struct mail_storage *storage,
314 const struct mail_storage *storage_class,
315 const struct mailbox_list_settings *set)
316 {
317 if (strcmp(storage->name, storage_class->name) != 0)
318 return FALSE;
319
320 if ((storage->class_flags & MAIL_STORAGE_CLASS_FLAG_UNIQUE_ROOT) != 0 &&
321 strcmp(storage->unique_root_dir,
322 (set->root_dir != NULL ? set->root_dir : "")) != 0)
323 return FALSE;
324
325 if (strcmp(storage->name, "shared") == 0) {
326 /* allow multiple independent shared namespaces */
327 return FALSE;
328 }
329 return TRUE;
330 }
331
332 static struct mail_storage *
mail_storage_find(struct mail_user * user,const struct mail_storage * storage_class,const struct mailbox_list_settings * set)333 mail_storage_find(struct mail_user *user,
334 const struct mail_storage *storage_class,
335 const struct mailbox_list_settings *set)
336 {
337 struct mail_storage *storage = user->storages;
338
339 for (; storage != NULL; storage = storage->next) {
340 if (mail_storage_match_class(storage, storage_class, set))
341 return storage;
342 }
343 return NULL;
344 }
345
mail_storage_create_full(struct mail_namespace * ns,const char * driver,const char * data,enum mail_storage_flags flags,struct mail_storage ** storage_r,const char ** error_r)346 int mail_storage_create_full(struct mail_namespace *ns, const char *driver,
347 const char *data, enum mail_storage_flags flags,
348 struct mail_storage **storage_r,
349 const char **error_r)
350 {
351 struct mail_storage *storage_class, *storage = NULL;
352 struct mailbox_list *list;
353 struct mailbox_list_settings list_set;
354 enum mailbox_list_flags list_flags = 0;
355 const char *p;
356
357 if ((flags & MAIL_STORAGE_FLAG_KEEP_HEADER_MD5) == 0 &&
358 ns->mail_set->pop3_uidl_format != NULL) {
359 /* if pop3_uidl_format contains %m, we want to keep the
360 header MD5 sums stored even if we're not running POP3
361 right now. */
362 p = ns->mail_set->pop3_uidl_format;
363 while ((p = strchr(p, '%')) != NULL) {
364 if (p[1] == '%')
365 p += 2;
366 else if (var_get_key(++p) == 'm') {
367 flags |= MAIL_STORAGE_FLAG_KEEP_HEADER_MD5;
368 break;
369 }
370 }
371 }
372
373 mailbox_list_settings_init_defaults(&list_set);
374 if (data == NULL) {
375 /* autodetect */
376 } else if (driver != NULL && strcmp(driver, "shared") == 0) {
377 /* internal shared namespace */
378 list_set.root_dir = ns->user->set->base_dir;
379 } else {
380 if (driver == NULL)
381 mail_storage_set_autodetection(&data, &driver);
382 if (mailbox_list_settings_parse(ns->user, data, &list_set,
383 error_r) < 0)
384 return -1;
385 }
386
387 storage_class = mail_storage_get_class(ns, driver, &list_set, flags,
388 error_r);
389 if (storage_class == NULL)
390 return -1;
391 i_assert(list_set.layout != NULL);
392
393 if (ns->list == NULL) {
394 /* first storage for namespace */
395 if (mail_storage_is_mailbox_file(storage_class))
396 list_flags |= MAILBOX_LIST_FLAG_MAILBOX_FILES;
397 if ((storage_class->class_flags & MAIL_STORAGE_CLASS_FLAG_NO_ROOT) != 0)
398 list_flags |= MAILBOX_LIST_FLAG_NO_MAIL_FILES;
399 if ((storage_class->class_flags & MAIL_STORAGE_CLASS_FLAG_NO_LIST_DELETES) != 0)
400 list_flags |= MAILBOX_LIST_FLAG_NO_DELETES;
401 if (mailbox_list_create(list_set.layout, ns, &list_set,
402 list_flags, &list, error_r) < 0) {
403 *error_r = t_strdup_printf("Mailbox list driver %s: %s",
404 list_set.layout, *error_r);
405 return -1;
406 }
407 if ((storage_class->class_flags & MAIL_STORAGE_CLASS_FLAG_NO_ROOT) == 0) {
408 if (mail_storage_create_root(ns->list, flags, error_r) < 0)
409 return -1;
410 }
411 }
412
413 storage = mail_storage_find(ns->user, storage_class, &list_set);
414 if (storage != NULL) {
415 /* using an existing storage */
416 storage->refcount++;
417 mail_namespace_add_storage(ns, storage);
418 *storage_r = storage;
419 return 0;
420 }
421
422 storage = storage_class->v.alloc();
423 if (storage->lost_mailbox_prefix == NULL)
424 storage->lost_mailbox_prefix = MAIL_STORAGE_LOST_MAILBOX_PREFIX;
425 storage->refcount = 1;
426 storage->storage_class = storage_class;
427 storage->user = ns->user;
428 storage->set = ns->mail_set;
429 storage->flags = flags;
430 storage->event = event_create(ns->user->event);
431 if (storage_class->event_category != NULL)
432 event_add_category(storage->event, storage_class->event_category);
433 p_array_init(&storage->module_contexts, storage->pool, 5);
434
435 if (storage->v.create != NULL &&
436 storage->v.create(storage, ns, error_r) < 0) {
437 *error_r = t_strdup_printf("%s: %s", storage->name, *error_r);
438 event_unref(&storage->event);
439 pool_unref(&storage->pool);
440 return -1;
441 }
442
443 /* If storage supports list index rebuild,
444 provide default mailboxes_fs unless storage
445 wants to use its own. */
446 if (storage->v.list_index_rebuild != NULL &&
447 storage->mailboxes_fs == NULL) {
448 struct fs_settings fs_set;
449 struct ssl_iostream_settings ssl_set;
450 const char *error;
451 i_zero(&fs_set);
452
453 mail_user_init_fs_settings(storage->user, &fs_set, &ssl_set);
454 if (fs_init("posix", "", &fs_set, &storage->mailboxes_fs,
455 &error) < 0) {
456 *error_r = t_strdup_printf("fs_init(posix) failed: %s", error);
457 storage->v.destroy(storage);
458 return -1;
459 }
460 }
461
462 T_BEGIN {
463 hook_mail_storage_created(storage);
464 } T_END;
465
466 i_assert(storage->unique_root_dir != NULL ||
467 (storage->class_flags & MAIL_STORAGE_CLASS_FLAG_UNIQUE_ROOT) == 0);
468 DLLIST_PREPEND(&ns->user->storages, storage);
469 mail_namespace_add_storage(ns, storage);
470 *storage_r = storage;
471 return 0;
472 }
473
mail_storage_create(struct mail_namespace * ns,const char * driver,enum mail_storage_flags flags,const char ** error_r)474 int mail_storage_create(struct mail_namespace *ns, const char *driver,
475 enum mail_storage_flags flags, const char **error_r)
476 {
477 struct mail_storage *storage;
478
479 return mail_storage_create_full(ns, driver, ns->set->location,
480 flags, &storage, error_r);
481 }
482
mail_storage_unref(struct mail_storage ** _storage)483 void mail_storage_unref(struct mail_storage **_storage)
484 {
485 struct mail_storage *storage = *_storage;
486
487 i_assert(storage->refcount > 0);
488
489 /* set *_storage=NULL only after calling destroy() callback.
490 for example mdbox wants to access ns->storage */
491 if (--storage->refcount > 0) {
492 *_storage = NULL;
493 return;
494 }
495
496 if (storage->mailboxes != NULL) {
497 i_panic("Trying to deinit storage without freeing mailbox %s",
498 storage->mailboxes->vname);
499 }
500 if (storage->obj_refcount != 0)
501 i_panic("Trying to deinit storage before freeing its objects");
502
503 DLLIST_REMOVE(&storage->user->storages, storage);
504
505 storage->v.destroy(storage);
506 i_free(storage->last_internal_error);
507 i_free(storage->error_string);
508 if (array_is_created(&storage->error_stack)) {
509 i_assert(array_count(&storage->error_stack) == 0);
510 array_free(&storage->error_stack);
511 }
512 fs_unref(&storage->mailboxes_fs);
513 event_unref(&storage->event);
514
515 *_storage = NULL;
516 pool_unref(&storage->pool);
517
518 mail_index_alloc_cache_destroy_unrefed();
519 }
520
mail_storage_obj_ref(struct mail_storage * storage)521 void mail_storage_obj_ref(struct mail_storage *storage)
522 {
523 i_assert(storage->refcount > 0);
524
525 if (storage->obj_refcount++ == 0)
526 mail_user_ref(storage->user);
527 }
528
mail_storage_obj_unref(struct mail_storage * storage)529 void mail_storage_obj_unref(struct mail_storage *storage)
530 {
531 i_assert(storage->refcount > 0);
532 i_assert(storage->obj_refcount > 0);
533
534 if (--storage->obj_refcount == 0) {
535 struct mail_user *user = storage->user;
536 mail_user_unref(&user);
537 }
538 }
539
mail_storage_clear_error(struct mail_storage * storage)540 void mail_storage_clear_error(struct mail_storage *storage)
541 {
542 i_free_and_null(storage->error_string);
543
544 i_free(storage->last_internal_error);
545 storage->last_error_is_internal = FALSE;
546 storage->error = MAIL_ERROR_NONE;
547 }
548
mail_storage_set_error(struct mail_storage * storage,enum mail_error error,const char * string)549 void mail_storage_set_error(struct mail_storage *storage,
550 enum mail_error error, const char *string)
551 {
552 if (storage->error_string != string) {
553 i_free(storage->error_string);
554 storage->error_string = i_strdup(string);
555 }
556 storage->last_error_is_internal = FALSE;
557 storage->error = error;
558 }
559
mail_storage_set_internal_error(struct mail_storage * storage)560 void mail_storage_set_internal_error(struct mail_storage *storage)
561 {
562 const char *str;
563
564 str = t_strflocaltime(MAIL_ERRSTR_CRITICAL_MSG_STAMP, ioloop_time);
565
566 i_free(storage->error_string);
567 storage->error_string = i_strdup(str);
568 storage->error = MAIL_ERROR_TEMP;
569
570 /* this function doesn't set last_internal_error, so
571 last_error_is_internal can't be TRUE. */
572 storage->last_error_is_internal = FALSE;
573 i_free(storage->last_internal_error);
574 }
575
mail_storage_set_critical(struct mail_storage * storage,const char * fmt,...)576 void mail_storage_set_critical(struct mail_storage *storage,
577 const char *fmt, ...)
578 {
579 char *old_error = storage->error_string;
580 char *old_internal_error = storage->last_internal_error;
581 va_list va;
582
583 storage->error_string = NULL;
584 storage->last_internal_error = NULL;
585 /* critical errors may contain sensitive data, so let user
586 see only "Internal error" with a timestamp to make it
587 easier to look from log files the actual error message. */
588 mail_storage_set_internal_error(storage);
589
590 va_start(va, fmt);
591 storage->last_internal_error = i_strdup_vprintf(fmt, va);
592 va_end(va);
593 storage->last_error_is_internal = TRUE;
594 e_error(storage->event, "%s", storage->last_internal_error);
595
596 /* free the old_error and old_internal_error only after the new error
597 is generated, because they may be one of the parameters. */
598 i_free(old_error);
599 i_free(old_internal_error);
600 }
601
mailbox_set_critical(struct mailbox * box,const char * fmt,...)602 void mailbox_set_critical(struct mailbox *box, const char *fmt, ...)
603 {
604 va_list va;
605
606 va_start(va, fmt);
607 T_BEGIN {
608 mail_storage_set_critical(box->storage, "Mailbox %s: %s",
609 box->vname, t_strdup_vprintf(fmt, va));
610 } T_END;
611 va_end(va);
612 }
613
mail_set_critical(struct mail * mail,const char * fmt,...)614 void mail_set_critical(struct mail *mail, const char *fmt, ...)
615 {
616 va_list va;
617
618 va_start(va, fmt);
619 T_BEGIN {
620 if (mail->saving) {
621 mailbox_set_critical(mail->box, "Saving mail: %s",
622 t_strdup_vprintf(fmt, va));
623 } else {
624 mailbox_set_critical(mail->box, "UID=%u: %s",
625 mail->uid, t_strdup_vprintf(fmt, va));
626 }
627 } T_END;
628 va_end(va);
629 }
630
mail_storage_get_last_internal_error(struct mail_storage * storage,enum mail_error * error_r)631 const char *mail_storage_get_last_internal_error(struct mail_storage *storage,
632 enum mail_error *error_r)
633 {
634 if (error_r != NULL)
635 *error_r = storage->error;
636 if (storage->last_error_is_internal) {
637 i_assert(storage->last_internal_error != NULL);
638 return storage->last_internal_error;
639 }
640 return mail_storage_get_last_error(storage, error_r);
641 }
642
mailbox_get_last_internal_error(struct mailbox * box,enum mail_error * error_r)643 const char *mailbox_get_last_internal_error(struct mailbox *box,
644 enum mail_error *error_r)
645 {
646 return mail_storage_get_last_internal_error(mailbox_get_storage(box),
647 error_r);
648 }
649
mail_storage_copy_error(struct mail_storage * dest,struct mail_storage * src)650 void mail_storage_copy_error(struct mail_storage *dest,
651 struct mail_storage *src)
652 {
653 const char *str;
654 enum mail_error error;
655
656 if (src == dest)
657 return;
658
659 str = mail_storage_get_last_error(src, &error);
660 mail_storage_set_error(dest, error, str);
661 }
662
mail_storage_copy_list_error(struct mail_storage * storage,struct mailbox_list * list)663 void mail_storage_copy_list_error(struct mail_storage *storage,
664 struct mailbox_list *list)
665 {
666 const char *str;
667 enum mail_error error;
668
669 str = mailbox_list_get_last_error(list, &error);
670 mail_storage_set_error(storage, error, str);
671 }
672
mailbox_set_index_error(struct mailbox * box)673 void mailbox_set_index_error(struct mailbox *box)
674 {
675 if (mail_index_is_deleted(box->index)) {
676 mailbox_set_deleted(box);
677 mail_index_reset_error(box->index);
678 } else {
679 mail_storage_set_index_error(box->storage, box->index);
680 }
681 }
682
mail_storage_set_index_error(struct mail_storage * storage,struct mail_index * index)683 void mail_storage_set_index_error(struct mail_storage *storage,
684 struct mail_index *index)
685 {
686 const char *index_error;
687
688 mail_storage_set_internal_error(storage);
689 /* use the lib-index's error as our internal error string */
690 index_error = mail_index_get_error_message(index);
691 if (index_error == NULL)
692 index_error = "BUG: Unknown internal index error";
693 storage->last_internal_error = i_strdup(index_error);
694 storage->last_error_is_internal = TRUE;
695 mail_index_reset_error(index);
696 }
697
698 const struct mail_storage_settings *
mail_storage_get_settings(struct mail_storage * storage)699 mail_storage_get_settings(struct mail_storage *storage)
700 {
701 return storage->set;
702 }
703
mail_storage_get_user(struct mail_storage * storage)704 struct mail_user *mail_storage_get_user(struct mail_storage *storage)
705 {
706 return storage->user;
707 }
708
mail_storage_set_callbacks(struct mail_storage * storage,struct mail_storage_callbacks * callbacks,void * context)709 void mail_storage_set_callbacks(struct mail_storage *storage,
710 struct mail_storage_callbacks *callbacks,
711 void *context)
712 {
713 storage->callbacks = *callbacks;
714 storage->callback_context = context;
715 }
716
mail_storage_purge(struct mail_storage * storage)717 int mail_storage_purge(struct mail_storage *storage)
718 {
719 return storage->v.purge == NULL ? 0 :
720 storage->v.purge(storage);
721 }
722
mail_storage_get_last_error(struct mail_storage * storage,enum mail_error * error_r)723 const char *mail_storage_get_last_error(struct mail_storage *storage,
724 enum mail_error *error_r)
725 {
726 /* We get here only in error situations, so we have to return some
727 error. If storage->error is NONE, it means we forgot to set it at
728 some point.. */
729 if (storage->error == MAIL_ERROR_NONE) {
730 if (error_r != NULL)
731 *error_r = MAIL_ERROR_TEMP;
732 return storage->error_string != NULL ? storage->error_string :
733 "BUG: Unknown internal error";
734 }
735
736 if (storage->error_string == NULL) {
737 /* This shouldn't happen.. */
738 storage->error_string =
739 i_strdup_printf("BUG: Unknown 0x%x error",
740 storage->error);
741 }
742
743 if (error_r != NULL)
744 *error_r = storage->error;
745 return storage->error_string;
746 }
747
mailbox_get_last_error(struct mailbox * box,enum mail_error * error_r)748 const char *mailbox_get_last_error(struct mailbox *box,
749 enum mail_error *error_r)
750 {
751 return mail_storage_get_last_error(box->storage, error_r);
752 }
753
mailbox_get_last_mail_error(struct mailbox * box)754 enum mail_error mailbox_get_last_mail_error(struct mailbox *box)
755 {
756 enum mail_error error;
757
758 mail_storage_get_last_error(box->storage, &error);
759 return error;
760 }
761
mail_storage_last_error_push(struct mail_storage * storage)762 void mail_storage_last_error_push(struct mail_storage *storage)
763 {
764 struct mail_storage_error *err;
765
766 if (!array_is_created(&storage->error_stack))
767 i_array_init(&storage->error_stack, 2);
768 err = array_append_space(&storage->error_stack);
769 err->error_string = i_strdup(storage->error_string);
770 err->error = storage->error;
771 err->last_error_is_internal = storage->last_error_is_internal;
772 if (err->last_error_is_internal)
773 err->last_internal_error = i_strdup(storage->last_internal_error);
774 }
775
mail_storage_last_error_pop(struct mail_storage * storage)776 void mail_storage_last_error_pop(struct mail_storage *storage)
777 {
778 unsigned int count = array_count(&storage->error_stack);
779 const struct mail_storage_error *err =
780 array_idx(&storage->error_stack, count-1);
781
782 i_free(storage->error_string);
783 i_free(storage->last_internal_error);
784 storage->error_string = err->error_string;
785 storage->error = err->error;
786 storage->last_error_is_internal = err->last_error_is_internal;
787 storage->last_internal_error = err->last_internal_error;
788 array_delete(&storage->error_stack, count-1, 1);
789 }
790
mail_storage_is_mailbox_file(struct mail_storage * storage)791 bool mail_storage_is_mailbox_file(struct mail_storage *storage)
792 {
793 return (storage->class_flags &
794 MAIL_STORAGE_CLASS_FLAG_MAILBOX_IS_FILE) != 0;
795 }
796
mail_storage_set_error_from_errno(struct mail_storage * storage)797 bool mail_storage_set_error_from_errno(struct mail_storage *storage)
798 {
799 const char *error_string;
800 enum mail_error error;
801
802 if (!mail_error_from_errno(&error, &error_string))
803 return FALSE;
804 if (event_want_debug_log(storage->event) && error != MAIL_ERROR_NOTFOUND) {
805 /* debugging is enabled - admin may be debugging a
806 (permission) problem, so return FALSE to get the caller to
807 log the full error message. */
808 return FALSE;
809 }
810
811 mail_storage_set_error(storage, error, error_string);
812 return TRUE;
813 }
814
815 const struct mailbox_settings *
mailbox_settings_find(struct mail_namespace * ns,const char * vname)816 mailbox_settings_find(struct mail_namespace *ns, const char *vname)
817 {
818 struct mailbox_settings *box_set;
819
820 if (!array_is_created(&ns->set->mailboxes))
821 return NULL;
822
823 if (ns->prefix_len > 0 &&
824 strncmp(ns->prefix, vname, ns->prefix_len-1) == 0) {
825 if (vname[ns->prefix_len-1] == mail_namespace_get_sep(ns))
826 vname += ns->prefix_len;
827 else if (vname[ns->prefix_len-1] == '\0') {
828 /* namespace prefix itself */
829 vname = "";
830 }
831 }
832 array_foreach_elem(&ns->set->mailboxes, box_set) {
833 if (strcmp(box_set->name, vname) == 0)
834 return box_set;
835 }
836 return NULL;
837 }
838
mailbox_alloc(struct mailbox_list * list,const char * vname,enum mailbox_flags flags)839 struct mailbox *mailbox_alloc(struct mailbox_list *list, const char *vname,
840 enum mailbox_flags flags)
841 {
842 struct mailbox_list *new_list = list;
843 struct mail_storage *storage;
844 struct mailbox *box;
845 enum mail_error open_error = 0;
846 const char *errstr = NULL;
847
848 i_assert(uni_utf8_str_is_valid(vname));
849
850 if (strncasecmp(vname, "INBOX", 5) == 0 &&
851 !str_begins(vname, "INBOX")) {
852 /* make sure INBOX shows up in uppercase everywhere. do this
853 regardless of whether we're in inbox=yes namespace, because
854 clients expect INBOX to be case insensitive regardless of
855 server's internal configuration. */
856 if (vname[5] == '\0')
857 vname = "INBOX";
858 else if (vname[5] != mail_namespace_get_sep(list->ns))
859 /* not INBOX prefix */ ;
860 else if (strncasecmp(list->ns->prefix, vname, 6) == 0 &&
861 !str_begins(list->ns->prefix, "INBOX")) {
862 mailbox_list_set_critical(list,
863 "Invalid server configuration: "
864 "Namespace prefix=%s must be uppercase INBOX",
865 list->ns->prefix);
866 open_error = MAIL_ERROR_TEMP;
867 } else {
868 vname = t_strconcat("INBOX", vname + 5, NULL);
869 }
870 }
871
872 T_BEGIN {
873 if (mailbox_list_get_storage(&new_list, vname, &storage) < 0) {
874 /* do a delayed failure at mailbox_open() */
875 storage = mail_namespace_get_default_storage(list->ns);
876 errstr = mailbox_list_get_last_error(new_list, &open_error);
877 errstr = t_strdup(errstr);
878 }
879
880 box = storage->v.mailbox_alloc(storage, new_list, vname, flags);
881 box->set = mailbox_settings_find(new_list->ns, vname);
882 box->open_error = open_error;
883 if (open_error != 0)
884 mail_storage_set_error(storage, open_error, errstr);
885 hook_mailbox_allocated(box);
886 } T_END;
887
888 DLLIST_PREPEND(&box->storage->mailboxes, box);
889 mail_storage_obj_ref(box->storage);
890 return box;
891 }
892
mailbox_alloc_guid(struct mailbox_list * list,const guid_128_t guid,enum mailbox_flags flags)893 struct mailbox *mailbox_alloc_guid(struct mailbox_list *list,
894 const guid_128_t guid,
895 enum mailbox_flags flags)
896 {
897 struct mailbox *box = NULL;
898 struct mailbox_metadata metadata;
899 enum mail_error open_error = MAIL_ERROR_TEMP;
900 const char *vname;
901
902 if (mailbox_guid_cache_find(list, guid, &vname) < 0) {
903 vname = NULL;
904 } else if (vname != NULL) {
905 box = mailbox_alloc(list, vname, flags);
906 if (mailbox_get_metadata(box, MAILBOX_METADATA_GUID,
907 &metadata) < 0) {
908 } else if (memcmp(metadata.guid, guid,
909 sizeof(metadata.guid)) != 0) {
910 /* GUID mismatch, refresh cache and try again */
911 mailbox_free(&box);
912 mailbox_guid_cache_refresh(list);
913 return mailbox_alloc_guid(list, guid, flags);
914 } else {
915 /* successfully opened the correct mailbox */
916 return box;
917 }
918 e_error(list->ns->user->event, "mailbox_alloc_guid(%s): "
919 "Couldn't verify mailbox GUID: %s",
920 guid_128_to_string(guid),
921 mailbox_get_last_internal_error(box, NULL));
922 vname = NULL;
923 mailbox_free(&box);
924 } else {
925 vname = t_strdup_printf("(nonexistent mailbox with GUID=%s)",
926 guid_128_to_string(guid));
927 open_error = MAIL_ERROR_NOTFOUND;
928 }
929
930 if (vname == NULL) {
931 vname = t_strdup_printf("(error in mailbox with GUID=%s)",
932 guid_128_to_string(guid));
933 }
934 box = mailbox_alloc(list, vname, flags);
935 box->open_error = open_error;
936 return box;
937 }
938
939 static bool
str_contains_special_use(const char * str,const char * special_use)940 str_contains_special_use(const char *str, const char *special_use)
941 {
942 const char *const *uses;
943
944 i_assert(special_use != NULL);
945 if (*special_use != '\\')
946 return FALSE;
947
948 bool ret;
949 T_BEGIN {
950 uses = t_strsplit_spaces(str, " ");
951 ret = str_array_icase_find(uses, special_use);
952 } T_END;
953 return ret;
954 }
955
956 static int
namespace_find_special_use(struct mail_namespace * ns,const char * special_use,const char ** vname_r,enum mail_error * error_code_r)957 namespace_find_special_use(struct mail_namespace *ns, const char *special_use,
958 const char **vname_r, enum mail_error *error_code_r)
959 {
960 struct mailbox_list *list = ns->list;
961 struct mailbox_list_iterate_context *ctx;
962 const struct mailbox_info *info;
963 int ret = 0;
964
965 *vname_r = NULL;
966 *error_code_r = MAIL_ERROR_NONE;
967
968 if (!ns->special_use_mailboxes)
969 return 0;
970 if (!HAS_ALL_BITS(ns->type, MAIL_NAMESPACE_TYPE_PRIVATE))
971 return 0;
972
973 ctx = mailbox_list_iter_init(list, "*",
974 MAILBOX_LIST_ITER_SELECT_SPECIALUSE |
975 MAILBOX_LIST_ITER_RETURN_SPECIALUSE);
976 while ((info = mailbox_list_iter_next(ctx)) != NULL) {
977 if ((info->flags &
978 (MAILBOX_NOSELECT | MAILBOX_NONEXISTENT)) != 0)
979 continue;
980 /* iter can only return mailboxes that have non-empty
981 special-use */
982 i_assert(info->special_use != NULL &&
983 *info->special_use != '\0');
984
985 if (str_contains_special_use(info->special_use, special_use)) {
986 *vname_r = t_strdup(info->vname);
987 ret = 1;
988 break;
989 }
990 }
991 if (mailbox_list_iter_deinit(&ctx) < 0) {
992 const char *error;
993
994 error = mailbox_list_get_last_error(ns->list, error_code_r);
995 e_error(ns->user->event,
996 "Failed to find mailbox with SPECIAL-USE flag '%s' "
997 "in namespace '%s': %s",
998 special_use, ns->prefix, error);
999 return -1;
1000 }
1001 return ret;
1002 }
1003
1004 static int
namespaces_find_special_use(struct mail_namespace * namespaces,const char * special_use,struct mail_namespace ** ns_r,const char ** vname_r,enum mail_error * error_code_r)1005 namespaces_find_special_use(struct mail_namespace *namespaces,
1006 const char *special_use,
1007 struct mail_namespace **ns_r,
1008 const char **vname_r, enum mail_error *error_code_r)
1009 {
1010 struct mail_namespace *ns_inbox;
1011 int ret;
1012
1013 *error_code_r = MAIL_ERROR_NONE;
1014 *vname_r = NULL;
1015
1016 /* check user's INBOX namespace first */
1017 *ns_r = ns_inbox = mail_namespace_find_inbox(namespaces);
1018 ret = namespace_find_special_use(*ns_r, special_use,
1019 vname_r, error_code_r);
1020 if (ret != 0)
1021 return ret;
1022
1023 /* check other namespaces */
1024 for (*ns_r = namespaces; *ns_r != NULL; *ns_r = (*ns_r)->next) {
1025 if (*ns_r == ns_inbox) {
1026 /* already checked */
1027 continue;
1028 }
1029 ret = namespace_find_special_use(*ns_r, special_use,
1030 vname_r, error_code_r);
1031 if (ret != 0)
1032 return ret;
1033 }
1034
1035 *ns_r = ns_inbox;
1036 return 0;
1037 }
1038
1039 struct mailbox *
mailbox_alloc_for_user(struct mail_user * user,const char * mname,enum mailbox_flags flags)1040 mailbox_alloc_for_user(struct mail_user *user, const char *mname,
1041 enum mailbox_flags flags)
1042 {
1043 struct mail_namespace *ns;
1044 struct mailbox *box;
1045 const char *vname;
1046 enum mail_error open_error = MAIL_ERROR_NONE;
1047 int ret;
1048
1049 if (HAS_ALL_BITS(flags, MAILBOX_FLAG_SPECIAL_USE)) {
1050 ret = namespaces_find_special_use(user->namespaces, mname,
1051 &ns, &vname, &open_error);
1052 if (ret < 0) {
1053 i_assert(open_error != MAIL_ERROR_NONE);
1054 vname = t_strdup_printf(
1055 "(error finding mailbox with SPECIAL-USE=%s)",
1056 mname);
1057 } else if (ret == 0) {
1058 i_assert(open_error == MAIL_ERROR_NONE);
1059 vname = t_strdup_printf(
1060 "(nonexistent mailbox with SPECIAL-USE=%s)",
1061 mname);
1062 open_error = MAIL_ERROR_NOTFOUND;
1063 }
1064 } else {
1065 vname = mname;
1066 ns = mail_namespace_find(user->namespaces, mname);
1067 }
1068
1069 if (HAS_ALL_BITS(flags, MAILBOX_FLAG_POST_SESSION)) {
1070 flags |= MAILBOX_FLAG_SAVEONLY;
1071
1072 if (strcmp(vname, ns->prefix) == 0 &&
1073 (ns->flags & NAMESPACE_FLAG_INBOX_USER) != 0) {
1074 /* delivering to a namespace prefix means we actually
1075 want to deliver to the INBOX instead */
1076 vname = "INBOX";
1077 ns = mail_namespace_find_inbox(user->namespaces);
1078 }
1079
1080 if (strcasecmp(vname, "INBOX") == 0) {
1081 /* deliveries to INBOX must always succeed,
1082 regardless of ACLs */
1083 flags |= MAILBOX_FLAG_IGNORE_ACLS;
1084 }
1085 }
1086
1087 i_assert(ns != NULL);
1088 box = mailbox_alloc(ns->list, vname, flags);
1089 if (open_error != MAIL_ERROR_NONE)
1090 box->open_error = open_error;
1091 return box;
1092 }
1093
mailbox_set_reason(struct mailbox * box,const char * reason)1094 void mailbox_set_reason(struct mailbox *box, const char *reason)
1095 {
1096 i_assert(reason != NULL);
1097
1098 box->reason = p_strdup(box->pool, reason);
1099 }
1100
mailbox_is_autocreated(struct mailbox * box)1101 bool mailbox_is_autocreated(struct mailbox *box)
1102 {
1103 if (box->inbox_user)
1104 return TRUE;
1105 if ((box->flags & MAILBOX_FLAG_AUTO_CREATE) != 0)
1106 return TRUE;
1107 return box->set != NULL &&
1108 strcmp(box->set->autocreate, MAILBOX_SET_AUTO_NO) != 0;
1109 }
1110
mailbox_is_autosubscribed(struct mailbox * box)1111 bool mailbox_is_autosubscribed(struct mailbox *box)
1112 {
1113 if ((box->flags & MAILBOX_FLAG_AUTO_SUBSCRIBE) != 0)
1114 return TRUE;
1115 return box->set != NULL &&
1116 strcmp(box->set->autocreate, MAILBOX_SET_AUTO_SUBSCRIBE) == 0;
1117 }
1118
mailbox_autocreate(struct mailbox * box)1119 static int mailbox_autocreate(struct mailbox *box)
1120 {
1121 const char *errstr;
1122 enum mail_error error;
1123
1124 if (mailbox_create(box, NULL, FALSE) < 0) {
1125 errstr = mailbox_get_last_internal_error(box, &error);
1126 if (error == MAIL_ERROR_NOTFOUND && box->acl_no_lookup_right) {
1127 /* ACL prevents creating this mailbox */
1128 return -1;
1129 }
1130 if (error != MAIL_ERROR_EXISTS) {
1131 mailbox_set_critical(box,
1132 "Failed to autocreate mailbox: %s",
1133 errstr);
1134 return -1;
1135 }
1136 } else if (mailbox_is_autosubscribed(box)) {
1137 if (mailbox_set_subscribed(box, TRUE) < 0) {
1138 mailbox_set_critical(box,
1139 "Failed to autosubscribe to mailbox: %s",
1140 mailbox_get_last_internal_error(box, NULL));
1141 return -1;
1142 }
1143 }
1144 return 0;
1145 }
1146
mailbox_autocreate_and_reopen(struct mailbox * box)1147 static int mailbox_autocreate_and_reopen(struct mailbox *box)
1148 {
1149 int ret;
1150
1151 if (mailbox_autocreate(box) < 0)
1152 return -1;
1153 mailbox_close(box);
1154
1155 ret = box->v.open(box);
1156 if (ret < 0 && box->inbox_user && !box->acl_no_lookup_right &&
1157 !box->storage->user->inbox_open_error_logged) {
1158 box->storage->user->inbox_open_error_logged = TRUE;
1159 mailbox_set_critical(box,
1160 "Opening INBOX failed: %s",
1161 mailbox_get_last_internal_error(box, NULL));
1162 }
1163 return ret;
1164 }
1165
1166 static bool
mailbox_name_verify_extra_separators(const char * vname,char sep,const char ** error_r)1167 mailbox_name_verify_extra_separators(const char *vname, char sep,
1168 const char **error_r)
1169 {
1170 unsigned int i;
1171 bool prev_sep = FALSE;
1172
1173 /* Make sure the vname doesn't have extra separators:
1174
1175 1) Must not have adjacent separators. If we allow these, these could
1176 end up pointing to existing mailboxes due to kernel ignoring
1177 duplicate '/' in paths. However, this might cause us to handle some
1178 of our own checks wrong, such as skipping ACLs.
1179
1180 2) Must not end with separator. Similar reasoning as above.
1181 */
1182 for (i = 0; vname[i] != '\0'; i++) {
1183 if (vname[i] == sep) {
1184 if (prev_sep) {
1185 *error_r = "Has adjacent hierarchy separators";
1186 return FALSE;
1187 }
1188 prev_sep = TRUE;
1189 } else {
1190 prev_sep = FALSE;
1191 }
1192 }
1193 if (prev_sep && i > 0) {
1194 *error_r = "Ends with hierarchy separator";
1195 return FALSE;
1196 }
1197 return TRUE;
1198 }
1199
1200 static bool
mailbox_verify_name_prefix(struct mail_namespace * ns,const char ** vnamep,const char ** error_r)1201 mailbox_verify_name_prefix(struct mail_namespace *ns, const char **vnamep,
1202 const char **error_r)
1203 {
1204 const char *vname = *vnamep;
1205
1206 if (ns->prefix_len == 0)
1207 return TRUE;
1208
1209 /* vname is either "namespace/box" or "namespace" */
1210 if (strncmp(vname, ns->prefix, ns->prefix_len-1) != 0 ||
1211 (vname[ns->prefix_len-1] != '\0' &&
1212 vname[ns->prefix_len-1] != ns->prefix[ns->prefix_len-1])) {
1213 /* User input shouldn't normally be able to get us in
1214 here. The main reason this isn't an assert is to
1215 allow any input at all to mailbox_verify_*_name()
1216 without crashing. */
1217 *error_r = t_strdup_printf("Missing namespace prefix '%s'",
1218 ns->prefix);
1219 return FALSE;
1220 }
1221 vname += ns->prefix_len - 1;
1222 if (vname[0] != '\0') {
1223 i_assert(vname[0] == ns->prefix[ns->prefix_len-1]);
1224 vname++;
1225
1226 if (vname[0] == '\0') {
1227 /* "namespace/" isn't a valid mailbox name. */
1228 *error_r = "Ends with hierarchy separator";
1229 return FALSE;
1230 }
1231 }
1232 *vnamep = vname;
1233 return TRUE;
1234 }
1235
mailbox_verify_name_int(struct mailbox * box)1236 static int mailbox_verify_name_int(struct mailbox *box)
1237 {
1238 struct mail_namespace *ns = box->list->ns;
1239 const char *error, *vname = box->vname;
1240 char list_sep, ns_sep;
1241
1242 if (box->inbox_user) {
1243 /* this is INBOX - don't bother with further checks */
1244 return 0;
1245 }
1246
1247 /* Verify the namespace prefix here. Change vname to skip the prefix
1248 for the following checks. */
1249 if (!mailbox_verify_name_prefix(box->list->ns, &vname, &error)) {
1250 mail_storage_set_error(box->storage, MAIL_ERROR_PARAMS,
1251 t_strdup_printf("Invalid mailbox name '%s': %s",
1252 str_sanitize(vname, 80), error));
1253 return -1;
1254 }
1255
1256 list_sep = mailbox_list_get_hierarchy_sep(box->list);
1257 ns_sep = mail_namespace_get_sep(ns);
1258
1259 /* If namespace { separator } differs from the mailbox_list separator,
1260 the list separator can't actually be used in the mailbox name
1261 unless it's escaped with storage_name_escape_char. For example if
1262 namespace separator is '/' and LAYOUT=Maildir++ has '.' as the
1263 separator, there's no way to use '.' in the mailbox name (without
1264 escaping) because it would end up becoming a hierarchy separator. */
1265 if (ns_sep != list_sep &&
1266 box->list->set.storage_name_escape_char == '\0' &&
1267 strchr(vname, list_sep) != NULL) {
1268 mail_storage_set_error(box->storage, MAIL_ERROR_PARAMS, t_strdup_printf(
1269 "Character not allowed in mailbox name: '%c'", list_sep));
1270 return -1;
1271 }
1272 /* vname must not begin with the hierarchy separator normally.
1273 For example we don't want to allow accessing /etc/passwd. However,
1274 if mail_full_filesystem_access=yes, we do actually want to allow
1275 that. */
1276 if (vname[0] == ns_sep &&
1277 !box->storage->set->mail_full_filesystem_access) {
1278 mail_storage_set_error(box->storage, MAIL_ERROR_PARAMS,
1279 "Invalid mailbox name: Begins with hierarchy separator");
1280 return -1;
1281 }
1282
1283 if (!mailbox_name_verify_extra_separators(vname, ns_sep, &error) ||
1284 !mailbox_list_is_valid_name(box->list, box->name, &error)) {
1285 mail_storage_set_error(box->storage, MAIL_ERROR_PARAMS,
1286 t_strdup_printf("Invalid mailbox name: %s", error));
1287 return -1;
1288 }
1289 return 0;
1290 }
1291
mailbox_verify_name(struct mailbox * box)1292 int mailbox_verify_name(struct mailbox *box)
1293 {
1294 int ret;
1295 T_BEGIN {
1296 ret = mailbox_verify_name_int(box);
1297 } T_END;
1298 return ret;
1299 }
1300
mailbox_verify_existing_name_int(struct mailbox * box)1301 static int mailbox_verify_existing_name_int(struct mailbox *box)
1302 {
1303 const char *path;
1304
1305 if (box->opened)
1306 return 0;
1307
1308 if (mailbox_verify_name(box) < 0)
1309 return -1;
1310
1311 /* Make sure box->_path is set, so mailbox_get_path() works from
1312 now on. Note that this may also fail with some backends if the
1313 mailbox doesn't exist. */
1314 if (mailbox_get_path_to(box, MAILBOX_LIST_PATH_TYPE_MAILBOX, &path) < 0) {
1315 if (box->storage->error != MAIL_ERROR_NOTFOUND ||
1316 !mailbox_is_autocreated(box))
1317 return -1;
1318 /* if this is an autocreated mailbox, create it now */
1319 if (mailbox_autocreate(box) < 0)
1320 return -1;
1321 mailbox_close(box);
1322 if (mailbox_get_path_to(box, MAILBOX_LIST_PATH_TYPE_MAILBOX,
1323 &path) < 0)
1324 return -1;
1325 }
1326 return 0;
1327 }
1328
mailbox_verify_existing_name(struct mailbox * box)1329 static int mailbox_verify_existing_name(struct mailbox *box)
1330 {
1331 int ret;
1332 T_BEGIN {
1333 ret = mailbox_verify_existing_name_int(box);
1334 } T_END;
1335 return ret;
1336 }
1337
mailbox_name_has_control_chars(const char * name)1338 static bool mailbox_name_has_control_chars(const char *name)
1339 {
1340 const char *p;
1341
1342 for (p = name; *p != '\0'; p++) {
1343 if ((unsigned char)*p < ' ')
1344 return TRUE;
1345 }
1346 return FALSE;
1347 }
1348
mailbox_skip_create_name_restrictions(struct mailbox * box,bool set)1349 void mailbox_skip_create_name_restrictions(struct mailbox *box, bool set)
1350 {
1351 box->skip_create_name_restrictions = set;
1352 }
1353
mailbox_verify_create_name(struct mailbox * box)1354 int mailbox_verify_create_name(struct mailbox *box)
1355 {
1356 /* mailbox_alloc() already checks that vname is valid UTF8,
1357 so we don't need to verify that.
1358
1359 check vname instead of storage name, because vname is what is
1360 visible to users, while storage name may be a fixed length GUID. */
1361 if (mailbox_verify_name(box) < 0)
1362 return -1;
1363 if (box->skip_create_name_restrictions)
1364 return 0;
1365 if (mailbox_name_has_control_chars(box->vname)) {
1366 mail_storage_set_error(box->storage, MAIL_ERROR_PARAMS,
1367 "Control characters not allowed in new mailbox names");
1368 return -1;
1369 }
1370 if (strlen(box->vname) > MAILBOX_LIST_NAME_MAX_LENGTH) {
1371 mail_storage_set_error(box->storage, MAIL_ERROR_PARAMS,
1372 "Mailbox name too long");
1373 return -1;
1374 }
1375 /* check individual component names, too */
1376 const char *old_name = box->name;
1377 const char *name;
1378 const char sep = mailbox_list_get_hierarchy_sep(box->list);
1379 while((name = strchr(old_name, sep)) != NULL) {
1380 if (name - old_name > MAILBOX_MAX_HIERARCHY_NAME_LENGTH) {
1381 mail_storage_set_error(box->storage, MAIL_ERROR_PARAMS,
1382 "Mailbox name too long");
1383 return -1;
1384 }
1385 name++;
1386 old_name = name;
1387 }
1388 if (strlen(old_name) > MAILBOX_MAX_HIERARCHY_NAME_LENGTH) {
1389 mail_storage_set_error(box->storage, MAIL_ERROR_PARAMS,
1390 "Mailbox name too long");
1391 return -1;
1392 }
1393 return 0;
1394 }
1395
have_listable_namespace_prefix(struct mail_namespace * ns,const char * name)1396 static bool have_listable_namespace_prefix(struct mail_namespace *ns,
1397 const char *name)
1398 {
1399 size_t name_len = strlen(name);
1400
1401 for (; ns != NULL; ns = ns->next) {
1402 if ((ns->flags & (NAMESPACE_FLAG_LIST_PREFIX |
1403 NAMESPACE_FLAG_LIST_CHILDREN)) == 0)
1404 continue;
1405
1406 if (ns->prefix_len <= name_len)
1407 continue;
1408
1409 /* if prefix has multiple hierarchies, match
1410 any of the hierarchies */
1411 if (strncmp(ns->prefix, name, name_len) == 0 &&
1412 ns->prefix[name_len] == mail_namespace_get_sep(ns))
1413 return TRUE;
1414 }
1415 return FALSE;
1416 }
1417
mailbox_exists(struct mailbox * box,bool auto_boxes,enum mailbox_existence * existence_r)1418 int mailbox_exists(struct mailbox *box, bool auto_boxes,
1419 enum mailbox_existence *existence_r)
1420 {
1421 switch (box->open_error) {
1422 case 0:
1423 break;
1424 case MAIL_ERROR_NOTFOUND:
1425 *existence_r = MAILBOX_EXISTENCE_NONE;
1426 return 0;
1427 default:
1428 /* unsure if this exists or not */
1429 return -1;
1430 }
1431 if (mailbox_verify_name(box) < 0) {
1432 /* the mailbox name is invalid. we don't know if it currently
1433 exists or not, but since it can never be accessed in any way
1434 report it as if it didn't exist. */
1435 *existence_r = MAILBOX_EXISTENCE_NONE;
1436 return 0;
1437 }
1438
1439 if (box->v.exists(box, auto_boxes, existence_r) < 0)
1440 return -1;
1441
1442 if (!box->inbox_user && *existence_r == MAILBOX_EXISTENCE_NOSELECT &&
1443 have_listable_namespace_prefix(box->storage->user->namespaces,
1444 box->vname)) {
1445 /* listable namespace prefix always exists. */
1446 *existence_r = MAILBOX_EXISTENCE_NOSELECT;
1447 return 0;
1448 }
1449
1450 /* if this is a shared namespace with only INBOX and
1451 mail_shared_explicit_inbox=no, we'll need to mark the namespace as
1452 usable here since nothing else will. */
1453 box->list->ns->flags |= NAMESPACE_FLAG_USABLE;
1454 return 0;
1455 }
1456
1457 static int ATTR_NULL(2)
mailbox_open_full(struct mailbox * box,struct istream * input)1458 mailbox_open_full(struct mailbox *box, struct istream *input)
1459 {
1460 int ret;
1461
1462 if (box->opened)
1463 return 0;
1464
1465 if (box->reason != NULL) {
1466 e_debug(box->event,
1467 "Mailbox opened because: %s",
1468 box->reason);
1469 }
1470
1471 switch (box->open_error) {
1472 case 0:
1473 break;
1474 case MAIL_ERROR_NOTFOUND:
1475 mail_storage_set_error(box->storage, MAIL_ERROR_NOTFOUND,
1476 T_MAIL_ERR_MAILBOX_NOT_FOUND(box->vname));
1477 return -1;
1478 default:
1479 mail_storage_set_internal_error(box->storage);
1480 box->storage->error = box->open_error;
1481 return -1;
1482 }
1483
1484 if (mailbox_verify_existing_name(box) < 0)
1485 return -1;
1486
1487 if (input != NULL) {
1488 if ((box->storage->class_flags &
1489 MAIL_STORAGE_CLASS_FLAG_OPEN_STREAMS) == 0) {
1490 mailbox_set_critical(box,
1491 "Storage doesn't support streamed mailboxes");
1492 return -1;
1493 }
1494 box->input = input;
1495 box->flags |= MAILBOX_FLAG_READONLY;
1496 i_stream_ref(box->input);
1497 }
1498
1499 T_BEGIN {
1500 ret = box->v.open(box);
1501 } T_END;
1502
1503 if (ret < 0 && box->storage->error == MAIL_ERROR_NOTFOUND &&
1504 !box->deleting && !box->creating &&
1505 box->input == NULL && mailbox_is_autocreated(box)) T_BEGIN {
1506 ret = mailbox_autocreate_and_reopen(box);
1507 } T_END;
1508
1509 if (ret < 0) {
1510 if (box->input != NULL)
1511 i_stream_unref(&box->input);
1512 return -1;
1513 }
1514
1515 box->list->ns->flags |= NAMESPACE_FLAG_USABLE;
1516 return 0;
1517 }
1518
mailbox_try_undelete(struct mailbox * box)1519 static bool mailbox_try_undelete(struct mailbox *box)
1520 {
1521 time_t mtime;
1522
1523 i_assert(!box->mailbox_undeleting);
1524
1525 if ((box->flags & MAILBOX_FLAG_READONLY) != 0) {
1526 /* most importantly we don't do this because we want to avoid
1527 a loop: mdbox storage rebuild -> mailbox_open() ->
1528 mailbox_mark_index_deleted() -> mailbox_sync() ->
1529 mdbox storage rebuild. */
1530 return FALSE;
1531 }
1532 if (mail_index_get_modification_time(box->index, &mtime) < 0)
1533 return FALSE;
1534 if (mtime + MAILBOX_DELETE_RETRY_SECS > time(NULL))
1535 return FALSE;
1536
1537 box->mailbox_undeleting = TRUE;
1538 int ret = mailbox_mark_index_deleted(box, FALSE);
1539 box->mailbox_undeleting = FALSE;
1540 if (ret < 0)
1541 return FALSE;
1542 box->mailbox_deleted = FALSE;
1543 return TRUE;
1544 }
1545
mailbox_open(struct mailbox * box)1546 int mailbox_open(struct mailbox *box)
1547 {
1548 if (mailbox_open_full(box, NULL) < 0) {
1549 if (!box->mailbox_deleted || box->mailbox_undeleting)
1550 return -1;
1551
1552 /* mailbox has been marked as deleted. if this deletion
1553 started (and crashed) a long time ago, it can be confusing
1554 to user that the mailbox can't be opened. so we'll just
1555 undelete it and reopen. */
1556 if(!mailbox_try_undelete(box))
1557 return -1;
1558
1559 /* make sure we close the mailbox in the middle. some backends
1560 may not have fully opened the mailbox while it was being
1561 undeleted. */
1562 mailbox_close(box);
1563 if (mailbox_open_full(box, NULL) < 0)
1564 return -1;
1565 }
1566 return 0;
1567 }
1568
mailbox_alloc_index_pvt(struct mailbox * box)1569 static int mailbox_alloc_index_pvt(struct mailbox *box)
1570 {
1571 const char *index_dir;
1572 int ret;
1573
1574 if (box->index_pvt != NULL)
1575 return 1;
1576
1577 ret = mailbox_get_path_to(box, MAILBOX_LIST_PATH_TYPE_INDEX_PRIVATE,
1578 &index_dir);
1579 if (ret <= 0)
1580 return ret; /* error / no private indexes */
1581
1582 if (mailbox_create_missing_dir(box, MAILBOX_LIST_PATH_TYPE_INDEX_PRIVATE) < 0)
1583 return -1;
1584
1585 /* Note that this may cause box->event to live longer than box */
1586 box->index_pvt = mail_index_alloc_cache_get(box->event,
1587 NULL, index_dir, t_strconcat(box->index_prefix, ".pvt", NULL));
1588 mail_index_set_fsync_mode(box->index_pvt,
1589 box->storage->set->parsed_fsync_mode, 0);
1590 mail_index_set_lock_method(box->index_pvt,
1591 box->storage->set->parsed_lock_method,
1592 mail_storage_get_lock_timeout(box->storage, UINT_MAX));
1593 return 1;
1594 }
1595
mailbox_open_index_pvt(struct mailbox * box)1596 int mailbox_open_index_pvt(struct mailbox *box)
1597 {
1598 enum mail_index_open_flags index_flags;
1599 int ret;
1600
1601 if (box->view_pvt != NULL)
1602 return 1;
1603 if (mailbox_get_private_flags_mask(box) == 0)
1604 return 0;
1605
1606 if ((ret = mailbox_alloc_index_pvt(box)) <= 0)
1607 return ret;
1608 index_flags = MAIL_INDEX_OPEN_FLAG_CREATE |
1609 mail_storage_settings_to_index_flags(box->storage->set);
1610 if ((box->flags & MAILBOX_FLAG_SAVEONLY) != 0)
1611 index_flags |= MAIL_INDEX_OPEN_FLAG_SAVEONLY;
1612 if (mail_index_open(box->index_pvt, index_flags) < 0)
1613 return -1;
1614 box->view_pvt = mail_index_view_open(box->index_pvt);
1615 return 1;
1616 }
1617
mailbox_open_stream(struct mailbox * box,struct istream * input)1618 int mailbox_open_stream(struct mailbox *box, struct istream *input)
1619 {
1620 return mailbox_open_full(box, input);
1621 }
1622
mailbox_enable(struct mailbox * box,enum mailbox_feature features)1623 int mailbox_enable(struct mailbox *box, enum mailbox_feature features)
1624 {
1625 if (mailbox_verify_name(box) < 0)
1626 return -1;
1627 return box->v.enable(box, features);
1628 }
1629
mailbox_get_enabled_features(struct mailbox * box)1630 enum mailbox_feature mailbox_get_enabled_features(struct mailbox *box)
1631 {
1632 return box->enabled_features;
1633 }
1634
mail_storage_free_binary_cache(struct mail_storage * storage)1635 void mail_storage_free_binary_cache(struct mail_storage *storage)
1636 {
1637 if (storage->binary_cache.box == NULL)
1638 return;
1639
1640 timeout_remove(&storage->binary_cache.to);
1641 i_stream_destroy(&storage->binary_cache.input);
1642 i_zero(&storage->binary_cache);
1643 }
1644
mailbox_close(struct mailbox * box)1645 void mailbox_close(struct mailbox *box)
1646 {
1647 if (!box->opened)
1648 return;
1649
1650 if (box->transaction_count != 0) {
1651 i_panic("Trying to close mailbox %s with open transactions",
1652 box->name);
1653 }
1654 box->v.close(box);
1655
1656 if (box->storage->binary_cache.box == box)
1657 mail_storage_free_binary_cache(box->storage);
1658 box->opened = FALSE;
1659 box->mailbox_deleted = FALSE;
1660 array_clear(&box->search_results);
1661
1662 if (array_is_created(&box->recent_flags))
1663 array_free(&box->recent_flags);
1664 box->recent_flags_prev_uid = 0;
1665 box->recent_flags_count = 0;
1666 }
1667
mailbox_free(struct mailbox ** _box)1668 void mailbox_free(struct mailbox **_box)
1669 {
1670 struct mailbox *box = *_box;
1671
1672 *_box = NULL;
1673
1674 mailbox_close(box);
1675 box->v.free(box);
1676
1677 if (box->attribute_iter_count != 0) {
1678 i_panic("Trying to free mailbox %s with %u open attribute iterators",
1679 box->name, box->attribute_iter_count);
1680 }
1681
1682 DLLIST_REMOVE(&box->storage->mailboxes, box);
1683 mail_storage_obj_unref(box->storage);
1684 pool_unref(&box->pool);
1685 }
1686
mailbox_equals(const struct mailbox * box1,const struct mail_namespace * ns2,const char * vname2)1687 bool mailbox_equals(const struct mailbox *box1,
1688 const struct mail_namespace *ns2, const char *vname2)
1689 {
1690 struct mail_namespace *ns1 = mailbox_get_namespace(box1);
1691 const char *name1;
1692
1693 if (ns1 != ns2)
1694 return FALSE;
1695
1696 name1 = mailbox_get_vname(box1);
1697 if (strcmp(name1, vname2) == 0)
1698 return TRUE;
1699
1700 return strcasecmp(name1, "INBOX") == 0 &&
1701 strcasecmp(vname2, "INBOX") == 0;
1702 }
1703
mailbox_is_any_inbox(struct mailbox * box)1704 bool mailbox_is_any_inbox(struct mailbox *box)
1705 {
1706 return box->inbox_any;
1707 }
1708
mailbox_has_special_use(struct mailbox * box,const char * special_use)1709 bool mailbox_has_special_use(struct mailbox *box, const char *special_use)
1710 {
1711 if (box->set == NULL)
1712 return FALSE;
1713 return str_contains_special_use(box->set->special_use, special_use);
1714 }
1715
mailbox_copy_cache_decisions_from_inbox(struct mailbox * box)1716 static void mailbox_copy_cache_decisions_from_inbox(struct mailbox *box)
1717 {
1718 struct mail_namespace *ns =
1719 mail_namespace_find_inbox(box->storage->user->namespaces);
1720 struct mailbox *inbox =
1721 mailbox_alloc(ns->list, "INBOX", MAILBOX_FLAG_READONLY);
1722 enum mailbox_existence existence;
1723
1724 /* this should be NoSelect but since inbox can never be
1725 NoSelect we use EXISTENCE_NONE to avoid creating inbox by accident */
1726 mailbox_set_reason(inbox, "copy caching decisions");
1727 if (mailbox_exists(inbox, FALSE, &existence) == 0 &&
1728 existence != MAILBOX_EXISTENCE_NONE &&
1729 mailbox_open(inbox) == 0 &&
1730 mailbox_open(box) == 0) {
1731 /* we can't do much about errors here */
1732 (void)mail_cache_decisions_copy(inbox->cache, box->cache);
1733 }
1734
1735 mailbox_free(&inbox);
1736 }
1737
mailbox_create(struct mailbox * box,const struct mailbox_update * update,bool directory)1738 int mailbox_create(struct mailbox *box, const struct mailbox_update *update,
1739 bool directory)
1740 {
1741 int ret;
1742
1743 if (mailbox_verify_create_name(box) < 0)
1744 return -1;
1745
1746 /* Avoid race conditions by keeping mailbox list locked during changes.
1747 This especially fixes a race during INBOX creation with LAYOUT=index
1748 because it scans for missing mailboxes if INBOX doesn't exist. The
1749 second process's scan can find a half-created INBOX and add it,
1750 causing the first process to become confused. */
1751 if (mailbox_list_lock(box->list) < 0) {
1752 mail_storage_copy_list_error(box->storage, box->list);
1753 return -1;
1754 }
1755 box->creating = TRUE;
1756 T_BEGIN {
1757 ret = box->v.create_box(box, update, directory);
1758 } T_END;
1759 box->creating = FALSE;
1760 mailbox_list_unlock(box->list);
1761
1762 if (ret == 0) {
1763 box->list->guid_cache_updated = TRUE;
1764 if (!box->inbox_any) T_BEGIN {
1765 mailbox_copy_cache_decisions_from_inbox(box);
1766 } T_END;
1767 } else if (box->opened) {
1768 /* Creation failed after (partially) opening the mailbox.
1769 It may not be in a valid state, so close it. */
1770 mail_storage_last_error_push(box->storage);
1771 mailbox_close(box);
1772 mail_storage_last_error_pop(box->storage);
1773 }
1774 return ret;
1775 }
1776
mailbox_update(struct mailbox * box,const struct mailbox_update * update)1777 int mailbox_update(struct mailbox *box, const struct mailbox_update *update)
1778 {
1779 int ret;
1780
1781 i_assert(update->min_next_uid == 0 ||
1782 update->min_first_recent_uid == 0 ||
1783 update->min_first_recent_uid <= update->min_next_uid);
1784
1785 if (mailbox_verify_existing_name(box) < 0)
1786 return -1;
1787 ret = box->v.update_box(box, update);
1788 if (!guid_128_is_empty(update->mailbox_guid))
1789 box->list->guid_cache_invalidated = TRUE;
1790 return ret;
1791 }
1792
mailbox_mark_index_deleted(struct mailbox * box,bool del)1793 int mailbox_mark_index_deleted(struct mailbox *box, bool del)
1794 {
1795 struct mail_index_transaction *trans;
1796 enum mail_index_transaction_flags trans_flags = 0;
1797 enum mailbox_flags old_flag;
1798 int ret;
1799
1800 e_debug(box->event, "Attempting to %s mailbox", del ?
1801 "delete" : "undelete");
1802
1803 if (box->marked_deleted && del) {
1804 /* we already marked it deleted. this allows plugins to
1805 "lock" the deletion earlier. */
1806 return 0;
1807 }
1808
1809 old_flag = box->flags & MAILBOX_FLAG_OPEN_DELETED;
1810 box->flags |= MAILBOX_FLAG_OPEN_DELETED;
1811 ret = mailbox_open(box);
1812 box->flags = (box->flags & ENUM_NEGATE(MAILBOX_FLAG_OPEN_DELETED)) | old_flag;
1813 if (ret < 0)
1814 return -1;
1815
1816 trans_flags = del ? 0 : MAIL_INDEX_TRANSACTION_FLAG_EXTERNAL;
1817 trans = mail_index_transaction_begin(box->view, trans_flags);
1818 if (del)
1819 mail_index_set_deleted(trans);
1820 else
1821 mail_index_set_undeleted(trans);
1822 if (mail_index_transaction_commit(&trans) < 0) {
1823 mailbox_set_index_error(box);
1824 return -1;
1825 }
1826
1827 if (del) {
1828 /* sync the mailbox. this finishes the index deletion and it
1829 can succeed only for a single session. we do it here, so the
1830 rest of the deletion code doesn't have to worry about race
1831 conditions. */
1832 box->delete_sync_check = TRUE;
1833 ret = mailbox_sync(box, MAILBOX_SYNC_FLAG_FULL_READ);
1834 box->delete_sync_check = FALSE;
1835 if (ret < 0)
1836 return -1;
1837 }
1838
1839 box->marked_deleted = del;
1840 return 0;
1841 }
1842
mailbox_close_reset_path(struct mailbox * box)1843 static void mailbox_close_reset_path(struct mailbox *box)
1844 {
1845 i_zero(&box->_perm);
1846 box->_path = NULL;
1847 box->_index_path = NULL;
1848 }
1849
mailbox_delete_real(struct mailbox * box)1850 static int mailbox_delete_real(struct mailbox *box)
1851 {
1852 bool list_locked;
1853 int ret;
1854
1855 if (*box->name == '\0') {
1856 mail_storage_set_error(box->storage, MAIL_ERROR_PARAMS,
1857 "Storage root can't be deleted");
1858 return -1;
1859 }
1860
1861 box->deleting = TRUE;
1862 if (mailbox_open(box) < 0) {
1863 if (mailbox_get_last_mail_error(box) != MAIL_ERROR_NOTFOUND &&
1864 !box->mailbox_deleted)
1865 return -1;
1866 /* might be a \noselect mailbox, so continue deletion */
1867 }
1868
1869 if (mailbox_list_lock(box->list) < 0) {
1870 mail_storage_copy_list_error(box->storage, box->list);
1871 list_locked = FALSE;
1872 ret = -1;
1873 } else {
1874 list_locked = TRUE;
1875 ret = box->v.delete_box(box);
1876 }
1877 if (ret < 0 && box->marked_deleted) {
1878 /* deletion failed. revert the mark so it can maybe be
1879 tried again later. */
1880 if (mailbox_mark_index_deleted(box, FALSE) < 0)
1881 ret = -1;
1882 }
1883 if (list_locked)
1884 mailbox_list_unlock(box->list);
1885
1886 box->deleting = FALSE;
1887 mailbox_close(box);
1888
1889 /* if mailbox is reopened, its path may be different with
1890 LAYOUT=index */
1891 mailbox_close_reset_path(box);
1892 return ret;
1893 }
1894
mailbox_delete(struct mailbox * box)1895 int mailbox_delete(struct mailbox *box)
1896 {
1897 int ret;
1898 T_BEGIN {
1899 ret = mailbox_delete_real(box);
1900 } T_END;
1901 return ret;
1902 }
1903
mailbox_delete_empty(struct mailbox * box)1904 int mailbox_delete_empty(struct mailbox *box)
1905 {
1906 int ret;
1907
1908 /* FIXME: should be a parameter to delete(), but since it changes API
1909 don't do it for now */
1910 box->deleting_must_be_empty = TRUE;
1911 ret = mailbox_delete(box);
1912 box->deleting_must_be_empty = FALSE;
1913 return ret;
1914 }
1915
1916 static bool
mail_storages_rename_compatible(struct mail_storage * storage1,struct mail_storage * storage2,const char ** error_r)1917 mail_storages_rename_compatible(struct mail_storage *storage1,
1918 struct mail_storage *storage2,
1919 const char **error_r)
1920 {
1921 if (storage1 == storage2)
1922 return TRUE;
1923
1924 if (strcmp(storage1->name, storage2->name) != 0) {
1925 *error_r = t_strdup_printf("storage %s != %s",
1926 storage1->name, storage2->name);
1927 return FALSE;
1928 }
1929 if ((storage1->class_flags & MAIL_STORAGE_CLASS_FLAG_UNIQUE_ROOT) != 0) {
1930 /* e.g. mdbox where all mails are in storage/ directory and
1931 they can't be easily moved from there. */
1932 *error_r = t_strdup_printf("storage %s uses unique root",
1933 storage1->name);
1934 return FALSE;
1935 }
1936 return TRUE;
1937 }
1938
nullequals(const void * p1,const void * p2)1939 static bool nullequals(const void *p1, const void *p2)
1940 {
1941 return (p1 == NULL && p2 == NULL) || (p1 != NULL && p2 != NULL);
1942 }
1943
1944 static bool
mailbox_lists_rename_compatible(struct mailbox_list * list1,struct mailbox_list * list2,const char ** error_r)1945 mailbox_lists_rename_compatible(struct mailbox_list *list1,
1946 struct mailbox_list *list2,
1947 const char **error_r)
1948 {
1949 if (!nullequals(list1->set.alt_dir, list2->set.alt_dir)) {
1950 *error_r = t_strdup_printf("Namespace %s has alt dir, %s doesn't",
1951 list1->ns->prefix, list2->ns->prefix);
1952 return FALSE;
1953 }
1954 if (!nullequals(list1->set.index_dir, list2->set.index_dir)) {
1955 *error_r = t_strdup_printf("Namespace %s has index dir, %s doesn't",
1956 list1->ns->prefix, list2->ns->prefix);
1957 return FALSE;
1958 }
1959 if (!nullequals(list1->set.index_cache_dir, list2->set.index_cache_dir)) {
1960 *error_r = t_strdup_printf("Namespace %s has index cache dir, %s doesn't",
1961 list1->ns->prefix, list2->ns->prefix);
1962 return FALSE;
1963 }
1964 if (!nullequals(list1->set.control_dir, list2->set.control_dir)) {
1965 *error_r = t_strdup_printf("Namespace %s has control dir, %s doesn't",
1966 list1->ns->prefix, list2->ns->prefix);
1967 return FALSE;
1968 }
1969 return TRUE;
1970 }
1971
1972 static
mailbox_rename_check_children(struct mailbox * src,struct mailbox * dest)1973 int mailbox_rename_check_children(struct mailbox *src, struct mailbox *dest)
1974 {
1975 int ret = 0;
1976 size_t src_prefix_len = strlen(src->vname)+1; /* include separator */
1977 size_t dest_prefix_len = strlen(dest->vname)+1;
1978 /* this can return folders with * in their name, that are not
1979 actually our children */
1980 char ns_sep = mail_namespace_get_sep(src->list->ns);
1981 const char *pattern = t_strdup_printf("%s%c*", src->vname, ns_sep);
1982
1983 struct mailbox_list_iterate_context *iter = mailbox_list_iter_init(src->list, pattern,
1984 MAILBOX_LIST_ITER_RETURN_NO_FLAGS);
1985
1986 const struct mailbox_info *child;
1987 while((child = mailbox_list_iter_next(iter)) != NULL) {
1988 if (strncmp(child->vname, src->vname, src_prefix_len-1) != 0 ||
1989 child->vname[src_prefix_len-1] != ns_sep)
1990 continue; /* not our child */
1991 /* if total length of new name exceeds the limit, fail */
1992 if (strlen(child->vname + src_prefix_len)+dest_prefix_len > MAILBOX_LIST_NAME_MAX_LENGTH) {
1993 mail_storage_set_error(src->storage, MAIL_ERROR_PARAMS,
1994 "Mailbox or child name too long");
1995 ret = -1;
1996 break;
1997 }
1998 }
1999
2000 /* something went bad */
2001 if (mailbox_list_iter_deinit(&iter) < 0) {
2002 mail_storage_copy_list_error(src->storage, src->list);
2003 ret = -1;
2004 }
2005 return ret;
2006 }
2007
mailbox_rename_real(struct mailbox * src,struct mailbox * dest)2008 static int mailbox_rename_real(struct mailbox *src, struct mailbox *dest)
2009 {
2010 const char *error = NULL;
2011
2012 /* Check only name validity, \Noselect don't necessarily exist. */
2013 if (mailbox_verify_name(src) < 0)
2014 return -1;
2015 if (*src->name == '\0') {
2016 mail_storage_set_error(src->storage, MAIL_ERROR_PARAMS,
2017 "Can't rename mailbox root");
2018 return -1;
2019 }
2020 if (mailbox_verify_create_name(dest) < 0) {
2021 mail_storage_copy_error(src->storage, dest->storage);
2022 return -1;
2023 }
2024 if (mailbox_rename_check_children(src, dest) != 0) {
2025 return -1;
2026 }
2027
2028 if (!mail_storages_rename_compatible(src->storage,
2029 dest->storage, &error) ||
2030 !mailbox_lists_rename_compatible(src->list,
2031 dest->list, &error)) {
2032 e_debug(src->event,
2033 "Can't rename '%s' to '%s': %s",
2034 src->vname, dest->vname, error);
2035 mail_storage_set_error(src->storage, MAIL_ERROR_NOTPOSSIBLE,
2036 "Can't rename mailboxes across specified storages.");
2037 return -1;
2038 }
2039 if (src->list != dest->list &&
2040 (src->list->ns->type != MAIL_NAMESPACE_TYPE_PRIVATE ||
2041 dest->list->ns->type != MAIL_NAMESPACE_TYPE_PRIVATE)) {
2042 mail_storage_set_error(src->storage, MAIL_ERROR_NOTPOSSIBLE,
2043 "Renaming not supported across non-private namespaces.");
2044 return -1;
2045 }
2046 if (src->list == dest->list && strcmp(src->name, dest->name) == 0) {
2047 mail_storage_set_error(src->storage, MAIL_ERROR_EXISTS,
2048 "Can't rename mailbox to itself.");
2049 return -1;
2050 }
2051
2052 /* It would be safer to lock both source and destination, but that
2053 could lead to deadlocks. So at least for now lets just lock only the
2054 destination list. */
2055 if (mailbox_list_lock(dest->list) < 0) {
2056 mail_storage_copy_list_error(src->storage, dest->list);
2057 return -1;
2058 }
2059 int ret = src->v.rename_box(src, dest);
2060 mailbox_list_unlock(dest->list);
2061 if (ret < 0)
2062 return -1;
2063 src->list->guid_cache_invalidated = TRUE;
2064 dest->list->guid_cache_invalidated = TRUE;
2065 return 0;
2066 }
2067
mailbox_rename(struct mailbox * src,struct mailbox * dest)2068 int mailbox_rename(struct mailbox *src, struct mailbox *dest)
2069 {
2070 int ret;
2071 T_BEGIN {
2072 ret = mailbox_rename_real(src, dest);
2073 } T_END;
2074 return ret;
2075 }
2076
mailbox_set_subscribed(struct mailbox * box,bool set)2077 int mailbox_set_subscribed(struct mailbox *box, bool set)
2078 {
2079 if (mailbox_verify_name(box) < 0)
2080 return -1;
2081 if (mailbox_list_iter_subscriptions_refresh(box->list) < 0) {
2082 mail_storage_copy_list_error(box->storage, box->list);
2083 return -1;
2084 }
2085 if (mailbox_is_subscribed(box) == set)
2086 return 0;
2087 return box->v.set_subscribed(box, set);
2088 }
2089
mailbox_is_subscribed(struct mailbox * box)2090 bool mailbox_is_subscribed(struct mailbox *box)
2091 {
2092 struct mailbox_node *node;
2093
2094 i_assert(box->list->subscriptions != NULL);
2095
2096 node = mailbox_tree_lookup(box->list->subscriptions, box->vname);
2097 return node != NULL && (node->flags & MAILBOX_SUBSCRIBED) != 0;
2098 }
2099
mailbox_get_storage(const struct mailbox * box)2100 struct mail_storage *mailbox_get_storage(const struct mailbox *box)
2101 {
2102 return box->storage;
2103 }
2104
2105 struct mail_namespace *
mailbox_get_namespace(const struct mailbox * box)2106 mailbox_get_namespace(const struct mailbox *box)
2107 {
2108 return box->list->ns;
2109 }
2110
mailbox_get_settings(struct mailbox * box)2111 const struct mail_storage_settings *mailbox_get_settings(struct mailbox *box)
2112 {
2113 return box->storage->set;
2114 }
2115
mailbox_get_name(const struct mailbox * box)2116 const char *mailbox_get_name(const struct mailbox *box)
2117 {
2118 return box->name;
2119 }
2120
mailbox_get_vname(const struct mailbox * box)2121 const char *mailbox_get_vname(const struct mailbox *box)
2122 {
2123 return box->vname;
2124 }
2125
mailbox_is_readonly(struct mailbox * box)2126 bool mailbox_is_readonly(struct mailbox *box)
2127 {
2128 i_assert(box->opened);
2129
2130 return box->v.is_readonly(box);
2131 }
2132
mailbox_backends_equal(const struct mailbox * box1,const struct mailbox * box2)2133 bool mailbox_backends_equal(const struct mailbox *box1,
2134 const struct mailbox *box2)
2135 {
2136 struct mail_namespace *ns1 = box1->list->ns, *ns2 = box2->list->ns;
2137
2138 if (strcmp(box1->name, box2->name) != 0)
2139 return FALSE;
2140
2141 while (ns1->alias_for != NULL)
2142 ns1 = ns1->alias_for;
2143 while (ns2->alias_for != NULL)
2144 ns2 = ns2->alias_for;
2145 return ns1 == ns2;
2146 }
2147
2148 static void
mailbox_get_status_set_defaults(struct mailbox * box,struct mailbox_status * status_r)2149 mailbox_get_status_set_defaults(struct mailbox *box,
2150 struct mailbox_status *status_r)
2151 {
2152 i_zero(status_r);
2153 if ((box->storage->class_flags & MAIL_STORAGE_CLASS_FLAG_HAVE_MAIL_GUIDS) != 0)
2154 status_r->have_guids = TRUE;
2155 if ((box->storage->class_flags & MAIL_STORAGE_CLASS_FLAG_HAVE_MAIL_SAVE_GUIDS) != 0)
2156 status_r->have_save_guids = TRUE;
2157 if ((box->storage->class_flags & MAIL_STORAGE_CLASS_FLAG_HAVE_MAIL_GUID128) != 0)
2158 status_r->have_only_guid128 = TRUE;
2159 }
2160
mailbox_get_status(struct mailbox * box,enum mailbox_status_items items,struct mailbox_status * status_r)2161 int mailbox_get_status(struct mailbox *box,
2162 enum mailbox_status_items items,
2163 struct mailbox_status *status_r)
2164 {
2165 mailbox_get_status_set_defaults(box, status_r);
2166 if (mailbox_verify_existing_name(box) < 0)
2167 return -1;
2168
2169 if (box->v.get_status(box, items, status_r) < 0)
2170 return -1;
2171 i_assert(status_r->have_guids || !status_r->have_save_guids);
2172 return 0;
2173 }
2174
mailbox_get_open_status(struct mailbox * box,enum mailbox_status_items items,struct mailbox_status * status_r)2175 void mailbox_get_open_status(struct mailbox *box,
2176 enum mailbox_status_items items,
2177 struct mailbox_status *status_r)
2178 {
2179 i_assert(box->opened);
2180 i_assert((items & MAILBOX_STATUS_FAILING_ITEMS) == 0);
2181
2182 mailbox_get_status_set_defaults(box, status_r);
2183 if (box->v.get_status(box, items, status_r) < 0)
2184 i_unreached();
2185 }
2186
mailbox_get_metadata(struct mailbox * box,enum mailbox_metadata_items items,struct mailbox_metadata * metadata_r)2187 int mailbox_get_metadata(struct mailbox *box, enum mailbox_metadata_items items,
2188 struct mailbox_metadata *metadata_r)
2189 {
2190 i_zero(metadata_r);
2191 if (mailbox_verify_existing_name(box) < 0)
2192 return -1;
2193
2194 if (box->v.get_metadata(box, items, metadata_r) < 0)
2195 return -1;
2196
2197 i_assert((items & MAILBOX_METADATA_GUID) == 0 ||
2198 !guid_128_is_empty(metadata_r->guid));
2199 return 0;
2200 }
2201
mailbox_get_private_flags_mask(struct mailbox * box)2202 enum mail_flags mailbox_get_private_flags_mask(struct mailbox *box)
2203 {
2204 if (box->v.get_private_flags_mask != NULL)
2205 return box->v.get_private_flags_mask(box);
2206 else if (box->list->set.index_pvt_dir != NULL)
2207 return MAIL_SEEN; /* FIXME */
2208 else
2209 return 0;
2210 }
2211
2212 struct mailbox_sync_context *
mailbox_sync_init(struct mailbox * box,enum mailbox_sync_flags flags)2213 mailbox_sync_init(struct mailbox *box, enum mailbox_sync_flags flags)
2214 {
2215 struct mailbox_sync_context *ctx;
2216
2217 if (box->transaction_count != 0) {
2218 i_panic("Trying to sync mailbox %s with open transactions",
2219 box->name);
2220 }
2221 if (!box->opened) {
2222 if (mailbox_open(box) < 0) {
2223 ctx = i_new(struct mailbox_sync_context, 1);
2224 ctx->box = box;
2225 ctx->flags = flags;
2226 ctx->open_failed = TRUE;
2227 return ctx;
2228 }
2229 }
2230 T_BEGIN {
2231 ctx = box->v.sync_init(box, flags);
2232 } T_END;
2233 return ctx;
2234 }
2235
mailbox_sync_next(struct mailbox_sync_context * ctx,struct mailbox_sync_rec * sync_rec_r)2236 bool mailbox_sync_next(struct mailbox_sync_context *ctx,
2237 struct mailbox_sync_rec *sync_rec_r)
2238 {
2239 if (ctx->open_failed)
2240 return FALSE;
2241 return ctx->box->v.sync_next(ctx, sync_rec_r);
2242 }
2243
mailbox_sync_deinit(struct mailbox_sync_context ** _ctx,struct mailbox_sync_status * status_r)2244 int mailbox_sync_deinit(struct mailbox_sync_context **_ctx,
2245 struct mailbox_sync_status *status_r)
2246 {
2247 struct mailbox_sync_context *ctx = *_ctx;
2248 struct mailbox *box = ctx->box;
2249 const char *errormsg;
2250 enum mail_error error;
2251 int ret;
2252
2253 *_ctx = NULL;
2254
2255 i_zero(status_r);
2256
2257 if (!ctx->open_failed)
2258 ret = box->v.sync_deinit(ctx, status_r);
2259 else {
2260 i_free(ctx);
2261 ret = -1;
2262 }
2263 if (ret < 0 && box->inbox_user &&
2264 !box->storage->user->inbox_open_error_logged) {
2265 errormsg = mailbox_get_last_internal_error(box, &error);
2266 if (error == MAIL_ERROR_NOTPOSSIBLE) {
2267 box->storage->user->inbox_open_error_logged = TRUE;
2268 e_error(box->event, "Syncing INBOX failed: %s", errormsg);
2269 }
2270 }
2271 if (ret == 0)
2272 box->synced = TRUE;
2273 return ret;
2274 }
2275
mailbox_sync(struct mailbox * box,enum mailbox_sync_flags flags)2276 int mailbox_sync(struct mailbox *box, enum mailbox_sync_flags flags)
2277 {
2278 struct mailbox_sync_context *ctx;
2279 struct mailbox_sync_status status;
2280
2281 if (array_count(&box->search_results) == 0) {
2282 /* we don't care about mailbox's current state, so we might
2283 as well fix inconsistency state */
2284 flags |= MAILBOX_SYNC_FLAG_FIX_INCONSISTENT;
2285 }
2286
2287 ctx = mailbox_sync_init(box, flags);
2288 return mailbox_sync_deinit(&ctx, &status);
2289 }
2290
2291 #undef mailbox_notify_changes
mailbox_notify_changes(struct mailbox * box,mailbox_notify_callback_t * callback,void * context)2292 void mailbox_notify_changes(struct mailbox *box,
2293 mailbox_notify_callback_t *callback, void *context)
2294 {
2295 i_assert(box->opened);
2296
2297 box->notify_callback = callback;
2298 box->notify_context = context;
2299
2300 box->v.notify_changes(box);
2301 }
2302
mailbox_notify_changes_stop(struct mailbox * box)2303 void mailbox_notify_changes_stop(struct mailbox *box)
2304 {
2305 i_assert(box->opened);
2306
2307 box->notify_callback = NULL;
2308 box->notify_context = NULL;
2309
2310 box->v.notify_changes(box);
2311 }
2312
2313 struct mail_search_context *
mailbox_search_init(struct mailbox_transaction_context * t,struct mail_search_args * args,const enum mail_sort_type * sort_program,enum mail_fetch_field wanted_fields,struct mailbox_header_lookup_ctx * wanted_headers)2314 mailbox_search_init(struct mailbox_transaction_context *t,
2315 struct mail_search_args *args,
2316 const enum mail_sort_type *sort_program,
2317 enum mail_fetch_field wanted_fields,
2318 struct mailbox_header_lookup_ctx *wanted_headers)
2319 {
2320 i_assert(wanted_headers == NULL || wanted_headers->box == t->box);
2321
2322 mail_search_args_ref(args);
2323 if (!args->simplified)
2324 mail_search_args_simplify(args);
2325 return t->box->v.search_init(t, args, sort_program,
2326 wanted_fields, wanted_headers);
2327 }
2328
mailbox_search_deinit(struct mail_search_context ** _ctx)2329 int mailbox_search_deinit(struct mail_search_context **_ctx)
2330 {
2331 struct mail_search_context *ctx = *_ctx;
2332 struct mail_search_args *args = ctx->args;
2333 int ret;
2334
2335 *_ctx = NULL;
2336 mailbox_search_results_initial_done(ctx);
2337 ret = ctx->transaction->box->v.search_deinit(ctx);
2338 mail_search_args_unref(&args);
2339 return ret;
2340 }
2341
mailbox_search_next(struct mail_search_context * ctx,struct mail ** mail_r)2342 bool mailbox_search_next(struct mail_search_context *ctx, struct mail **mail_r)
2343 {
2344 bool tryagain;
2345
2346 while (!mailbox_search_next_nonblock(ctx, mail_r, &tryagain)) {
2347 if (!tryagain)
2348 return FALSE;
2349 }
2350 return TRUE;
2351 }
2352
mailbox_search_next_nonblock(struct mail_search_context * ctx,struct mail ** mail_r,bool * tryagain_r)2353 bool mailbox_search_next_nonblock(struct mail_search_context *ctx,
2354 struct mail **mail_r, bool *tryagain_r)
2355 {
2356 struct mailbox *box = ctx->transaction->box;
2357
2358 *mail_r = NULL;
2359 *tryagain_r = FALSE;
2360
2361 if (!box->v.search_next_nonblock(ctx, mail_r, tryagain_r))
2362 return FALSE;
2363 else {
2364 mailbox_search_results_add(ctx, (*mail_r)->uid);
2365 return TRUE;
2366 }
2367 }
2368
mailbox_search_seen_lost_data(struct mail_search_context * ctx)2369 bool mailbox_search_seen_lost_data(struct mail_search_context *ctx)
2370 {
2371 return ctx->seen_lost_data;
2372 }
2373
mailbox_search_mail_detach(struct mail_search_context * ctx,struct mail * mail)2374 void mailbox_search_mail_detach(struct mail_search_context *ctx,
2375 struct mail *mail)
2376 {
2377 struct mail_private *pmail =
2378 container_of(mail, struct mail_private, mail);
2379 struct mail *const *mailp;
2380
2381 array_foreach(&ctx->mails, mailp) {
2382 if (*mailp == mail) {
2383 pmail->search_mail = FALSE;
2384 array_delete(&ctx->mails,
2385 array_foreach_idx(&ctx->mails, mailp), 1);
2386 return;
2387 }
2388 }
2389 i_unreached();
2390 }
2391
mailbox_search_result_build(struct mailbox_transaction_context * t,struct mail_search_args * args,enum mailbox_search_result_flags flags,struct mail_search_result ** result_r)2392 int mailbox_search_result_build(struct mailbox_transaction_context *t,
2393 struct mail_search_args *args,
2394 enum mailbox_search_result_flags flags,
2395 struct mail_search_result **result_r)
2396 {
2397 struct mail_search_context *ctx;
2398 struct mail *mail;
2399 int ret;
2400
2401 ctx = mailbox_search_init(t, args, NULL, 0, NULL);
2402 *result_r = mailbox_search_result_save(ctx, flags);
2403 while (mailbox_search_next(ctx, &mail)) ;
2404
2405 ret = mailbox_search_deinit(&ctx);
2406 if (ret < 0)
2407 mailbox_search_result_free(result_r);
2408 return ret;
2409 }
2410
2411 struct mailbox_transaction_context *
mailbox_transaction_begin(struct mailbox * box,enum mailbox_transaction_flags flags,const char * reason)2412 mailbox_transaction_begin(struct mailbox *box,
2413 enum mailbox_transaction_flags flags,
2414 const char *reason)
2415 {
2416 struct mailbox_transaction_context *trans;
2417
2418 i_assert(box->opened);
2419
2420 box->transaction_count++;
2421 trans = box->v.transaction_begin(box, flags, reason);
2422 i_assert(trans->reason != NULL);
2423 return trans;
2424 }
2425
mailbox_transaction_commit(struct mailbox_transaction_context ** t)2426 int mailbox_transaction_commit(struct mailbox_transaction_context **t)
2427 {
2428 struct mail_transaction_commit_changes changes;
2429 int ret;
2430
2431 /* Store changes temporarily so that plugins overriding
2432 transaction_commit() can look at them. */
2433 ret = mailbox_transaction_commit_get_changes(t, &changes);
2434 pool_unref(&changes.pool);
2435 return ret;
2436 }
2437
mailbox_transaction_commit_get_changes(struct mailbox_transaction_context ** _t,struct mail_transaction_commit_changes * changes_r)2438 int mailbox_transaction_commit_get_changes(
2439 struct mailbox_transaction_context **_t,
2440 struct mail_transaction_commit_changes *changes_r)
2441 {
2442 struct mailbox_transaction_context *t = *_t;
2443 struct mailbox *box = t->box;
2444 unsigned int save_count = t->save_count;
2445 int ret;
2446
2447 changes_r->pool = NULL;
2448
2449 *_t = NULL;
2450 T_BEGIN {
2451 ret = box->v.transaction_commit(t, changes_r);
2452 } T_END;
2453 /* either all the saved messages get UIDs or none, because a) we
2454 failed, b) MAILBOX_TRANSACTION_FLAG_ASSIGN_UIDS not set,
2455 c) backend doesn't support it (e.g. virtual plugin) */
2456 i_assert(ret < 0 ||
2457 seq_range_count(&changes_r->saved_uids) == save_count ||
2458 array_count(&changes_r->saved_uids) == 0);
2459 /* decrease the transaction count only after transaction_commit().
2460 that way if it creates and destroys transactions internally, we
2461 don't see transaction_count=0 until the parent transaction is fully
2462 finished */
2463 box->transaction_count--;
2464 if (ret < 0 && changes_r->pool != NULL)
2465 pool_unref(&changes_r->pool);
2466 return ret;
2467 }
2468
mailbox_transaction_rollback(struct mailbox_transaction_context ** _t)2469 void mailbox_transaction_rollback(struct mailbox_transaction_context **_t)
2470 {
2471 struct mailbox_transaction_context *t = *_t;
2472 struct mailbox *box = t->box;
2473
2474 *_t = NULL;
2475 box->v.transaction_rollback(t);
2476 box->transaction_count--;
2477 }
2478
mailbox_transaction_get_count(const struct mailbox * box)2479 unsigned int mailbox_transaction_get_count(const struct mailbox *box)
2480 {
2481 return box->transaction_count;
2482 }
2483
mailbox_transaction_set_max_modseq(struct mailbox_transaction_context * t,uint64_t max_modseq,ARRAY_TYPE (seq_range)* seqs)2484 void mailbox_transaction_set_max_modseq(struct mailbox_transaction_context *t,
2485 uint64_t max_modseq,
2486 ARRAY_TYPE(seq_range) *seqs)
2487 {
2488 mail_index_transaction_set_max_modseq(t->itrans, max_modseq, seqs);
2489 }
2490
2491 struct mailbox *
mailbox_transaction_get_mailbox(const struct mailbox_transaction_context * t)2492 mailbox_transaction_get_mailbox(const struct mailbox_transaction_context *t)
2493 {
2494 return t->box;
2495 }
2496
mailbox_save_dest_mail_close(struct mail_save_context * ctx)2497 static void mailbox_save_dest_mail_close(struct mail_save_context *ctx)
2498 {
2499 struct mail_private *mail = (struct mail_private *)ctx->dest_mail;
2500
2501 mail->v.close(&mail->mail);
2502 }
2503
2504 struct mail_save_context *
mailbox_save_alloc(struct mailbox_transaction_context * t)2505 mailbox_save_alloc(struct mailbox_transaction_context *t)
2506 {
2507 struct mail_save_context *ctx;
2508 T_BEGIN {
2509 ctx = t->box->v.save_alloc(t);
2510 } T_END;
2511 i_assert(!ctx->unfinished);
2512 ctx->unfinished = TRUE;
2513 ctx->data.received_date = (time_t)-1;
2514 ctx->data.save_date = (time_t)-1;
2515
2516 /* Always have a dest_mail available. A lot of plugins make use
2517 of this. */
2518 if (ctx->dest_mail == NULL)
2519 ctx->dest_mail = mail_alloc(t, 0, NULL);
2520 else {
2521 /* make sure the mail isn't used before mail_set_seq_saving() */
2522 mailbox_save_dest_mail_close(ctx);
2523 }
2524
2525 return ctx;
2526 }
2527
mailbox_save_context_deinit(struct mail_save_context * ctx)2528 void mailbox_save_context_deinit(struct mail_save_context *ctx)
2529 {
2530 i_assert(ctx->dest_mail != NULL);
2531
2532 mail_free(&ctx->dest_mail);
2533 }
2534
mailbox_save_set_flags(struct mail_save_context * ctx,enum mail_flags flags,struct mail_keywords * keywords)2535 void mailbox_save_set_flags(struct mail_save_context *ctx,
2536 enum mail_flags flags,
2537 struct mail_keywords *keywords)
2538 {
2539 struct mailbox *box = ctx->transaction->box;
2540
2541 if (ctx->data.keywords != NULL)
2542 mailbox_keywords_unref(&ctx->data.keywords);
2543
2544 ctx->data.flags = flags & ENUM_NEGATE(mailbox_get_private_flags_mask(box));
2545 ctx->data.pvt_flags = flags & mailbox_get_private_flags_mask(box);
2546 ctx->data.keywords = keywords;
2547 if (keywords != NULL)
2548 mailbox_keywords_ref(keywords);
2549 }
2550
mailbox_save_copy_flags(struct mail_save_context * ctx,struct mail * mail)2551 void mailbox_save_copy_flags(struct mail_save_context *ctx, struct mail *mail)
2552 {
2553 const char *const *keywords_list;
2554 struct mail_keywords *keywords;
2555
2556 keywords_list = mail_get_keywords(mail);
2557 keywords = str_array_length(keywords_list) == 0 ? NULL :
2558 mailbox_keywords_create_valid(ctx->transaction->box,
2559 keywords_list);
2560 mailbox_save_set_flags(ctx, mail_get_flags(mail), keywords);
2561 if (keywords != NULL)
2562 mailbox_keywords_unref(&keywords);
2563 }
2564
mailbox_save_set_min_modseq(struct mail_save_context * ctx,uint64_t min_modseq)2565 void mailbox_save_set_min_modseq(struct mail_save_context *ctx,
2566 uint64_t min_modseq)
2567 {
2568 ctx->data.min_modseq = min_modseq;
2569 }
2570
mailbox_save_set_received_date(struct mail_save_context * ctx,time_t received_date,int timezone_offset)2571 void mailbox_save_set_received_date(struct mail_save_context *ctx,
2572 time_t received_date, int timezone_offset)
2573 {
2574 ctx->data.received_date = received_date;
2575 ctx->data.received_tz_offset = timezone_offset;
2576 }
2577
mailbox_save_set_save_date(struct mail_save_context * ctx,time_t save_date)2578 void mailbox_save_set_save_date(struct mail_save_context *ctx,
2579 time_t save_date)
2580 {
2581 ctx->data.save_date = save_date;
2582 }
2583
mailbox_save_set_from_envelope(struct mail_save_context * ctx,const char * envelope)2584 void mailbox_save_set_from_envelope(struct mail_save_context *ctx,
2585 const char *envelope)
2586 {
2587 i_free(ctx->data.from_envelope);
2588 ctx->data.from_envelope = i_strdup(envelope);
2589 }
2590
mailbox_save_set_uid(struct mail_save_context * ctx,uint32_t uid)2591 void mailbox_save_set_uid(struct mail_save_context *ctx, uint32_t uid)
2592 {
2593 ctx->data.uid = uid;
2594 }
2595
mailbox_save_set_guid(struct mail_save_context * ctx,const char * guid)2596 void mailbox_save_set_guid(struct mail_save_context *ctx, const char *guid)
2597 {
2598 i_assert(guid == NULL || *guid != '\0');
2599
2600 i_free(ctx->data.guid);
2601 ctx->data.guid = i_strdup(guid);
2602 }
2603
mailbox_save_set_pop3_uidl(struct mail_save_context * ctx,const char * uidl)2604 void mailbox_save_set_pop3_uidl(struct mail_save_context *ctx, const char *uidl)
2605 {
2606 i_assert(*uidl != '\0');
2607 i_assert(strchr(uidl, '\n') == NULL);
2608
2609 i_free(ctx->data.pop3_uidl);
2610 ctx->data.pop3_uidl = i_strdup(uidl);
2611 }
2612
mailbox_save_set_pop3_order(struct mail_save_context * ctx,unsigned int order)2613 void mailbox_save_set_pop3_order(struct mail_save_context *ctx,
2614 unsigned int order)
2615 {
2616 i_assert(order > 0);
2617
2618 ctx->data.pop3_order = order;
2619 }
2620
mailbox_save_get_dest_mail(struct mail_save_context * ctx)2621 struct mail *mailbox_save_get_dest_mail(struct mail_save_context *ctx)
2622 {
2623 return ctx->dest_mail;
2624 }
2625
mailbox_save_begin(struct mail_save_context ** ctx,struct istream * input)2626 int mailbox_save_begin(struct mail_save_context **ctx, struct istream *input)
2627 {
2628 struct mailbox *box = (*ctx)->transaction->box;
2629 int ret;
2630
2631 if (mail_index_is_deleted(box->index)) {
2632 mailbox_set_deleted(box);
2633 mailbox_save_cancel(ctx);
2634 return -1;
2635 }
2636
2637 /* make sure parts get parsed early on */
2638 const struct mail_storage_settings *mail_set =
2639 mailbox_get_settings(box);
2640 if (mail_set->parsed_mail_attachment_detection_add_flags)
2641 mail_add_temp_wanted_fields((*ctx)->dest_mail,
2642 MAIL_FETCH_MESSAGE_PARTS, NULL);
2643
2644 if (!(*ctx)->copying_or_moving) {
2645 /* We're actually saving the mail. We're not being called by
2646 mail_storage_copy() because backend didn't support fast
2647 copying. */
2648 i_assert(!(*ctx)->copying_via_save);
2649 (*ctx)->saving = TRUE;
2650 } else {
2651 i_assert((*ctx)->copying_via_save);
2652 }
2653 if (box->v.save_begin == NULL) {
2654 mail_storage_set_error(box->storage, MAIL_ERROR_NOTPOSSIBLE,
2655 "Saving messages not supported");
2656 ret = -1;
2657 } else T_BEGIN {
2658 ret = box->v.save_begin(*ctx, input);
2659 } T_END;
2660
2661 if (ret < 0) {
2662 mailbox_save_cancel(ctx);
2663 return -1;
2664 }
2665 return 0;
2666 }
2667
mailbox_save_continue(struct mail_save_context * ctx)2668 int mailbox_save_continue(struct mail_save_context *ctx)
2669 {
2670 int ret;
2671
2672 T_BEGIN {
2673 ret = ctx->transaction->box->v.save_continue(ctx);
2674 } T_END;
2675 return ret;
2676 }
2677
2678 static void
mailbox_save_add_pvt_flags(struct mailbox_transaction_context * t,enum mail_flags pvt_flags)2679 mailbox_save_add_pvt_flags(struct mailbox_transaction_context *t,
2680 enum mail_flags pvt_flags)
2681 {
2682 struct mail_save_private_changes *save;
2683
2684 if (!array_is_created(&t->pvt_saves))
2685 i_array_init(&t->pvt_saves, 8);
2686 save = array_append_space(&t->pvt_saves);
2687 save->mailnum = t->save_count;
2688 save->flags = pvt_flags;
2689 }
2690
2691 static void
mailbox_save_context_reset(struct mail_save_context * ctx,bool success)2692 mailbox_save_context_reset(struct mail_save_context *ctx, bool success)
2693 {
2694 i_assert(!ctx->unfinished);
2695 if (!ctx->copying_or_moving) {
2696 /* we're finishing a save (not copy/move). Note that we could
2697 have come here also from mailbox_save_cancel(), in which
2698 case ctx->saving may be FALSE. */
2699 i_assert(!ctx->copying_via_save);
2700 i_assert(ctx->saving || !success);
2701 ctx->saving = FALSE;
2702 } else {
2703 i_assert(ctx->copying_via_save || !success);
2704 /* We came from mailbox_copy(). saving==TRUE is possible here
2705 if we also came from mailbox_save_using_mail(). Don't set
2706 saving=FALSE yet in that case, because copy() is still
2707 running. */
2708 }
2709 }
2710
mailbox_save_finish(struct mail_save_context ** _ctx)2711 int mailbox_save_finish(struct mail_save_context **_ctx)
2712 {
2713 struct mail_save_context *ctx = *_ctx;
2714 struct mailbox_transaction_context *t = ctx->transaction;
2715 /* we need to keep a copy of this because save_finish implementations
2716 will likely zero the data structure during cleanup */
2717 enum mail_flags pvt_flags = ctx->data.pvt_flags;
2718 bool copying_via_save = ctx->copying_via_save;
2719 int ret;
2720
2721 /* Do one final continue. The caller may not have done it if the
2722 input stream's offset already matched the number of bytes that
2723 were wanted to be saved. But due to nested istreams some of the
2724 underlying ones may not have seen the EOF yet, and haven't flushed
2725 out the pending data. */
2726 if (mailbox_save_continue(ctx) < 0) {
2727 mailbox_save_cancel(_ctx);
2728 return -1;
2729 }
2730 *_ctx = NULL;
2731
2732 ctx->finishing = TRUE;
2733 T_BEGIN {
2734 ret = t->box->v.save_finish(ctx);
2735 } T_END;
2736 ctx->finishing = FALSE;
2737
2738 if (ret == 0 && !copying_via_save) {
2739 if (pvt_flags != 0)
2740 mailbox_save_add_pvt_flags(t, pvt_flags);
2741 t->save_count++;
2742 }
2743
2744 mailbox_save_context_reset(ctx, TRUE);
2745 return ret;
2746 }
2747
mailbox_save_cancel(struct mail_save_context ** _ctx)2748 void mailbox_save_cancel(struct mail_save_context **_ctx)
2749 {
2750 struct mail_save_context *ctx = *_ctx;
2751
2752 *_ctx = NULL;
2753 T_BEGIN {
2754 ctx->transaction->box->v.save_cancel(ctx);
2755 } T_END;
2756
2757 /* the dest_mail is no longer valid. if we're still saving
2758 more mails, the mail sequence may get reused. make sure
2759 the mail gets reset in between */
2760 mailbox_save_dest_mail_close(ctx);
2761
2762 mailbox_save_context_reset(ctx, FALSE);
2763 }
2764
2765 struct mailbox_transaction_context *
mailbox_save_get_transaction(struct mail_save_context * ctx)2766 mailbox_save_get_transaction(struct mail_save_context *ctx)
2767 {
2768 return ctx->transaction;
2769 }
2770
mailbox_copy_int(struct mail_save_context ** _ctx,struct mail * mail)2771 static int mailbox_copy_int(struct mail_save_context **_ctx, struct mail *mail)
2772 {
2773 struct mail_save_context *ctx = *_ctx;
2774 struct mailbox_transaction_context *t = ctx->transaction;
2775 enum mail_flags pvt_flags = ctx->data.pvt_flags;
2776 struct mail *backend_mail;
2777 int ret;
2778
2779 *_ctx = NULL;
2780
2781 if (mail_index_is_deleted(t->box->index)) {
2782 mailbox_set_deleted(t->box);
2783 mailbox_save_cancel(&ctx);
2784 return -1;
2785 }
2786
2787 /* bypass virtual storage, so hard linking can be used whenever
2788 possible */
2789 if (mail_get_backend_mail(mail, &backend_mail) < 0) {
2790 mailbox_save_cancel(&ctx);
2791 return -1;
2792 }
2793
2794 i_assert(!ctx->copying_or_moving);
2795 i_assert(ctx->copy_src_mail == NULL);
2796 ctx->copying_or_moving = TRUE;
2797 ctx->copy_src_mail = mail;
2798 ctx->finishing = TRUE;
2799 T_BEGIN {
2800 ret = t->box->v.copy(ctx, backend_mail);
2801 } T_END;
2802 ctx->finishing = FALSE;
2803 if (ret == 0) {
2804 if (pvt_flags != 0)
2805 mailbox_save_add_pvt_flags(t, pvt_flags);
2806 t->save_count++;
2807 }
2808 i_assert(!ctx->unfinished);
2809
2810 ctx->copy_src_mail = NULL;
2811 ctx->copying_via_save = FALSE;
2812 ctx->copying_or_moving = FALSE;
2813 ctx->saving = FALSE; /* if we came from mailbox_save_using_mail() */
2814 return ret;
2815 }
2816
mailbox_copy(struct mail_save_context ** _ctx,struct mail * mail)2817 int mailbox_copy(struct mail_save_context **_ctx, struct mail *mail)
2818 {
2819 struct mail_save_context *ctx = *_ctx;
2820
2821 i_assert(!ctx->saving);
2822 i_assert(!ctx->moving);
2823
2824 int ret;
2825 T_BEGIN {
2826 ret = mailbox_copy_int(_ctx, mail);
2827 } T_END;
2828
2829 return ret;
2830 }
2831
mailbox_move(struct mail_save_context ** _ctx,struct mail * mail)2832 int mailbox_move(struct mail_save_context **_ctx, struct mail *mail)
2833 {
2834 struct mail_save_context *ctx = *_ctx;
2835 int ret;
2836
2837 i_assert(!ctx->saving);
2838 i_assert(!ctx->moving);
2839
2840 ctx->moving = TRUE;
2841 T_BEGIN {
2842 if ((ret = mailbox_copy_int(_ctx, mail)) == 0)
2843 mail_expunge(mail);
2844 } T_END;
2845 ctx->moving = FALSE;
2846 return ret;
2847 }
2848
mailbox_save_using_mail(struct mail_save_context ** _ctx,struct mail * mail)2849 int mailbox_save_using_mail(struct mail_save_context **_ctx, struct mail *mail)
2850 {
2851 struct mail_save_context *ctx = *_ctx;
2852
2853 i_assert(!ctx->saving);
2854 i_assert(!ctx->moving);
2855
2856 ctx->saving = TRUE;
2857 return mailbox_copy_int(_ctx, mail);
2858 }
2859
mailbox_is_inconsistent(struct mailbox * box)2860 bool mailbox_is_inconsistent(struct mailbox *box)
2861 {
2862 return box->mailbox_deleted || box->v.is_inconsistent(box);
2863 }
2864
mailbox_set_deleted(struct mailbox * box)2865 void mailbox_set_deleted(struct mailbox *box)
2866 {
2867 mail_storage_set_error(box->storage, MAIL_ERROR_NOTFOUND,
2868 "Mailbox was deleted under us");
2869 box->mailbox_deleted = TRUE;
2870 }
2871
get_path_to(struct mailbox * box,enum mailbox_list_path_type type,const char ** internal_path,const char ** path_r)2872 static int get_path_to(struct mailbox *box, enum mailbox_list_path_type type,
2873 const char **internal_path, const char **path_r)
2874 {
2875 int ret;
2876
2877 if (internal_path != NULL && *internal_path != NULL) {
2878 if ((*internal_path)[0] == '\0') {
2879 *path_r = NULL;
2880 return 0;
2881 }
2882 *path_r = *internal_path;
2883 return 1;
2884 }
2885 ret = mailbox_list_get_path(box->list, box->name, type, path_r);
2886 if (ret < 0) {
2887 mail_storage_copy_list_error(box->storage, box->list);
2888 return -1;
2889 }
2890 if (internal_path != NULL && *internal_path == NULL)
2891 *internal_path = ret == 0 ? "" : p_strdup(box->pool, *path_r);
2892 return ret;
2893 }
2894
mailbox_get_path_to(struct mailbox * box,enum mailbox_list_path_type type,const char ** path_r)2895 int mailbox_get_path_to(struct mailbox *box, enum mailbox_list_path_type type,
2896 const char **path_r)
2897 {
2898 if (type == MAILBOX_LIST_PATH_TYPE_MAILBOX)
2899 return get_path_to(box, type, &box->_path, path_r);
2900 if (type == MAILBOX_LIST_PATH_TYPE_INDEX)
2901 return get_path_to(box, type, &box->_index_path, path_r);
2902 return get_path_to(box, type, NULL, path_r);
2903 }
2904
mailbox_get_path(struct mailbox * box)2905 const char *mailbox_get_path(struct mailbox *box)
2906 {
2907 i_assert(box->_path != NULL);
2908 i_assert(box->_path[0] != '\0');
2909 return box->_path;
2910 }
2911
mailbox_get_index_path(struct mailbox * box)2912 const char *mailbox_get_index_path(struct mailbox *box)
2913 {
2914 i_assert(box->_index_path != NULL);
2915 i_assert(box->_index_path[0] != '\0');
2916 return box->_index_path;
2917 }
2918
mailbox_get_permissions_if_not_set(struct mailbox * box)2919 static void mailbox_get_permissions_if_not_set(struct mailbox *box)
2920 {
2921 if (box->_perm.file_create_mode != 0)
2922 return;
2923
2924 if (box->input != NULL) {
2925 box->_perm.file_uid = geteuid();
2926 box->_perm.file_create_mode = 0600;
2927 box->_perm.dir_create_mode = 0700;
2928 box->_perm.file_create_gid = (gid_t)-1;
2929 box->_perm.file_create_gid_origin = "defaults";
2930 return;
2931 }
2932
2933 struct mailbox_permissions perm;
2934 mailbox_list_get_permissions(box->list, box->name, &perm);
2935 mailbox_permissions_copy(&box->_perm, &perm, box->pool);
2936 }
2937
mailbox_get_permissions(struct mailbox * box)2938 const struct mailbox_permissions *mailbox_get_permissions(struct mailbox *box)
2939 {
2940 mailbox_get_permissions_if_not_set(box);
2941
2942 if (!box->_perm.mail_index_permissions_set && box->index != NULL) {
2943 box->_perm.mail_index_permissions_set = TRUE;
2944 mail_index_set_permissions(box->index,
2945 box->_perm.file_create_mode,
2946 box->_perm.file_create_gid,
2947 box->_perm.file_create_gid_origin);
2948 }
2949 return &box->_perm;
2950 }
2951
mailbox_refresh_permissions(struct mailbox * box)2952 void mailbox_refresh_permissions(struct mailbox *box)
2953 {
2954 i_zero(&box->_perm);
2955 (void)mailbox_get_permissions(box);
2956 }
2957
mailbox_create_fd(struct mailbox * box,const char * path,int flags,int * fd_r)2958 int mailbox_create_fd(struct mailbox *box, const char *path, int flags,
2959 int *fd_r)
2960 {
2961 const struct mailbox_permissions *perm = mailbox_get_permissions(box);
2962 mode_t old_mask;
2963 int fd;
2964
2965 i_assert((flags & O_CREAT) != 0);
2966
2967 *fd_r = -1;
2968
2969 old_mask = umask(0);
2970 fd = open(path, flags, perm->file_create_mode);
2971 umask(old_mask);
2972
2973 if (fd != -1) {
2974 /* ok */
2975 } else if (errno == EEXIST) {
2976 /* O_EXCL used, caller will handle this error */
2977 return 0;
2978 } else if (errno == ENOENT) {
2979 mailbox_set_deleted(box);
2980 return -1;
2981 } else if (errno == ENOTDIR) {
2982 mail_storage_set_error(box->storage, MAIL_ERROR_NOTPOSSIBLE,
2983 "Mailbox doesn't allow inferior mailboxes");
2984 return -1;
2985 } else if (mail_storage_set_error_from_errno(box->storage)) {
2986 return -1;
2987 } else {
2988 mailbox_set_critical(box, "open(%s, O_CREAT) failed: %m", path);
2989 return -1;
2990 }
2991
2992 if (perm->file_create_gid != (gid_t)-1) {
2993 if (fchown(fd, (uid_t)-1, perm->file_create_gid) == 0) {
2994 /* ok */
2995 } else if (errno == EPERM) {
2996 mailbox_set_critical(box, "%s",
2997 eperm_error_get_chgrp("fchown", path,
2998 perm->file_create_gid,
2999 perm->file_create_gid_origin));
3000 } else {
3001 mailbox_set_critical(box,
3002 "fchown(%s) failed: %m", path);
3003 }
3004 }
3005 *fd_r = fd;
3006 return 1;
3007 }
3008
mailbox_mkdir(struct mailbox * box,const char * path,enum mailbox_list_path_type type)3009 int mailbox_mkdir(struct mailbox *box, const char *path,
3010 enum mailbox_list_path_type type)
3011 {
3012 const struct mailbox_permissions *perm = mailbox_get_permissions(box);
3013 const char *root_dir;
3014
3015 if (!perm->gid_origin_is_mailbox_path) {
3016 /* mailbox root directory doesn't exist, create it */
3017 root_dir = mailbox_list_get_root_forced(box->list, type);
3018 if (mailbox_list_mkdir_root(box->list, root_dir, type) < 0) {
3019 mail_storage_copy_list_error(box->storage, box->list);
3020 return -1;
3021 }
3022 }
3023
3024 if (mkdir_parents_chgrp(path, perm->dir_create_mode,
3025 perm->file_create_gid,
3026 perm->file_create_gid_origin) == 0)
3027 return 1;
3028 else if (errno == EEXIST)
3029 return 0;
3030 else if (errno == ENOTDIR) {
3031 mail_storage_set_error(box->storage, MAIL_ERROR_NOTPOSSIBLE,
3032 "Mailbox doesn't allow inferior mailboxes");
3033 return -1;
3034 } else if (mail_storage_set_error_from_errno(box->storage)) {
3035 return -1;
3036 } else {
3037 mailbox_set_critical(box, "mkdir_parents(%s) failed: %m", path);
3038 return -1;
3039 }
3040 }
3041
mailbox_create_missing_dir(struct mailbox * box,enum mailbox_list_path_type type)3042 int mailbox_create_missing_dir(struct mailbox *box,
3043 enum mailbox_list_path_type type)
3044 {
3045 const char *mail_dir, *dir;
3046 struct stat st;
3047 int ret;
3048
3049 if ((ret = mailbox_get_path_to(box, type, &dir)) <= 0)
3050 return ret;
3051 if (mailbox_get_path_to(box, MAILBOX_LIST_PATH_TYPE_MAILBOX,
3052 &mail_dir) < 0)
3053 return -1;
3054 if (null_strcmp(dir, mail_dir) != 0) {
3055 /* Mailbox directory is different - create a missing dir */
3056 } else if ((box->list->props & MAILBOX_LIST_PROP_AUTOCREATE_DIRS) != 0) {
3057 /* This layout (e.g. imapc) wants to autocreate missing mailbox
3058 directories as well. */
3059 } else {
3060 /* If the mailbox directory doesn't exist, the mailbox
3061 shouldn't exist at all. So just assume that it's already
3062 created and if there's a race condition just fail later. */
3063 return 0;
3064 }
3065
3066 /* we call this function even when the directory exists, so first do a
3067 quick check to see if we need to mkdir anything */
3068 if (stat(dir, &st) == 0)
3069 return 0;
3070
3071 if ((box->storage->class_flags & MAIL_STORAGE_CLASS_FLAG_NO_ROOT) == 0 &&
3072 null_strcmp(dir, mail_dir) != 0 && mail_dir != NULL &&
3073 stat(mail_dir, &st) < 0 && (errno == ENOENT || errno == ENOTDIR)) {
3074 /* Race condition - mail root directory doesn't exist
3075 anymore either. We shouldn't create this directory
3076 anymore. */
3077 mailbox_set_deleted(box);
3078 return -1;
3079 }
3080
3081 return mailbox_mkdir(box, dir, type);
3082 }
3083
mail_storage_get_lock_timeout(struct mail_storage * storage,unsigned int secs)3084 unsigned int mail_storage_get_lock_timeout(struct mail_storage *storage,
3085 unsigned int secs)
3086 {
3087 return storage->set->mail_max_lock_timeout == 0 ? secs :
3088 I_MIN(secs, storage->set->mail_max_lock_timeout);
3089 }
3090
3091 enum mail_index_open_flags
mail_storage_settings_to_index_flags(const struct mail_storage_settings * set)3092 mail_storage_settings_to_index_flags(const struct mail_storage_settings *set)
3093 {
3094 enum mail_index_open_flags index_flags = 0;
3095
3096 #ifndef MMAP_CONFLICTS_WRITE
3097 if (set->mmap_disable)
3098 #endif
3099 index_flags |= MAIL_INDEX_OPEN_FLAG_MMAP_DISABLE;
3100 if (set->dotlock_use_excl)
3101 index_flags |= MAIL_INDEX_OPEN_FLAG_DOTLOCK_USE_EXCL;
3102 if (set->mail_nfs_index)
3103 index_flags |= MAIL_INDEX_OPEN_FLAG_NFS_FLUSH;
3104 return index_flags;
3105 }
3106
mail_parse_human_timestamp(const char * str,time_t * timestamp_r,bool * utc_r)3107 int mail_parse_human_timestamp(const char *str, time_t *timestamp_r,
3108 bool *utc_r)
3109 {
3110 struct tm tm;
3111 unsigned int secs;
3112 const char *error;
3113
3114 if (i_isdigit(str[0]) && i_isdigit(str[1]) &&
3115 i_isdigit(str[2]) && i_isdigit(str[3]) && str[4] == '-' &&
3116 i_isdigit(str[5]) && i_isdigit(str[6]) && str[7] == '-' &&
3117 i_isdigit(str[8]) && i_isdigit(str[9]) && str[10] == '\0') {
3118 /* yyyy-mm-dd */
3119 i_zero(&tm);
3120 tm.tm_year = (str[0]-'0') * 1000 + (str[1]-'0') * 100 +
3121 (str[2]-'0') * 10 + (str[3]-'0') - 1900;
3122 tm.tm_mon = (str[5]-'0') * 10 + (str[6]-'0') - 1;
3123 tm.tm_mday = (str[8]-'0') * 10 + (str[9]-'0');
3124 *timestamp_r = mktime(&tm);
3125 *utc_r = FALSE;
3126 return 0;
3127 } else if (imap_parse_date(str, timestamp_r)) {
3128 /* imap date */
3129 *utc_r = FALSE;
3130 return 0;
3131 } else if (str_to_time(str, timestamp_r) == 0) {
3132 /* unix timestamp */
3133 *utc_r = TRUE;
3134 return 0;
3135 } else if (settings_get_time(str, &secs, &error) == 0) {
3136 *timestamp_r = ioloop_time - secs;
3137 *utc_r = TRUE;
3138 return 0;
3139 } else {
3140 return -1;
3141 }
3142 }
3143
mail_set_mail_cache_corrupted(struct mail * mail,const char * fmt,...)3144 void mail_set_mail_cache_corrupted(struct mail *mail, const char *fmt, ...)
3145 {
3146 struct mail_cache_view *cache_view =
3147 mail->transaction->cache_view;
3148
3149 i_assert(cache_view != NULL);
3150
3151 va_list va;
3152 va_start(va, fmt);
3153
3154 T_BEGIN {
3155 mail_cache_set_seq_corrupted_reason(cache_view, mail->seq,
3156 t_strdup_printf("UID %u: %s",
3157 mail->uid,
3158 t_strdup_vprintf(fmt, va)));
3159 } T_END;
3160
3161 /* update also the storage's internal error */
3162 mailbox_set_index_error(mail->box);
3163
3164 va_end(va);
3165 }
3166
3167 static int
mail_storage_dotlock_create(const char * lock_path,const struct file_create_settings * lock_set,const struct mail_storage_settings * mail_set,struct file_lock ** lock_r,const char ** error_r)3168 mail_storage_dotlock_create(const char *lock_path,
3169 const struct file_create_settings *lock_set,
3170 const struct mail_storage_settings *mail_set,
3171 struct file_lock **lock_r, const char **error_r)
3172 {
3173 const struct dotlock_settings dotlock_set = {
3174 .timeout = lock_set->lock_timeout_secs,
3175 .stale_timeout = I_MAX(60*5, lock_set->lock_timeout_secs),
3176 .lock_suffix = "",
3177
3178 .use_excl_lock = mail_set->dotlock_use_excl,
3179 .nfs_flush = mail_set->mail_nfs_storage,
3180 .use_io_notify = TRUE,
3181 };
3182 struct dotlock *dotlock;
3183 int ret = file_dotlock_create(&dotlock_set, lock_path, 0, &dotlock);
3184 if (ret <= 0) {
3185 *error_r = t_strdup_printf("file_dotlock_create(%s) failed: %m",
3186 lock_path);
3187 return ret;
3188 }
3189 *lock_r = file_lock_from_dotlock(&dotlock);
3190 return 1;
3191 }
3192
mail_storage_lock_create(const char * lock_path,const struct file_create_settings * lock_set,const struct mail_storage_settings * mail_set,struct file_lock ** lock_r,const char ** error_r)3193 int mail_storage_lock_create(const char *lock_path,
3194 const struct file_create_settings *lock_set,
3195 const struct mail_storage_settings *mail_set,
3196 struct file_lock **lock_r, const char **error_r)
3197 {
3198 struct file_create_settings lock_set_new = *lock_set;
3199 bool created;
3200
3201 if (lock_set->lock_settings.lock_method == FILE_LOCK_METHOD_DOTLOCK)
3202 return mail_storage_dotlock_create(lock_path, lock_set, mail_set, lock_r, error_r);
3203
3204 lock_set_new.lock_settings.close_on_free = TRUE;
3205 lock_set_new.lock_settings.unlink_on_free = TRUE;
3206 if (file_create_locked(lock_path, &lock_set_new, lock_r,
3207 &created, error_r) == -1) {
3208 *error_r = t_strdup_printf("file_create_locked(%s) failed: %s",
3209 lock_path, *error_r);
3210 return errno == EAGAIN ? 0 : -1;
3211 }
3212 return 1;
3213 }
3214
mailbox_lock_file_create(struct mailbox * box,const char * lock_fname,unsigned int lock_secs,struct file_lock ** lock_r,const char ** error_r)3215 int mailbox_lock_file_create(struct mailbox *box, const char *lock_fname,
3216 unsigned int lock_secs, struct file_lock **lock_r,
3217 const char **error_r)
3218 {
3219 const struct mailbox_permissions *perm;
3220 struct file_create_settings set;
3221 const char *lock_path;
3222
3223 perm = mailbox_get_permissions(box);
3224 i_zero(&set);
3225 set.lock_timeout_secs =
3226 mail_storage_get_lock_timeout(box->storage, lock_secs);
3227 set.lock_settings.lock_method = box->storage->set->parsed_lock_method;
3228 set.mode = perm->file_create_mode;
3229 set.gid = perm->file_create_gid;
3230 set.gid_origin = perm->file_create_gid_origin;
3231
3232 if (box->list->set.volatile_dir == NULL)
3233 lock_path = t_strdup_printf("%s/%s", box->index->dir, lock_fname);
3234 else {
3235 unsigned char box_name_sha1[SHA1_RESULTLEN];
3236 string_t *str = t_str_new(128);
3237
3238 /* Keep this simple: Use the lock_fname with a SHA1 of the
3239 mailbox name as the suffix. The mailbox name itself could
3240 be too large as a filename and creating the full directory
3241 structure would be pretty troublesome. It would also make
3242 it more difficult to perform the automated deletion of empty
3243 lock directories. */
3244 str_printfa(str, "%s/%s.", box->list->set.volatile_dir,
3245 lock_fname);
3246 sha1_get_digest(box->name, strlen(box->name), box_name_sha1);
3247 binary_to_hex_append(str, box_name_sha1, sizeof(box_name_sha1));
3248 lock_path = str_c(str);
3249 set.mkdir_mode = 0700;
3250 }
3251
3252 return mail_storage_lock_create(lock_path, &set,
3253 box->storage->set, lock_r, error_r);
3254 }
3255
mailbox_sync_notify(struct mailbox * box,uint32_t uid,enum mailbox_sync_type sync_type)3256 void mailbox_sync_notify(struct mailbox *box, uint32_t uid,
3257 enum mailbox_sync_type sync_type)
3258 {
3259 if (box->v.sync_notify != NULL)
3260 box->v.sync_notify(box, uid, sync_type);
3261
3262 /* Send an event for expunged mail. */
3263 if (sync_type == MAILBOX_SYNC_TYPE_EXPUNGE) {
3264 e_debug(event_create_passthrough(box->event)->
3265 set_name("mail_expunged")->
3266 add_int("uid", uid)->event(),
3267 "UID %u: Mail expunged", uid);
3268 }
3269 }
3270