60
61
/* put the temp files into tmp/ directory preferrably */
61
62
storage->temp_prefix = p_strconcat(_storage->pool, "tmp/",
62
63
storage->temp_prefix, NULL);
63
dir = mailbox_list_get_path(list, NULL,
64
MAILBOX_LIST_PATH_TYPE_DIR);
64
dir = mailbox_list_get_root_forced(list, MAILBOX_LIST_PATH_TYPE_DIR);
66
66
/* control dir should also be writable */
67
dir = mailbox_list_get_path(list, NULL,
68
MAILBOX_LIST_PATH_TYPE_CONTROL);
67
dir = mailbox_list_get_root_forced(list, MAILBOX_LIST_PATH_TYPE_CONTROL);
70
69
_storage->temp_path_prefix = p_strconcat(_storage->pool, dir, "/",
71
70
storage->temp_prefix, NULL);
98
97
/* we'll need to figure out the maildir location ourself.
99
98
It's ~/Maildir unless we are chrooted. */
100
if (mail_user_get_home(ns->owner, &home) > 0) {
99
if (ns->owner != NULL &&
100
mail_user_get_home(ns->owner, &home) > 0) {
101
101
path = t_strconcat(home, "/Maildir", NULL);
102
102
if (access(path, R_OK|W_OK|X_OK) == 0) {
168
167
if (errno != ENOENT) {
169
mail_storage_set_critical(storage,
168
mail_storage_set_critical(box->storage,
170
169
"stat(%s) failed: %m", dir);
175
if (mkdir_parents_chgrp(dir, mode, gid, gid_origin) == 0)
174
perm = mailbox_get_permissions(box);
175
if (mkdir_parents_chgrp(dir, perm->dir_create_mode,
176
perm->file_create_gid,
177
perm->file_create_gid_origin) == 0)
178
180
if (errno == EEXIST) {
181
mail_storage_set_error(storage, MAIL_ERROR_EXISTS,
183
mail_storage_set_error(box->storage, MAIL_ERROR_EXISTS,
182
184
"Mailbox already exists");
183
185
} else if (errno == ENOENT) {
184
mail_storage_set_error(storage, MAIL_ERROR_NOTFOUND,
186
mail_storage_set_error(box->storage, MAIL_ERROR_NOTFOUND,
185
187
"Mailbox was deleted while it was being created");
186
188
} else if (errno == EACCES) {
187
if (ns->type == NAMESPACE_SHARED) {
189
if (box->list->ns->type == MAIL_NAMESPACE_TYPE_SHARED) {
188
190
/* shared namespace, don't log permission errors */
189
mail_storage_set_error(storage, MAIL_ERROR_PERM,
191
mail_storage_set_error(box->storage, MAIL_ERROR_PERM,
190
192
MAIL_ERRSTR_NO_PERMISSION);
193
mail_storage_set_critical(storage, "%s",
195
mail_storage_set_critical(box->storage, "%s",
194
196
mail_error_create_eacces_msg("mkdir", dir));
196
mail_storage_set_critical(storage,
198
mail_storage_set_critical(box->storage,
197
199
"mkdir(%s) failed: %m", dir);
235
237
/* create or fix maildir, ignore if it already exists */
236
static int create_maildir(struct mailbox *box, bool verify)
238
static int create_maildir_subdirs(struct mailbox *box, bool verify)
238
const struct mailbox_permissions *perm = mailbox_get_permissions(box);
240
const char *path, *box_path;
241
242
enum mail_error error;
245
if (mailbox_get_path_to(box, MAILBOX_LIST_PATH_TYPE_MAILBOX,
244
249
for (i = 0; i < N_ELEMENTS(maildir_subdirs); i++) {
245
path = t_strconcat(mailbox_get_path(box), "/",
246
maildir_subdirs[i], NULL);
247
if (mkdir_verify(box->storage, box->list->ns, path,
248
perm->dir_create_mode, perm->file_create_gid,
249
perm->file_create_gid_origin, verify) < 0) {
250
path = t_strconcat(box_path, "/", maildir_subdirs[i], NULL);
251
if (mkdir_verify(box, path, verify) < 0) {
250
252
error = mailbox_get_last_mail_error(box);
251
253
if (error != MAIL_ERROR_EXISTS)
353
/* tmp/ directory doesn't exist. does the maildir? */
354
root_dir = mailbox_list_get_path(box->list, NULL,
355
MAILBOX_LIST_PATH_TYPE_MAILBOX);
354
/* tmp/ directory doesn't exist. does the maildir? autocreate missing
355
dirs only with Maildir++ and imapdir layouts. */
356
if (strcmp(box->list->name, MAILBOX_LIST_NAME_MAILDIRPLUSPLUS) != 0 &&
357
strcmp(box->list->name, MAILBOX_LIST_NAME_IMAPDIR) != 0) {
358
mail_storage_set_error(box->storage, MAIL_ERROR_NOTFOUND,
359
T_MAIL_ERR_MAILBOX_NOT_FOUND(box->vname));
362
root_dir = mailbox_list_get_root_forced(box->list,
363
MAILBOX_LIST_PATH_TYPE_MAILBOX);
356
364
if (strcmp(box_path, root_dir) == 0) {
357
365
/* root directory. either INBOX or some other namespace root */
359
367
} else if (stat(box_path, &st) == 0) {
360
368
/* yes, we'll need to create the missing dirs */
361
if (create_maildir(box, TRUE) < 0)
369
if (create_maildir_subdirs(box, TRUE) < 0)
364
372
return maildir_mailbox_open_existing(box);
380
388
const struct mailbox_permissions *perm = mailbox_get_permissions(box);
381
389
const char *path;
393
ret = mailbox_get_path_to(box, MAILBOX_LIST_PATH_TYPE_MAILBOX,
385
399
old_mask = umask(0);
386
path = t_strconcat(mailbox_get_path(box), "/dovecot-shared", NULL);
400
path = t_strconcat(path, "/dovecot-shared", NULL);
387
401
fd = open(path, O_WRONLY | O_CREAT, perm->file_create_mode);
422
437
uidlist = mbox->uidlist;
424
if (maildir_uidlist_lock(uidlist) <= 0)
439
if (update->uid_validity != 0 || update->min_next_uid != 0 ||
440
!guid_128_is_empty(update->mailbox_guid)) {
441
if (maildir_uidlist_lock(uidlist) <= 0)
427
if (!guid_128_is_empty(update->mailbox_guid))
428
maildir_uidlist_set_mailbox_guid(uidlist, update->mailbox_guid);
429
if (update->uid_validity != 0)
430
maildir_uidlist_set_uid_validity(uidlist, update->uid_validity);
431
if (update->min_next_uid != 0) {
432
maildir_uidlist_set_next_uid(uidlist, update->min_next_uid,
445
if (!guid_128_is_empty(update->mailbox_guid))
446
maildir_uidlist_set_mailbox_guid(uidlist, update->mailbox_guid);
447
if (update->uid_validity != 0)
448
maildir_uidlist_set_uid_validity(uidlist, update->uid_validity);
449
if (update->min_next_uid != 0) {
450
maildir_uidlist_set_next_uid(uidlist, update->min_next_uid,
453
ret = maildir_uidlist_update(uidlist);
435
ret = maildir_uidlist_update(uidlist);
437
456
ret = index_storage_mailbox_update(box, update);
438
maildir_uidlist_unlock(uidlist);
458
maildir_uidlist_unlock(uidlist);
462
static int maildir_create_maildirfolder_file(struct mailbox *box)
464
const struct mailbox_permissions *perm;
469
/* Maildir++ spec wants that maildirfolder named file is created for
470
all subfolders. Do this only with Maildir++ layout. */
471
if (strcmp(box->list->name, MAILBOX_LIST_NAME_MAILDIRPLUSPLUS) != 0)
473
perm = mailbox_get_permissions(box);
475
path = t_strconcat(mailbox_get_path(box),
476
"/"MAILDIR_SUBFOLDER_FILENAME, NULL);
478
fd = open(path, O_CREAT | O_WRONLY, perm->file_create_mode);
482
} else if (errno == ENOENT) {
483
mail_storage_set_error(box->storage, MAIL_ERROR_NOTFOUND,
484
"Mailbox was deleted while it was being created");
487
mail_storage_set_critical(box->storage,
488
"open(%s, O_CREAT) failed: %m", path);
492
if (perm->file_create_gid != (gid_t)-1) {
493
if (fchown(fd, (uid_t)-1, perm->file_create_gid) == 0) {
495
} else if (errno == EPERM) {
496
mail_storage_set_critical(box->storage, "%s",
497
eperm_error_get_chgrp("fchown", path,
498
perm->file_create_gid,
499
perm->file_create_gid_origin));
501
mail_storage_set_critical(box->storage,
502
"fchown(%s) failed: %m", path);
443
510
maildir_mailbox_create(struct mailbox *box, const struct mailbox_update *update,
451
(box->list->props & MAILBOX_LIST_PROP_NO_NOSELECT) == 0)
454
ret = maildir_check_tmp(box->storage, mailbox_get_path(box));
456
mail_storage_set_error(box->storage, MAIL_ERROR_EXISTS,
457
"Mailbox already exists");
463
if (create_maildir(box, FALSE) < 0)
517
if ((ret = index_storage_mailbox_create(box, directory)) <= 0)
520
/* the maildir is created now. finish the creation as best as we can */
521
if (create_maildir_subdirs(box, FALSE) < 0)
523
if (maildir_create_maildirfolder_file(box) < 0)
466
525
/* if dovecot-shared exists in the root dir, copy it to newly
467
526
created mailboxes */
468
root_dir = mailbox_list_get_path(box->list, NULL,
469
MAILBOX_LIST_PATH_TYPE_MAILBOX);
527
root_dir = mailbox_list_get_root_forced(box->list,
528
MAILBOX_LIST_PATH_TYPE_MAILBOX);
470
529
shared_path = t_strconcat(root_dir, "/dovecot-shared", NULL);
471
530
if (stat(shared_path, &st) == 0) {
472
531
if (maildir_create_shared(box) < 0)
476
return update == NULL ? 0 : maildir_mailbox_update(box, update);
534
if (update != NULL) {
535
if (maildir_mailbox_update(box, update) < 0)
568
629
return mbox->_private_flags_mask;
569
630
mbox->private_flags_mask_set = TRUE;
571
path = mailbox_list_get_path(box->list, NULL,
572
MAILBOX_LIST_PATH_TYPE_MAILBOX);
573
path2 = mailbox_list_get_path(box->list, NULL,
574
MAILBOX_LIST_PATH_TYPE_INDEX);
575
if (strcmp(path, path2) == 0) {
632
path = mailbox_list_get_root_forced(box->list, MAILBOX_LIST_PATH_TYPE_MAILBOX);
633
if (box->list->set.index_pvt_dir != NULL) {
634
/* private index directory is set. we'll definitely have
636
mbox->_private_flags_mask = MAIL_SEEN;
637
} else if (!mailbox_list_get_root_path(box->list,
638
MAILBOX_LIST_PATH_TYPE_INDEX,
640
strcmp(path, path2) == 0) {
576
641
/* no separate index directory. we can't have private flags,
577
642
so don't even bother checking if dovecot-shared exists */
600
665
struct mail_storage maildir_storage = {
601
666
.name = MAILDIR_STORAGE_NAME,
602
.class_flags = MAIL_STORAGE_CLASS_FLAG_FILE_PER_MSG,
667
.class_flags = MAIL_STORAGE_CLASS_FLAG_FILE_PER_MSG |
668
MAIL_STORAGE_CLASS_FLAG_HAVE_MAIL_GUIDS |
669
MAIL_STORAGE_CLASS_FLAG_HAVE_MAIL_SAVE_GUIDS |
670
MAIL_STORAGE_CLASS_FLAG_BINARY_DATA,
605
673
maildir_get_setting_parser_info,
606
674
maildir_storage_alloc,
607
675
maildir_storage_create,
676
index_storage_destroy,
609
677
maildir_storage_add_list,
610
678
maildir_storage_get_list_settings,
611
679
maildir_storage_autodetect,
629
697
index_storage_get_status,
630
698
maildir_mailbox_get_metadata,
631
699
index_storage_set_subscribed,
700
index_storage_attribute_set,
701
index_storage_attribute_get,
702
index_storage_attribute_iter_init,
703
index_storage_attribute_iter_next,
704
index_storage_attribute_iter_deinit,
632
705
maildir_list_index_has_changed,
633
706
maildir_list_index_update_sync,
634
707
maildir_storage_sync_init,