cydir-storage.c revision 71c4ac143fefd57aeec6298489c4559b6f13c67b
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
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen/* Copyright (c) 2007-2008 Dovecot authors, see the included COPYING file */
2cfe9983ce7a6280636ee12beccc2e865111967bTimo Sirainen#define CREATE_MODE 0770 /* umask() should limit it more */
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen MODULE_CONTEXT(obj, cydir_mailbox_list_module)
ccc895c0358108d2304239063e940b7d75f364abTimo Sirainenstatic MODULE_CONTEXT_DEFINE_INIT(cydir_mailbox_list_module,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainencydir_list_delete_mailbox(struct mailbox_list *list, const char *name);
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainenstatic int cydir_list_iter_is_mailbox(struct mailbox_list_iterate_context *ctx,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainencydir_get_list_settings(struct mailbox_list_settings *list_set,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen const char *data, enum mail_storage_flags flags,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen bool debug = (flags & MAIL_STORAGE_FLAG_DEBUG) != 0;
b6a7e0a7899e7f5d60c23cdaa50e025e4c67d05fTimo Sirainen list_set->subscription_fname = CYDIR_SUBSCRIPTION_FILE_NAME;
b6a7e0a7899e7f5d60c23cdaa50e025e4c67d05fTimo Sirainen if (data == NULL || *data == '\0' || *data == ':') {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen /* we won't do any guessing for this format. */
b6a7e0a7899e7f5d60c23cdaa50e025e4c67d05fTimo Sirainen return mailbox_list_settings_parse(data, list_set, layout_r, NULL,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen pool = pool_alloconly_create("cydir storage", 512+256);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen storage = p_new(pool, struct cydir_storage, 1);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenstatic int cydir_create(struct mail_storage *_storage, const char *data,
55773f17bccf6361d6599ffcbe072d7c9fe205bfTimo Sirainen const char **error_r)
90adcaa0a00eba29b7fbd50ca66be11c8d086d6aTimo Sirainen struct cydir_storage *storage = (struct cydir_storage *)_storage;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (cydir_get_list_settings(&list_set, data, _storage->flags,
ccc895c0358108d2304239063e940b7d75f364abTimo Sirainen list_set.mail_storage_flags = &_storage->flags;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen list_set.lock_method = &_storage->lock_method;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if ((_storage->flags & MAIL_STORAGE_FLAG_NO_AUTOCREATE) != 0) {
b6a7e0a7899e7f5d60c23cdaa50e025e4c67d05fTimo Sirainen "Root mail directory doesn't exist: %s",
90adcaa0a00eba29b7fbd50ca66be11c8d086d6aTimo Sirainen "stat(%s) failed: %m",
90adcaa0a00eba29b7fbd50ca66be11c8d086d6aTimo Sirainen *error_r = mail_storage_eacces_msg("mkdir", list_set.root_dir);
90adcaa0a00eba29b7fbd50ca66be11c8d086d6aTimo Sirainen *error_r = t_strdup_printf("mkdir(%s) failed: %m",
8000c86be02008b74acc71fa422444dc432e2c01Timo Sirainen if (mailbox_list_alloc(layout, &_storage->list, error_r) < 0)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen storage->list_module_ctx.super = _storage->list->v;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen _storage->list->v.iter_is_mailbox = cydir_list_iter_is_mailbox;
90adcaa0a00eba29b7fbd50ca66be11c8d086d6aTimo Sirainen _storage->list->v.delete_mailbox = cydir_list_delete_mailbox;
90adcaa0a00eba29b7fbd50ca66be11c8d086d6aTimo Sirainen MODULE_CONTEXT_SET_FULL(_storage->list, cydir_mailbox_list_module,
a63bc30f167a221691ad0a3fe5cd45c57444411eTimo Sirainen /* finish list init after we've overridden vfuncs */
90adcaa0a00eba29b7fbd50ca66be11c8d086d6aTimo Sirainen mailbox_list_init(_storage->list, _storage->ns, &list_set,
90adcaa0a00eba29b7fbd50ca66be11c8d086d6aTimo Sirainen mail_storage_get_list_flags(_storage->flags));
90adcaa0a00eba29b7fbd50ca66be11c8d086d6aTimo Sirainenstatic int create_cydir(struct mail_storage *storage, const char *path)
90adcaa0a00eba29b7fbd50ca66be11c8d086d6aTimo Sirainen if (mkdir_parents(path, CREATE_MODE) < 0 && errno != EEXIST) {
a63bc30f167a221691ad0a3fe5cd45c57444411eTimo Sirainen if (!mail_storage_set_error_from_errno(storage)) {
3ec2c1f31631bb5ff86f5fc93a563c33e5cae90dTimo Sirainenstatic struct mailbox *
3ec2c1f31631bb5ff86f5fc93a563c33e5cae90dTimo Sirainencydir_open(struct cydir_storage *storage, const char *name,
3ec2c1f31631bb5ff86f5fc93a563c33e5cae90dTimo Sirainen struct mail_storage *_storage = &storage->storage;
c36ec256c1bd1abe1c12e792cf64f0b7e3b3135aTimo Sirainen path = mailbox_list_get_path(_storage->list, name,
c36ec256c1bd1abe1c12e792cf64f0b7e3b3135aTimo Sirainen index = index_storage_alloc(_storage, name, flags, CYDIR_INDEX_PREFIX);
c36ec256c1bd1abe1c12e792cf64f0b7e3b3135aTimo Sirainen mail_index_set_fsync_types(index, MAIL_INDEX_SYNC_TYPE_APPEND |
c36ec256c1bd1abe1c12e792cf64f0b7e3b3135aTimo Sirainen pool = pool_alloconly_create("cydir mailbox", 1024+512);
c36ec256c1bd1abe1c12e792cf64f0b7e3b3135aTimo Sirainen index_storage_mailbox_init(&mbox->ibox, name, flags, FALSE);
c36ec256c1bd1abe1c12e792cf64f0b7e3b3135aTimo Sirainenstatic struct mailbox *
c36ec256c1bd1abe1c12e792cf64f0b7e3b3135aTimo Sirainencydir_mailbox_open(struct mail_storage *_storage, const char *name,
c36ec256c1bd1abe1c12e792cf64f0b7e3b3135aTimo Sirainen struct istream *input, enum mailbox_open_flags flags)
c36ec256c1bd1abe1c12e792cf64f0b7e3b3135aTimo Sirainen struct cydir_storage *storage = (struct cydir_storage *)_storage;
c36ec256c1bd1abe1c12e792cf64f0b7e3b3135aTimo Sirainen "cydir doesn't support streamed mailboxes");
c36ec256c1bd1abe1c12e792cf64f0b7e3b3135aTimo Sirainen path = mailbox_list_get_path(_storage->list, name,
c36ec256c1bd1abe1c12e792cf64f0b7e3b3135aTimo Sirainen /* INBOX always exists, create it */
c36ec256c1bd1abe1c12e792cf64f0b7e3b3135aTimo Sirainen mail_storage_set_error(_storage, MAIL_ERROR_NOTFOUND,
c36ec256c1bd1abe1c12e792cf64f0b7e3b3135aTimo Sirainen mail_storage_set_critical(_storage, "stat(%s) failed: %m",
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenstatic int cydir_mailbox_create(struct mail_storage *_storage,
c36ec256c1bd1abe1c12e792cf64f0b7e3b3135aTimo Sirainen path = mailbox_list_get_path(_storage->list, name,
d67fde1a8ebc1d85704c5986d8f93aae97eccef3Timo Sirainen mail_storage_set_error(_storage, MAIL_ERROR_NOTPOSSIBLE,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen "Mailbox already exists");
b142deb9a831c89b1bb9129ada655f3e56b9d4ccTimo Sirainencydir_delete_nonrecursive(struct mailbox_list *list, const char *path,
c36ec256c1bd1abe1c12e792cf64f0b7e3b3135aTimo Sirainen unsigned int dir_len;
c36ec256c1bd1abe1c12e792cf64f0b7e3b3135aTimo Sirainen if (!mailbox_list_set_error_from_errno(list)) {
c36ec256c1bd1abe1c12e792cf64f0b7e3b3135aTimo Sirainen /* skip . and .. */
c36ec256c1bd1abe1c12e792cf64f0b7e3b3135aTimo Sirainen if (d->d_name[1] == '.' && d->d_name[2] == '\0')
c36ec256c1bd1abe1c12e792cf64f0b7e3b3135aTimo Sirainen /* trying to unlink() a directory gives either EPERM or EISDIR
c36ec256c1bd1abe1c12e792cf64f0b7e3b3135aTimo Sirainen (non-POSIX). it doesn't really work anywhere in practise,
c36ec256c1bd1abe1c12e792cf64f0b7e3b3135aTimo Sirainen so don't bother stat()ing the file first */
c36ec256c1bd1abe1c12e792cf64f0b7e3b3135aTimo Sirainen else if (errno != ENOENT && errno != EISDIR && errno != EPERM) {
c36ec256c1bd1abe1c12e792cf64f0b7e3b3135aTimo Sirainen mailbox_list_set_critical(list, "unlink(%s) failed: %m",
366d6311c9d5bac6613e3cd64619eb878adce9ecTimo Sirainen mailbox_list_set_critical(list, "closedir(%s) failed: %m",
3ec2c1f31631bb5ff86f5fc93a563c33e5cae90dTimo Sirainen else if (errno != ENOENT && errno != ENOTEMPTY) {
683253c6f556b71d7946452644fc3d633f47153cTimo Sirainen mailbox_list_set_critical(list, "rmdir(%s) failed: %m", path);
b142deb9a831c89b1bb9129ada655f3e56b9d4ccTimo Sirainen mailbox_list_set_error(list, MAIL_ERROR_NOTPOSSIBLE,
d67fde1a8ebc1d85704c5986d8f93aae97eccef3Timo Sirainencydir_list_delete_mailbox(struct mailbox_list *list, const char *name)
d67fde1a8ebc1d85704c5986d8f93aae97eccef3Timo Sirainen struct cydir_storage *storage = CYDIR_LIST_CONTEXT(list);
d67fde1a8ebc1d85704c5986d8f93aae97eccef3Timo Sirainen const char *src;
b142deb9a831c89b1bb9129ada655f3e56b9d4ccTimo Sirainen /* Make sure the indexes are closed before trying to delete the
d67fde1a8ebc1d85704c5986d8f93aae97eccef3Timo Sirainen directory that contains them. It can still fail with some NFS
d67fde1a8ebc1d85704c5986d8f93aae97eccef3Timo Sirainen implementations if indexes are opened by another session, but
d67fde1a8ebc1d85704c5986d8f93aae97eccef3Timo Sirainen that can't really be helped. */
d67fde1a8ebc1d85704c5986d8f93aae97eccef3Timo Sirainen /* delete the index and control directories */
b6a7e0a7899e7f5d60c23cdaa50e025e4c67d05fTimo Sirainen if (storage->list_module_ctx.super.delete_mailbox(list, name) < 0)
944d096df698dd2b476e376277e9afd634b53270Timo Sirainen /* check if the mailbox actually exists */
b6a7e0a7899e7f5d60c23cdaa50e025e4c67d05fTimo Sirainen src = mailbox_list_get_path(list, name, MAILBOX_LIST_PATH_TYPE_MAILBOX);
b142deb9a831c89b1bb9129ada655f3e56b9d4ccTimo Sirainen mailbox_list_set_error(list, MAIL_ERROR_NOTFOUND,
d67fde1a8ebc1d85704c5986d8f93aae97eccef3Timo Sirainen return cydir_delete_nonrecursive(list, src, name);
b6a7e0a7899e7f5d60c23cdaa50e025e4c67d05fTimo Sirainenstatic void cydir_notify_changes(struct mailbox *box)
b6a7e0a7899e7f5d60c23cdaa50e025e4c67d05fTimo Sirainen struct cydir_mailbox *mbox = (struct cydir_mailbox *)box;
b6a7e0a7899e7f5d60c23cdaa50e025e4c67d05fTimo Sirainen index_mailbox_check_add(&mbox->ibox, mbox->path);
d67fde1a8ebc1d85704c5986d8f93aae97eccef3Timo Sirainenstatic int cydir_list_iter_is_mailbox(struct mailbox_list_iterate_context *ctx
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen /* try to avoid stat() with these checks */
6ef7e31619edfaa17ed044b45861d106a86191efTimo Sirainen /* it's a file */
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen *flags |= MAILBOX_NOSELECT | MAILBOX_NOINFERIORS;
910fa4e4204a73d3d24c03f3059dd24e727ca057Timo Sirainen /* need to stat() then */
910fa4e4204a73d3d24c03f3059dd24e727ca057Timo Sirainen mail_path = t_strconcat(dir, "/", fname, NULL);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen /* non-directory */
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen *flags |= MAILBOX_NOSELECT | MAILBOX_NOINFERIORS;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen /* no subdirectories */
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen } else if (*ctx->list->set.maildir_name != '\0') {
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen /* non-default configuration: we have one directory
a12399903f415a7e14c2816cffa2f7a09dcbb097Timo Sirainen containing the mailboxes. if there are 3 links,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen either this is a selectable mailbox without children
439980f88f421039dea8335e92d3fa82b3f470a1Timo Sirainen or non-selectable mailbox with children */
90adcaa0a00eba29b7fbd50ca66be11c8d086d6aTimo Sirainen /* default configuration: all subdirectories are
90adcaa0a00eba29b7fbd50ca66be11c8d086d6aTimo Sirainen child mailboxes. */
87460b08cb97b31cde640d4975a6aa2c1d0e7226Timo Sirainen /* non-selectable. probably either access denied, or symlink
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen destination not found. don't bother logging errors. */
static void cydir_class_init(void)
static void cydir_class_deinit(void)
NULL,
NULL,
NULL,
NULL,