Cross Reference: /dovecot/src/lib-storage/mailbox-list.c
mailbox-list.c revision 3f2dd5867a85b15555eb43a33ea5029393a45103
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
2e37d45867d081db150ab78dad303b9077aea24fTimo Sirainen/* Copyright (c) 2006-2011 Dovecot authors, see the included COPYING file */
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen#include "lib.h"
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen#include "array.h"
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen#include "ioloop.h"
472369cba85d9f7c995dda60e7cd01d78b4a960aTimo Sirainen#include "mkdir-parents.h"
e28fa207d1a097fa6e4a867f74ee0761472ef1ceTimo Sirainen#include "str.h"
37847ec8eaec9ad55c9df10ae109efe7b37ac573Timo Sirainen#include "sha1.h"
bd4e36a8cd7257cca7d1434c49a1e343ed7c5100Timo Sirainen#include "hash.h"
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen#include "home-expand.h"
1c1cecd3dfaf71b0c9499b044023e631841e88aaTimo Sirainen#include "unichar.h"
94d8e51119003d2bc5a100c663f90141f297385dTimo Sirainen#include "settings-parser.h"
e28fa207d1a097fa6e4a867f74ee0761472ef1ceTimo Sirainen#include "imap-utf7.h"
37847ec8eaec9ad55c9df10ae109efe7b37ac573Timo Sirainen#include "mailbox-log.h"
ef50336eefcb9ba99f73c6af37420eaf8857a39bTimo Sirainen#include "mailbox-tree.h"
13d98ffa534f2e7d04a832c9d0153fc9c568b878Timo Sirainen#include "mail-storage.h"
13d98ffa534f2e7d04a832c9d0153fc9c568b878Timo Sirainen#include "mail-storage-hooks.h"
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen#include "mailbox-list-private.h"
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen#include <time.h>
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen#include <ctype.h>
5694eeb99b69dea8033ca77ad69743c6b4871370Timo Sirainen#include <unistd.h>
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen#include <dirent.h>
5694eeb99b69dea8033ca77ad69743c6b4871370Timo Sirainen#include <sys/stat.h>
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen/* 20 * (200+1) < 4096 which is the standard PATH_MAX. Having these settings
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen prevents malicious user from creating eg. "a/a/a/.../a" mailbox name and
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen then start renaming them to larger names from end to beginning, which
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen eventually would start causing the failures when trying to use too
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen long mailbox names. */
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen#define MAILBOX_MAX_HIERARCHY_LEVELS 20
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen#define MAILBOX_MAX_HIERARCHY_NAME_LENGTH 200
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainenstruct mailbox_list_module_register mailbox_list_module_register = { 0 };
220e21750948941dc6e33b8f11b552fa21d7f81eTimo Sirainen
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainenstatic ARRAY_DEFINE(mailbox_list_drivers, const struct mailbox_list *);
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
8a0ad174adb1eb5108511b90e97f4e5f9089b0eeTimo Sirainenvoid mailbox_lists_init(void)
8a0ad174adb1eb5108511b90e97f4e5f9089b0eeTimo Sirainen{
8a0ad174adb1eb5108511b90e97f4e5f9089b0eeTimo Sirainen i_array_init(&mailbox_list_drivers, 4);
8a0ad174adb1eb5108511b90e97f4e5f9089b0eeTimo Sirainen}
8a0ad174adb1eb5108511b90e97f4e5f9089b0eeTimo Sirainen
8a0ad174adb1eb5108511b90e97f4e5f9089b0eeTimo Sirainenvoid mailbox_lists_deinit(void)
8a0ad174adb1eb5108511b90e97f4e5f9089b0eeTimo Sirainen{
8a0ad174adb1eb5108511b90e97f4e5f9089b0eeTimo Sirainen array_free(&mailbox_list_drivers);
8a0ad174adb1eb5108511b90e97f4e5f9089b0eeTimo Sirainen}
8a0ad174adb1eb5108511b90e97f4e5f9089b0eeTimo Sirainen
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainenstatic bool mailbox_list_driver_find(const char *name, unsigned int *idx_r)
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen{
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen const struct mailbox_list *const *drivers;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen unsigned int i, count;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen drivers = array_get(&mailbox_list_drivers, &count);
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen for (i = 0; i < count; i++) {
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen if (strcasecmp(drivers[i]->name, name) == 0) {
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen *idx_r = i;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen return TRUE;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen }
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen }
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen return FALSE;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen}
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainenvoid mailbox_list_register(const struct mailbox_list *list)
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen{
8a0ad174adb1eb5108511b90e97f4e5f9089b0eeTimo Sirainen unsigned int idx;
8a0ad174adb1eb5108511b90e97f4e5f9089b0eeTimo Sirainen
8a0ad174adb1eb5108511b90e97f4e5f9089b0eeTimo Sirainen if (mailbox_list_driver_find(list->name, &idx)) {
8a0ad174adb1eb5108511b90e97f4e5f9089b0eeTimo Sirainen i_fatal("mailbox_list_register(%s): duplicate driver",
8a0ad174adb1eb5108511b90e97f4e5f9089b0eeTimo Sirainen list->name);
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen }
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen array_append(&mailbox_list_drivers, &list, 1);
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen}
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainenvoid mailbox_list_unregister(const struct mailbox_list *list)
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen{
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen unsigned int idx;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen if (!mailbox_list_driver_find(list->name, &idx)) {
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen i_fatal("mailbox_list_unregister(%s): unknown driver",
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen list->name);
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen }
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen array_delete(&mailbox_list_drivers, idx, 1);
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen}
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
a24519c36d5f8fa22f58b2c693ba547e8d175a54Timo Sirainenconst struct mailbox_list *
a24519c36d5f8fa22f58b2c693ba547e8d175a54Timo Sirainenmailbox_list_find_class(const char *driver)
a24519c36d5f8fa22f58b2c693ba547e8d175a54Timo Sirainen{
a24519c36d5f8fa22f58b2c693ba547e8d175a54Timo Sirainen const struct mailbox_list *const *class_p;
a24519c36d5f8fa22f58b2c693ba547e8d175a54Timo Sirainen unsigned int idx;
a24519c36d5f8fa22f58b2c693ba547e8d175a54Timo Sirainen
a24519c36d5f8fa22f58b2c693ba547e8d175a54Timo Sirainen if (!mailbox_list_driver_find(driver, &idx))
a24519c36d5f8fa22f58b2c693ba547e8d175a54Timo Sirainen return NULL;
a24519c36d5f8fa22f58b2c693ba547e8d175a54Timo Sirainen
a24519c36d5f8fa22f58b2c693ba547e8d175a54Timo Sirainen class_p = array_idx(&mailbox_list_drivers, idx);
a24519c36d5f8fa22f58b2c693ba547e8d175a54Timo Sirainen return *class_p;
a24519c36d5f8fa22f58b2c693ba547e8d175a54Timo Sirainen}
a24519c36d5f8fa22f58b2c693ba547e8d175a54Timo Sirainen
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainenint mailbox_list_create(const char *driver, struct mail_namespace *ns,
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen const struct mailbox_list_settings *set,
db8b0a3f74a20528d66a3c4be7df920e5c4554c2Timo Sirainen enum mailbox_list_flags flags,
db8b0a3f74a20528d66a3c4be7df920e5c4554c2Timo Sirainen struct mailbox_list **list_r, const char **error_r)
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen{
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen const struct mailbox_list *const *class_p;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen struct mailbox_list *list;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen unsigned int idx;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
db8b0a3f74a20528d66a3c4be7df920e5c4554c2Timo Sirainen i_assert(ns->list == NULL ||
db8b0a3f74a20528d66a3c4be7df920e5c4554c2Timo Sirainen (flags & MAILBOX_LIST_FLAG_SECONDARY) != 0);
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen i_assert(set->subscription_fname == NULL ||
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen *set->subscription_fname != '\0');
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen if (!mailbox_list_driver_find(driver, &idx)) {
2649b237dd4690575e75a30b2bf3b39ebd37b835Timo Sirainen *error_r = "Unknown driver name";
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen return -1;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen }
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
1701e3f91107051b1704721bf1dc1e32491faaf9Timo Sirainen class_p = array_idx(&mailbox_list_drivers, idx);
2649b237dd4690575e75a30b2bf3b39ebd37b835Timo Sirainen if (((*class_p)->props & MAILBOX_LIST_PROP_NO_MAILDIR_NAME) != 0 &&
6600c05e2ab38e9f662582b63c56b0c980a03748Timo Sirainen set->maildir_name != NULL && *set->maildir_name != '\0') {
2649b237dd4690575e75a30b2bf3b39ebd37b835Timo Sirainen *error_r = "maildir_name not supported by this driver";
2649b237dd4690575e75a30b2bf3b39ebd37b835Timo Sirainen return -1;
2649b237dd4690575e75a30b2bf3b39ebd37b835Timo Sirainen }
2649b237dd4690575e75a30b2bf3b39ebd37b835Timo Sirainen if (((*class_p)->props & MAILBOX_LIST_PROP_NO_ALT_DIR) != 0 &&
2649b237dd4690575e75a30b2bf3b39ebd37b835Timo Sirainen set->alt_dir != NULL) {
2649b237dd4690575e75a30b2bf3b39ebd37b835Timo Sirainen *error_r = "alt_dir not supported by this driver";
2649b237dd4690575e75a30b2bf3b39ebd37b835Timo Sirainen return -1;
2649b237dd4690575e75a30b2bf3b39ebd37b835Timo Sirainen }
2649b237dd4690575e75a30b2bf3b39ebd37b835Timo Sirainen
a24519c36d5f8fa22f58b2c693ba547e8d175a54Timo Sirainen i_assert(set->root_dir == NULL || *set->root_dir != '\0' ||
a24519c36d5f8fa22f58b2c693ba547e8d175a54Timo Sirainen ((*class_p)->props & MAILBOX_LIST_PROP_NO_ROOT) != 0);
a24519c36d5f8fa22f58b2c693ba547e8d175a54Timo Sirainen
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen list = (*class_p)->v.alloc();
1701e3f91107051b1704721bf1dc1e32491faaf9Timo Sirainen array_create(&list->module_contexts, list->pool, sizeof(void *), 5);
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen list->ns = ns;
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen list->mail_set = ns->mail_set;
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen list->flags = flags;
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen list->file_create_mode = (mode_t)-1;
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen list->dir_create_mode = (mode_t)-1;
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen list->file_create_gid = (gid_t)-1;
3fe67ec75ccae1230bb9eb9f16affc48377f6441Timo Sirainen list->changelog_timestamp = (time_t)-1;
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen /* copy settings */
2a6dcd984104fed84bed8795ccdfabb20e41ce52Timo Sirainen if (set->root_dir != NULL) {
2a6dcd984104fed84bed8795ccdfabb20e41ce52Timo Sirainen list->set.root_dir = p_strdup(list->pool, set->root_dir);
2a6dcd984104fed84bed8795ccdfabb20e41ce52Timo Sirainen list->set.index_dir = set->index_dir == NULL ||
2a6dcd984104fed84bed8795ccdfabb20e41ce52Timo Sirainen strcmp(set->index_dir, set->root_dir) == 0 ? NULL :
2a6dcd984104fed84bed8795ccdfabb20e41ce52Timo Sirainen p_strdup(list->pool, set->index_dir);
2a6dcd984104fed84bed8795ccdfabb20e41ce52Timo Sirainen list->set.control_dir = set->control_dir == NULL ||
2a6dcd984104fed84bed8795ccdfabb20e41ce52Timo Sirainen strcmp(set->control_dir, set->root_dir) == 0 ? NULL :
2a6dcd984104fed84bed8795ccdfabb20e41ce52Timo Sirainen p_strdup(list->pool, set->control_dir);
2a6dcd984104fed84bed8795ccdfabb20e41ce52Timo Sirainen }
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen list->set.inbox_path = p_strdup(list->pool, set->inbox_path);
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen list->set.subscription_fname =
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen p_strdup(list->pool, set->subscription_fname);
2649b237dd4690575e75a30b2bf3b39ebd37b835Timo Sirainen list->set.maildir_name = set->maildir_name == NULL ? "" :
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen p_strdup(list->pool, set->maildir_name);
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen list->set.mailbox_dir_name =
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen p_strdup(list->pool, set->mailbox_dir_name);
27586e4785d56aeb76e1fd96af8db799688dc64aTimo Sirainen list->set.alt_dir = p_strdup(list->pool, set->alt_dir);
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen if (set->mailbox_dir_name == NULL || *set->mailbox_dir_name == '\0')
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen list->set.mailbox_dir_name = "";
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen else if (set->mailbox_dir_name[strlen(set->mailbox_dir_name)-1] == '/') {
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen list->set.mailbox_dir_name =
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen p_strdup(list->pool, set->mailbox_dir_name);
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen } else {
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen list->set.mailbox_dir_name =
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen p_strconcat(list->pool, set->mailbox_dir_name, "/", NULL);
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen }
1c1cecd3dfaf71b0c9499b044023e631841e88aaTimo Sirainen list->set.utf8 = set->utf8;
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen if (ns->mail_set->mail_debug) {
7920a47321690c932ffd4d286cd16b4048d22d41Timo Sirainen i_debug("%s: root=%s, index=%s, control=%s, inbox=%s, alt=%s",
e5acc283bf030b0b5c79ca4e52d315c516a299faPascal Volk list->name,
e5acc283bf030b0b5c79ca4e52d315c516a299faPascal Volk list->set.root_dir == NULL ? "" : list->set.root_dir,
e5acc283bf030b0b5c79ca4e52d315c516a299faPascal Volk list->set.index_dir == NULL ? "" : list->set.index_dir,
e5acc283bf030b0b5c79ca4e52d315c516a299faPascal Volk list->set.control_dir == NULL ?
e5acc283bf030b0b5c79ca4e52d315c516a299faPascal Volk "" : list->set.control_dir,
e5acc283bf030b0b5c79ca4e52d315c516a299faPascal Volk list->set.inbox_path == NULL ?
7920a47321690c932ffd4d286cd16b4048d22d41Timo Sirainen "" : list->set.inbox_path,
7920a47321690c932ffd4d286cd16b4048d22d41Timo Sirainen list->set.alt_dir == NULL ? "" : list->set.alt_dir);
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen }
db8b0a3f74a20528d66a3c4be7df920e5c4554c2Timo Sirainen if ((flags & MAILBOX_LIST_FLAG_SECONDARY) == 0)
db8b0a3f74a20528d66a3c4be7df920e5c4554c2Timo Sirainen mail_namespace_finish_list_init(ns, list);
db8b0a3f74a20528d66a3c4be7df920e5c4554c2Timo Sirainen
db8b0a3f74a20528d66a3c4be7df920e5c4554c2Timo Sirainen *list_r = list;
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen
5666a3d6a7ea89362b8d9e8b39b15424cd9d6388Timo Sirainen hook_mailbox_list_created(list);
1701e3f91107051b1704721bf1dc1e32491faaf9Timo Sirainen return 0;
1701e3f91107051b1704721bf1dc1e32491faaf9Timo Sirainen}
1701e3f91107051b1704721bf1dc1e32491faaf9Timo Sirainen
b365bd121cdc87f63e1dd47c5085a27091118e00Timo Sirainenstatic int fix_path(struct mail_user *user, const char *path,
94b0ff77495c3ed14bdd4b5d7ae1eb37e8c9efb5Timo Sirainen const char **path_r, const char **error_r)
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen{
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen size_t len = strlen(path);
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen if (len > 1 && path[len-1] == '/')
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen path = t_strndup(path, len-1);
9abf5be0962538e1f6f5c73c838ff677341da0c9Timo Sirainen if (path[0] == '~' && path[1] != '/' && path[1] != '\0') {
94b0ff77495c3ed14bdd4b5d7ae1eb37e8c9efb5Timo Sirainen /* ~otheruser/dir */
94b0ff77495c3ed14bdd4b5d7ae1eb37e8c9efb5Timo Sirainen if (home_try_expand(&path) < 0) {
94b0ff77495c3ed14bdd4b5d7ae1eb37e8c9efb5Timo Sirainen *error_r = t_strconcat(
94b0ff77495c3ed14bdd4b5d7ae1eb37e8c9efb5Timo Sirainen "No home directory for system user. "
94b0ff77495c3ed14bdd4b5d7ae1eb37e8c9efb5Timo Sirainen "Can't expand ", t_strcut(path, '/'),
94b0ff77495c3ed14bdd4b5d7ae1eb37e8c9efb5Timo Sirainen " for ", NULL);
94b0ff77495c3ed14bdd4b5d7ae1eb37e8c9efb5Timo Sirainen return -1;
94b0ff77495c3ed14bdd4b5d7ae1eb37e8c9efb5Timo Sirainen }
94b0ff77495c3ed14bdd4b5d7ae1eb37e8c9efb5Timo Sirainen } else {
b365bd121cdc87f63e1dd47c5085a27091118e00Timo Sirainen if (mail_user_try_home_expand(user, &path) < 0) {
94b0ff77495c3ed14bdd4b5d7ae1eb37e8c9efb5Timo Sirainen *error_r = "Home directory not set for user. "
94b0ff77495c3ed14bdd4b5d7ae1eb37e8c9efb5Timo Sirainen "Can't expand ~/ for ";
94b0ff77495c3ed14bdd4b5d7ae1eb37e8c9efb5Timo Sirainen return -1;
94b0ff77495c3ed14bdd4b5d7ae1eb37e8c9efb5Timo Sirainen }
94b0ff77495c3ed14bdd4b5d7ae1eb37e8c9efb5Timo Sirainen }
02e61e13a8360a9d3ec92c5fa5ae60c0f0181b71Timo Sirainen *path_r = path;
02e61e13a8360a9d3ec92c5fa5ae60c0f0181b71Timo Sirainen return 0;
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen}
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen
c1d19144dd7b1de6822df6ed1d10af0c9cb38840Timo Sirainenstatic const char *split_next_arg(const char *const **_args)
c1d19144dd7b1de6822df6ed1d10af0c9cb38840Timo Sirainen{
c1d19144dd7b1de6822df6ed1d10af0c9cb38840Timo Sirainen const char *const *args = *_args;
c1d19144dd7b1de6822df6ed1d10af0c9cb38840Timo Sirainen const char *str = args[0];
c1d19144dd7b1de6822df6ed1d10af0c9cb38840Timo Sirainen
c1d19144dd7b1de6822df6ed1d10af0c9cb38840Timo Sirainen args++;
c1d19144dd7b1de6822df6ed1d10af0c9cb38840Timo Sirainen while (*args != NULL && **args == '\0') {
c1d19144dd7b1de6822df6ed1d10af0c9cb38840Timo Sirainen args++;
c1d19144dd7b1de6822df6ed1d10af0c9cb38840Timo Sirainen if (*args == NULL) {
5c597df6aa8d81de4053c6986fab7739f3b44b20Timo Sirainen /* string ends with ":", just ignore it. */
c1d19144dd7b1de6822df6ed1d10af0c9cb38840Timo Sirainen break;
c1d19144dd7b1de6822df6ed1d10af0c9cb38840Timo Sirainen }
c1d19144dd7b1de6822df6ed1d10af0c9cb38840Timo Sirainen str = t_strconcat(str, ":", *args, NULL);
c1d19144dd7b1de6822df6ed1d10af0c9cb38840Timo Sirainen args++;
c1d19144dd7b1de6822df6ed1d10af0c9cb38840Timo Sirainen }
c1d19144dd7b1de6822df6ed1d10af0c9cb38840Timo Sirainen *_args = args;
c1d19144dd7b1de6822df6ed1d10af0c9cb38840Timo Sirainen return str;
c1d19144dd7b1de6822df6ed1d10af0c9cb38840Timo Sirainen}
c1d19144dd7b1de6822df6ed1d10af0c9cb38840Timo Sirainen
b365bd121cdc87f63e1dd47c5085a27091118e00Timo Sirainenint mailbox_list_settings_parse(struct mail_user *user, const char *data,
b365bd121cdc87f63e1dd47c5085a27091118e00Timo Sirainen struct mailbox_list_settings *set_r,
b365bd121cdc87f63e1dd47c5085a27091118e00Timo Sirainen const char **error_r)
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen{
94b0ff77495c3ed14bdd4b5d7ae1eb37e8c9efb5Timo Sirainen const char *const *tmp, *key, *value, **dest, *str, *error;
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen *error_r = NULL;
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen
b365bd121cdc87f63e1dd47c5085a27091118e00Timo Sirainen memset(set_r, 0, sizeof(*set_r));
b365bd121cdc87f63e1dd47c5085a27091118e00Timo Sirainen
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen if (*data == '\0')
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen return 0;
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen /* <root dir> */
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen tmp = t_strsplit(data, ":");
c1d19144dd7b1de6822df6ed1d10af0c9cb38840Timo Sirainen str = split_next_arg(&tmp);
b365bd121cdc87f63e1dd47c5085a27091118e00Timo Sirainen if (fix_path(user, str, &set_r->root_dir, &error) < 0) {
94b0ff77495c3ed14bdd4b5d7ae1eb37e8c9efb5Timo Sirainen *error_r = t_strconcat(error, "mail root dir in: ", data, NULL);
02e61e13a8360a9d3ec92c5fa5ae60c0f0181b71Timo Sirainen return -1;
02e61e13a8360a9d3ec92c5fa5ae60c0f0181b71Timo Sirainen }
c58c12049c883b281c088d47a2a7278c21c390e1Timo Sirainen if (strncmp(set_r->root_dir, "INBOX=", 6) == 0) {
c58c12049c883b281c088d47a2a7278c21c390e1Timo Sirainen /* probably mbox user trying to avoid root_dir */
c58c12049c883b281c088d47a2a7278c21c390e1Timo Sirainen *error_r = t_strconcat("Mail root directory not given: ",
c58c12049c883b281c088d47a2a7278c21c390e1Timo Sirainen data, NULL);
c58c12049c883b281c088d47a2a7278c21c390e1Timo Sirainen return -1;
c58c12049c883b281c088d47a2a7278c21c390e1Timo Sirainen }
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen
c1d19144dd7b1de6822df6ed1d10af0c9cb38840Timo Sirainen while (*tmp != NULL) {
c1d19144dd7b1de6822df6ed1d10af0c9cb38840Timo Sirainen str = split_next_arg(&tmp);
1c1cecd3dfaf71b0c9499b044023e631841e88aaTimo Sirainen if (strcmp(str, "UTF-8") == 0) {
1c1cecd3dfaf71b0c9499b044023e631841e88aaTimo Sirainen set_r->utf8 = TRUE;
1c1cecd3dfaf71b0c9499b044023e631841e88aaTimo Sirainen continue;
1c1cecd3dfaf71b0c9499b044023e631841e88aaTimo Sirainen }
1c1cecd3dfaf71b0c9499b044023e631841e88aaTimo Sirainen
c1d19144dd7b1de6822df6ed1d10af0c9cb38840Timo Sirainen value = strchr(str, '=');
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen if (value == NULL) {
c1d19144dd7b1de6822df6ed1d10af0c9cb38840Timo Sirainen key = str;
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen value = "";
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen } else {
c1d19144dd7b1de6822df6ed1d10af0c9cb38840Timo Sirainen key = t_strdup_until(str, value);
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen value++;
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen }
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen if (strcmp(key, "INBOX") == 0)
b365bd121cdc87f63e1dd47c5085a27091118e00Timo Sirainen dest = &set_r->inbox_path;
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen else if (strcmp(key, "INDEX") == 0)
b365bd121cdc87f63e1dd47c5085a27091118e00Timo Sirainen dest = &set_r->index_dir;
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen else if (strcmp(key, "CONTROL") == 0)
b365bd121cdc87f63e1dd47c5085a27091118e00Timo Sirainen dest = &set_r->control_dir;
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen else if (strcmp(key, "ALT") == 0)
b365bd121cdc87f63e1dd47c5085a27091118e00Timo Sirainen dest = &set_r->alt_dir;
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen else if (strcmp(key, "LAYOUT") == 0)
b365bd121cdc87f63e1dd47c5085a27091118e00Timo Sirainen dest = &set_r->layout;
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen else if (strcmp(key, "SUBSCRIPTIONS") == 0)
b365bd121cdc87f63e1dd47c5085a27091118e00Timo Sirainen dest = &set_r->subscription_fname;
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen else if (strcmp(key, "DIRNAME") == 0)
b365bd121cdc87f63e1dd47c5085a27091118e00Timo Sirainen dest = &set_r->maildir_name;
5494a6bc149da8f02fd25c0434a9d612ac33f659Timo Sirainen else if (strcmp(key, "MAILBOXDIR") == 0)
b365bd121cdc87f63e1dd47c5085a27091118e00Timo Sirainen dest = &set_r->mailbox_dir_name;
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen else {
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen *error_r = t_strdup_printf("Unknown setting: %s", key);
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen return -1;
02e61e13a8360a9d3ec92c5fa5ae60c0f0181b71Timo Sirainen }
b365bd121cdc87f63e1dd47c5085a27091118e00Timo Sirainen if (fix_path(user, value, dest, &error) < 0) {
94b0ff77495c3ed14bdd4b5d7ae1eb37e8c9efb5Timo Sirainen *error_r = t_strconcat(error, key, " in: ", data, NULL);
02e61e13a8360a9d3ec92c5fa5ae60c0f0181b71Timo Sirainen return -1;
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen }
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen }
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen
b365bd121cdc87f63e1dd47c5085a27091118e00Timo Sirainen if (set_r->index_dir != NULL && strcmp(set_r->index_dir, "MEMORY") == 0)
b365bd121cdc87f63e1dd47c5085a27091118e00Timo Sirainen set_r->index_dir = "";
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen return 0;
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen}
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainenconst char *mailbox_list_get_unexpanded_path(struct mailbox_list *list,
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen enum mailbox_list_path_type type)
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen{
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen const struct mail_storage_settings *mail_set;
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen const char *location = list->ns->unexpanded_set->location;
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen struct mail_user *user = list->ns->user;
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen struct mailbox_list_settings set;
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen const char *p, *error;
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen
94d8e51119003d2bc5a100c663f90141f297385dTimo Sirainen if (*location == SETTING_STRVAR_EXPANDED[0]) {
1433bf361ddb0bba8878c8ada5726d0284edad57Timo Sirainen /* set using -o or userdb lookup. */
1433bf361ddb0bba8878c8ada5726d0284edad57Timo Sirainen return "";
1433bf361ddb0bba8878c8ada5726d0284edad57Timo Sirainen }
1433bf361ddb0bba8878c8ada5726d0284edad57Timo Sirainen
94d8e51119003d2bc5a100c663f90141f297385dTimo Sirainen i_assert(*location == SETTING_STRVAR_UNEXPANDED[0]);
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen location++;
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen if (*location == '\0') {
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen mail_set = mail_user_set_get_driver_settings(user->set_info,
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen user->unexpanded_set, MAIL_STORAGE_SET_DRIVER_NAME);
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen i_assert(mail_set != NULL);
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen location = mail_set->mail_location;
94d8e51119003d2bc5a100c663f90141f297385dTimo Sirainen if (*location == SETTING_STRVAR_EXPANDED[0])
4a514fb20e04df397842cde11cc9ea92abfe9728Timo Sirainen return "";
94d8e51119003d2bc5a100c663f90141f297385dTimo Sirainen i_assert(*location == SETTING_STRVAR_UNEXPANDED[0]);
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen location++;
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen }
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen /* type:settings */
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen p = strchr(location, ':');
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen if (p == NULL)
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen return "";
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen if (mailbox_list_settings_parse(user, p + 1, &set, &error) < 0)
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen return "";
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen return mailbox_list_get_root_path(&set, type);
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen}
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainenstatic const char *
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainenmailbox_list_escape_name(struct mailbox_list *list, const char *vname)
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen{
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen char ns_sep = mail_namespace_get_sep(list->ns);
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen char list_sep = mailbox_list_get_hierarchy_sep(list);
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen string_t *escaped_name = t_str_new(64);
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen /* no escaping of namespace prefix */
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen if (strncmp(list->ns->prefix, vname, list->ns->prefix_len) == 0) {
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen str_append_n(escaped_name, vname, list->ns->prefix_len);
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen vname += list->ns->prefix_len;
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen }
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen /* escape the mailbox name */
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen if (*vname == '~') {
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen str_printfa(escaped_name, "%c%02x",
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen list->set.escape_char, *vname);
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen vname++;
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen }
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen for (; *vname != '\0'; vname++) {
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen if (*vname == ns_sep)
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen str_append_c(escaped_name, *vname);
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen else if (*vname == list_sep ||
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen *vname == list->set.escape_char ||
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen *vname == '/') {
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen str_printfa(escaped_name, "%c%02x",
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen list->set.escape_char, *vname);
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen } else {
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen str_append_c(escaped_name, *vname);
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen }
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen }
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen return str_c(escaped_name);
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen}
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainenconst char *mailbox_list_default_get_storage_name(struct mailbox_list *list,
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen const char *vname)
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen{
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen struct mail_namespace *ns = list->ns;
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen unsigned int prefix_len = strlen(ns->prefix);
636f017be100bce67d66fd3ae1544a47681efd33Timo Sirainen const char *storage_name = vname;
636f017be100bce67d66fd3ae1544a47681efd33Timo Sirainen string_t *str;
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen char list_sep, ns_sep, *ret, *p;
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen
636f017be100bce67d66fd3ae1544a47681efd33Timo Sirainen if (strcasecmp(storage_name, "INBOX") == 0)
636f017be100bce67d66fd3ae1544a47681efd33Timo Sirainen storage_name = "INBOX";
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen else if (list->set.escape_char != '\0')
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen storage_name = mailbox_list_escape_name(list, vname);
494a5de15db3b2806ab31d5ecc3e1c306ae14d06Timo Sirainen
08ed4ab71fd2a4e800d9025a736f0f46b771ea90Timo Sirainen if (prefix_len > 0 && strcmp(storage_name, "INBOX") != 0) {
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen /* skip namespace prefix, except if this is INBOX */
636f017be100bce67d66fd3ae1544a47681efd33Timo Sirainen if (strncmp(ns->prefix, storage_name, prefix_len) == 0)
636f017be100bce67d66fd3ae1544a47681efd33Timo Sirainen storage_name += prefix_len;
636f017be100bce67d66fd3ae1544a47681efd33Timo Sirainen else if (strncmp(ns->prefix, storage_name, prefix_len-1) == 0 &&
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen ns->prefix[prefix_len-1] == mail_namespace_get_sep(ns)) {
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen /* trying to access the namespace prefix itself */
636f017be100bce67d66fd3ae1544a47681efd33Timo Sirainen storage_name = "";
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen } else {
08ed4ab71fd2a4e800d9025a736f0f46b771ea90Timo Sirainen /* we're converting a nonexistent mailbox name,
08ed4ab71fd2a4e800d9025a736f0f46b771ea90Timo Sirainen such as a LIST pattern. */
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen }
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen }
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen
1c1cecd3dfaf71b0c9499b044023e631841e88aaTimo Sirainen if (!list->set.utf8) {
1c1cecd3dfaf71b0c9499b044023e631841e88aaTimo Sirainen /* UTF-8 -> mUTF-7 conversion */
1c1cecd3dfaf71b0c9499b044023e631841e88aaTimo Sirainen str = t_str_new(strlen(storage_name)*2);
1c1cecd3dfaf71b0c9499b044023e631841e88aaTimo Sirainen if (imap_utf8_to_utf7(storage_name, str) < 0)
1c1cecd3dfaf71b0c9499b044023e631841e88aaTimo Sirainen i_panic("Mailbox name not UTF-8: %s", vname);
1c1cecd3dfaf71b0c9499b044023e631841e88aaTimo Sirainen storage_name = str_c(str);
1c1cecd3dfaf71b0c9499b044023e631841e88aaTimo Sirainen }
636f017be100bce67d66fd3ae1544a47681efd33Timo Sirainen
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen list_sep = mailbox_list_get_hierarchy_sep(list);
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen ns_sep = mail_namespace_get_sep(ns);
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen if (list_sep == ns_sep)
636f017be100bce67d66fd3ae1544a47681efd33Timo Sirainen return storage_name;
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen if (ns->type == NAMESPACE_SHARED &&
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen (ns->flags & NAMESPACE_FLAG_AUTOCREATED) == 0) {
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen /* shared namespace root. the backend storage's hierarchy
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen separator isn't known yet, so do nothing. */
636f017be100bce67d66fd3ae1544a47681efd33Timo Sirainen return storage_name;
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen }
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen
636f017be100bce67d66fd3ae1544a47681efd33Timo Sirainen ret = p_strdup(unsafe_data_stack_pool, storage_name);
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen for (p = ret; *p != '\0'; p++) {
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen if (*p == ns_sep)
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen *p = list_sep;
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen }
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen return ret;
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen}
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainenconst char *mailbox_list_get_storage_name(struct mailbox_list *list,
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen const char *vname)
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen{
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen return list->v.get_storage_name(list, vname);
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen}
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainenstatic const char *
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainenmailbox_list_unescape_name(struct mailbox_list *list, const char *src)
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen{
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen char ns_sep = mail_namespace_get_sep(list->ns);
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen char list_sep = mailbox_list_get_hierarchy_sep(list);
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen string_t *dest = t_str_new(strlen(src));
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen unsigned int num;
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen for (; *src != '\0'; src++) {
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen if (*src == list->set.escape_char &&
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen i_isxdigit(src[1]) && i_isxdigit(src[2])) {
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen if (src[1] >= '0' && src[1] <= '9')
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen num = src[1] - '0';
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen else
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen num = i_toupper(src[1]) - 'A' + 10;
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen num *= 16;
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen if (src[2] >= '0' && src[2] <= '9')
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen num += src[2] - '0';
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen else
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen num += i_toupper(src[2]) - 'A' + 10;
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen str_append_c(dest, num);
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen src += 2;
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen } else if (*src == list_sep)
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen str_append_c(dest, ns_sep);
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen else
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen str_append_c(dest, *src);
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen }
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen return str_c(dest);
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen}
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainenconst char *mailbox_list_default_get_vname(struct mailbox_list *list,
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen const char *storage_name)
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen{
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen unsigned int i, prefix_len, name_len;
636f017be100bce67d66fd3ae1544a47681efd33Timo Sirainen const char *vname = storage_name;
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen char list_sep, ns_sep, *ret;
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen if ((list->ns->flags & NAMESPACE_FLAG_INBOX_USER) != 0 &&
9b00ecffbe74fd864d0d72e6112ec53b86f619baTimo Sirainen strcmp(vname, "INBOX") == 0 &&
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen list->ns->user == list->ns->owner) {
9b00ecffbe74fd864d0d72e6112ec53b86f619baTimo Sirainen /* user's INBOX - use as-is. NOTE: don't do case-insensitive
9b00ecffbe74fd864d0d72e6112ec53b86f619baTimo Sirainen comparison, otherwise we can't differentiate between INBOX
9b00ecffbe74fd864d0d72e6112ec53b86f619baTimo Sirainen and <ns prefix>/inBox. */
9b00ecffbe74fd864d0d72e6112ec53b86f619baTimo Sirainen return vname;
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen }
636f017be100bce67d66fd3ae1544a47681efd33Timo Sirainen if (*vname == '\0') {
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen /* return namespace prefix without the separator */
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen if (list->ns->prefix_len == 0)
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen return list->ns->prefix;
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen else {
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen return t_strndup(list->ns->prefix,
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen list->ns->prefix_len - 1);
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen }
1c1cecd3dfaf71b0c9499b044023e631841e88aaTimo Sirainen } else if (!list->set.utf8) {
636f017be100bce67d66fd3ae1544a47681efd33Timo Sirainen /* mUTF-7 -> UTF-8 conversion */
636f017be100bce67d66fd3ae1544a47681efd33Timo Sirainen string_t *str = t_str_new(strlen(vname));
636f017be100bce67d66fd3ae1544a47681efd33Timo Sirainen if (imap_utf7_to_utf8(vname, str) == 0)
636f017be100bce67d66fd3ae1544a47681efd33Timo Sirainen vname = str_c(str);
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen }
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen prefix_len = strlen(list->ns->prefix);
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen list_sep = mailbox_list_get_hierarchy_sep(list);
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen ns_sep = mail_namespace_get_sep(list->ns);
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen if (list_sep != ns_sep || prefix_len > 0) {
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen /* @UNSAFE */
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen name_len = strlen(vname);
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen ret = t_malloc(prefix_len + name_len + 1);
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen memcpy(ret, list->ns->prefix, prefix_len);
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen for (i = 0; i < name_len; i++) {
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen ret[i + prefix_len] =
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen vname[i] == list_sep ? ns_sep : vname[i];
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen }
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen ret[i + prefix_len] = '\0';
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen vname = ret;
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen }
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen if (list->set.escape_char != '\0')
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen vname = mailbox_list_unescape_name(list, vname);
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen return vname;
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen}
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainenconst char *mailbox_list_get_vname(struct mailbox_list *list, const char *name)
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen{
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen return list->v.get_vname(list, name);
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen}
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainenvoid mailbox_list_destroy(struct mailbox_list **_list)
1701e3f91107051b1704721bf1dc1e32491faaf9Timo Sirainen{
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen struct mailbox_list *list = *_list;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen *_list = NULL;
ff7056842f14fd3b30a2d327dfab165b9d15dd30Timo Sirainen i_free_and_null(list->error_string);
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
bd4e36a8cd7257cca7d1434c49a1e343ed7c5100Timo Sirainen if (list->guid_cache != NULL) {
bd4e36a8cd7257cca7d1434c49a1e343ed7c5100Timo Sirainen hash_table_destroy(&list->guid_cache);
bd4e36a8cd7257cca7d1434c49a1e343ed7c5100Timo Sirainen pool_unref(&list->guid_cache_pool);
bd4e36a8cd7257cca7d1434c49a1e343ed7c5100Timo Sirainen }
bd4e36a8cd7257cca7d1434c49a1e343ed7c5100Timo Sirainen
cb933f0a570a9cef5c975eadb818aa6b1002a269Timo Sirainen if (list->subscriptions != NULL)
cb933f0a570a9cef5c975eadb818aa6b1002a269Timo Sirainen mailbox_tree_deinit(&list->subscriptions);
37847ec8eaec9ad55c9df10ae109efe7b37ac573Timo Sirainen if (list->changelog != NULL)
37847ec8eaec9ad55c9df10ae109efe7b37ac573Timo Sirainen mailbox_log_free(&list->changelog);
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen list->v.deinit(list);
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen}
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
68a4946b12583b88fa802e52ebee45cd96056772Timo Sirainenconst char *mailbox_list_get_driver_name(const struct mailbox_list *list)
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen{
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen return list->name;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen}
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
68a4946b12583b88fa802e52ebee45cd96056772Timo Sirainenenum mailbox_list_flags mailbox_list_get_flags(const struct mailbox_list *list)
c58906589cafc32df4c04ffbef933baadd3f2276Timo Sirainen{
c58906589cafc32df4c04ffbef933baadd3f2276Timo Sirainen return list->flags;
c58906589cafc32df4c04ffbef933baadd3f2276Timo Sirainen}
c58906589cafc32df4c04ffbef933baadd3f2276Timo Sirainen
68a4946b12583b88fa802e52ebee45cd96056772Timo Sirainenstruct mail_namespace *
68a4946b12583b88fa802e52ebee45cd96056772Timo Sirainenmailbox_list_get_namespace(const struct mailbox_list *list)
c58906589cafc32df4c04ffbef933baadd3f2276Timo Sirainen{
c58906589cafc32df4c04ffbef933baadd3f2276Timo Sirainen return list->ns;
c58906589cafc32df4c04ffbef933baadd3f2276Timo Sirainen}
c58906589cafc32df4c04ffbef933baadd3f2276Timo Sirainen
6dd77763f5451269ace733579cf58f2f3b18bca4Timo Sirainenstatic mode_t get_dir_mode(mode_t mode)
6dd77763f5451269ace733579cf58f2f3b18bca4Timo Sirainen{
6dd77763f5451269ace733579cf58f2f3b18bca4Timo Sirainen /* add the execute bit if either read or write bit is set */
6dd77763f5451269ace733579cf58f2f3b18bca4Timo Sirainen if ((mode & 0600) != 0) mode |= 0100;
6dd77763f5451269ace733579cf58f2f3b18bca4Timo Sirainen if ((mode & 0060) != 0) mode |= 0010;
6dd77763f5451269ace733579cf58f2f3b18bca4Timo Sirainen if ((mode & 0006) != 0) mode |= 0001;
6dd77763f5451269ace733579cf58f2f3b18bca4Timo Sirainen return mode;
6dd77763f5451269ace733579cf58f2f3b18bca4Timo Sirainen}
6dd77763f5451269ace733579cf58f2f3b18bca4Timo Sirainen
0df9428baed48afaff90b4d4f03792d2fd756a43Timo Sirainenstruct mail_user *
0df9428baed48afaff90b4d4f03792d2fd756a43Timo Sirainenmailbox_list_get_user(const struct mailbox_list *list)
0df9428baed48afaff90b4d4f03792d2fd756a43Timo Sirainen{
0df9428baed48afaff90b4d4f03792d2fd756a43Timo Sirainen return list->ns->user;
0df9428baed48afaff90b4d4f03792d2fd756a43Timo Sirainen}
0df9428baed48afaff90b4d4f03792d2fd756a43Timo Sirainen
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainenint mailbox_list_get_storage(struct mailbox_list **list, const char *vname,
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen struct mail_storage **storage_r)
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen{
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen if ((*list)->v.get_storage != NULL)
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen return (*list)->v.get_storage(list, vname, storage_r);
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen else {
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen *storage_r = (*list)->ns->storage;
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen return 0;
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen }
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen}
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainenvoid mailbox_list_get_closest_storage(struct mailbox_list *list,
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen struct mail_storage **storage)
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen{
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen *storage = list->ns->storage;
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen}
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainenchar mailbox_list_get_hierarchy_sep(struct mailbox_list *list)
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen{
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen return list->v.get_hierarchy_sep(list);
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen}
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen
47d5cc09738defd0020c797866e2a25a344aa65aTimo Sirainenvoid mailbox_list_get_permissions(struct mailbox_list *list, const char *name,
47d5cc09738defd0020c797866e2a25a344aa65aTimo Sirainen struct mailbox_permissions *permissions_r)
d02d34e138e32b4266f5a403d6c51d7803bf322fTimo Sirainen{
d06c46087e9e6e66bbbbb9df1d5b33154349515cTimo Sirainen const char *path, *parent_name, *p;
d02d34e138e32b4266f5a403d6c51d7803bf322fTimo Sirainen struct stat st;
d02d34e138e32b4266f5a403d6c51d7803bf322fTimo Sirainen
3f2dd5867a85b15555eb43a33ea5029393a45103Timo Sirainen memset(permissions_r, 0, sizeof(*permissions_r));
47d5cc09738defd0020c797866e2a25a344aa65aTimo Sirainen
a24519c36d5f8fa22f58b2c693ba547e8d175a54Timo Sirainen /* use safe defaults */
47d5cc09738defd0020c797866e2a25a344aa65aTimo Sirainen permissions_r->file_uid = (uid_t)-1;
47d5cc09738defd0020c797866e2a25a344aa65aTimo Sirainen permissions_r->file_gid = (gid_t)-1;
47d5cc09738defd0020c797866e2a25a344aa65aTimo Sirainen permissions_r->file_create_mode = 0600;
47d5cc09738defd0020c797866e2a25a344aa65aTimo Sirainen permissions_r->dir_create_mode = 0700;
47d5cc09738defd0020c797866e2a25a344aa65aTimo Sirainen permissions_r->file_create_gid = (gid_t)-1;
47d5cc09738defd0020c797866e2a25a344aa65aTimo Sirainen permissions_r->file_create_gid_origin = "defaults";
a24519c36d5f8fa22f58b2c693ba547e8d175a54Timo Sirainen
b82d6d7f02734007c129fa25bc876049c8d9bddeTimo Sirainen path = mailbox_list_get_path(list, name, MAILBOX_LIST_PATH_TYPE_DIR);
a24519c36d5f8fa22f58b2c693ba547e8d175a54Timo Sirainen if (path == NULL) {
a24519c36d5f8fa22f58b2c693ba547e8d175a54Timo Sirainen /* no filesystem support in storage */
a24519c36d5f8fa22f58b2c693ba547e8d175a54Timo Sirainen } else if (stat(path, &st) < 0) {
d02d34e138e32b4266f5a403d6c51d7803bf322fTimo Sirainen if (!ENOTFOUND(errno)) {
d02d34e138e32b4266f5a403d6c51d7803bf322fTimo Sirainen mailbox_list_set_critical(list, "stat(%s) failed: %m",
d02d34e138e32b4266f5a403d6c51d7803bf322fTimo Sirainen path);
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen } else if (list->mail_set->mail_debug) {
e200d1ba38eeebfb0b9e60150d93753ec6d823c8Timo Sirainen i_debug("Namespace %s: %s doesn't exist yet, "
e200d1ba38eeebfb0b9e60150d93753ec6d823c8Timo Sirainen "using default permissions",
e200d1ba38eeebfb0b9e60150d93753ec6d823c8Timo Sirainen list->ns->prefix, path);
d02d34e138e32b4266f5a403d6c51d7803bf322fTimo Sirainen }
1d2b188f0eedc3cab6e27ceac5425a037f38042eTimo Sirainen if (name != NULL) {
d06c46087e9e6e66bbbbb9df1d5b33154349515cTimo Sirainen /* return parent mailbox */
d06c46087e9e6e66bbbbb9df1d5b33154349515cTimo Sirainen p = strrchr(name, mailbox_list_get_hierarchy_sep(list));
d06c46087e9e6e66bbbbb9df1d5b33154349515cTimo Sirainen if (p == NULL) {
d06c46087e9e6e66bbbbb9df1d5b33154349515cTimo Sirainen /* return root defaults */
d06c46087e9e6e66bbbbb9df1d5b33154349515cTimo Sirainen parent_name = NULL;
d06c46087e9e6e66bbbbb9df1d5b33154349515cTimo Sirainen } else {
d06c46087e9e6e66bbbbb9df1d5b33154349515cTimo Sirainen parent_name = t_strdup_until(name, p);
d06c46087e9e6e66bbbbb9df1d5b33154349515cTimo Sirainen }
d06c46087e9e6e66bbbbb9df1d5b33154349515cTimo Sirainen mailbox_list_get_permissions(list, parent_name,
47d5cc09738defd0020c797866e2a25a344aa65aTimo Sirainen permissions_r);
1d2b188f0eedc3cab6e27ceac5425a037f38042eTimo Sirainen return;
1d2b188f0eedc3cab6e27ceac5425a037f38042eTimo Sirainen }
47d5cc09738defd0020c797866e2a25a344aa65aTimo Sirainen /* assume current defaults for mailboxes that don't exist or
47d5cc09738defd0020c797866e2a25a344aa65aTimo Sirainen can't be looked up for some other reason */
47d5cc09738defd0020c797866e2a25a344aa65aTimo Sirainen permissions_r->file_uid = geteuid();
47d5cc09738defd0020c797866e2a25a344aa65aTimo Sirainen permissions_r->file_gid = getegid();
490f66d6476d51cc02333d6eb398a5cd94b67f48Timo Sirainen } else {
47d5cc09738defd0020c797866e2a25a344aa65aTimo Sirainen permissions_r->file_uid = st.st_uid;
47d5cc09738defd0020c797866e2a25a344aa65aTimo Sirainen permissions_r->file_gid = st.st_gid;
47d5cc09738defd0020c797866e2a25a344aa65aTimo Sirainen permissions_r->file_create_mode = (st.st_mode & 0666) | 0600;
47d5cc09738defd0020c797866e2a25a344aa65aTimo Sirainen permissions_r->dir_create_mode = (st.st_mode & 0777) | 0700;
47d5cc09738defd0020c797866e2a25a344aa65aTimo Sirainen permissions_r->file_create_gid_origin = path;
e91543761d0b7b97a1dc28e036e44d76405545c2Timo Sirainen
490f66d6476d51cc02333d6eb398a5cd94b67f48Timo Sirainen if (!S_ISDIR(st.st_mode)) {
490f66d6476d51cc02333d6eb398a5cd94b67f48Timo Sirainen /* we're getting permissions from a file.
490f66d6476d51cc02333d6eb398a5cd94b67f48Timo Sirainen apply +x modes as necessary. */
47d5cc09738defd0020c797866e2a25a344aa65aTimo Sirainen permissions_r->dir_create_mode =
47d5cc09738defd0020c797866e2a25a344aa65aTimo Sirainen get_dir_mode(permissions_r->dir_create_mode);
490f66d6476d51cc02333d6eb398a5cd94b67f48Timo Sirainen }
d02d34e138e32b4266f5a403d6c51d7803bf322fTimo Sirainen
490f66d6476d51cc02333d6eb398a5cd94b67f48Timo Sirainen if (S_ISDIR(st.st_mode) && (st.st_mode & S_ISGID) != 0) {
490f66d6476d51cc02333d6eb398a5cd94b67f48Timo Sirainen /* directory's GID is used automatically for new
490f66d6476d51cc02333d6eb398a5cd94b67f48Timo Sirainen files */
47d5cc09738defd0020c797866e2a25a344aa65aTimo Sirainen permissions_r->file_create_gid = (gid_t)-1;
93688bfedcfb2b9c02750b8d4d409123a386de5cTimo Sirainen } else if ((st.st_mode & 0070) >> 3 == (st.st_mode & 0007)) {
93688bfedcfb2b9c02750b8d4d409123a386de5cTimo Sirainen /* group has same permissions as world, so don't bother
490f66d6476d51cc02333d6eb398a5cd94b67f48Timo Sirainen changing it */
47d5cc09738defd0020c797866e2a25a344aa65aTimo Sirainen permissions_r->file_create_gid = (gid_t)-1;
490f66d6476d51cc02333d6eb398a5cd94b67f48Timo Sirainen } else if (getegid() == st.st_gid) {
490f66d6476d51cc02333d6eb398a5cd94b67f48Timo Sirainen /* using our own gid, no need to change it */
47d5cc09738defd0020c797866e2a25a344aa65aTimo Sirainen permissions_r->file_create_gid = (gid_t)-1;
490f66d6476d51cc02333d6eb398a5cd94b67f48Timo Sirainen } else {
47d5cc09738defd0020c797866e2a25a344aa65aTimo Sirainen permissions_r->file_create_gid = st.st_gid;
490f66d6476d51cc02333d6eb398a5cd94b67f48Timo Sirainen }
6dd77763f5451269ace733579cf58f2f3b18bca4Timo Sirainen }
6dd77763f5451269ace733579cf58f2f3b18bca4Timo Sirainen
490f66d6476d51cc02333d6eb398a5cd94b67f48Timo Sirainen if (name == NULL) {
47d5cc09738defd0020c797866e2a25a344aa65aTimo Sirainen list->file_create_mode = permissions_r->file_create_mode;
47d5cc09738defd0020c797866e2a25a344aa65aTimo Sirainen list->dir_create_mode = permissions_r->dir_create_mode;
47d5cc09738defd0020c797866e2a25a344aa65aTimo Sirainen list->file_create_gid = permissions_r->file_create_gid;
e156adefc1260d31a145df2f5e9b3c82050d4163Timo Sirainen list->file_create_gid_origin =
47d5cc09738defd0020c797866e2a25a344aa65aTimo Sirainen p_strdup(list->pool,
47d5cc09738defd0020c797866e2a25a344aa65aTimo Sirainen permissions_r->file_create_gid_origin);
d02d34e138e32b4266f5a403d6c51d7803bf322fTimo Sirainen }
d02d34e138e32b4266f5a403d6c51d7803bf322fTimo Sirainen
fe813f74aaccb12f38e1bd9cd338c6a37fa646e5Timo Sirainen if (list->mail_set->mail_debug && name == NULL) {
e5acc283bf030b0b5c79ca4e52d315c516a299faPascal Volk i_debug("Namespace %s: Using permissions from %s: "
a24519c36d5f8fa22f58b2c693ba547e8d175a54Timo Sirainen "mode=0%o gid=%ld", list->ns->prefix,
a24519c36d5f8fa22f58b2c693ba547e8d175a54Timo Sirainen path != NULL ? path : "",
e5acc283bf030b0b5c79ca4e52d315c516a299faPascal Volk (int)list->dir_create_mode,
e5acc283bf030b0b5c79ca4e52d315c516a299faPascal Volk list->file_create_gid == (gid_t)-1 ? -1L :
e5acc283bf030b0b5c79ca4e52d315c516a299faPascal Volk (long)list->file_create_gid);
c78e7a94528078728cc639b26a1c83e11b4d7e1bTimo Sirainen }
490f66d6476d51cc02333d6eb398a5cd94b67f48Timo Sirainen}
490f66d6476d51cc02333d6eb398a5cd94b67f48Timo Sirainen
17cf149e5f47183bfcc1503649dfb92a14f9dcd9Timo Sirainenvoid mailbox_list_get_root_permissions(struct mailbox_list *list,
e5aa8d4c9bdda79c2db03391ec45b37bf774df14Timo Sirainen mode_t *file_mode_r, mode_t *dir_mode_r,
e5aa8d4c9bdda79c2db03391ec45b37bf774df14Timo Sirainen gid_t *gid_r, const char **gid_origin_r)
17cf149e5f47183bfcc1503649dfb92a14f9dcd9Timo Sirainen{
47d5cc09738defd0020c797866e2a25a344aa65aTimo Sirainen struct mailbox_permissions perm;
47d5cc09738defd0020c797866e2a25a344aa65aTimo Sirainen
17cf149e5f47183bfcc1503649dfb92a14f9dcd9Timo Sirainen if (list->file_create_mode != (mode_t)-1) {
e5aa8d4c9bdda79c2db03391ec45b37bf774df14Timo Sirainen *file_mode_r = list->file_create_mode;
e5aa8d4c9bdda79c2db03391ec45b37bf774df14Timo Sirainen *dir_mode_r = list->dir_create_mode;
490f66d6476d51cc02333d6eb398a5cd94b67f48Timo Sirainen *gid_r = list->file_create_gid;
e156adefc1260d31a145df2f5e9b3c82050d4163Timo Sirainen *gid_origin_r = list->file_create_gid_origin;
17cf149e5f47183bfcc1503649dfb92a14f9dcd9Timo Sirainen } else {
47d5cc09738defd0020c797866e2a25a344aa65aTimo Sirainen mailbox_list_get_permissions(list, NULL, &perm);
47d5cc09738defd0020c797866e2a25a344aa65aTimo Sirainen
47d5cc09738defd0020c797866e2a25a344aa65aTimo Sirainen *file_mode_r = perm.file_create_mode;
47d5cc09738defd0020c797866e2a25a344aa65aTimo Sirainen *dir_mode_r = perm.dir_create_mode;
47d5cc09738defd0020c797866e2a25a344aa65aTimo Sirainen *gid_r = perm.file_create_gid;
47d5cc09738defd0020c797866e2a25a344aa65aTimo Sirainen *gid_origin_r = perm.file_create_gid_origin;
490f66d6476d51cc02333d6eb398a5cd94b67f48Timo Sirainen }
fea7b8b3fc182e415b1875d79587c0aa1adb09d7Timo Sirainen}
fea7b8b3fc182e415b1875d79587c0aa1adb09d7Timo Sirainen
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainenstatic int
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainenmailbox_list_stat_parent(struct mailbox_list *list, const char *path,
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen const char **root_dir_r, struct stat *st_r)
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen{
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen const char *p;
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen while (stat(path, st_r) < 0) {
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen if (errno != ENOENT || strcmp(path, "/") == 0) {
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen mailbox_list_set_critical(list, "stat(%s) failed: %m",
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen path);
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen return -1;
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen }
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen p = strrchr(path, '/');
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen if (p == NULL)
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen path = "/";
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen else
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen path = t_strdup_until(path, p);
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen }
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen *root_dir_r = path;
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen return 0;
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen}
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainenstatic const char *
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainenget_expanded_path(const char *unexpanded_start, const char *unexpanded_stop,
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen const char *expanded_full)
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen{
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen const char *ret;
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen unsigned int i, slash_count = 0, slash2_count = 0;
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen /* get the expanded path up to the same amount of '/' characters.
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen if there isn't the same amount of '/' characters, it means %variable
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen expansion added more of them and we can't handle this. */
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen for (i = 0; unexpanded_start+i != unexpanded_stop; i++) {
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen if (unexpanded_start[i] == '/')
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen slash_count++;
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen }
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen for (; unexpanded_start[i] != '\0'; i++) {
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen if (unexpanded_start[i] == '/')
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen slash2_count++;
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen }
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen for (i = 0; expanded_full[i] != '\0'; i++) {
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen if (expanded_full[i] == '/') {
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen if (slash_count == 0)
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen break;
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen slash_count--;
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen }
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen }
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen if (slash_count != 0)
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen return "";
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen ret = t_strndup(expanded_full, i);
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen for (; expanded_full[i] != '\0'; i++) {
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen if (expanded_full[i] == '/') {
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen if (slash2_count == 0)
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen return "";
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen slash2_count--;
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen }
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen }
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen if (slash2_count != 0)
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen return "";
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen return ret;
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen}
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen
be110f0a3888a24282f06820ec0b5068d2b8f906Timo Sirainenint mailbox_list_mkdir_root(struct mailbox_list *list, const char *path,
be110f0a3888a24282f06820ec0b5068d2b8f906Timo Sirainen enum mailbox_list_path_type type)
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen{
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen const char *expanded, *unexpanded, *root_dir, *p, *origin;
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen struct stat st;
e5aa8d4c9bdda79c2db03391ec45b37bf774df14Timo Sirainen mode_t file_mode, dir_mode;
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen gid_t gid;
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen
e5aa8d4c9bdda79c2db03391ec45b37bf774df14Timo Sirainen mailbox_list_get_root_permissions(list, &file_mode, &dir_mode,
e5aa8d4c9bdda79c2db03391ec45b37bf774df14Timo Sirainen &gid, &origin);
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen /* get the directory path up to last %variable. for example
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen unexpanded path may be "/var/mail/%d/%2n/%n/Maildir", and we want
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen to get expanded="/var/mail/domain/nn" */
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen unexpanded = mailbox_list_get_unexpanded_path(list, type);
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen p = strrchr(unexpanded, '%');
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen if (p == NULL)
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen expanded = "";
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen else {
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen while (p != unexpanded && *p != '/') p--;
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen if (p == unexpanded)
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen expanded = "";
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen else {
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen expanded = mailbox_list_get_path(list, NULL, type);
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen expanded = get_expanded_path(unexpanded, p, expanded);
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen }
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen }
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen if (*expanded != '\0') {
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen /* up to this directory get the permissions from the first
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen parent directory that exists, if it has setgid bit
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen enabled. */
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen if (mailbox_list_stat_parent(list, expanded,
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen &root_dir, &st) < 0)
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen return -1;
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen if ((st.st_mode & S_ISGID) != 0 && root_dir != expanded) {
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen if (mkdir_parents_chgrp(expanded, st.st_mode,
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen (gid_t)-1, root_dir) < 0 &&
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen errno != EEXIST) {
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen mailbox_list_set_critical(list,
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen "mkdir(%s) failed: %m", expanded);
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen return -1;
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen }
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen }
e5aa8d4c9bdda79c2db03391ec45b37bf774df14Timo Sirainen if (gid == (gid_t)-1 && (dir_mode & S_ISGID) == 0) {
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen /* change the group for user directories */
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen gid = getegid();
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen }
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen }
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen /* the rest of the directories exist only for one user. create them
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen with default directory permissions */
e5aa8d4c9bdda79c2db03391ec45b37bf774df14Timo Sirainen if (mkdir_parents_chgrp(path, dir_mode, gid, origin) < 0 &&
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen errno != EEXIST) {
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen mailbox_list_set_critical(list, "mkdir(%s) failed: %m", path);
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen return -1;
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen }
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen return 0;
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen}
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen
533bfba437e4120aa29dd45bca2aa87e30ee28a2Timo Sirainenbool mailbox_list_is_valid_pattern(struct mailbox_list *list,
533bfba437e4120aa29dd45bca2aa87e30ee28a2Timo Sirainen const char *pattern)
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen{
6d931bbce16786df431e9ae8201a78a95084316dTimo Sirainen bool ret;
6d931bbce16786df431e9ae8201a78a95084316dTimo Sirainen
6d931bbce16786df431e9ae8201a78a95084316dTimo Sirainen T_BEGIN {
6d931bbce16786df431e9ae8201a78a95084316dTimo Sirainen ret = list->v.is_valid_pattern(list, pattern);
6d931bbce16786df431e9ae8201a78a95084316dTimo Sirainen } T_END;
6d931bbce16786df431e9ae8201a78a95084316dTimo Sirainen return ret;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen}
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainenbool mailbox_list_is_valid_existing_name(struct mailbox_list *list,
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen const char *name)
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen{
6d931bbce16786df431e9ae8201a78a95084316dTimo Sirainen bool ret;
6d931bbce16786df431e9ae8201a78a95084316dTimo Sirainen
9f1a154d6f436e67f22f737f66bb148b502d4d2aTimo Sirainen if (*name == '\0' && *list->ns->prefix != '\0') {
1c885b304f060e3ac4fe04195a2f53457d0ac99eTimo Sirainen /* an ugly way to get to mailbox root (e.g. Maildir/ when
1c885b304f060e3ac4fe04195a2f53457d0ac99eTimo Sirainen it's not the INBOX) */
1c885b304f060e3ac4fe04195a2f53457d0ac99eTimo Sirainen return TRUE;
1c885b304f060e3ac4fe04195a2f53457d0ac99eTimo Sirainen }
1c885b304f060e3ac4fe04195a2f53457d0ac99eTimo Sirainen
6d931bbce16786df431e9ae8201a78a95084316dTimo Sirainen T_BEGIN {
6d931bbce16786df431e9ae8201a78a95084316dTimo Sirainen ret = list->v.is_valid_existing_name(list, name);
6d931bbce16786df431e9ae8201a78a95084316dTimo Sirainen } T_END;
6d931bbce16786df431e9ae8201a78a95084316dTimo Sirainen return ret;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen}
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainenbool mailbox_list_is_valid_create_name(struct mailbox_list *list,
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen const char *name)
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen{
6b067886457724ca13d81e869240500c5bd5d7e2Timo Sirainen const char *p;
e28fa207d1a097fa6e4a867f74ee0761472ef1ceTimo Sirainen int ret;
e28fa207d1a097fa6e4a867f74ee0761472ef1ceTimo Sirainen
6b067886457724ca13d81e869240500c5bd5d7e2Timo Sirainen /* safer to just disallow all control characters */
6b067886457724ca13d81e869240500c5bd5d7e2Timo Sirainen for (p = name; *p != '\0'; p++) {
1c1cecd3dfaf71b0c9499b044023e631841e88aaTimo Sirainen if ((unsigned char)*p < ' ')
6b067886457724ca13d81e869240500c5bd5d7e2Timo Sirainen return FALSE;
6b067886457724ca13d81e869240500c5bd5d7e2Timo Sirainen }
6b067886457724ca13d81e869240500c5bd5d7e2Timo Sirainen
1c1cecd3dfaf71b0c9499b044023e631841e88aaTimo Sirainen if (list->set.utf8)
1c1cecd3dfaf71b0c9499b044023e631841e88aaTimo Sirainen ret = uni_utf8_str_is_valid(name) ? 0 : -1;
1c1cecd3dfaf71b0c9499b044023e631841e88aaTimo Sirainen else T_BEGIN {
e28fa207d1a097fa6e4a867f74ee0761472ef1ceTimo Sirainen string_t *str = t_str_new(256);
e28fa207d1a097fa6e4a867f74ee0761472ef1ceTimo Sirainen ret = imap_utf7_to_utf8(name, str);
e28fa207d1a097fa6e4a867f74ee0761472ef1ceTimo Sirainen } T_END;
e28fa207d1a097fa6e4a867f74ee0761472ef1ceTimo Sirainen return ret < 0 ? FALSE :
e28fa207d1a097fa6e4a867f74ee0761472ef1ceTimo Sirainen list->v.is_valid_create_name(list, name);
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen}
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainenconst char *mailbox_list_get_path(struct mailbox_list *list, const char *name,
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen enum mailbox_list_path_type type)
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen{
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen return list->v.get_path(list, name, type);
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen}
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
e0ca8f2484847b57e20798a9f9c7040708696a90Timo Sirainenconst char *
e0ca8f2484847b57e20798a9f9c7040708696a90Timo Sirainenmailbox_list_get_root_path(const struct mailbox_list_settings *set,
e0ca8f2484847b57e20798a9f9c7040708696a90Timo Sirainen enum mailbox_list_path_type type)
e0ca8f2484847b57e20798a9f9c7040708696a90Timo Sirainen{
e0ca8f2484847b57e20798a9f9c7040708696a90Timo Sirainen const char *path;
e0ca8f2484847b57e20798a9f9c7040708696a90Timo Sirainen
e0ca8f2484847b57e20798a9f9c7040708696a90Timo Sirainen switch (type) {
e0ca8f2484847b57e20798a9f9c7040708696a90Timo Sirainen case MAILBOX_LIST_PATH_TYPE_DIR:
e0ca8f2484847b57e20798a9f9c7040708696a90Timo Sirainen return set->root_dir;
e0ca8f2484847b57e20798a9f9c7040708696a90Timo Sirainen case MAILBOX_LIST_PATH_TYPE_ALT_DIR:
e0ca8f2484847b57e20798a9f9c7040708696a90Timo Sirainen return set->alt_dir;
e0ca8f2484847b57e20798a9f9c7040708696a90Timo Sirainen case MAILBOX_LIST_PATH_TYPE_MAILBOX:
e0ca8f2484847b57e20798a9f9c7040708696a90Timo Sirainen if (*set->mailbox_dir_name == '\0')
e0ca8f2484847b57e20798a9f9c7040708696a90Timo Sirainen return set->root_dir;
e0ca8f2484847b57e20798a9f9c7040708696a90Timo Sirainen path = t_strconcat(set->root_dir, "/",
e0ca8f2484847b57e20798a9f9c7040708696a90Timo Sirainen set->mailbox_dir_name, NULL);
e0ca8f2484847b57e20798a9f9c7040708696a90Timo Sirainen return t_strndup(path, strlen(path)-1);
e0ca8f2484847b57e20798a9f9c7040708696a90Timo Sirainen case MAILBOX_LIST_PATH_TYPE_ALT_MAILBOX:
e0ca8f2484847b57e20798a9f9c7040708696a90Timo Sirainen if (*set->mailbox_dir_name == '\0')
e0ca8f2484847b57e20798a9f9c7040708696a90Timo Sirainen return set->root_dir;
e0ca8f2484847b57e20798a9f9c7040708696a90Timo Sirainen path = t_strconcat(set->alt_dir, "/",
e0ca8f2484847b57e20798a9f9c7040708696a90Timo Sirainen set->mailbox_dir_name, NULL);
2becb54a6342cf326c25db0c9ad010983979e2b4Timo Sirainen return path == NULL ? NULL : t_strndup(path, strlen(path)-1);
e0ca8f2484847b57e20798a9f9c7040708696a90Timo Sirainen case MAILBOX_LIST_PATH_TYPE_CONTROL:
e0ca8f2484847b57e20798a9f9c7040708696a90Timo Sirainen return set->control_dir != NULL ?
e0ca8f2484847b57e20798a9f9c7040708696a90Timo Sirainen set->control_dir : set->root_dir;
e0ca8f2484847b57e20798a9f9c7040708696a90Timo Sirainen case MAILBOX_LIST_PATH_TYPE_INDEX:
e0ca8f2484847b57e20798a9f9c7040708696a90Timo Sirainen return set->index_dir != NULL ?
e0ca8f2484847b57e20798a9f9c7040708696a90Timo Sirainen set->index_dir : set->root_dir;
e0ca8f2484847b57e20798a9f9c7040708696a90Timo Sirainen }
e0ca8f2484847b57e20798a9f9c7040708696a90Timo Sirainen i_unreached();
e0ca8f2484847b57e20798a9f9c7040708696a90Timo Sirainen}
e0ca8f2484847b57e20798a9f9c7040708696a90Timo Sirainen
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainenconst char *mailbox_list_get_temp_prefix(struct mailbox_list *list)
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen{
c040ee67d0ac0fb7375bb543965bf67dcae6affaTimo Sirainen return list->v.get_temp_prefix(list, FALSE);
c040ee67d0ac0fb7375bb543965bf67dcae6affaTimo Sirainen}
c040ee67d0ac0fb7375bb543965bf67dcae6affaTimo Sirainen
c040ee67d0ac0fb7375bb543965bf67dcae6affaTimo Sirainenconst char *mailbox_list_get_global_temp_prefix(struct mailbox_list *list)
c040ee67d0ac0fb7375bb543965bf67dcae6affaTimo Sirainen{
c040ee67d0ac0fb7375bb543965bf67dcae6affaTimo Sirainen return list->v.get_temp_prefix(list, TRUE);
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen}
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
533bfba437e4120aa29dd45bca2aa87e30ee28a2Timo Sirainenconst char *mailbox_list_join_refpattern(struct mailbox_list *list,
533bfba437e4120aa29dd45bca2aa87e30ee28a2Timo Sirainen const char *ref, const char *pattern)
5fb3bff645380804c9db2510940c41db6b8fdb01Timo Sirainen{
533bfba437e4120aa29dd45bca2aa87e30ee28a2Timo Sirainen if (list->v.join_refpattern != NULL)
533bfba437e4120aa29dd45bca2aa87e30ee28a2Timo Sirainen return list->v.join_refpattern(list, ref, pattern);
5160580b0ec3f3288a320987abdf12a990f09df5Timo Sirainen
5160580b0ec3f3288a320987abdf12a990f09df5Timo Sirainen /* the default implementation: */
5160580b0ec3f3288a320987abdf12a990f09df5Timo Sirainen if (*ref != '\0') {
533bfba437e4120aa29dd45bca2aa87e30ee28a2Timo Sirainen /* merge reference and pattern */
533bfba437e4120aa29dd45bca2aa87e30ee28a2Timo Sirainen pattern = t_strconcat(ref, pattern, NULL);
5160580b0ec3f3288a320987abdf12a990f09df5Timo Sirainen }
533bfba437e4120aa29dd45bca2aa87e30ee28a2Timo Sirainen return pattern;
5fb3bff645380804c9db2510940c41db6b8fdb01Timo Sirainen}
5fb3bff645380804c9db2510940c41db6b8fdb01Timo Sirainen
9b2bbd89073e5b78f3f39a19f3f8d7c6d03bbd4cTimo Sirainenint mailbox_has_children(struct mailbox_list *list, const char *name)
9b2bbd89073e5b78f3f39a19f3f8d7c6d03bbd4cTimo Sirainen{
9b2bbd89073e5b78f3f39a19f3f8d7c6d03bbd4cTimo Sirainen struct mailbox_list_iterate_context *iter;
9b2bbd89073e5b78f3f39a19f3f8d7c6d03bbd4cTimo Sirainen const char *pattern;
9b2bbd89073e5b78f3f39a19f3f8d7c6d03bbd4cTimo Sirainen int ret;
9b2bbd89073e5b78f3f39a19f3f8d7c6d03bbd4cTimo Sirainen
9b2bbd89073e5b78f3f39a19f3f8d7c6d03bbd4cTimo Sirainen pattern = t_strdup_printf("%s%c%%", name,
9b2bbd89073e5b78f3f39a19f3f8d7c6d03bbd4cTimo Sirainen mail_namespace_get_sep(list->ns));
9b2bbd89073e5b78f3f39a19f3f8d7c6d03bbd4cTimo Sirainen iter = mailbox_list_iter_init(list, pattern,
9b2bbd89073e5b78f3f39a19f3f8d7c6d03bbd4cTimo Sirainen MAILBOX_LIST_ITER_RETURN_NO_FLAGS);
9b2bbd89073e5b78f3f39a19f3f8d7c6d03bbd4cTimo Sirainen ret = mailbox_list_iter_next(iter) != NULL ? 1 : 0;
9b2bbd89073e5b78f3f39a19f3f8d7c6d03bbd4cTimo Sirainen if (mailbox_list_iter_deinit(&iter) < 0)
9b2bbd89073e5b78f3f39a19f3f8d7c6d03bbd4cTimo Sirainen ret = -1;
9b2bbd89073e5b78f3f39a19f3f8d7c6d03bbd4cTimo Sirainen return ret;
9b2bbd89073e5b78f3f39a19f3f8d7c6d03bbd4cTimo Sirainen}
9b2bbd89073e5b78f3f39a19f3f8d7c6d03bbd4cTimo Sirainen
1c885b304f060e3ac4fe04195a2f53457d0ac99eTimo Sirainenint mailbox_list_mailbox(struct mailbox_list *list, const char *name,
1c885b304f060e3ac4fe04195a2f53457d0ac99eTimo Sirainen enum mailbox_info_flags *flags_r)
1c885b304f060e3ac4fe04195a2f53457d0ac99eTimo Sirainen{
f7ee94201b23b4bd5764cb85cb51d5c995e475ecTimo Sirainen const char *path, *fname, *rootdir, *dir, *inbox;
b6eced3d628ad0c50a3cbc9f966da0edc20108abTimo Sirainen unsigned int len;
1c885b304f060e3ac4fe04195a2f53457d0ac99eTimo Sirainen
688d869f3449827ac9b5a0a02dbc1b27177b6d20Timo Sirainen *flags_r = 0;
688d869f3449827ac9b5a0a02dbc1b27177b6d20Timo Sirainen
9ba91492d2eb29199674b669c673332ae2b01438Timo Sirainen if ((list->ns->flags & NAMESPACE_FLAG_INBOX_USER) != 0 &&
9ba91492d2eb29199674b669c673332ae2b01438Timo Sirainen strcasecmp(name, "INBOX") == 0) {
9ba91492d2eb29199674b669c673332ae2b01438Timo Sirainen /* special handling for INBOX, mainly because with Maildir++
9ba91492d2eb29199674b669c673332ae2b01438Timo Sirainen layout it needs to check if the cur/ directory exists,
9ba91492d2eb29199674b669c673332ae2b01438Timo Sirainen which the Maildir++ layout backend itself can't do.. */
9ba91492d2eb29199674b669c673332ae2b01438Timo Sirainen struct mailbox *box;
9ba91492d2eb29199674b669c673332ae2b01438Timo Sirainen enum mailbox_existence existence;
9ba91492d2eb29199674b669c673332ae2b01438Timo Sirainen int ret;
9ba91492d2eb29199674b669c673332ae2b01438Timo Sirainen
7cf1c7dd3dfd989cba1ed32a8e17c1b031c4629bTimo Sirainen /* kludge: with imapc backend we can get here with
7cf1c7dd3dfd989cba1ed32a8e17c1b031c4629bTimo Sirainen list=Maildir++ (for indexes), but list->ns->list=imapc */
7cf1c7dd3dfd989cba1ed32a8e17c1b031c4629bTimo Sirainen box = mailbox_alloc(list->ns->list, "INBOX", 0);
9ba91492d2eb29199674b669c673332ae2b01438Timo Sirainen ret = mailbox_exists(box, FALSE, &existence);
9ba91492d2eb29199674b669c673332ae2b01438Timo Sirainen mailbox_free(&box);
9ba91492d2eb29199674b669c673332ae2b01438Timo Sirainen if (ret < 0) {
9ba91492d2eb29199674b669c673332ae2b01438Timo Sirainen /* this can only be an internal error */
9ba91492d2eb29199674b669c673332ae2b01438Timo Sirainen mailbox_list_set_internal_error(list);
9ba91492d2eb29199674b669c673332ae2b01438Timo Sirainen return -1;
9ba91492d2eb29199674b669c673332ae2b01438Timo Sirainen }
9ba91492d2eb29199674b669c673332ae2b01438Timo Sirainen switch (existence) {
9ba91492d2eb29199674b669c673332ae2b01438Timo Sirainen case MAILBOX_EXISTENCE_NONE:
9ba91492d2eb29199674b669c673332ae2b01438Timo Sirainen case MAILBOX_EXISTENCE_NOSELECT:
9ba91492d2eb29199674b669c673332ae2b01438Timo Sirainen *flags_r |= MAILBOX_NONEXISTENT;
9ba91492d2eb29199674b669c673332ae2b01438Timo Sirainen return 0;
9ba91492d2eb29199674b669c673332ae2b01438Timo Sirainen case MAILBOX_EXISTENCE_SELECT:
9ba91492d2eb29199674b669c673332ae2b01438Timo Sirainen break;
9ba91492d2eb29199674b669c673332ae2b01438Timo Sirainen }
9ba91492d2eb29199674b669c673332ae2b01438Timo Sirainen return 1;
9ba91492d2eb29199674b669c673332ae2b01438Timo Sirainen }
9ba91492d2eb29199674b669c673332ae2b01438Timo Sirainen
ba36444cdf332c75ecdd2696e34c391eea75597cTimo Sirainen if (list->v.get_mailbox_flags == NULL) {
ba36444cdf332c75ecdd2696e34c391eea75597cTimo Sirainen /* can't do this optimized. do it the slow way. */
ba36444cdf332c75ecdd2696e34c391eea75597cTimo Sirainen struct mailbox_list_iterate_context *iter;
ba36444cdf332c75ecdd2696e34c391eea75597cTimo Sirainen const struct mailbox_info *info;
ba36444cdf332c75ecdd2696e34c391eea75597cTimo Sirainen const char *vname;
ba36444cdf332c75ecdd2696e34c391eea75597cTimo Sirainen
ba36444cdf332c75ecdd2696e34c391eea75597cTimo Sirainen vname = mailbox_list_get_vname(list, name);
ba36444cdf332c75ecdd2696e34c391eea75597cTimo Sirainen iter = mailbox_list_iter_init(list, vname, 0);
ba36444cdf332c75ecdd2696e34c391eea75597cTimo Sirainen info = mailbox_list_iter_next(iter);
ba36444cdf332c75ecdd2696e34c391eea75597cTimo Sirainen if (info == NULL)
ba36444cdf332c75ecdd2696e34c391eea75597cTimo Sirainen *flags_r = MAILBOX_NONEXISTENT;
ba36444cdf332c75ecdd2696e34c391eea75597cTimo Sirainen else
ba36444cdf332c75ecdd2696e34c391eea75597cTimo Sirainen *flags_r = info->flags;
ba36444cdf332c75ecdd2696e34c391eea75597cTimo Sirainen return mailbox_list_iter_deinit(&iter);
ba36444cdf332c75ecdd2696e34c391eea75597cTimo Sirainen }
ba36444cdf332c75ecdd2696e34c391eea75597cTimo Sirainen
b6eced3d628ad0c50a3cbc9f966da0edc20108abTimo Sirainen rootdir = mailbox_list_get_path(list, NULL,
b6eced3d628ad0c50a3cbc9f966da0edc20108abTimo Sirainen MAILBOX_LIST_PATH_TYPE_MAILBOX);
ba36444cdf332c75ecdd2696e34c391eea75597cTimo Sirainen i_assert(rootdir != NULL);
1c885b304f060e3ac4fe04195a2f53457d0ac99eTimo Sirainen path = mailbox_list_get_path(list, name, MAILBOX_LIST_PATH_TYPE_DIR);
b6eced3d628ad0c50a3cbc9f966da0edc20108abTimo Sirainen
f7ee94201b23b4bd5764cb85cb51d5c995e475ecTimo Sirainen fname = strrchr(path, '/');
f7ee94201b23b4bd5764cb85cb51d5c995e475ecTimo Sirainen if (fname == NULL) {
f7ee94201b23b4bd5764cb85cb51d5c995e475ecTimo Sirainen fname = path;
f7ee94201b23b4bd5764cb85cb51d5c995e475ecTimo Sirainen dir = "/";
f7ee94201b23b4bd5764cb85cb51d5c995e475ecTimo Sirainen } else {
f7ee94201b23b4bd5764cb85cb51d5c995e475ecTimo Sirainen dir = t_strdup_until(path, fname);
f7ee94201b23b4bd5764cb85cb51d5c995e475ecTimo Sirainen fname++;
f7ee94201b23b4bd5764cb85cb51d5c995e475ecTimo Sirainen }
f7ee94201b23b4bd5764cb85cb51d5c995e475ecTimo Sirainen
b6eced3d628ad0c50a3cbc9f966da0edc20108abTimo Sirainen len = strlen(rootdir);
b6eced3d628ad0c50a3cbc9f966da0edc20108abTimo Sirainen if (strncmp(path, rootdir, len) == 0 && path[len] == '/') {
f7ee94201b23b4bd5764cb85cb51d5c995e475ecTimo Sirainen /* looking up a regular mailbox under mail root dir */
f7ee94201b23b4bd5764cb85cb51d5c995e475ecTimo Sirainen } else if ((list->ns->flags & NAMESPACE_FLAG_INBOX_USER) != 0 &&
f7ee94201b23b4bd5764cb85cb51d5c995e475ecTimo Sirainen strcasecmp(name, "INBOX") == 0) {
f7ee94201b23b4bd5764cb85cb51d5c995e475ecTimo Sirainen /* looking up INBOX that's elsewhere */
dca6d617a23e3f93af3b8df59acb46478179fe55Timo Sirainen } else {
f7ee94201b23b4bd5764cb85cb51d5c995e475ecTimo Sirainen /* looking up the root dir itself */
f7ee94201b23b4bd5764cb85cb51d5c995e475ecTimo Sirainen dir = path;
b6eced3d628ad0c50a3cbc9f966da0edc20108abTimo Sirainen fname = "";
dca6d617a23e3f93af3b8df59acb46478179fe55Timo Sirainen }
e22efc90e109ade2936eea0b062a99480310fd41Timo Sirainen if (*fname == '\0' && *name == '\0' &&
eb64c3586d854cddd693f0b811d897399076a441Timo Sirainen (list->ns->flags & NAMESPACE_FLAG_INBOX_USER) != 0) {
e22efc90e109ade2936eea0b062a99480310fd41Timo Sirainen /* if INBOX is in e.g. ~/Maildir, it shouldn't be possible to
e22efc90e109ade2936eea0b062a99480310fd41Timo Sirainen access it also via namespace prefix. */
e22efc90e109ade2936eea0b062a99480310fd41Timo Sirainen inbox = mailbox_list_get_path(list, "INBOX",
e22efc90e109ade2936eea0b062a99480310fd41Timo Sirainen MAILBOX_LIST_PATH_TYPE_MAILBOX);
f7ee94201b23b4bd5764cb85cb51d5c995e475ecTimo Sirainen if (strcmp(inbox, dir) == 0) {
e22efc90e109ade2936eea0b062a99480310fd41Timo Sirainen *flags_r |= MAILBOX_NONEXISTENT;
e22efc90e109ade2936eea0b062a99480310fd41Timo Sirainen return 0;
e22efc90e109ade2936eea0b062a99480310fd41Timo Sirainen }
e22efc90e109ade2936eea0b062a99480310fd41Timo Sirainen }
f7ee94201b23b4bd5764cb85cb51d5c995e475ecTimo Sirainen return list->v.get_mailbox_flags(list, dir, fname,
dca6d617a23e3f93af3b8df59acb46478179fe55Timo Sirainen MAILBOX_LIST_FILE_TYPE_UNKNOWN,
fb365addee8210c28e6856e34d690dd8d1636993Timo Sirainen flags_r);
1c885b304f060e3ac4fe04195a2f53457d0ac99eTimo Sirainen}
1c885b304f060e3ac4fe04195a2f53457d0ac99eTimo Sirainen
78bb4a443b4ca97ce27976916953e4898aa8a125Timo Sirainenstatic bool mailbox_list_init_changelog(struct mailbox_list *list)
78bb4a443b4ca97ce27976916953e4898aa8a125Timo Sirainen{
78bb4a443b4ca97ce27976916953e4898aa8a125Timo Sirainen const char *path;
e5aa8d4c9bdda79c2db03391ec45b37bf774df14Timo Sirainen mode_t file_mode, dir_mode;
32f4b9ab23148bec295196a8029a43ff89ce124dTimo Sirainen gid_t gid;
32f4b9ab23148bec295196a8029a43ff89ce124dTimo Sirainen const char *gid_origin;
78bb4a443b4ca97ce27976916953e4898aa8a125Timo Sirainen
78bb4a443b4ca97ce27976916953e4898aa8a125Timo Sirainen if (list->changelog != NULL)
78bb4a443b4ca97ce27976916953e4898aa8a125Timo Sirainen return TRUE;
78bb4a443b4ca97ce27976916953e4898aa8a125Timo Sirainen
78bb4a443b4ca97ce27976916953e4898aa8a125Timo Sirainen /* don't do this in mailbox_list_create(), because _get_path() might be
78bb4a443b4ca97ce27976916953e4898aa8a125Timo Sirainen overridden by storage (mbox). */
78bb4a443b4ca97ce27976916953e4898aa8a125Timo Sirainen path = mailbox_list_get_path(list, NULL, MAILBOX_LIST_PATH_TYPE_INDEX);
76a8438e7420ae212ac5a37c20312738e04aa63eTimo Sirainen if (*path == '\0')
78bb4a443b4ca97ce27976916953e4898aa8a125Timo Sirainen return FALSE;
32f4b9ab23148bec295196a8029a43ff89ce124dTimo Sirainen
32f4b9ab23148bec295196a8029a43ff89ce124dTimo Sirainen path = t_strconcat(path, "/"MAILBOX_LOG_FILE_NAME, NULL);
32f4b9ab23148bec295196a8029a43ff89ce124dTimo Sirainen list->changelog = mailbox_log_alloc(path);
32f4b9ab23148bec295196a8029a43ff89ce124dTimo Sirainen
e5aa8d4c9bdda79c2db03391ec45b37bf774df14Timo Sirainen mailbox_list_get_root_permissions(list, &file_mode, &dir_mode,
e5aa8d4c9bdda79c2db03391ec45b37bf774df14Timo Sirainen &gid, &gid_origin);
e5aa8d4c9bdda79c2db03391ec45b37bf774df14Timo Sirainen mailbox_log_set_permissions(list->changelog, dir_mode, gid, gid_origin);
32f4b9ab23148bec295196a8029a43ff89ce124dTimo Sirainen return TRUE;
78bb4a443b4ca97ce27976916953e4898aa8a125Timo Sirainen}
78bb4a443b4ca97ce27976916953e4898aa8a125Timo Sirainen
37847ec8eaec9ad55c9df10ae109efe7b37ac573Timo Sirainenvoid mailbox_list_add_change(struct mailbox_list *list,
37847ec8eaec9ad55c9df10ae109efe7b37ac573Timo Sirainen enum mailbox_log_record_type type,
de62ce819d59a529530da4b57be1b8d6dad13d6bTimo Sirainen const guid_128_t mailbox_guid)
37847ec8eaec9ad55c9df10ae109efe7b37ac573Timo Sirainen{
37847ec8eaec9ad55c9df10ae109efe7b37ac573Timo Sirainen struct mailbox_log_record rec;
3fe67ec75ccae1230bb9eb9f16affc48377f6441Timo Sirainen time_t stamp;
37847ec8eaec9ad55c9df10ae109efe7b37ac573Timo Sirainen
3fe67ec75ccae1230bb9eb9f16affc48377f6441Timo Sirainen if (!mailbox_list_init_changelog(list) ||
de62ce819d59a529530da4b57be1b8d6dad13d6bTimo Sirainen guid_128_is_empty(mailbox_guid))
37847ec8eaec9ad55c9df10ae109efe7b37ac573Timo Sirainen return;
37847ec8eaec9ad55c9df10ae109efe7b37ac573Timo Sirainen
4d84348ffcbb60de566108562c95ad64629e7a53Timo Sirainen if (!list->index_root_dir_created) {
4d84348ffcbb60de566108562c95ad64629e7a53Timo Sirainen if (mailbox_list_create_missing_index_dir(list, NULL) < 0)
4d84348ffcbb60de566108562c95ad64629e7a53Timo Sirainen return;
4d84348ffcbb60de566108562c95ad64629e7a53Timo Sirainen }
4d84348ffcbb60de566108562c95ad64629e7a53Timo Sirainen
3fe67ec75ccae1230bb9eb9f16affc48377f6441Timo Sirainen stamp = list->changelog_timestamp != (time_t)-1 ?
3fe67ec75ccae1230bb9eb9f16affc48377f6441Timo Sirainen list->changelog_timestamp : ioloop_time;
3fe67ec75ccae1230bb9eb9f16affc48377f6441Timo Sirainen
37847ec8eaec9ad55c9df10ae109efe7b37ac573Timo Sirainen memset(&rec, 0, sizeof(rec));
37847ec8eaec9ad55c9df10ae109efe7b37ac573Timo Sirainen rec.type = type;
37847ec8eaec9ad55c9df10ae109efe7b37ac573Timo Sirainen memcpy(rec.mailbox_guid, mailbox_guid, sizeof(rec.mailbox_guid));
3fe67ec75ccae1230bb9eb9f16affc48377f6441Timo Sirainen mailbox_log_record_set_timestamp(&rec, stamp);
37847ec8eaec9ad55c9df10ae109efe7b37ac573Timo Sirainen (void)mailbox_log_append(list->changelog, &rec);
37847ec8eaec9ad55c9df10ae109efe7b37ac573Timo Sirainen}
37847ec8eaec9ad55c9df10ae109efe7b37ac573Timo Sirainen
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainenint mailbox_list_set_subscribed(struct mailbox_list *list,
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen const char *name, bool set)
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen{
de62ce819d59a529530da4b57be1b8d6dad13d6bTimo Sirainen guid_128_t guid;
5a0fc34c5cc525334c5a10531713017ae321c573Timo Sirainen int ret;
37847ec8eaec9ad55c9df10ae109efe7b37ac573Timo Sirainen
b13f738e8eb3f24dc2abf2c804f954b4d864ac6fTimo Sirainen /* make sure we'll refresh the file on next list */
b13f738e8eb3f24dc2abf2c804f954b4d864ac6fTimo Sirainen list->subscriptions_mtime = (time_t)-1;
b13f738e8eb3f24dc2abf2c804f954b4d864ac6fTimo Sirainen
5a0fc34c5cc525334c5a10531713017ae321c573Timo Sirainen if ((ret = list->v.set_subscribed(list, name, set)) <= 0)
5a0fc34c5cc525334c5a10531713017ae321c573Timo Sirainen return ret;
37847ec8eaec9ad55c9df10ae109efe7b37ac573Timo Sirainen
37847ec8eaec9ad55c9df10ae109efe7b37ac573Timo Sirainen /* subscriptions are about names, not about mailboxes. it's possible
7fc0f80480063a9d4cb9e8c07b50db2a5627799eTimo Sirainen to have a subscription to nonexistent mailbox. renames also don't
37847ec8eaec9ad55c9df10ae109efe7b37ac573Timo Sirainen change subscriptions. so instead of using actual GUIDs, we'll use
37847ec8eaec9ad55c9df10ae109efe7b37ac573Timo Sirainen hash of the name. */
9c66dd5c3e2ba484a5c7cdb98a139bda31fdfaa4Timo Sirainen mailbox_name_get_sha128(name, guid);
37847ec8eaec9ad55c9df10ae109efe7b37ac573Timo Sirainen mailbox_list_add_change(list, set ? MAILBOX_LOG_RECORD_SUBSCRIBE :
37847ec8eaec9ad55c9df10ae109efe7b37ac573Timo Sirainen MAILBOX_LOG_RECORD_UNSUBSCRIBE, guid);
37847ec8eaec9ad55c9df10ae109efe7b37ac573Timo Sirainen return 0;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen}
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
a91bd6256b33729531c33ff8bc66ee1ae95840f9Timo Sirainenint mailbox_list_create_dir(struct mailbox_list *list, const char *name)
a91bd6256b33729531c33ff8bc66ee1ae95840f9Timo Sirainen{
1c1e571f549f09f6547ed142f4b3a725dd9f7245Timo Sirainen if (!mailbox_list_is_valid_create_name(list, name) || *name == '\0') {
a91bd6256b33729531c33ff8bc66ee1ae95840f9Timo Sirainen mailbox_list_set_error(list, MAIL_ERROR_PARAMS,
a91bd6256b33729531c33ff8bc66ee1ae95840f9Timo Sirainen "Invalid mailbox name");
a91bd6256b33729531c33ff8bc66ee1ae95840f9Timo Sirainen return -1;
a91bd6256b33729531c33ff8bc66ee1ae95840f9Timo Sirainen }
a91bd6256b33729531c33ff8bc66ee1ae95840f9Timo Sirainen return list->v.create_mailbox_dir(list, name,
a91bd6256b33729531c33ff8bc66ee1ae95840f9Timo Sirainen MAILBOX_DIR_CREATE_TYPE_ONLY_NOSELECT);
a91bd6256b33729531c33ff8bc66ee1ae95840f9Timo Sirainen}
a91bd6256b33729531c33ff8bc66ee1ae95840f9Timo Sirainen
2f30b72d49fbff0c4096125c139e4bdfef45669cTimo Sirainenint mailbox_list_delete_dir(struct mailbox_list *list, const char *name)
2f30b72d49fbff0c4096125c139e4bdfef45669cTimo Sirainen{
2f30b72d49fbff0c4096125c139e4bdfef45669cTimo Sirainen if (!mailbox_list_is_valid_existing_name(list, name) || *name == '\0') {
2f30b72d49fbff0c4096125c139e4bdfef45669cTimo Sirainen mailbox_list_set_error(list, MAIL_ERROR_PARAMS,
2f30b72d49fbff0c4096125c139e4bdfef45669cTimo Sirainen "Invalid mailbox name");
2f30b72d49fbff0c4096125c139e4bdfef45669cTimo Sirainen return -1;
2f30b72d49fbff0c4096125c139e4bdfef45669cTimo Sirainen }
2f30b72d49fbff0c4096125c139e4bdfef45669cTimo Sirainen return list->v.delete_dir(list, name);
2f30b72d49fbff0c4096125c139e4bdfef45669cTimo Sirainen}
2f30b72d49fbff0c4096125c139e4bdfef45669cTimo Sirainen
0b25846ba794ce19536a24d4065beaf2a0bd9464Timo Sirainenint mailbox_list_delete_symlink(struct mailbox_list *list, const char *name)
0b25846ba794ce19536a24d4065beaf2a0bd9464Timo Sirainen{
0b25846ba794ce19536a24d4065beaf2a0bd9464Timo Sirainen if (!mailbox_list_is_valid_existing_name(list, name) || *name == '\0') {
0b25846ba794ce19536a24d4065beaf2a0bd9464Timo Sirainen mailbox_list_set_error(list, MAIL_ERROR_PARAMS,
0b25846ba794ce19536a24d4065beaf2a0bd9464Timo Sirainen "Invalid mailbox name");
0b25846ba794ce19536a24d4065beaf2a0bd9464Timo Sirainen return -1;
0b25846ba794ce19536a24d4065beaf2a0bd9464Timo Sirainen }
0b25846ba794ce19536a24d4065beaf2a0bd9464Timo Sirainen return list->v.delete_symlink(list, name);
0b25846ba794ce19536a24d4065beaf2a0bd9464Timo Sirainen}
0b25846ba794ce19536a24d4065beaf2a0bd9464Timo Sirainen
de62ce819d59a529530da4b57be1b8d6dad13d6bTimo Sirainenvoid mailbox_name_get_sha128(const char *name, guid_128_t guid_128_r)
0185427dd52fddec6fc76d6e99c7659620d4366eTimo Sirainen{
9c66dd5c3e2ba484a5c7cdb98a139bda31fdfaa4Timo Sirainen unsigned char sha[SHA1_RESULTLEN];
6bc5fed79741503437c6d46d9f282b66bd029c6bTimo Sirainen
9c66dd5c3e2ba484a5c7cdb98a139bda31fdfaa4Timo Sirainen sha1_get_digest(name, strlen(name), sha);
de62ce819d59a529530da4b57be1b8d6dad13d6bTimo Sirainen memcpy(guid_128_r, sha, I_MIN(GUID_128_SIZE, sizeof(sha)));
6bc5fed79741503437c6d46d9f282b66bd029c6bTimo Sirainen}
6bc5fed79741503437c6d46d9f282b66bd029c6bTimo Sirainen
37847ec8eaec9ad55c9df10ae109efe7b37ac573Timo Sirainenstruct mailbox_log *mailbox_list_get_changelog(struct mailbox_list *list)
37847ec8eaec9ad55c9df10ae109efe7b37ac573Timo Sirainen{
78bb4a443b4ca97ce27976916953e4898aa8a125Timo Sirainen return !mailbox_list_init_changelog(list) ? NULL : list->changelog;
37847ec8eaec9ad55c9df10ae109efe7b37ac573Timo Sirainen}
37847ec8eaec9ad55c9df10ae109efe7b37ac573Timo Sirainen
3fe67ec75ccae1230bb9eb9f16affc48377f6441Timo Sirainenvoid mailbox_list_set_changelog_timestamp(struct mailbox_list *list,
3fe67ec75ccae1230bb9eb9f16affc48377f6441Timo Sirainen time_t stamp)
5a0b68eeaf48cd1655057f36f19357146bf08e1dTimo Sirainen{
3fe67ec75ccae1230bb9eb9f16affc48377f6441Timo Sirainen list->changelog_timestamp = stamp;
5a0b68eeaf48cd1655057f36f19357146bf08e1dTimo Sirainen}
5a0b68eeaf48cd1655057f36f19357146bf08e1dTimo Sirainen
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainenbool mailbox_list_name_is_too_large(const char *name, char sep)
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen{
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen unsigned int levels = 1, level_len = 0;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen for (; *name != '\0'; name++) {
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen if (*name == sep) {
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen if (level_len > MAILBOX_MAX_HIERARCHY_NAME_LENGTH)
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen return TRUE;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen levels++;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen level_len = 0;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen } else {
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen level_len++;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen }
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen }
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen if (level_len > MAILBOX_MAX_HIERARCHY_NAME_LENGTH)
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen return TRUE;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen if (levels > MAILBOX_MAX_HIERARCHY_LEVELS)
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen return TRUE;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen return FALSE;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen}
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
ff4bb2dfb5714eeb0408d3bb862de1646351d097Timo Sirainenenum mailbox_list_file_type
43d32cbe60fdaef2699d99f1ca259053e9350411Timo Sirainenmailbox_list_get_file_type(const struct dirent *d ATTR_UNUSED)
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen{
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen enum mailbox_list_file_type type;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen#ifdef HAVE_DIRENT_D_TYPE
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen switch (d->d_type) {
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen case DT_UNKNOWN:
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen type = MAILBOX_LIST_FILE_TYPE_UNKNOWN;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen break;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen case DT_REG:
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen type = MAILBOX_LIST_FILE_TYPE_FILE;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen break;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen case DT_DIR:
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen type = MAILBOX_LIST_FILE_TYPE_DIR;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen break;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen case DT_LNK:
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen type = MAILBOX_LIST_FILE_TYPE_SYMLINK;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen break;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen default:
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen type = MAILBOX_LIST_FILE_TYPE_OTHER;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen break;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen }
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen#else
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen type = MAILBOX_LIST_FILE_TYPE_UNKNOWN;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen#endif
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen return type;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen}
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
ff1777f61db8b45c72d8bcb843f9106eb0227ab6Timo Sirainenstatic bool
ff1777f61db8b45c72d8bcb843f9106eb0227ab6Timo Sirainenmailbox_list_try_get_home_path(struct mailbox_list *list, const char **name)
ff1777f61db8b45c72d8bcb843f9106eb0227ab6Timo Sirainen{
ff1777f61db8b45c72d8bcb843f9106eb0227ab6Timo Sirainen if ((*name)[1] == '/') {
ff1777f61db8b45c72d8bcb843f9106eb0227ab6Timo Sirainen /* ~/dir - use the configured home directory */
ff1777f61db8b45c72d8bcb843f9106eb0227ab6Timo Sirainen if (mail_user_try_home_expand(list->ns->user, name) < 0)
ff1777f61db8b45c72d8bcb843f9106eb0227ab6Timo Sirainen return FALSE;
ff1777f61db8b45c72d8bcb843f9106eb0227ab6Timo Sirainen } else {
ff1777f61db8b45c72d8bcb843f9106eb0227ab6Timo Sirainen /* ~otheruser/dir - assume we're using system users */
ff1777f61db8b45c72d8bcb843f9106eb0227ab6Timo Sirainen if (home_try_expand(name) < 0)
ff1777f61db8b45c72d8bcb843f9106eb0227ab6Timo Sirainen return FALSE;
ff1777f61db8b45c72d8bcb843f9106eb0227ab6Timo Sirainen }
ff1777f61db8b45c72d8bcb843f9106eb0227ab6Timo Sirainen return TRUE;
ff1777f61db8b45c72d8bcb843f9106eb0227ab6Timo Sirainen}
ff1777f61db8b45c72d8bcb843f9106eb0227ab6Timo Sirainen
96f2533c48ce5def0004931606a2fdf275578880Timo Sirainenbool mailbox_list_try_get_absolute_path(struct mailbox_list *list,
96f2533c48ce5def0004931606a2fdf275578880Timo Sirainen const char **name)
96f2533c48ce5def0004931606a2fdf275578880Timo Sirainen{
ff1777f61db8b45c72d8bcb843f9106eb0227ab6Timo Sirainen const char *root_dir, *path, *mailbox_name;
ff1777f61db8b45c72d8bcb843f9106eb0227ab6Timo Sirainen unsigned int len;
96f2533c48ce5def0004931606a2fdf275578880Timo Sirainen
ff1777f61db8b45c72d8bcb843f9106eb0227ab6Timo Sirainen if (!list->mail_set->mail_full_filesystem_access)
96f2533c48ce5def0004931606a2fdf275578880Timo Sirainen return FALSE;
96f2533c48ce5def0004931606a2fdf275578880Timo Sirainen
ff1777f61db8b45c72d8bcb843f9106eb0227ab6Timo Sirainen if (**name == '~') {
ff1777f61db8b45c72d8bcb843f9106eb0227ab6Timo Sirainen /* try to expand home directory */
ff1777f61db8b45c72d8bcb843f9106eb0227ab6Timo Sirainen if (!mailbox_list_try_get_home_path(list, name)) {
ff1777f61db8b45c72d8bcb843f9106eb0227ab6Timo Sirainen /* fallback to using actual "~name" mailbox */
ff1777f61db8b45c72d8bcb843f9106eb0227ab6Timo Sirainen return FALSE;
ff1777f61db8b45c72d8bcb843f9106eb0227ab6Timo Sirainen }
96f2533c48ce5def0004931606a2fdf275578880Timo Sirainen } else {
ff1777f61db8b45c72d8bcb843f9106eb0227ab6Timo Sirainen if (**name != '/')
ff1777f61db8b45c72d8bcb843f9106eb0227ab6Timo Sirainen return FALSE;
96f2533c48ce5def0004931606a2fdf275578880Timo Sirainen }
ff1777f61db8b45c72d8bcb843f9106eb0227ab6Timo Sirainen
ff1777f61db8b45c72d8bcb843f9106eb0227ab6Timo Sirainen /* okay, we have an absolute path now. but check first if it points to
ff1777f61db8b45c72d8bcb843f9106eb0227ab6Timo Sirainen same directory as one of our regular mailboxes. */
ff1777f61db8b45c72d8bcb843f9106eb0227ab6Timo Sirainen root_dir = mailbox_list_get_path(list, NULL,
ff1777f61db8b45c72d8bcb843f9106eb0227ab6Timo Sirainen MAILBOX_LIST_PATH_TYPE_MAILBOX);
ff1777f61db8b45c72d8bcb843f9106eb0227ab6Timo Sirainen len = strlen(root_dir);
ff1777f61db8b45c72d8bcb843f9106eb0227ab6Timo Sirainen if (strncmp(root_dir, *name, len) == 0 && (*name)[len] == '/') {
ff1777f61db8b45c72d8bcb843f9106eb0227ab6Timo Sirainen mailbox_name = *name + len + 1;
ff1777f61db8b45c72d8bcb843f9106eb0227ab6Timo Sirainen path = mailbox_list_get_path(list, mailbox_name,
ff1777f61db8b45c72d8bcb843f9106eb0227ab6Timo Sirainen MAILBOX_LIST_PATH_TYPE_MAILBOX);
ff1777f61db8b45c72d8bcb843f9106eb0227ab6Timo Sirainen if (strcmp(path, *name) == 0) {
ff1777f61db8b45c72d8bcb843f9106eb0227ab6Timo Sirainen /* yeah, we can replace the full path with mailbox
ff1777f61db8b45c72d8bcb843f9106eb0227ab6Timo Sirainen name. this way we can use indexes. */
ff1777f61db8b45c72d8bcb843f9106eb0227ab6Timo Sirainen *name = mailbox_name;
ff1777f61db8b45c72d8bcb843f9106eb0227ab6Timo Sirainen return FALSE;
ff1777f61db8b45c72d8bcb843f9106eb0227ab6Timo Sirainen }
ff1777f61db8b45c72d8bcb843f9106eb0227ab6Timo Sirainen }
ff1777f61db8b45c72d8bcb843f9106eb0227ab6Timo Sirainen return TRUE;
96f2533c48ce5def0004931606a2fdf275578880Timo Sirainen}
96f2533c48ce5def0004931606a2fdf275578880Timo Sirainen
be110f0a3888a24282f06820ec0b5068d2b8f906Timo Sirainenint mailbox_list_mkdir(struct mailbox_list *list,
be110f0a3888a24282f06820ec0b5068d2b8f906Timo Sirainen const char *mailbox, const char *path)
472369cba85d9f7c995dda60e7cd01d78b4a960aTimo Sirainen{
47d5cc09738defd0020c797866e2a25a344aa65aTimo Sirainen struct mailbox_permissions perm;
472369cba85d9f7c995dda60e7cd01d78b4a960aTimo Sirainen
47d5cc09738defd0020c797866e2a25a344aa65aTimo Sirainen mailbox_list_get_permissions(list, mailbox, &perm);
47d5cc09738defd0020c797866e2a25a344aa65aTimo Sirainen if (mkdir_parents_chgrp(path, perm.dir_create_mode,
47d5cc09738defd0020c797866e2a25a344aa65aTimo Sirainen perm.file_create_gid,
47d5cc09738defd0020c797866e2a25a344aa65aTimo Sirainen perm.file_create_gid_origin) < 0 &&
472369cba85d9f7c995dda60e7cd01d78b4a960aTimo Sirainen errno != EEXIST) {
472369cba85d9f7c995dda60e7cd01d78b4a960aTimo Sirainen mailbox_list_set_critical(list, "mkdir_parents(%s) failed: %m",
be110f0a3888a24282f06820ec0b5068d2b8f906Timo Sirainen path);
472369cba85d9f7c995dda60e7cd01d78b4a960aTimo Sirainen return -1;
472369cba85d9f7c995dda60e7cd01d78b4a960aTimo Sirainen }
472369cba85d9f7c995dda60e7cd01d78b4a960aTimo Sirainen return 0;
472369cba85d9f7c995dda60e7cd01d78b4a960aTimo Sirainen}
472369cba85d9f7c995dda60e7cd01d78b4a960aTimo Sirainen
be110f0a3888a24282f06820ec0b5068d2b8f906Timo Sirainenint mailbox_list_mkdir_parent(struct mailbox_list *list,
be110f0a3888a24282f06820ec0b5068d2b8f906Timo Sirainen const char *mailbox, const char *path)
be110f0a3888a24282f06820ec0b5068d2b8f906Timo Sirainen{
be110f0a3888a24282f06820ec0b5068d2b8f906Timo Sirainen const char *p;
be110f0a3888a24282f06820ec0b5068d2b8f906Timo Sirainen
be110f0a3888a24282f06820ec0b5068d2b8f906Timo Sirainen p = strrchr(path, '/');
be110f0a3888a24282f06820ec0b5068d2b8f906Timo Sirainen if (p == NULL)
be110f0a3888a24282f06820ec0b5068d2b8f906Timo Sirainen return 0;
be110f0a3888a24282f06820ec0b5068d2b8f906Timo Sirainen
be110f0a3888a24282f06820ec0b5068d2b8f906Timo Sirainen return mailbox_list_mkdir(list, mailbox, t_strdup_until(path, p));
be110f0a3888a24282f06820ec0b5068d2b8f906Timo Sirainen}
be110f0a3888a24282f06820ec0b5068d2b8f906Timo Sirainen
4d84348ffcbb60de566108562c95ad64629e7a53Timo Sirainenint mailbox_list_create_missing_index_dir(struct mailbox_list *list,
4d84348ffcbb60de566108562c95ad64629e7a53Timo Sirainen const char *name)
4d84348ffcbb60de566108562c95ad64629e7a53Timo Sirainen{
47d5cc09738defd0020c797866e2a25a344aa65aTimo Sirainen const char *root_dir, *index_dir, *parent_dir, *p;
47d5cc09738defd0020c797866e2a25a344aa65aTimo Sirainen struct mailbox_permissions perm;
4d84348ffcbb60de566108562c95ad64629e7a53Timo Sirainen unsigned int n = 0;
4d84348ffcbb60de566108562c95ad64629e7a53Timo Sirainen
4d84348ffcbb60de566108562c95ad64629e7a53Timo Sirainen list->index_root_dir_created = TRUE;
4d84348ffcbb60de566108562c95ad64629e7a53Timo Sirainen root_dir = mailbox_list_get_path(list, name,
4d84348ffcbb60de566108562c95ad64629e7a53Timo Sirainen MAILBOX_LIST_PATH_TYPE_MAILBOX);
4d84348ffcbb60de566108562c95ad64629e7a53Timo Sirainen index_dir = mailbox_list_get_path(list, name,
4d84348ffcbb60de566108562c95ad64629e7a53Timo Sirainen MAILBOX_LIST_PATH_TYPE_INDEX);
7cf1c7dd3dfd989cba1ed32a8e17c1b031c4629bTimo Sirainen if (*index_dir == '\0')
4d84348ffcbb60de566108562c95ad64629e7a53Timo Sirainen return 0;
7cf1c7dd3dfd989cba1ed32a8e17c1b031c4629bTimo Sirainen if (strcmp(index_dir, root_dir) == 0) {
7cf1c7dd3dfd989cba1ed32a8e17c1b031c4629bTimo Sirainen if ((list->props & MAILBOX_LIST_PROP_AUTOCREATE_DIRS) == 0)
7cf1c7dd3dfd989cba1ed32a8e17c1b031c4629bTimo Sirainen return 0;
7cf1c7dd3dfd989cba1ed32a8e17c1b031c4629bTimo Sirainen /* the directory might not have been created yet */
7cf1c7dd3dfd989cba1ed32a8e17c1b031c4629bTimo Sirainen }
4d84348ffcbb60de566108562c95ad64629e7a53Timo Sirainen
b30f98f260924a50343c4d0493a7c4fe5e714d0fTimo Sirainen if (name == NULL) {
be110f0a3888a24282f06820ec0b5068d2b8f906Timo Sirainen return mailbox_list_mkdir_root(list, index_dir,
be110f0a3888a24282f06820ec0b5068d2b8f906Timo Sirainen MAILBOX_LIST_PATH_TYPE_INDEX);
b30f98f260924a50343c4d0493a7c4fe5e714d0fTimo Sirainen }
be110f0a3888a24282f06820ec0b5068d2b8f906Timo Sirainen
47d5cc09738defd0020c797866e2a25a344aa65aTimo Sirainen mailbox_list_get_permissions(list, name, &perm);
47d5cc09738defd0020c797866e2a25a344aa65aTimo Sirainen while (mkdir_chgrp(index_dir, perm.dir_create_mode,
47d5cc09738defd0020c797866e2a25a344aa65aTimo Sirainen perm.file_create_gid,
47d5cc09738defd0020c797866e2a25a344aa65aTimo Sirainen perm.file_create_gid_origin) < 0) {
4d84348ffcbb60de566108562c95ad64629e7a53Timo Sirainen if (errno == EEXIST)
4d84348ffcbb60de566108562c95ad64629e7a53Timo Sirainen break;
4d84348ffcbb60de566108562c95ad64629e7a53Timo Sirainen
4d84348ffcbb60de566108562c95ad64629e7a53Timo Sirainen p = strrchr(index_dir, '/');
4d84348ffcbb60de566108562c95ad64629e7a53Timo Sirainen if (errno != ENOENT || p == NULL || ++n == 2) {
4d84348ffcbb60de566108562c95ad64629e7a53Timo Sirainen mailbox_list_set_critical(list,
4d84348ffcbb60de566108562c95ad64629e7a53Timo Sirainen "mkdir(%s) failed: %m", index_dir);
4d84348ffcbb60de566108562c95ad64629e7a53Timo Sirainen return -1;
4d84348ffcbb60de566108562c95ad64629e7a53Timo Sirainen }
4d84348ffcbb60de566108562c95ad64629e7a53Timo Sirainen /* create the parent directory first */
4d84348ffcbb60de566108562c95ad64629e7a53Timo Sirainen parent_dir = t_strdup_until(index_dir, p);
be110f0a3888a24282f06820ec0b5068d2b8f906Timo Sirainen if (mailbox_list_mkdir_root(list, parent_dir,
be110f0a3888a24282f06820ec0b5068d2b8f906Timo Sirainen MAILBOX_LIST_PATH_TYPE_INDEX) < 0)
4d84348ffcbb60de566108562c95ad64629e7a53Timo Sirainen return -1;
4d84348ffcbb60de566108562c95ad64629e7a53Timo Sirainen }
4d84348ffcbb60de566108562c95ad64629e7a53Timo Sirainen return 0;
4d84348ffcbb60de566108562c95ad64629e7a53Timo Sirainen}
4d84348ffcbb60de566108562c95ad64629e7a53Timo Sirainen
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainenconst char *mailbox_list_get_last_error(struct mailbox_list *list,
ff7056842f14fd3b30a2d327dfab165b9d15dd30Timo Sirainen enum mail_error *error_r)
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen{
563273bdac80393af63b9520cbf4d24cc0efd028Timo Sirainen if (error_r != NULL)
563273bdac80393af63b9520cbf4d24cc0efd028Timo Sirainen *error_r = list->error;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
ff7056842f14fd3b30a2d327dfab165b9d15dd30Timo Sirainen return list->error_string != NULL ? list->error_string :
ff7056842f14fd3b30a2d327dfab165b9d15dd30Timo Sirainen "Unknown internal list error";
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen}
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainenvoid mailbox_list_clear_error(struct mailbox_list *list)
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen{
ff7056842f14fd3b30a2d327dfab165b9d15dd30Timo Sirainen i_free_and_null(list->error_string);
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
ff7056842f14fd3b30a2d327dfab165b9d15dd30Timo Sirainen list->error = MAIL_ERROR_NONE;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen}
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
ff7056842f14fd3b30a2d327dfab165b9d15dd30Timo Sirainenvoid mailbox_list_set_error(struct mailbox_list *list,
ff7056842f14fd3b30a2d327dfab165b9d15dd30Timo Sirainen enum mail_error error, const char *string)
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen{
ff7056842f14fd3b30a2d327dfab165b9d15dd30Timo Sirainen i_free(list->error_string);
ff7056842f14fd3b30a2d327dfab165b9d15dd30Timo Sirainen list->error_string = i_strdup(string);
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
ff7056842f14fd3b30a2d327dfab165b9d15dd30Timo Sirainen list->error = error;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen}
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
5fb3bff645380804c9db2510940c41db6b8fdb01Timo Sirainenvoid mailbox_list_set_internal_error(struct mailbox_list *list)
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen{
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen struct tm *tm;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen char str[256];
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen tm = localtime(&ioloop_time);
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
ff7056842f14fd3b30a2d327dfab165b9d15dd30Timo Sirainen i_free(list->error_string);
ff7056842f14fd3b30a2d327dfab165b9d15dd30Timo Sirainen list->error_string =
ac4e6609cbdca594db1b1c02afb1e372ab22e060Timo Sirainen strftime(str, sizeof(str),
ac4e6609cbdca594db1b1c02afb1e372ab22e060Timo Sirainen MAIL_ERRSTR_CRITICAL_MSG_STAMP, tm) > 0 ?
ac4e6609cbdca594db1b1c02afb1e372ab22e060Timo Sirainen i_strdup(str) : i_strdup(MAIL_ERRSTR_CRITICAL_MSG);
ff7056842f14fd3b30a2d327dfab165b9d15dd30Timo Sirainen list->error = MAIL_ERROR_TEMP;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen}
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainenvoid mailbox_list_set_critical(struct mailbox_list *list, const char *fmt, ...)
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen{
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen va_list va;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen va_start(va, fmt);
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen i_error("%s", t_strdup_vprintf(fmt, va));
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen va_end(va);
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen /* critical errors may contain sensitive data, so let user
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen see only "Internal error" with a timestamp to make it
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen easier to look from log files the actual error message. */
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen mailbox_list_set_internal_error(list);
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen}
ff7056842f14fd3b30a2d327dfab165b9d15dd30Timo Sirainen
ff7056842f14fd3b30a2d327dfab165b9d15dd30Timo Sirainenbool mailbox_list_set_error_from_errno(struct mailbox_list *list)
ff7056842f14fd3b30a2d327dfab165b9d15dd30Timo Sirainen{
ff7056842f14fd3b30a2d327dfab165b9d15dd30Timo Sirainen const char *error_string;
ff7056842f14fd3b30a2d327dfab165b9d15dd30Timo Sirainen enum mail_error error;
ff7056842f14fd3b30a2d327dfab165b9d15dd30Timo Sirainen
ff7056842f14fd3b30a2d327dfab165b9d15dd30Timo Sirainen if (!mail_error_from_errno(&error, &error_string))
ff7056842f14fd3b30a2d327dfab165b9d15dd30Timo Sirainen return FALSE;
ff7056842f14fd3b30a2d327dfab165b9d15dd30Timo Sirainen
ff7056842f14fd3b30a2d327dfab165b9d15dd30Timo Sirainen mailbox_list_set_error(list, error, error_string);
ff7056842f14fd3b30a2d327dfab165b9d15dd30Timo Sirainen return TRUE;
ff7056842f14fd3b30a2d327dfab165b9d15dd30Timo Sirainen}