372
432
str_printfa(escaped_name, "%c%02x",
373
433
list->set.escape_char, *vname);
376
437
for (; *vname != '\0'; vname++) {
377
438
if (*vname == ns_sep)
378
str_append_c(escaped_name, *vname);
439
str_append_c(escaped_name, list_sep);
379
440
else if (*vname == list_sep ||
380
441
*vname == list->set.escape_char ||
444
need_escape_dirstart(vname, list->set.maildir_name))) {
382
445
str_printfa(escaped_name, "%c%02x",
383
446
list->set.escape_char, *vname);
385
448
str_append_c(escaped_name, *vname);
450
dirstart = *vname == '/';
388
452
return str_c(escaped_name);
456
mailbox_list_unescape_broken_chars(struct mailbox_list *list, char *name)
461
if ((src = strchr(name, list->set.broken_char)) == NULL)
465
while (*src != '\0') {
466
if (*src == list->set.broken_char) {
467
if (src[1] >= '0' && src[1] <= '9')
468
chr = (src[1]-'0') * 0x10;
469
else if (src[1] >= 'a' && src[1] <= 'f')
470
chr = (src[1]-'a' + 10) * 0x10;
474
if (src[2] >= '0' && src[2] <= '9')
476
else if (src[2] >= 'a' && src[2] <= 'f')
477
chr += src[2]-'a' + 10;
490
static char *mailbox_list_convert_sep(const char *storage_name, char src, char dest)
494
ret = p_strdup(unsafe_data_stack_pool, storage_name);
495
for (p = ret; *p != '\0'; p++) {
391
502
const char *mailbox_list_default_get_storage_name(struct mailbox_list *list,
392
503
const char *vname)
395
506
unsigned int prefix_len = strlen(ns->prefix);
396
507
const char *storage_name = vname;
398
char list_sep, ns_sep, *ret, *p;
509
char list_sep, ns_sep, *ret;
400
if (strcasecmp(storage_name, "INBOX") == 0)
511
if (strcasecmp(storage_name, "INBOX") == 0 &&
512
(ns->flags & NAMESPACE_FLAG_INBOX_USER) != 0)
401
513
storage_name = "INBOX";
402
514
else if (list->set.escape_char != '\0')
403
515
storage_name = mailbox_list_escape_name(list, vname);
405
if (prefix_len > 0 && strcmp(storage_name, "INBOX") != 0) {
517
if (prefix_len > 0 && (strcmp(storage_name, "INBOX") != 0 ||
518
(ns->flags & NAMESPACE_FLAG_INBOX_USER) == 0)) {
406
519
/* skip namespace prefix, except if this is INBOX */
407
520
if (strncmp(ns->prefix, storage_name, prefix_len) == 0)
408
521
storage_name += prefix_len;
409
522
else if (strncmp(ns->prefix, storage_name, prefix_len-1) == 0 &&
523
strlen(storage_name) == prefix_len-1 &&
410
524
ns->prefix[prefix_len-1] == mail_namespace_get_sep(ns)) {
411
525
/* trying to access the namespace prefix itself */
412
526
storage_name = "";
427
541
list_sep = mailbox_list_get_hierarchy_sep(list);
428
542
ns_sep = mail_namespace_get_sep(ns);
430
if (*storage_name == '\0' && ns->type == NAMESPACE_SHARED &&
544
if (*storage_name == '\0' && ns->type == MAIL_NAMESPACE_TYPE_SHARED &&
431
545
(ns->flags & NAMESPACE_FLAG_INBOX_ANY) != 0 &&
432
546
!list->mail_set->mail_shared_explicit_inbox) {
433
547
/* opening shared/$user. it's the same as INBOX. */
434
548
storage_name = "INBOX";
437
if (list_sep == ns_sep)
439
if (ns->type == NAMESPACE_SHARED &&
440
(ns->flags & NAMESPACE_FLAG_AUTOCREATED) == 0) {
441
/* shared namespace root. the backend storage's hierarchy
442
separator isn't known yet, so do nothing. */
551
if (list_sep != ns_sep && list->set.escape_char == '\0') {
552
if (ns->type == MAIL_NAMESPACE_TYPE_SHARED &&
553
(ns->flags & NAMESPACE_FLAG_AUTOCREATED) == 0) {
554
/* shared namespace root. the backend storage's
555
hierarchy separator isn't known yet, so do
560
ret = mailbox_list_convert_sep(storage_name, ns_sep, list_sep);
561
} else if (list->set.broken_char == '\0' ||
562
strchr(storage_name, list->set.broken_char) == NULL) {
563
/* no need to convert broken chars */
566
ret = p_strdup(unsafe_data_stack_pool, storage_name);
446
ret = p_strdup(unsafe_data_stack_pool, storage_name);
447
for (p = ret; *p != '\0'; p++) {
569
if (list->set.broken_char != '\0') {
570
if (mailbox_list_unescape_broken_chars(list, ret) < 0) {
571
ret = mailbox_list_convert_sep(storage_name,
606
781
return list->ns->user;
785
mailbox_list_get_storage_driver(struct mailbox_list *list, const char *driver,
786
struct mail_storage **storage_r)
788
struct mail_storage *const *storagep;
789
const char *error, *data;
791
array_foreach(&list->ns->all_storages, storagep) {
792
if (strcmp((*storagep)->name, driver) == 0) {
793
*storage_r = *storagep;
798
data = strchr(list->ns->set->location, ':');
803
if (mail_storage_create_full(list->ns, driver, data, 0,
804
storage_r, &error) < 0) {
805
mailbox_list_set_critical(list,
806
"Namespace %s: Failed to create storage '%s': %s",
807
list->ns->prefix, driver, error);
609
813
int mailbox_list_get_storage(struct mailbox_list **list, const char *vname,
610
814
struct mail_storage **storage_r)
816
const struct mailbox_settings *set;
612
818
if ((*list)->v.get_storage != NULL)
613
819
return (*list)->v.get_storage(list, vname, storage_r);
615
*storage_r = (*list)->ns->storage;
821
set = mailbox_settings_find((*list)->ns->user, vname);
822
if (set != NULL && set->driver != NULL && set->driver[0] != '\0') {
823
return mailbox_list_get_storage_driver(*list, set->driver,
826
*storage_r = mail_namespace_get_default_storage((*list)->ns);
620
void mailbox_list_get_closest_storage(struct mailbox_list *list,
830
void mailbox_list_get_default_storage(struct mailbox_list *list,
621
831
struct mail_storage **storage)
623
*storage = list->ns->storage;
833
*storage = mail_namespace_get_default_storage(list->ns);
626
836
char mailbox_list_get_hierarchy_sep(struct mailbox_list *list)
702
928
permissions_r->file_create_gid = st.st_gid;
930
if (!S_ISDIR(st.st_mode) &&
931
permissions_r->file_create_gid != (gid_t)-1) {
932
/* we need to stat() the parent directory to see if
933
it has setgid-bit set */
934
p = strrchr(path, '/');
935
parent_path = p == NULL ? NULL :
936
t_strdup_until(path, p);
937
if (parent_path != NULL &&
938
stat(parent_path, &st) == 0 &&
939
(st.st_mode & S_ISGID) != 0) {
940
/* directory's GID is used automatically for
942
permissions_r->file_create_gid = (gid_t)-1;
706
947
if (name == NULL) {
707
list->file_create_mode = permissions_r->file_create_mode;
708
list->dir_create_mode = permissions_r->dir_create_mode;
709
list->file_create_gid = permissions_r->file_create_gid;
710
list->file_create_gid_origin =
948
list->root_permissions = *permissions_r;
949
list->root_permissions.file_create_gid_origin =
711
950
p_strdup(list->pool,
712
951
permissions_r->file_create_gid_origin);
715
954
if (list->mail_set->mail_debug && name == NULL) {
716
955
i_debug("Namespace %s: Using permissions from %s: "
717
"mode=0%o gid=%ld", list->ns->prefix,
956
"mode=0%o gid=%s", list->ns->prefix,
718
957
path != NULL ? path : "",
719
(int)list->dir_create_mode,
720
list->file_create_gid == (gid_t)-1 ? -1L :
721
(long)list->file_create_gid);
958
(int)permissions_r->dir_create_mode,
959
permissions_r->file_create_gid == (gid_t)-1 ? "default" :
960
dec2str(permissions_r->file_create_gid));
964
void mailbox_list_get_permissions(struct mailbox_list *list, const char *name,
965
struct mailbox_permissions *permissions_r)
967
mailbox_list_get_permissions_internal(list, name, permissions_r);
725
970
void mailbox_list_get_root_permissions(struct mailbox_list *list,
726
mode_t *file_mode_r, mode_t *dir_mode_r,
727
gid_t *gid_r, const char **gid_origin_r)
729
struct mailbox_permissions perm;
731
if (list->file_create_mode != (mode_t)-1) {
732
*file_mode_r = list->file_create_mode;
733
*dir_mode_r = list->dir_create_mode;
734
*gid_r = list->file_create_gid;
735
*gid_origin_r = list->file_create_gid_origin;
737
mailbox_list_get_permissions(list, NULL, &perm);
739
*file_mode_r = perm.file_create_mode;
740
*dir_mode_r = perm.dir_create_mode;
741
*gid_r = perm.file_create_gid;
742
*gid_origin_r = perm.file_create_gid_origin;
747
mailbox_list_stat_parent(const char *path, const char **root_dir_r,
748
struct stat *st_r, const char **error_r)
752
while (stat(path, st_r) < 0) {
753
if (errno != ENOENT || strcmp(path, "/") == 0) {
754
*error_r = t_strdup_printf("stat(%s) failed: %m", path);
757
p = strrchr(path, '/');
761
path = t_strdup_until(path, p);
971
struct mailbox_permissions *permissions_r)
973
if (list->root_permissions.file_create_mode != (mode_t)-1)
974
*permissions_r = list->root_permissions;
976
mailbox_list_get_permissions_internal(list, NULL,
767
981
static const char *
809
int mailbox_list_mkdir_root(struct mailbox_list *list, const char *path,
810
enum mailbox_list_path_type type,
811
const char **error_r)
1024
mailbox_list_try_mkdir_root_parent(struct mailbox_list *list,
1025
enum mailbox_list_path_type type,
1026
struct mailbox_permissions *perm,
1027
const char **error_r)
813
const char *expanded, *unexpanded, *root_dir, *p, *origin, *error;
1029
const char *expanded, *unexpanded, *root_dir, *p;
815
mode_t file_mode, dir_mode;
818
if (stat(path, &st) == 0) {
819
/* looks like it already exists, don't bother checking
824
if (!mail_user_is_path_mounted(list->ns->user, path, &error)) {
825
*error_r = t_strdup_printf(
826
"Can't create mailbox root dir %s: %s", path, error);
830
mailbox_list_get_root_permissions(list, &file_mode, &dir_mode,
833
1033
/* get the directory path up to last %variable. for example
834
1034
unexpanded path may be "/var/mail/%d/%2n/%n/Maildir", and we want
835
1035
to get expanded="/var/mail/domain/nn" */
836
1036
unexpanded = mailbox_list_get_unexpanded_path(list, type);
837
1037
p = strrchr(unexpanded, '%');
1038
if ((p == unexpanded && p[1] == 'h') ||
1039
(p == NULL && unexpanded[0] == '~')) {
1040
/* home directory used */
1041
if (!mailbox_list_get_root_path(list, type, &expanded))
1044
} else if (p == NULL) {
841
1047
while (p != unexpanded && *p != '/') p--;
842
1048
if (p == unexpanded)
845
expanded = mailbox_list_get_path(list, NULL, type);
846
expanded = get_expanded_path(unexpanded, p, expanded);
850
if (*expanded != '\0') {
851
/* up to this directory get the permissions from the first
852
parent directory that exists, if it has setgid bit
854
if (mailbox_list_stat_parent(expanded, &root_dir, &st,
857
if ((st.st_mode & S_ISGID) != 0 && root_dir != expanded) {
1051
if (!mailbox_list_get_root_path(list, type, &expanded))
1053
expanded = get_expanded_path(unexpanded, p, expanded);
1054
if (*expanded == '\0')
1058
/* get the first existing parent directory's permissions */
1059
if (stat_first_parent(expanded, &root_dir, &st) < 0) {
1060
*error_r = errno == EACCES ?
1061
mail_error_eacces_msg("stat", root_dir) :
1062
t_strdup_printf("stat(%s) failed: %m", root_dir);
1066
/* if the parent directory doesn't have setgid-bit enabled, we don't
1067
copy any permissions from it. */
1068
if ((st.st_mode & S_ISGID) == 0)
1072
/* assuming we have e.g. /var/vmail/%d/%n directory, here we
1073
want to create up to /var/vmail/%d with permissions from
1074
the parent directory. we never want to create the %n
1075
directory itself. */
1076
if (root_dir == expanded) {
1077
/* this is the %n directory */
858
1079
if (mkdir_parents_chgrp(expanded, st.st_mode,
859
1080
(gid_t)-1, root_dir) < 0 &&
860
1081
errno != EEXIST) {
866
if (gid == (gid_t)-1 && (dir_mode & S_ISGID) == 0) {
1087
if (perm->file_create_gid == (gid_t)-1 &&
1088
(perm->dir_create_mode & S_ISGID) == 0) {
867
1089
/* change the group for user directories */
1090
perm->dir_create_mode |= S_ISGID;
1091
perm->file_create_gid = getegid();
1092
perm->file_create_gid_origin = "egid";
1093
perm->gid_origin_is_mailbox_path = FALSE;
1096
/* when using %h and the parent has setgid-bit,
1097
copy the permissions from it for the home we're creating */
1098
perm->file_create_mode = st.st_mode & 0666;
1099
perm->dir_create_mode = st.st_mode;
1100
perm->file_create_gid = (gid_t)-1;
1101
perm->file_create_gid_origin = "parent";
1102
perm->gid_origin_is_mailbox_path = FALSE;
1107
int mailbox_list_try_mkdir_root(struct mailbox_list *list, const char *path,
1108
enum mailbox_list_path_type type,
1109
const char **error_r)
1111
const char *root_dir, *error;
1113
struct mailbox_permissions perm;
1115
if (stat(path, &st) == 0) {
1116
/* looks like it already exists, don't bother checking
1121
mailbox_list_get_root_permissions(list, &perm);
1123
if (!mailbox_list_get_root_path(list, type, &root_dir))
1125
i_assert(strncmp(root_dir, path, strlen(root_dir)) == 0);
1126
if (strcmp(root_dir, path) != 0 && stat(root_dir, &st) == 0) {
1127
/* creating a subdirectory under an already existing root dir.
1128
use the root's permissions */
1129
} else if (mail_user_is_path_mounted(list->ns->user, path, &error)) {
1130
if (mailbox_list_try_mkdir_root_parent(list, type,
1131
&perm, error_r) < 0)
1134
*error_r = t_strdup_printf(
1135
"Can't create mailbox root dir %s: %s", path, error);
872
1139
/* the rest of the directories exist only for one user. create them
873
1140
with default directory permissions */
874
if (mkdir_parents_chgrp(path, dir_mode, gid, origin) < 0 &&
1141
if (mkdir_parents_chgrp(path, perm.dir_create_mode,
1142
perm.file_create_gid,
1143
perm.file_create_gid_origin) < 0 &&
875
1144
errno != EEXIST) {
876
1145
if (errno == EACCES)
877
1146
*error_r = mail_error_create_eacces_msg("mkdir", path);
885
bool mailbox_list_is_valid_pattern(struct mailbox_list *list,
1154
int mailbox_list_mkdir_root(struct mailbox_list *list, const char *path,
1155
enum mailbox_list_path_type type)
891
ret = list->v.is_valid_pattern(list, pattern);
1159
if (mailbox_list_try_mkdir_root(list, path, type, &error) < 0) {
1160
mailbox_list_set_critical(list, "%s", error);
1163
if (type == MAILBOX_LIST_PATH_TYPE_INDEX)
1164
list->index_root_dir_created = TRUE;
896
bool mailbox_list_is_valid_existing_name(struct mailbox_list *list,
1169
mailbox_list_is_valid_fs_name(struct mailbox_list *list, const char *name,
1170
const char **error_r)
901
if (*name == '\0' && *list->ns->prefix != '\0') {
902
/* an ugly way to get to mailbox root (e.g. Maildir/ when
903
it's not the INBOX) */
1172
bool ret, allow_internal_dirs;
1176
if (list->mail_set->mail_full_filesystem_access)
1179
/* make sure it's not absolute path */
1181
*error_r = "Begins with '/'";
1185
*error_r = "Begins with '~'";
1189
/* make sure the mailbox name doesn't contain any foolishness:
1190
"../" could give access outside the mailbox directory.
1191
"./" and "//" could fool ACL checks.
1193
some mailbox formats have reserved directory names, such as
1194
Maildir's cur/new/tmp. if any of those would conflict with the
1195
mailbox directory name, it's not valid. maildir++ is kludged here as
1196
a special case because all of its mailbox dirs begin with "." */
1197
allow_internal_dirs = list->v.is_internal_name == NULL ||
1198
*list->set.maildir_name != '\0' ||
1199
strcmp(list->name, MAILBOX_LIST_NAME_MAILDIRPLUSPLUS) == 0;
908
ret = list->v.is_valid_existing_name(list, name);
1201
const char *const *names;
1203
names = t_strsplit(name, "/");
1204
for (; *names != NULL; names++) {
1205
const char *n = *names;
1208
*error_r = "Has adjacent '/' chars";
1213
*error_r = "Contains '.' part";
1216
if (n[1] == '.' && n[2] == '\0') {
1217
*error_r = "Contains '..' part";
1221
if (*list->set.maildir_name != '\0' &&
1222
strcmp(list->set.maildir_name, n) == 0) {
1223
/* don't allow maildir_name to be used as part
1224
of the mailbox name */
1225
*error_r = "Contains reserved name";
1228
if (!allow_internal_dirs &&
1229
list->v.is_internal_name(list, n)) {
1230
*error_r = "Contains reserved name";
1234
ret = *names == NULL;
913
bool mailbox_list_is_valid_create_name(struct mailbox_list *list,
1241
bool mailbox_list_is_valid_name(struct mailbox_list *list,
1242
const char *name, const char **error_r)
919
/* safer to just disallow all control characters */
920
for (p = name; *p != '\0'; p++) {
921
if ((unsigned char)*p < ' ')
1244
if (*name == '\0') {
1245
if (*list->ns->prefix != '\0') {
1246
/* an ugly way to get to mailbox root (e.g. Maildir/
1247
when it's not the INBOX) */
1250
*error_r = "Name is empty";
926
ret = uni_utf8_str_is_valid(name) ? 0 : -1;
928
string_t *str = t_str_new(256);
929
ret = imap_utf7_to_utf8(name, str);
931
return ret < 0 ? FALSE :
932
list->v.is_valid_create_name(list, name);
935
const char *mailbox_list_get_path(struct mailbox_list *list, const char *name,
936
enum mailbox_list_path_type type)
938
return list->v.get_path(list, name, type);
942
mailbox_list_get_root_path(const struct mailbox_list_settings *set,
943
enum mailbox_list_path_type type)
1254
return mailbox_list_is_valid_fs_name(list, name, error_r);
1257
int mailbox_list_get_path(struct mailbox_list *list, const char *name,
1258
enum mailbox_list_path_type type,
1259
const char **path_r)
1263
if ((ret = list->v.get_path(list, name, type, path_r)) <= 0)
1266
i_assert(*path_r != NULL);
1270
bool mailbox_list_get_root_path(struct mailbox_list *list,
1271
enum mailbox_list_path_type type,
1272
const char **path_r)
1276
if ((ret = list->v.get_path(list, NULL, type, path_r)) < 0)
1281
i_assert(*path_r != NULL);
1285
const char *mailbox_list_get_root_forced(struct mailbox_list *list,
1286
enum mailbox_list_path_type type)
945
1288
const char *path;
1290
if (!mailbox_list_get_root_path(list, type, &path))
1295
bool mailbox_list_set_get_root_path(const struct mailbox_list_settings *set,
1296
enum mailbox_list_path_type type,
1297
const char **path_r)
1299
const char *path = NULL;
948
1302
case MAILBOX_LIST_PATH_TYPE_DIR:
949
return set->root_dir;
1303
path = set->root_dir;
950
1305
case MAILBOX_LIST_PATH_TYPE_ALT_DIR:
1306
path = set->alt_dir;
952
1308
case MAILBOX_LIST_PATH_TYPE_MAILBOX:
953
1309
if (*set->mailbox_dir_name == '\0')
954
return set->root_dir;
955
path = t_strconcat(set->root_dir, "/",
956
set->mailbox_dir_name, NULL);
957
return t_strndup(path, strlen(path)-1);
1310
path = set->root_dir;
1312
path = t_strconcat(set->root_dir, "/",
1313
set->mailbox_dir_name, NULL);
1314
path = t_strndup(path, strlen(path)-1);
958
1317
case MAILBOX_LIST_PATH_TYPE_ALT_MAILBOX:
959
1318
if (*set->mailbox_dir_name == '\0')
960
return set->root_dir;
961
path = t_strconcat(set->alt_dir, "/",
962
set->mailbox_dir_name, NULL);
963
return path == NULL ? NULL : t_strndup(path, strlen(path)-1);
1319
path = set->root_dir;
1320
else if (set->alt_dir != NULL) {
1321
path = t_strconcat(set->alt_dir, "/",
1322
set->mailbox_dir_name, NULL);
1323
path = t_strndup(path, strlen(path)-1);
964
1326
case MAILBOX_LIST_PATH_TYPE_CONTROL:
965
return set->control_dir != NULL ?
1327
path = set->control_dir != NULL ?
966
1328
set->control_dir : set->root_dir;
967
1330
case MAILBOX_LIST_PATH_TYPE_INDEX:
968
return set->index_dir != NULL ?
969
set->index_dir : set->root_dir;
1331
if (set->index_dir != NULL) {
1332
if (set->index_dir[0] == '\0') {
1333
/* in-memory indexes */
1336
path = set->index_dir;
1338
path = set->root_dir;
1341
case MAILBOX_LIST_PATH_TYPE_INDEX_PRIVATE:
1342
path = set->index_pvt_dir;
1346
return path != NULL;
974
1349
const char *mailbox_list_get_temp_prefix(struct mailbox_list *list)
1109
1485
static bool mailbox_list_init_changelog(struct mailbox_list *list)
1487
struct mailbox_permissions perm;
1111
1488
const char *path;
1112
mode_t file_mode, dir_mode;
1114
const char *gid_origin;
1116
1490
if (list->changelog != NULL)
1119
1493
/* don't do this in mailbox_list_create(), because _get_path() might be
1120
1494
overridden by storage (mbox). */
1121
path = mailbox_list_get_path(list, NULL, MAILBOX_LIST_PATH_TYPE_INDEX);
1495
if (!mailbox_list_get_root_path(list, MAILBOX_LIST_PATH_TYPE_INDEX, &path))
1125
1498
path = t_strconcat(path, "/"MAILBOX_LOG_FILE_NAME, NULL);
1126
1499
list->changelog = mailbox_log_alloc(path);
1128
mailbox_list_get_root_permissions(list, &file_mode, &dir_mode,
1130
mailbox_log_set_permissions(list->changelog, dir_mode, gid, gid_origin);
1501
mailbox_list_get_root_permissions(list, &perm);
1502
mailbox_log_set_permissions(list->changelog, perm.file_create_mode,
1503
perm.file_create_gid,
1504
perm.file_create_gid_origin);
1508
int mailbox_list_mkdir_missing_index_root(struct mailbox_list *list)
1510
const char *root_dir, *index_dir;
1513
if (list->index_root_dir_created)
1516
/* if index root dir hasn't been created yet, do it now */
1517
ret = mailbox_list_get_root_path(list, MAILBOX_LIST_PATH_TYPE_INDEX,
1521
ret = mailbox_list_get_root_path(list, MAILBOX_LIST_PATH_TYPE_MAILBOX,
1526
if (strcmp(root_dir, index_dir) != 0) {
1527
if (mailbox_list_mkdir_root(list, index_dir,
1528
MAILBOX_LIST_PATH_TYPE_INDEX) < 0)
1531
list->index_root_dir_created = TRUE;
1134
1535
void mailbox_list_add_change(struct mailbox_list *list,
1135
1536
enum mailbox_log_record_type type,
1136
1537
const guid_128_t mailbox_guid)
1169
1567
if ((ret = list->v.set_subscribed(list, name, set)) <= 0)
1172
/* subscriptions are about names, not about mailboxes. it's possible
1173
to have a subscription to nonexistent mailbox. renames also don't
1174
change subscriptions. so instead of using actual GUIDs, we'll use
1175
hash of the name. */
1176
mailbox_name_get_sha128(name, guid);
1177
mailbox_list_add_change(list, set ? MAILBOX_LOG_RECORD_SUBSCRIBE :
1178
MAILBOX_LOG_RECORD_UNSUBSCRIBE, guid);
1182
int mailbox_list_create_dir(struct mailbox_list *list, const char *name)
1184
if (!mailbox_list_is_valid_create_name(list, name) || *name == '\0') {
1185
mailbox_list_set_error(list, MAIL_ERROR_PARAMS,
1186
"Invalid mailbox name");
1189
return list->v.create_mailbox_dir(list, name,
1190
MAILBOX_DIR_CREATE_TYPE_ONLY_NOSELECT);
1193
1572
int mailbox_list_delete_dir(struct mailbox_list *list, const char *name)
1195
if (!mailbox_list_is_valid_existing_name(list, name) || *name == '\0') {
1576
if (!mailbox_list_is_valid_name(list, name, &error) || *name == '\0') {
1196
1577
mailbox_list_set_error(list, MAIL_ERROR_PARAMS,
1197
1578
"Invalid mailbox name");
1337
int mailbox_list_mkdir(struct mailbox_list *list,
1338
const char *mailbox, const char *path)
1340
struct mailbox_permissions perm;
1342
mailbox_list_get_permissions(list, mailbox, &perm);
1343
if (mkdir_parents_chgrp(path, perm.dir_create_mode,
1344
perm.file_create_gid,
1345
perm.file_create_gid_origin) < 0 &&
1347
mailbox_list_set_critical(list, "mkdir_parents(%s) failed: %m",
1354
int mailbox_list_mkdir_parent(struct mailbox_list *list,
1355
const char *mailbox, const char *path)
1359
p = strrchr(path, '/');
1363
return mailbox_list_mkdir(list, mailbox, t_strdup_until(path, p));
1366
int mailbox_list_create_missing_index_dir(struct mailbox_list *list,
1369
const char *root_dir, *index_dir, *parent_dir, *p, *error;
1370
struct mailbox_permissions perm;
1373
list->index_root_dir_created = TRUE;
1374
root_dir = mailbox_list_get_path(list, name,
1375
MAILBOX_LIST_PATH_TYPE_MAILBOX);
1376
index_dir = mailbox_list_get_path(list, name,
1377
MAILBOX_LIST_PATH_TYPE_INDEX);
1378
if (*index_dir == '\0')
1380
if (strcmp(index_dir, root_dir) == 0) {
1381
if ((list->props & MAILBOX_LIST_PROP_AUTOCREATE_DIRS) == 0)
1383
/* the directory might not have been created yet */
1387
if (mailbox_list_mkdir_root(list, index_dir,
1388
MAILBOX_LIST_PATH_TYPE_INDEX,
1390
mailbox_list_set_critical(list,
1391
"Couldn't create index root dir %s: %s",
1398
mailbox_list_get_permissions(list, name, &perm);
1399
while (mkdir_chgrp(index_dir, perm.dir_create_mode,
1400
perm.file_create_gid,
1401
perm.file_create_gid_origin) < 0) {
1402
if (errno == EEXIST)
1405
p = strrchr(index_dir, '/');
1406
if (errno != ENOENT || p == NULL || ++n == 2) {
1407
mailbox_list_set_critical(list,
1408
"mkdir(%s) failed: %m", index_dir);
1409
if (p == NULL || errno != EPERM ||
1410
perm.dir_create_mode == 0700)
1412
/* we can't use the GID. allow it anyway with more
1413
restricted permissions. */
1414
perm.file_create_gid = (gid_t)-1;
1415
perm.dir_create_mode = 0700;
1418
/* create the parent directory first */
1419
parent_dir = t_strdup_until(index_dir, p);
1420
if (mailbox_list_mkdir_root(list, parent_dir,
1421
MAILBOX_LIST_PATH_TYPE_INDEX,
1423
mailbox_list_set_critical(list,
1424
"Couldn't create index dir %s: %s",
1432
1754
const char *mailbox_list_get_last_error(struct mailbox_list *list,
1433
1755
enum mail_error *error_r)
1490
1812
mailbox_list_set_error(list, error, error_string);
1816
int mailbox_list_init_fs(struct mailbox_list *list, const char *driver,
1817
const char *args, const char *root_dir,
1818
struct fs **fs_r, const char **error_r)
1820
struct fs_settings fs_set;
1821
struct ssl_iostream_settings ssl_set;
1823
memset(&ssl_set, 0, sizeof(ssl_set));
1824
ssl_set.ca_dir = list->mail_set->ssl_client_ca_dir;
1825
ssl_set.ca_file = list->mail_set->ssl_client_ca_file;
1827
memset(&fs_set, 0, sizeof(fs_set));
1828
fs_set.temp_file_prefix = mailbox_list_get_global_temp_prefix(list);
1829
fs_set.base_dir = list->ns->user->set->base_dir;
1830
fs_set.temp_dir = list->ns->user->set->mail_temp_dir;
1831
fs_set.ssl_client_set = &ssl_set;
1832
fs_set.root_path = root_dir;
1833
fs_set.debug = list->ns->user->mail_debug;
1835
return fs_init(driver, args, &fs_set, fs_r, error_r);