1 /* Copyright (c) 2002-2018 Dovecot authors, see the included COPYING file */
2 
3 #include "lib.h"
4 #include "array.h"
5 #include "istream.h"
6 #include "ostream.h"
7 #include "ioloop.h"
8 #include "str.h"
9 #include "str-sanitize.h"
10 #include "mkdir-parents.h"
11 #include "dict.h"
12 #include "fs-api.h"
13 #include "message-header-parser.h"
14 #include "mail-index-alloc-cache.h"
15 #include "mail-index-private.h"
16 #include "mail-index-modseq.h"
17 #include "mailbox-log.h"
18 #include "mailbox-list-private.h"
19 #include "mail-search-build.h"
20 #include "index-storage.h"
21 #include "index-mail.h"
22 #include "index-attachment.h"
23 #include "index-thread-private.h"
24 #include "index-mailbox-size.h"
25 
26 #include <time.h>
27 #include <unistd.h>
28 #include <sys/stat.h>
29 
30 #define LOCK_NOTIFY_INTERVAL 30
31 
32 struct index_storage_module index_storage_module =
33 	MODULE_CONTEXT_INIT(&mail_storage_module_register);
34 
set_cache_decisions(struct mail_cache * cache,const char * set,const char * fields,enum mail_cache_decision_type dec)35 static void set_cache_decisions(struct mail_cache *cache,
36 				const char *set, const char *fields,
37 				enum mail_cache_decision_type dec)
38 {
39 	struct mail_cache_field field;
40 	const char *const *arr;
41 	unsigned int idx;
42 
43 	if (fields == NULL || *fields == '\0')
44 		return;
45 
46 	for (arr = t_strsplit_spaces(fields, " ,"); *arr != NULL; arr++) {
47 		const char *name = *arr;
48 
49 		idx = mail_cache_register_lookup(cache, name);
50 		if (idx != UINT_MAX) {
51 			field = *mail_cache_register_get_field(cache, idx);
52 		} else if (strncasecmp(name, "hdr.", 4) == 0) {
53 			/* Do some sanity checking for the header name. Mainly
54 			   to make sure there aren't UTF-8 characters that look
55 			   like their ASCII equivalents or are completely
56 			   invisible. */
57 			if (message_header_name_is_valid(name+4)) {
58 				i_zero(&field);
59 				field.name = name;
60 				field.type = MAIL_CACHE_FIELD_HEADER;
61 			} else {
62 				i_error("%s: Header name '%s' has invalid character, ignoring",
63 					set, name);
64 				continue;
65 			}
66 		} else {
67 			i_error("%s: Unknown cache field name '%s', ignoring",
68 				set, *arr);
69 			continue;
70 		}
71 
72 		field.decision = dec;
73 		mail_cache_register_fields(cache, &field, 1);
74 	}
75 }
76 
index_cache_register_defaults(struct mailbox * box)77 static void index_cache_register_defaults(struct mailbox *box)
78 {
79 	struct index_mailbox_context *ibox = INDEX_STORAGE_CONTEXT(box);
80 	const struct mail_storage_settings *set = box->storage->set;
81 	struct mail_cache *cache = box->cache;
82 
83 	ibox->cache_fields = i_malloc(sizeof(global_cache_fields));
84 	memcpy(ibox->cache_fields, global_cache_fields,
85 	       sizeof(global_cache_fields));
86 	mail_cache_register_fields(cache, ibox->cache_fields,
87 				   MAIL_INDEX_CACHE_FIELD_COUNT);
88 
89 	if (strcmp(set->mail_never_cache_fields, "*") == 0) {
90 		/* all caching disabled for now */
91 		box->mail_cache_disabled = TRUE;
92 		return;
93 	}
94 
95 	set_cache_decisions(cache, "mail_cache_fields",
96 			    set->mail_cache_fields,
97 			    MAIL_CACHE_DECISION_TEMP);
98 	set_cache_decisions(cache, "mail_always_cache_fields",
99 			    set->mail_always_cache_fields,
100 			    MAIL_CACHE_DECISION_YES |
101 			    MAIL_CACHE_DECISION_FORCED);
102 	set_cache_decisions(cache, "mail_never_cache_fields",
103 			    set->mail_never_cache_fields,
104 			    MAIL_CACHE_DECISION_NO |
105 			    MAIL_CACHE_DECISION_FORCED);
106 }
107 
index_storage_lock_notify(struct mailbox * box,enum mailbox_lock_notify_type notify_type,unsigned int secs_left)108 void index_storage_lock_notify(struct mailbox *box,
109 			       enum mailbox_lock_notify_type notify_type,
110 			       unsigned int secs_left)
111 {
112 	struct index_mailbox_context *ibox = INDEX_STORAGE_CONTEXT(box);
113 	struct mail_storage *storage = box->storage;
114 	const char *str;
115 	time_t now;
116 
117 	/* if notify type changes, print the message immediately */
118 	now = time(NULL);
119 	if (ibox->last_notify_type == MAILBOX_LOCK_NOTIFY_NONE ||
120 	    ibox->last_notify_type == notify_type) {
121 		if (ibox->last_notify_type == MAILBOX_LOCK_NOTIFY_NONE &&
122 		    notify_type == MAILBOX_LOCK_NOTIFY_MAILBOX_OVERRIDE) {
123 			/* first override notification, show it */
124 		} else {
125 			if (now < ibox->next_lock_notify || secs_left < 15)
126 				return;
127 		}
128 	}
129 
130 	ibox->next_lock_notify = now + LOCK_NOTIFY_INTERVAL;
131         ibox->last_notify_type = notify_type;
132 
133 	switch (notify_type) {
134 	case MAILBOX_LOCK_NOTIFY_NONE:
135 		break;
136 	case MAILBOX_LOCK_NOTIFY_MAILBOX_ABORT:
137 		if (storage->callbacks.notify_no == NULL)
138 			break;
139 
140 		str = t_strdup_printf("Mailbox is locked, will abort in "
141 				      "%u seconds", secs_left);
142 		storage->callbacks.
143 			notify_no(box, str, storage->callback_context);
144 		break;
145 	case MAILBOX_LOCK_NOTIFY_MAILBOX_OVERRIDE:
146 		if (storage->callbacks.notify_ok == NULL)
147 			break;
148 
149 		str = t_strdup_printf("Stale mailbox lock file detected, "
150 				      "will override in %u seconds", secs_left);
151 		storage->callbacks.
152 			notify_ok(box, str, storage->callback_context);
153 		break;
154 	}
155 }
156 
index_storage_lock_notify_reset(struct mailbox * box)157 void index_storage_lock_notify_reset(struct mailbox *box)
158 {
159 	struct index_mailbox_context *ibox = INDEX_STORAGE_CONTEXT(box);
160 
161 	ibox->next_lock_notify = time(NULL) + LOCK_NOTIFY_INTERVAL;
162 	ibox->last_notify_type = MAILBOX_LOCK_NOTIFY_NONE;
163 }
164 
165 static int
index_mailbox_alloc_index(struct mailbox * box,struct mail_index ** index_r)166 index_mailbox_alloc_index(struct mailbox *box, struct mail_index **index_r)
167 {
168 	const char *index_dir, *mailbox_path;
169 
170 	if (mailbox_get_path_to(box, MAILBOX_LIST_PATH_TYPE_MAILBOX,
171 				&mailbox_path) < 0)
172 		return -1;
173 	if ((box->flags & MAILBOX_FLAG_NO_INDEX_FILES) != 0 ||
174 	    mailbox_get_path_to(box, MAILBOX_LIST_PATH_TYPE_INDEX,
175 				&index_dir) <= 0)
176 		index_dir = NULL;
177 	/* Note that this may cause box->event to live longer than box */
178 	*index_r = mail_index_alloc_cache_get(box->event,
179 					      mailbox_path, index_dir,
180 					      box->index_prefix);
181 	return 0;
182 }
183 
index_storage_mailbox_exists(struct mailbox * box,bool auto_boxes,enum mailbox_existence * existence_r)184 int index_storage_mailbox_exists(struct mailbox *box, bool auto_boxes,
185 				 enum mailbox_existence *existence_r)
186 {
187 	if (auto_boxes && mailbox_is_autocreated(box)) {
188 		*existence_r = MAILBOX_EXISTENCE_SELECT;
189 		return 0;
190 	}
191 
192 	return index_storage_mailbox_exists_full(box, NULL, existence_r);
193 }
194 
index_storage_mailbox_exists_full(struct mailbox * box,const char * subdir,enum mailbox_existence * existence_r)195 int index_storage_mailbox_exists_full(struct mailbox *box, const char *subdir,
196 				      enum mailbox_existence *existence_r)
197 {
198 	struct stat st;
199 	const char *path, *path2, *index_path;
200 	int ret;
201 
202 	/* see if it's selectable */
203 	ret = mailbox_get_path_to(box, MAILBOX_LIST_PATH_TYPE_MAILBOX, &path);
204 	if (ret < 0) {
205 		if (mailbox_get_last_mail_error(box) != MAIL_ERROR_NOTFOUND)
206 			return -1;
207 		*existence_r = MAILBOX_EXISTENCE_NONE;
208 		return 0;
209 	}
210 	if (ret == 0) {
211 		/* no mailboxes in this storage? */
212 		*existence_r = MAILBOX_EXISTENCE_NONE;
213 		return 0;
214 	}
215 
216 	ret = (subdir != NULL || !box->list->set.iter_from_index_dir) ? 0 :
217 		mailbox_get_path_to(box, MAILBOX_LIST_PATH_TYPE_INDEX, &index_path);
218 	if (ret > 0 && strcmp(path, index_path) != 0) {
219 		/* index directory is different - prefer looking it up first
220 		   since it might be on a faster storage. since the directory
221 		   itself exists also for \NoSelect mailboxes, we'll need to
222 		   check the dovecot.index.log existence. */
223 		index_path = t_strconcat(index_path, "/", box->index_prefix,
224 					 ".log", NULL);
225 		if (stat(index_path, &st) == 0) {
226 			*existence_r = MAILBOX_EXISTENCE_SELECT;
227 			return 0;
228 		}
229 	}
230 
231 	if (subdir != NULL)
232 		path = t_strconcat(path, "/", subdir, NULL);
233 	if (stat(path, &st) == 0) {
234 		*existence_r = MAILBOX_EXISTENCE_SELECT;
235 		return 0;
236 	}
237 	if (!ENOTFOUND(errno) && errno != EACCES) {
238 		mailbox_set_critical(box, "stat(%s) failed: %m", path);
239 		return -1;
240 	}
241 
242 	/* see if it's non-selectable */
243 	if (mailbox_get_path_to(box, MAILBOX_LIST_PATH_TYPE_DIR, &path2) <= 0 ||
244 	    (strcmp(path, path2) != 0 && stat(path2, &st) == 0)) {
245 		*existence_r = MAILBOX_EXISTENCE_NOSELECT;
246 		return 0;
247 	}
248 	*existence_r = MAILBOX_EXISTENCE_NONE;
249 	return 0;
250 }
251 
index_storage_mailbox_alloc_index(struct mailbox * box)252 int index_storage_mailbox_alloc_index(struct mailbox *box)
253 {
254 	const char *cache_dir;
255 
256 	if (box->index != NULL)
257 		return 0;
258 
259 	if (mailbox_create_missing_dir(box, MAILBOX_LIST_PATH_TYPE_INDEX) < 0)
260 		return -1;
261 	if (index_mailbox_alloc_index(box, &box->index) < 0)
262 		return -1;
263 
264 	if (mailbox_get_path_to(box, MAILBOX_LIST_PATH_TYPE_INDEX_CACHE,
265 				&cache_dir) > 0) {
266 		if (mailbox_create_missing_dir(box, MAILBOX_LIST_PATH_TYPE_INDEX_CACHE) < 0)
267 			return -1;
268 		mail_index_set_cache_dir(box->index, cache_dir);
269 	}
270 	mail_index_set_fsync_mode(box->index,
271 				  box->storage->set->parsed_fsync_mode, 0);
272 	mail_index_set_lock_method(box->index,
273 		box->storage->set->parsed_lock_method,
274 		mail_storage_get_lock_timeout(box->storage, UINT_MAX));
275 
276 	const struct mail_storage_settings *set = box->storage->set;
277 	struct mail_index_optimization_settings optimization_set = {
278 		.index = {
279 			.rewrite_min_log_bytes = set->mail_index_rewrite_min_log_bytes,
280 			.rewrite_max_log_bytes = set->mail_index_rewrite_max_log_bytes,
281 		},
282 		.log = {
283 			.min_size = set->mail_index_log_rotate_min_size,
284 			.max_size = set->mail_index_log_rotate_max_size,
285 			.min_age_secs = set->mail_index_log_rotate_min_age,
286 			.log2_max_age_secs = set->mail_index_log2_max_age,
287 		},
288 		.cache = {
289 			.unaccessed_field_drop_secs = set->mail_cache_unaccessed_field_drop,
290 			.record_max_size = set->mail_cache_record_max_size,
291 			.max_size = set->mail_cache_max_size,
292 			.purge_min_size = set->mail_cache_purge_min_size,
293 			.purge_delete_percentage = set->mail_cache_purge_delete_percentage,
294 			.purge_continued_percentage = set->mail_cache_purge_continued_percentage,
295 			.purge_header_continue_count = set->mail_cache_purge_header_continue_count,
296 		},
297 	};
298 	mail_index_set_optimization_settings(box->index, &optimization_set);
299 	return 0;
300 }
301 
index_storage_mailbox_open(struct mailbox * box,bool move_to_memory)302 int index_storage_mailbox_open(struct mailbox *box, bool move_to_memory)
303 {
304 	struct index_mailbox_context *ibox = INDEX_STORAGE_CONTEXT(box);
305 	enum mail_index_open_flags index_flags;
306 	int ret;
307 
308 	i_assert(!box->opened);
309 
310 	index_flags = ibox->index_flags;
311 	if (move_to_memory)
312 		index_flags &= ENUM_NEGATE(MAIL_INDEX_OPEN_FLAG_CREATE);
313 
314 	if (index_storage_mailbox_alloc_index(box) < 0)
315 		return -1;
316 
317 	/* make sure mail_index_set_permissions() has been called */
318 	(void)mailbox_get_permissions(box);
319 
320 	ret = mail_index_open(box->index, index_flags);
321 	if (ret <= 0 || move_to_memory) {
322 		if ((index_flags & MAIL_INDEX_OPEN_FLAG_NEVER_IN_MEMORY) != 0) {
323 			i_assert(ret <= 0);
324 			mailbox_set_index_error(box);
325 			return -1;
326 		}
327 
328 		if (mail_index_move_to_memory(box->index) < 0) {
329 			/* try opening once more. it should be created
330 			   directly into memory now. */
331 			if (mail_index_open_or_create(box->index,
332 						      index_flags) < 0)
333 				i_panic("in-memory index creation failed");
334 		}
335 	}
336 	if ((index_flags & MAIL_INDEX_OPEN_FLAG_NEVER_IN_MEMORY) != 0) {
337 		if (mail_index_is_in_memory(box->index)) {
338 			mailbox_set_critical(box,
339 				"Couldn't create index file");
340 			mail_index_close(box->index);
341 			return -1;
342 		}
343 	}
344 
345 	if ((box->flags & MAILBOX_FLAG_OPEN_DELETED) == 0) {
346 		if (mail_index_is_deleted(box->index)) {
347 			mailbox_set_deleted(box);
348 			mail_index_close(box->index);
349 			return -1;
350 		}
351 	}
352 	if ((box->flags & MAILBOX_FLAG_FSCK) != 0) {
353 		if (mail_index_fsck(box->index) < 0) {
354 			mailbox_set_index_error(box);
355 			return -1;
356 		}
357 	}
358 
359 	box->cache = mail_index_get_cache(box->index);
360 	index_cache_register_defaults(box);
361 	box->view = mail_index_view_open(box->index);
362 	ibox->keyword_names = mail_index_get_keywords(box->index);
363 	box->vsize_hdr_ext_id =
364 		mail_index_ext_register(box->index, "hdr-vsize",
365 					sizeof(struct mailbox_index_vsize), 0,
366 					sizeof(uint64_t));
367 	box->pop3_uidl_hdr_ext_id =
368 		mail_index_ext_register(box->index, "hdr-pop3-uidl",
369 					sizeof(struct mailbox_index_pop3_uidl), 0, 0);
370 	box->box_name_hdr_ext_id =
371 		mail_index_ext_register(box->index, "box-name", 0, 0, 0);
372 
373 	box->box_last_rename_stamp_ext_id =
374 		mail_index_ext_register(box->index, "last-rename-stamp",
375 					sizeof(uint32_t), 0, sizeof(uint32_t));
376 	box->mail_vsize_ext_id = mail_index_ext_register(box->index, "vsize", 0,
377 							 sizeof(uint32_t),
378 							 sizeof(uint32_t));
379 
380 	box->opened = TRUE;
381 
382 	if ((box->enabled_features & MAILBOX_FEATURE_CONDSTORE) != 0)
383 		mail_index_modseq_enable(box->index);
384 
385 	index_thread_mailbox_opened(box);
386 	hook_mailbox_opened(box);
387 	return 0;
388 }
389 
index_storage_mailbox_alloc(struct mailbox * box,const char * vname,enum mailbox_flags flags,const char * index_prefix)390 void index_storage_mailbox_alloc(struct mailbox *box, const char *vname,
391 				 enum mailbox_flags flags,
392 				 const char *index_prefix)
393 {
394 	static unsigned int mailbox_generation_sequence = 0;
395 	struct index_mailbox_context *ibox;
396 
397 	i_assert(vname != NULL);
398 
399 	box->generation_sequence = ++mailbox_generation_sequence;
400 	box->vname = p_strdup(box->pool, vname);
401 	box->name = p_strdup(box->pool,
402 			     mailbox_list_get_storage_name(box->list, vname));
403 	box->flags = flags;
404 	box->index_prefix = p_strdup(box->pool, index_prefix);
405 	box->event = event_create(box->storage->event);
406 	event_add_category(box->event, &event_category_mailbox);
407 	event_add_str(box->event, "mailbox", box->vname);
408 	event_set_append_log_prefix(box->event,
409 		t_strdup_printf("Mailbox %s: ", str_sanitize(box->vname, 128)));
410 
411 	p_array_init(&box->search_results, box->pool, 16);
412 	array_create(&box->module_contexts,
413 		     box->pool, sizeof(void *), 5);
414 
415 	ibox = p_new(box->pool, struct index_mailbox_context, 1);
416 	ibox->list_index_sync_ext_id = (uint32_t)-1;
417 	ibox->index_flags = MAIL_INDEX_OPEN_FLAG_CREATE |
418 		mail_storage_settings_to_index_flags(box->storage->set);
419 	if ((box->flags & MAILBOX_FLAG_SAVEONLY) != 0)
420 		ibox->index_flags |= MAIL_INDEX_OPEN_FLAG_SAVEONLY;
421 	if (event_want_debug(box->event))
422 		ibox->index_flags |= MAIL_INDEX_OPEN_FLAG_DEBUG;
423 	ibox->next_lock_notify = time(NULL) + LOCK_NOTIFY_INTERVAL;
424 	MODULE_CONTEXT_SET(box, index_storage_module, ibox);
425 
426 	box->inbox_user = strcmp(box->name, "INBOX") == 0 &&
427 		(box->list->ns->flags & NAMESPACE_FLAG_INBOX_USER) != 0;
428 	box->inbox_any = strcmp(box->name, "INBOX") == 0 &&
429 		(box->list->ns->flags & NAMESPACE_FLAG_INBOX_ANY) != 0;
430 }
431 
index_storage_mailbox_enable(struct mailbox * box,enum mailbox_feature feature)432 int index_storage_mailbox_enable(struct mailbox *box,
433 				 enum mailbox_feature feature)
434 {
435 	if ((feature & MAILBOX_FEATURE_CONDSTORE) != 0) {
436 		box->enabled_features |= MAILBOX_FEATURE_CONDSTORE;
437 		if (box->opened)
438 			mail_index_modseq_enable(box->index);
439 	}
440 	return 0;
441 }
442 
index_storage_mailbox_close(struct mailbox * box)443 void index_storage_mailbox_close(struct mailbox *box)
444 {
445 	struct index_mailbox_context *ibox = INDEX_STORAGE_CONTEXT(box);
446 
447 	mailbox_watch_remove_all(box);
448 	i_stream_unref(&box->input);
449 
450 	if (box->view_pvt != NULL)
451 		mail_index_view_close(&box->view_pvt);
452 	if (box->index_pvt != NULL)
453 		mail_index_close(box->index_pvt);
454 	if (box->view != NULL) {
455 		mail_index_view_close(&box->view);
456 		mail_index_close(box->index);
457 	}
458 	box->cache = NULL;
459 
460 	ibox->keyword_names = NULL;
461 	i_free_and_null(ibox->cache_fields);
462 
463 	ibox->sync_last_check = 0;
464 }
465 
index_storage_mailbox_unref_indexes(struct mailbox * box)466 static void index_storage_mailbox_unref_indexes(struct mailbox *box)
467 {
468 	if (box->index_pvt != NULL)
469 		mail_index_alloc_cache_unref(&box->index_pvt);
470 	if (box->index != NULL)
471 		mail_index_alloc_cache_unref(&box->index);
472 }
473 
index_storage_mailbox_free(struct mailbox * box)474 void index_storage_mailbox_free(struct mailbox *box)
475 {
476 	index_storage_mailbox_unref_indexes(box);
477 	event_unref(&box->event);
478 }
479 
480 static void
index_storage_mailbox_update_cache(struct mailbox * box,const struct mailbox_update * update)481 index_storage_mailbox_update_cache(struct mailbox *box,
482 				   const struct mailbox_update *update)
483 {
484 	const struct mailbox_cache_field *updates = update->cache_updates;
485 	ARRAY(struct mail_cache_field) new_fields;
486 	const struct mail_cache_field *old_fields;
487 	struct mail_cache_field field;
488 	unsigned int i, j, old_count;
489 
490 	old_fields = mail_cache_register_get_list(box->cache,
491 						  pool_datastack_create(),
492 						  &old_count);
493 
494 	/* There shouldn't be many fields, so don't worry about O(n^2). */
495 	t_array_init(&new_fields, 32);
496 	for (i = 0; updates[i].name != NULL; i++) {
497 		/* see if it's an existing field */
498 		for (j = 0; j < old_count; j++) {
499 			if (strcmp(updates[i].name, old_fields[j].name) == 0)
500 				break;
501 		}
502 		if (j != old_count) {
503 			field = old_fields[j];
504 		} else if (str_begins(updates[i].name, "hdr.")) {
505 			/* new header */
506 			i_zero(&field);
507 			field.name = updates[i].name;
508 			field.type = MAIL_CACHE_FIELD_HEADER;
509 		} else {
510 			/* new unknown field. we can't do anything about
511 			   this since we don't know its type */
512 			continue;
513 		}
514 		field.decision = updates[i].decision;
515 		if (updates[i].last_used != (time_t)-1)
516 			field.last_used = updates[i].last_used;
517 		array_push_back(&new_fields, &field);
518 	}
519 	if (array_count(&new_fields) > 0) {
520 		mail_cache_register_fields(box->cache,
521 					   array_front_modifiable(&new_fields),
522 					   array_count(&new_fields));
523 	}
524 }
525 
526 static int
index_storage_mailbox_update_pvt(struct mailbox * box,const struct mailbox_update * update)527 index_storage_mailbox_update_pvt(struct mailbox *box,
528 				 const struct mailbox_update *update)
529 {
530 	struct mail_index_transaction *trans;
531 	struct mail_index_view *view;
532 	int ret;
533 
534 	if ((ret = mailbox_open_index_pvt(box)) <= 0)
535 		return ret;
536 
537 	mail_index_refresh(box->index_pvt);
538 	view = mail_index_view_open(box->index_pvt);
539 	trans = mail_index_transaction_begin(view,
540 					MAIL_INDEX_TRANSACTION_FLAG_EXTERNAL);
541 	if (update->min_highest_modseq != 0 &&
542 	    mail_index_modseq_get_highest(view) < update->min_highest_pvt_modseq) {
543 		mail_index_modseq_enable(box->index_pvt);
544 		mail_index_update_highest_modseq(trans,
545 						 update->min_highest_pvt_modseq);
546 	}
547 
548 	if ((ret = mail_index_transaction_commit(&trans)) < 0)
549 		mailbox_set_index_error(box);
550 	mail_index_view_close(&view);
551 	return ret;
552 }
553 
index_storage_mailbox_update_common(struct mailbox * box,const struct mailbox_update * update)554 int index_storage_mailbox_update_common(struct mailbox *box,
555 					const struct mailbox_update *update)
556 {
557 	int ret = 0;
558 
559 	if (update->cache_updates != NULL)
560 		index_storage_mailbox_update_cache(box, update);
561 
562 	if (update->min_highest_pvt_modseq != 0) {
563 		if (index_storage_mailbox_update_pvt(box, update) < 0)
564 			ret = -1;
565 	}
566 	return ret;
567 }
568 
index_storage_mailbox_update(struct mailbox * box,const struct mailbox_update * update)569 int index_storage_mailbox_update(struct mailbox *box,
570 				 const struct mailbox_update *update)
571 {
572 	const struct mail_index_header *hdr;
573 	struct mail_index_view *view;
574 	struct mail_index_transaction *trans;
575 	int ret;
576 
577 	if (mailbox_open(box) < 0)
578 		return -1;
579 
580 	/* make sure we get the latest index info */
581 	mail_index_refresh(box->index);
582 	view = mail_index_view_open(box->index);
583 	hdr = mail_index_get_header(view);
584 
585 	trans = mail_index_transaction_begin(view,
586 					MAIL_INDEX_TRANSACTION_FLAG_EXTERNAL);
587 	if (update->uid_validity != 0 &&
588 	    hdr->uid_validity != update->uid_validity) {
589 		uint32_t uid_validity = update->uid_validity;
590 
591 		if (hdr->uid_validity != 0) {
592 			/* UIDVALIDITY change requires index to be reset */
593 			mail_index_reset(trans);
594 		}
595 		mail_index_update_header(trans,
596 			offsetof(struct mail_index_header, uid_validity),
597 			&uid_validity, sizeof(uid_validity), TRUE);
598 	}
599 	if (update->min_next_uid != 0 &&
600 	    hdr->next_uid < update->min_next_uid) {
601 		uint32_t next_uid = update->min_next_uid;
602 
603 		mail_index_update_header(trans,
604 			offsetof(struct mail_index_header, next_uid),
605 			&next_uid, sizeof(next_uid), FALSE);
606 	}
607 	if (update->min_first_recent_uid != 0 &&
608 	    hdr->first_recent_uid < update->min_first_recent_uid) {
609 		uint32_t first_recent_uid = update->min_first_recent_uid;
610 
611 		mail_index_update_header(trans,
612 			offsetof(struct mail_index_header, first_recent_uid),
613 			&first_recent_uid, sizeof(first_recent_uid), FALSE);
614 	}
615 	if (update->min_highest_modseq != 0 &&
616 	    mail_index_modseq_get_highest(view) < update->min_highest_modseq) {
617 		mail_index_modseq_enable(box->index);
618 		mail_index_update_highest_modseq(trans,
619 						 update->min_highest_modseq);
620 	}
621 
622 	if ((ret = mail_index_transaction_commit(&trans)) < 0)
623 		mailbox_set_index_error(box);
624 	mail_index_view_close(&view);
625 	return ret < 0 ? -1 :
626 		index_storage_mailbox_update_common(box, update);
627 }
628 
index_storage_mailbox_create(struct mailbox * box,bool directory)629 int index_storage_mailbox_create(struct mailbox *box, bool directory)
630 {
631 	const char *path, *p;
632 	enum mailbox_list_path_type type;
633 	enum mailbox_existence existence;
634 	bool create_parent_dir;
635 	int ret;
636 
637 	if ((box->list->props & MAILBOX_LIST_PROP_NO_NOSELECT) != 0) {
638 		/* Layout doesn't support creating \NoSelect mailboxes.
639 		   Switch to creating a selectable mailbox. */
640 		directory = FALSE;
641 	}
642 
643 	type = directory ? MAILBOX_LIST_PATH_TYPE_DIR :
644 		MAILBOX_LIST_PATH_TYPE_MAILBOX;
645 	if ((ret = mailbox_get_path_to(box, type, &path)) < 0)
646 		return -1;
647 	if (ret == 0) {
648 		/* layout=none */
649 		mail_storage_set_error(box->storage, MAIL_ERROR_NOTPOSSIBLE,
650 				       "Mailbox creation not supported");
651 		return -1;
652 	}
653 	create_parent_dir = !directory &&
654 		(box->list->flags & MAILBOX_LIST_FLAG_MAILBOX_FILES) != 0;
655 	if (create_parent_dir) {
656 		/* we only need to make sure that the parent directory exists */
657 		p = strrchr(path, '/');
658 		if (p == NULL)
659 			return 1;
660 		path = t_strdup_until(path, p);
661 	}
662 
663 	if ((ret = mailbox_mkdir(box, path, type)) < 0)
664 		return -1;
665 	if (box->list->set.iter_from_index_dir) {
666 		/* need to also create the directory to index path or
667 		   iteration won't find it. */
668 		int ret2;
669 
670 		if (mailbox_get_path_to(box, MAILBOX_LIST_PATH_TYPE_INDEX, &path) <= 0)
671 			i_unreached();
672 		if ((ret2 = mailbox_mkdir(box, path, type)) < 0)
673 			return -1;
674 		if (ret == 0 && ret2 > 0) {
675 			/* finish partial creation: existed in mail directory,
676 			   but not in index directory. */
677 			ret = 1;
678 		}
679 	}
680 	mailbox_refresh_permissions(box);
681 	if (ret == 0) {
682 		/* directory already exists */
683 		if (create_parent_dir)
684 			return 1;
685 		if (!directory && *box->list->set.mailbox_dir_name == '\0') {
686 			/* For example: layout=fs, path=~/Maildir/foo
687 			   might itself exist, but does it have the
688 			   cur|new|tmp subdirs? */
689 			if (mailbox_exists(box, FALSE, &existence) < 0)
690 				return -1;
691 			if (existence != MAILBOX_EXISTENCE_SELECT)
692 				return 1;
693 		} else if (!box->storage->rebuilding_list_index) {
694 			/* ignore existing location if we are recovering list index */
695 			mail_storage_set_error(box->storage, MAIL_ERROR_EXISTS,
696 					       "Mailbox already exists");
697 			return -1;
698 		}
699 	}
700 
701 	if (directory) {
702 		/* we only wanted to create the directory and it's done now */
703 		return 0;
704 	}
705 	/* the caller should still create the mailbox */
706 	return 1;
707 }
708 
index_storage_mailbox_delete_dir(struct mailbox * box,bool mailbox_deleted)709 int index_storage_mailbox_delete_dir(struct mailbox *box, bool mailbox_deleted)
710 {
711 	guid_128_t dir_sha128;
712 	enum mail_error error;
713 
714 	if (mailbox_list_delete_dir(box->list, box->name) == 0)
715 		return 0;
716 
717 	mailbox_list_get_last_error(box->list, &error);
718 	if (error != MAIL_ERROR_NOTFOUND || !mailbox_deleted) {
719 		mail_storage_copy_list_error(box->storage, box->list);
720 		return -1;
721 	}
722 	/* failed directory deletion, but mailbox deletion succeeded.
723 	   this was probably maildir++, which internally deleted the
724 	   directory as well. add changelog record about that too. */
725 	mailbox_name_get_sha128(box->vname, dir_sha128);
726 	mailbox_list_add_change(box->list, MAILBOX_LOG_RECORD_DELETE_DIR,
727 				dir_sha128);
728 	return 0;
729 }
730 
731 static int
mailbox_delete_all_attributes(struct mailbox_transaction_context * t,enum mail_attribute_type type)732 mailbox_delete_all_attributes(struct mailbox_transaction_context *t,
733 			      enum mail_attribute_type type)
734 {
735 	struct mailbox_attribute_iter *iter;
736 	const char *key;
737 	int ret = 0;
738 	bool inbox = t->box->inbox_any;
739 
740 	iter = mailbox_attribute_iter_init(t->box, type, "");
741 	while ((key = mailbox_attribute_iter_next(iter)) != NULL) {
742 		if (inbox &&
743 		    str_begins(key, MAILBOX_ATTRIBUTE_PREFIX_DOVECOT_PVT_SERVER))
744 			continue;
745 
746 		if (mailbox_attribute_unset(t, type, key) < 0) {
747 			if (mailbox_get_last_mail_error(t->box) != MAIL_ERROR_NOTPOSSIBLE) {
748 				ret = -1;
749 				break;
750 			}
751 		}
752 	}
753 	if (mailbox_attribute_iter_deinit(&iter) < 0)
754 		ret = -1;
755 	return ret;
756 }
757 
mailbox_expunge_all_data(struct mailbox * box)758 static int mailbox_expunge_all_data(struct mailbox *box)
759 {
760 	struct mail_search_context *ctx;
761         struct mailbox_transaction_context *t;
762 	struct mail *mail;
763 	struct mail_search_args *search_args;
764 
765 	(void)mailbox_sync(box, MAILBOX_SYNC_FLAG_FULL_READ);
766 
767 	t = mailbox_transaction_begin(box, 0, __func__);
768 
769 	search_args = mail_search_build_init();
770 	mail_search_build_add_all(search_args);
771 	ctx = mailbox_search_init(t, search_args, NULL, 0, NULL);
772 	mail_search_args_unref(&search_args);
773 
774 	while (mailbox_search_next(ctx, &mail))
775 		mail_expunge(mail);
776 
777 	if (mailbox_search_deinit(&ctx) < 0) {
778 		mailbox_transaction_rollback(&t);
779 		return -1;
780 	}
781 
782 	if (mailbox_delete_all_attributes(t, MAIL_ATTRIBUTE_TYPE_PRIVATE) < 0 ||
783 	    mailbox_delete_all_attributes(t, MAIL_ATTRIBUTE_TYPE_SHARED) < 0) {
784 		mailbox_transaction_rollback(&t);
785 		return -1;
786 	}
787 	if (mailbox_transaction_commit(&t) < 0)
788 		return -1;
789 	/* sync to actually perform the expunges */
790 	return mailbox_sync(box, 0);
791 }
792 
index_storage_mailbox_delete_pre(struct mailbox * box)793 int index_storage_mailbox_delete_pre(struct mailbox *box)
794 {
795 	struct mailbox_status status;
796 
797 	if (!box->opened) {
798 		/* \noselect mailbox, try deleting only the directory */
799 		if (index_storage_mailbox_delete_dir(box, FALSE) == 0)
800 			return 0;
801 		if (mailbox_is_autocreated(box)) {
802 			/* Return success when trying to delete autocreated
803 			   mailbox. The client sees it as existing, so we
804 			   shouldn't be returning an error. */
805 			return 0;
806 		}
807 		return -1;
808 	}
809 
810 	if ((box->list->flags & MAILBOX_LIST_FLAG_MAILBOX_FILES) == 0) {
811 		/* specifically support symlinked shared mailboxes. a deletion
812 		   will simply remove the symlink, not actually expunge any
813 		   mails */
814 		if (mailbox_list_delete_symlink(box->list, box->name) == 0)
815 			return 0;
816 	}
817 
818 	/* we can't easily atomically delete all mails and the mailbox. so:
819 	   1) expunge all mails
820 	   2) mark the mailbox deleted (modifications after this will fail)
821 	   3) check if a race condition between 1) and 2) added any mails:
822 	     yes) abort and undelete mailbox
823 	     no) finish deleting the mailbox
824 	*/
825 
826 	if (!box->deleting_must_be_empty) {
827 		if (mailbox_expunge_all_data(box) < 0)
828 			return -1;
829 	}
830 	if (mailbox_mark_index_deleted(box, TRUE) < 0)
831 		return -1;
832 
833 	if (!box->delete_skip_empty_check || box->deleting_must_be_empty) {
834 		if (mailbox_sync(box, MAILBOX_SYNC_FLAG_FULL_READ) < 0)
835 			return -1;
836 		mailbox_get_open_status(box, STATUS_MESSAGES, &status);
837 		if (status.messages == 0)
838 			;
839 		else if (box->deleting_must_be_empty) {
840 			mail_storage_set_error(box->storage, MAIL_ERROR_EXISTS,
841 					       "Mailbox isn't empty");
842 			return -1;
843 		} else {
844 			mail_storage_set_error(box->storage, MAIL_ERROR_EXISTS,
845 				"New mails were added to mailbox during deletion");
846 			return -1;
847 		}
848 	}
849 	return 1;
850 }
851 
index_storage_mailbox_delete_post(struct mailbox * box)852 int index_storage_mailbox_delete_post(struct mailbox *box)
853 {
854 	struct mailbox_metadata metadata;
855 	int ret_guid;
856 
857 	ret_guid = mailbox_get_metadata(box, MAILBOX_METADATA_GUID, &metadata);
858 
859 	/* Make sure the indexes are closed before trying to delete the
860 	   directory that contains them. It can still fail with some NFS
861 	   implementations if indexes are opened by another session, but
862 	   that can't really be helped. */
863 	mailbox_close(box);
864 	index_storage_mailbox_unref_indexes(box);
865 	mail_index_alloc_cache_destroy_unrefed();
866 
867 	if (box->list->v.delete_mailbox(box->list, box->name) < 0) {
868 		mail_storage_copy_list_error(box->storage, box->list);
869 		return -1;
870 	}
871 
872 	if (ret_guid == 0) {
873 		mailbox_list_add_change(box->list,
874 					MAILBOX_LOG_RECORD_DELETE_MAILBOX,
875 					metadata.guid);
876 	}
877 	if (index_storage_mailbox_delete_dir(box, TRUE) < 0) {
878 		if (mailbox_get_last_mail_error(box) != MAIL_ERROR_EXISTS)
879 			return -1;
880 		/* we deleted the mailbox, but couldn't delete the directory
881 		   because it has children. that's not an error. */
882 	}
883 	return 0;
884 }
885 
index_storage_mailbox_delete(struct mailbox * box)886 int index_storage_mailbox_delete(struct mailbox *box)
887 {
888 	int ret;
889 
890 	if ((ret = index_storage_mailbox_delete_pre(box)) <= 0)
891 		return ret;
892 	/* mails have been now successfully deleted. some mailbox formats may
893 	   at this point do some other deletion that is required for it.
894 	   the _post() deletion will close the index and delete the
895 	   directory. */
896 	return index_storage_mailbox_delete_post(box);
897 }
898 
index_storage_mailbox_rename(struct mailbox * src,struct mailbox * dest)899 int index_storage_mailbox_rename(struct mailbox *src, struct mailbox *dest)
900 {
901 	guid_128_t guid;
902 
903 	if (src->list->v.rename_mailbox(src->list, src->name,
904 					dest->list, dest->name) < 0) {
905 		mail_storage_copy_list_error(src->storage, src->list);
906 		return -1;
907 	}
908 
909 	if (mailbox_open(dest) == 0) {
910 		struct mail_index_transaction *t =
911 			mail_index_transaction_begin(dest->view, 0);
912 
913 		uint32_t stamp = ioloop_time;
914 
915 		mail_index_update_header_ext(t, dest->box_last_rename_stamp_ext_id,
916 					     0, &stamp, sizeof(stamp));
917 
918 		/* can't do much if this fails anyways */
919 		(void)mail_index_transaction_commit(&t);
920 	}
921 
922 	/* we'll track mailbox names, instead of GUIDs. We may be renaming a
923 	   non-selectable mailbox (directory), which doesn't even have a GUID */
924 	mailbox_name_get_sha128(dest->vname, guid);
925 	mailbox_list_add_change(src->list, MAILBOX_LOG_RECORD_RENAME, guid);
926 	return 0;
927 }
928 
index_mailbox_update_last_temp_file_scan(struct mailbox * box)929 int index_mailbox_update_last_temp_file_scan(struct mailbox *box)
930 {
931 	uint32_t last_temp_file_scan = ioloop_time;
932 	struct mail_index_transaction *trans =
933 		mail_index_transaction_begin(box->view,
934 			MAIL_INDEX_TRANSACTION_FLAG_EXTERNAL);
935 	mail_index_update_header(trans,
936 		offsetof(struct mail_index_header, last_temp_file_scan),
937 		&last_temp_file_scan, sizeof(last_temp_file_scan), TRUE);
938 	if (mail_index_transaction_commit(&trans) < 0) {
939 		mailbox_set_index_error(box);
940 		return -1;
941 	}
942 	return 0;
943 }
944 
index_storage_is_readonly(struct mailbox * box)945 bool index_storage_is_readonly(struct mailbox *box)
946 {
947 	return (box->flags & MAILBOX_FLAG_READONLY) != 0;
948 }
949 
index_storage_is_inconsistent(struct mailbox * box)950 bool index_storage_is_inconsistent(struct mailbox *box)
951 {
952 	return box->view != NULL &&
953 		mail_index_view_is_inconsistent(box->view);
954 }
955 
index_save_context_free(struct mail_save_context * ctx)956 void index_save_context_free(struct mail_save_context *ctx)
957 {
958 	index_mail_save_finish(ctx);
959 	if (ctx->data.keywords != NULL)
960 		mailbox_keywords_unref(&ctx->data.keywords);
961 	i_free_and_null(ctx->data.from_envelope);
962 	i_free_and_null(ctx->data.guid);
963 	i_free_and_null(ctx->data.pop3_uidl);
964 	index_attachment_save_free(ctx);
965 	i_zero(&ctx->data);
966 
967 	ctx->unfinished = FALSE;
968 }
969 
970 static void
mail_copy_cache_field(struct mail_save_context * ctx,struct mail * src_mail,uint32_t dest_seq,const char * name,buffer_t * buf)971 mail_copy_cache_field(struct mail_save_context *ctx, struct mail *src_mail,
972 		      uint32_t dest_seq, const char *name, buffer_t *buf)
973 {
974 	struct mailbox_transaction_context *dest_trans = ctx->transaction;
975 	const struct mail_cache_field *dest_field;
976 	unsigned int src_field_idx, dest_field_idx;
977 	uint32_t t;
978 	bool add = FALSE;
979 
980 	src_field_idx = mail_cache_register_lookup(src_mail->box->cache, name);
981 	i_assert(src_field_idx != UINT_MAX);
982 
983 	dest_field_idx = mail_cache_register_lookup(dest_trans->box->cache, name);
984 	if (dest_field_idx == UINT_MAX) {
985 		/* unknown field */
986 		return;
987 	}
988 	dest_field = mail_cache_register_get_field(dest_trans->box->cache,
989 						   dest_field_idx);
990 	if ((dest_field->decision &
991 	     ENUM_NEGATE(MAIL_CACHE_DECISION_FORCED)) == MAIL_CACHE_DECISION_NO) {
992 		/* field not wanted in destination mailbox */
993 		return;
994 	}
995 
996 	buffer_set_used_size(buf, 0);
997 	if (strcmp(name, "date.save") == 0) {
998 		/* save date must update when mail is copied */
999 		t = ioloop_time;
1000 		buffer_append(buf, &t, sizeof(t));
1001 		add = TRUE;
1002 	} else if (mail_cache_lookup_field(src_mail->transaction->cache_view, buf,
1003 					   src_mail->seq, src_field_idx) <= 0) {
1004 		/* error / not found */
1005 		buffer_set_used_size(buf, 0);
1006 	} else {
1007 		if (strcmp(name, "size.physical") == 0 ||
1008 		    strcmp(name, "size.virtual") == 0) {
1009 			/* FIXME: until mail_cache_lookup() can read unwritten
1010 			   cached data from buffer, we'll do this optimization
1011 			   to make quota plugin's work faster */
1012 			struct index_mail *imail =
1013 				INDEX_MAIL(ctx->dest_mail);
1014 			uoff_t size;
1015 
1016 			i_assert(buf->used == sizeof(size));
1017 			memcpy(&size, buf->data, sizeof(size));
1018 			if (strcmp(name, "size.physical") == 0)
1019 				imail->data.physical_size = size;
1020 			else
1021 				imail->data.virtual_size = size;
1022 		}
1023 		/* NOTE: we'll want to add also nonexistent headers, which
1024 		   will keep the buf empty */
1025 		add = TRUE;
1026 	}
1027 	if (add) {
1028 		mail_cache_add(dest_trans->cache_trans, dest_seq,
1029 			       dest_field_idx, buf->data, buf->used);
1030 	}
1031 }
1032 
1033 static void
index_copy_vsize_extension(struct mail_save_context * ctx,struct mail * src_mail,uint32_t dest_seq)1034 index_copy_vsize_extension(struct mail_save_context *ctx,
1035 			   struct mail *src_mail, uint32_t dest_seq)
1036 {
1037 	const uint32_t *vsizep;
1038 	bool expunged ATTR_UNUSED;
1039 
1040 	vsizep = index_mail_get_vsize_extension(src_mail);
1041 	if (vsizep == NULL || *vsizep == 0)
1042 		return;
1043 	uint32_t vsize = *vsizep;
1044 
1045 	if (vsize < (uint32_t)-1) {
1046 		/* copy the vsize record to the destination index */
1047 		mail_index_update_ext(ctx->transaction->itrans, dest_seq,
1048 				      ctx->transaction->box->mail_vsize_ext_id,
1049 				      &vsize, NULL);
1050 	}
1051 }
1052 
index_copy_cache_fields(struct mail_save_context * ctx,struct mail * src_mail,uint32_t dest_seq)1053 void index_copy_cache_fields(struct mail_save_context *ctx,
1054 			     struct mail *src_mail, uint32_t dest_seq)
1055 {
1056 	T_BEGIN {
1057 		struct mailbox_metadata src_metadata, dest_metadata;
1058 		const struct mailbox_cache_field *field;
1059 		buffer_t *buf;
1060 
1061 		if (mailbox_get_metadata(src_mail->box,
1062 					 MAILBOX_METADATA_CACHE_FIELDS,
1063 					 &src_metadata) < 0)
1064 			i_unreached();
1065 		/* the only reason we're doing the destination lookup is to
1066 		   make sure that the cache file is opened and the cache
1067 		   decisions are up to date */
1068 		if (mailbox_get_metadata(ctx->transaction->box,
1069 					 MAILBOX_METADATA_CACHE_FIELDS,
1070 					 &dest_metadata) < 0)
1071 			i_unreached();
1072 
1073 		buf = t_buffer_create(1024);
1074 		array_foreach(src_metadata.cache_fields, field) {
1075 			mail_copy_cache_field(ctx, src_mail, dest_seq,
1076 					      field->name, buf);
1077 		}
1078 		index_copy_vsize_extension(ctx, src_mail, dest_seq);
1079 	} T_END;
1080 }
1081 
index_storage_set_subscribed(struct mailbox * box,bool set)1082 int index_storage_set_subscribed(struct mailbox *box, bool set)
1083 {
1084 	struct mail_namespace *ns;
1085 	struct mailbox_list *list = box->list;
1086 	const char *subs_name;
1087 	guid_128_t guid;
1088 
1089 	if ((list->ns->flags & NAMESPACE_FLAG_SUBSCRIPTIONS) != 0)
1090 		subs_name = box->name;
1091 	else {
1092 		/* subscriptions=no namespace, find another one where we can
1093 		   add the subscription to */
1094 		ns = mail_namespace_find_subscribable(list->ns->user->namespaces,
1095 						      box->vname);
1096 		if (ns == NULL) {
1097 			mail_storage_set_error(box->storage, MAIL_ERROR_NOTPOSSIBLE,
1098 				"This namespace has no subscriptions");
1099 			return -1;
1100 		}
1101 		/* use <orig ns prefix><orig storage name> as the
1102 		   subscription name */
1103 		subs_name = t_strconcat(list->ns->prefix, box->name, NULL);
1104 		/* drop the common prefix (typically there isn't one) */
1105 		i_assert(str_begins(subs_name, ns->prefix));
1106 		subs_name += strlen(ns->prefix);
1107 
1108 		list = ns->list;
1109 	}
1110 	if (mailbox_list_set_subscribed(list, subs_name, set) < 0) {
1111 		mail_storage_copy_list_error(box->storage, list);
1112 		return -1;
1113 	}
1114 
1115 	/* subscriptions are about names, not about mailboxes. it's possible
1116 	   to have a subscription to nonexistent mailbox. renames also don't
1117 	   change subscriptions. so instead of using actual GUIDs, we'll use
1118 	   hash of the name. */
1119 	mailbox_name_get_sha128(box->vname, guid);
1120 	mailbox_list_add_change(list, set ? MAILBOX_LOG_RECORD_SUBSCRIBE :
1121 				MAILBOX_LOG_RECORD_UNSUBSCRIBE, guid);
1122 	return 0;
1123 }
1124 
index_storage_destroy(struct mail_storage * storage)1125 void index_storage_destroy(struct mail_storage *storage)
1126 {
1127 	if (storage->_shared_attr_dict != NULL) {
1128 		dict_wait(storage->_shared_attr_dict);
1129 		dict_deinit(&storage->_shared_attr_dict);
1130 	}
1131 	fs_unref(&storage->mailboxes_fs);
1132 }
1133 
index_storage_expunging_init(struct mailbox * box)1134 static void index_storage_expunging_init(struct mailbox *box)
1135 {
1136 	struct index_mailbox_context *ibox = INDEX_STORAGE_CONTEXT(box);
1137 
1138 	if (ibox->vsize_update != NULL)
1139 		return;
1140 
1141 	ibox->vsize_update = index_mailbox_vsize_update_init(box);
1142 	if (!index_mailbox_vsize_want_updates(ibox->vsize_update) ||
1143 	    !index_mailbox_vsize_update_wait_lock(ibox->vsize_update))
1144 		index_mailbox_vsize_update_deinit(&ibox->vsize_update);
1145 }
1146 
index_storage_expunging_deinit(struct mailbox * box)1147 void index_storage_expunging_deinit(struct mailbox *box)
1148 {
1149 	struct index_mailbox_context *ibox = INDEX_STORAGE_CONTEXT(box);
1150 
1151 	if (ibox->vsize_update != NULL)
1152 		index_mailbox_vsize_update_deinit(&ibox->vsize_update);
1153 }
1154 
index_storage_expunging_want_updates(struct mailbox * box)1155 static bool index_storage_expunging_want_updates(struct mailbox *box)
1156 {
1157 	struct index_mailbox_context *ibox = INDEX_STORAGE_CONTEXT(box);
1158 	bool ret;
1159 
1160 	i_assert(ibox->vsize_update == NULL);
1161 
1162 	ibox->vsize_update = index_mailbox_vsize_update_init(box);
1163 	ret = index_mailbox_vsize_want_updates(ibox->vsize_update);
1164 	index_mailbox_vsize_update_deinit(&ibox->vsize_update);
1165 	return ret;
1166 }
1167 
index_storage_expunged_sync_begin(struct mailbox * box,struct mail_index_sync_ctx ** ctx_r,struct mail_index_view ** view_r,struct mail_index_transaction ** trans_r,enum mail_index_sync_flags flags)1168 int index_storage_expunged_sync_begin(struct mailbox *box,
1169 				      struct mail_index_sync_ctx **ctx_r,
1170 				      struct mail_index_view **view_r,
1171 				      struct mail_index_transaction **trans_r,
1172 				      enum mail_index_sync_flags flags)
1173 {
1174 	struct index_mailbox_context *ibox = INDEX_STORAGE_CONTEXT(box);
1175 	int ret;
1176 
1177 	/* try to avoid locking vsize updates by checking if we see any
1178 	   expunges */
1179 	if (mail_index_sync_have_any_expunges(box->index))
1180 		index_storage_expunging_init(box);
1181 
1182 	ret = mail_index_sync_begin(box->index, ctx_r, view_r,
1183 				    trans_r, flags);
1184 	if (ret <= 0) {
1185 		if (ret < 0)
1186 			mailbox_set_index_error(box);
1187 		index_storage_expunging_deinit(box);
1188 		return ret;
1189 	}
1190 	if (ibox->vsize_update == NULL &&
1191 	    mail_index_sync_has_expunges(*ctx_r) &&
1192 	    index_storage_expunging_want_updates(box)) {
1193 		/* race condition - need to abort the sync and retry with
1194 		   the vsize locked */
1195 		mail_index_sync_rollback(ctx_r);
1196 		index_storage_expunging_deinit(box);
1197 		return index_storage_expunged_sync_begin(box, ctx_r, view_r,
1198 							 trans_r, flags);
1199 	}
1200 	return 1;
1201 }
1202 
index_storage_save_continue(struct mail_save_context * ctx,struct istream * input,struct mail * cache_dest_mail)1203 int index_storage_save_continue(struct mail_save_context *ctx,
1204 				struct istream *input,
1205 				struct mail *cache_dest_mail)
1206 {
1207 	struct mail_storage *storage = ctx->transaction->box->storage;
1208 
1209 	do {
1210 		switch (o_stream_send_istream(ctx->data.output, input)) {
1211 		case OSTREAM_SEND_ISTREAM_RESULT_FINISHED:
1212 			break;
1213 		case OSTREAM_SEND_ISTREAM_RESULT_WAIT_INPUT:
1214 			break;
1215 		case OSTREAM_SEND_ISTREAM_RESULT_WAIT_OUTPUT:
1216 			i_unreached();
1217 		case OSTREAM_SEND_ISTREAM_RESULT_ERROR_INPUT:
1218 			/* handle below */
1219 			break;
1220 		case OSTREAM_SEND_ISTREAM_RESULT_ERROR_OUTPUT:
1221 			if (!mail_storage_set_error_from_errno(storage)) {
1222 				mail_set_critical(ctx->dest_mail,
1223 					"save: write(%s) failed: %s",
1224 					o_stream_get_name(ctx->data.output),
1225 					o_stream_get_error(ctx->data.output));
1226 			}
1227 			return -1;
1228 		}
1229 		if (cache_dest_mail != NULL)
1230 			index_mail_cache_parse_continue(cache_dest_mail);
1231 
1232 		/* both tee input readers may consume data from our primary
1233 		   input stream. we'll have to make sure we don't return with
1234 		   one of the streams still having data in them. */
1235 	} while (i_stream_read(input) > 0);
1236 
1237 	if (input->stream_errno != 0) {
1238 		mail_set_critical(ctx->dest_mail, "save: read(%s) failed: %s",
1239 			i_stream_get_name(input), i_stream_get_error(input));
1240 		return -1;
1241 	}
1242 	return 0;
1243 }
1244 
index_storage_save_abort_last(struct mail_save_context * ctx,uint32_t seq)1245 void index_storage_save_abort_last(struct mail_save_context *ctx, uint32_t seq)
1246 {
1247 	struct index_mail *imail = INDEX_MAIL(ctx->dest_mail);
1248 
1249 	/* Close the mail before it's expunged. This allows it to be
1250 	   reset cleanly. */
1251 	imail->data.no_caching = TRUE;
1252 	imail->mail.v.close(&imail->mail.mail);
1253 
1254 	mail_index_expunge(ctx->transaction->itrans, seq);
1255 	/* currently we can't just drop pending cache updates for this one
1256 	   specific record, so we'll reset the whole cache transaction. */
1257 	mail_cache_transaction_reset(ctx->transaction->cache_trans);
1258 }
1259 
index_mailbox_fix_inconsistent_existence(struct mailbox * box,const char * path)1260 int index_mailbox_fix_inconsistent_existence(struct mailbox *box,
1261 					     const char *path)
1262 {
1263 	const char *index_path;
1264 	struct stat st;
1265 
1266 	/* Could be a race condition or could be because ITERINDEX is used
1267 	   and the index directory exists, but the storage directory doesn't.
1268 	   Handle the existence inconsistency by creating this directory if
1269 	   the index directory exists (don't bother checking if ITERINDEX is
1270 	   set or not - it doesn't matter since either both dirs should exist
1271 	   or not). */
1272 	if (mailbox_get_path_to(box, MAILBOX_LIST_PATH_TYPE_INDEX,
1273 				&index_path) < 0)
1274 		return -1;
1275 
1276 	if (strcmp(index_path, path) == 0) {
1277 		/* there's no separate index path - mailbox was just deleted */
1278 	} else if (stat(index_path, &st) == 0) {
1279 		/* inconsistency - create also the mail directory */
1280 		return mailbox_mkdir(box, path, MAILBOX_LIST_PATH_TYPE_MAILBOX);
1281 	} else if (errno == ENOENT) {
1282 		/* race condition - mailbox was just deleted */
1283 	} else {
1284 		mailbox_set_critical(box, "stat(%s) failed: %m", index_path);
1285 		return -1;
1286 	}
1287 	mailbox_set_deleted(box);
1288 	return -1;
1289 }
1290