~ubuntu-branches/ubuntu/wily/dovecot/wily

1.13.16 by Jelmer Vernooij
Import upstream version 2.2.16
1
/* Copyright (c) 2013-2015 Dovecot authors, see the included COPYING file */
1.13.12 by Jaldhar H. Vyas
Import upstream version 2.2.5
2
3
#include "lib.h"
4
#include "str.h"
5
#include "mail-namespace.h"
6
#include "dsync-ibc.h"
7
#include "dsync-mailbox-tree.h"
8
#include "dsync-brain-private.h"
9
10
#include <ctype.h>
11
12
static void dsync_brain_check_namespaces(struct dsync_brain *brain)
13
{
14
	struct mail_namespace *ns, *first_ns = NULL;
15
	char sep;
16
17
	i_assert(brain->hierarchy_sep == '\0');
18
19
	for (ns = brain->user->namespaces; ns != NULL; ns = ns->next) {
20
		if (!dsync_brain_want_namespace(brain, ns))
21
			continue;
22
23
		sep = mail_namespace_get_sep(ns);
24
		if (first_ns == NULL) {
25
			brain->hierarchy_sep = sep;
26
			first_ns = ns;
27
		} else if (brain->hierarchy_sep != sep) {
28
			i_fatal("Synced namespaces have conflicting separators "
29
				"('%c' for prefix=\"%s\", '%c' for prefix=\"%s\")",
30
				brain->hierarchy_sep, first_ns->prefix,
31
				sep, ns->prefix);
32
		}
33
	}
34
	if (brain->hierarchy_sep != '\0')
35
		return;
36
37
	i_fatal("All your namespaces have a location setting. "
38
		"Only namespaces with empty location settings are converted. "
39
		"(One namespace should default to mail_location setting)");
40
}
41
42
void dsync_brain_mailbox_trees_init(struct dsync_brain *brain)
43
{
44
	struct mail_namespace *ns;
45
46
	dsync_brain_check_namespaces(brain);
47
48
	brain->local_mailbox_tree =
1.13.16 by Jelmer Vernooij
Import upstream version 2.2.16
49
		dsync_mailbox_tree_init(brain->hierarchy_sep, brain->alt_char);
1.13.12 by Jaldhar H. Vyas
Import upstream version 2.2.5
50
	/* we'll convert remote mailbox names to use our own separator */
51
	brain->remote_mailbox_tree =
1.13.16 by Jelmer Vernooij
Import upstream version 2.2.16
52
		dsync_mailbox_tree_init(brain->hierarchy_sep, brain->alt_char);
1.13.12 by Jaldhar H. Vyas
Import upstream version 2.2.5
53
54
	/* fill the local mailbox tree */
55
	for (ns = brain->user->namespaces; ns != NULL; ns = ns->next) {
56
		if (!dsync_brain_want_namespace(brain, ns))
57
			continue;
58
		if (dsync_mailbox_tree_fill(brain->local_mailbox_tree, ns,
59
					    brain->sync_box,
60
					    brain->sync_box_guid,
1.13.17 by Jelmer Vernooij
Import upstream version 2.2.18
61
					    brain->exclude_mailboxes,
62
					    &brain->mail_error) < 0) {
1.13.12 by Jaldhar H. Vyas
Import upstream version 2.2.5
63
			brain->failed = TRUE;
1.13.17 by Jelmer Vernooij
Import upstream version 2.2.18
64
			break;
65
		}
1.13.12 by Jaldhar H. Vyas
Import upstream version 2.2.5
66
	}
67
68
	brain->local_tree_iter =
69
		dsync_mailbox_tree_iter_init(brain->local_mailbox_tree);
70
}
71
1.13.16 by Jelmer Vernooij
Import upstream version 2.2.16
72
1.13.12 by Jaldhar H. Vyas
Import upstream version 2.2.5
73
void dsync_brain_send_mailbox_tree(struct dsync_brain *brain)
74
{
75
	struct dsync_mailbox_node *node;
76
	enum dsync_ibc_send_ret ret;
77
	const char *full_name;
78
	char sep[2];
79
80
	sep[0] = brain->hierarchy_sep; sep[1] = '\0';
81
	while (dsync_mailbox_tree_iter_next(brain->local_tree_iter,
82
					    &full_name, &node)) {
83
		T_BEGIN {
84
			const char *const *parts;
85
1.13.16 by Jelmer Vernooij
Import upstream version 2.2.16
86
			if (brain->debug) {
87
				i_debug("brain %c: Local mailbox tree: %s %s",
88
					brain->master_brain ? 'M' : 'S', full_name,
89
					dsync_mailbox_node_to_string(node));
90
			}
91
1.13.12 by Jaldhar H. Vyas
Import upstream version 2.2.5
92
			parts = t_strsplit(full_name, sep);
93
			ret = dsync_ibc_send_mailbox_tree_node(brain->ibc,
94
							       parts, node);
95
		} T_END;
96
		if (ret == DSYNC_IBC_SEND_RET_FULL)
97
			return;
98
	}
99
	dsync_mailbox_tree_iter_deinit(&brain->local_tree_iter);
100
	dsync_ibc_send_end_of_list(brain->ibc, DSYNC_IBC_EOL_MAILBOX_TREE);
101
102
	brain->state = DSYNC_STATE_SEND_MAILBOX_TREE_DELETES;
103
}
104
105
void dsync_brain_send_mailbox_tree_deletes(struct dsync_brain *brain)
106
{
107
	const struct dsync_mailbox_delete *deletes;
108
	unsigned int count;
109
110
	deletes = dsync_mailbox_tree_get_deletes(brain->local_mailbox_tree,
111
						 &count);
112
	dsync_ibc_send_mailbox_deletes(brain->ibc, deletes, count,
113
				       brain->hierarchy_sep);
114
115
	brain->state = DSYNC_STATE_RECV_MAILBOX_TREE;
116
}
117
118
static bool
119
dsync_namespace_match_parts(struct mail_namespace *ns,
120
			    const char *const *name_parts)
121
{
122
	const char *part, *prefix = ns->prefix;
123
	unsigned int part_len;
124
	char ns_sep = mail_namespace_get_sep(ns);
125
126
	if ((ns->flags & NAMESPACE_FLAG_INBOX_USER) != 0 &&
127
	    strcmp(name_parts[0], "INBOX") == 0 && name_parts[1] == NULL)
128
		return TRUE;
129
130
	for (; *name_parts != NULL && *prefix != '\0'; name_parts++) {
131
		part = *name_parts;
132
		part_len = strlen(part);
133
134
		if (strncmp(prefix, part, part_len) != 0)
135
			return FALSE;
136
		if (prefix[part_len] != ns_sep)
137
			return FALSE;
138
		prefix += part_len + 1;
139
	}
1.13.14 by Jelmer Vernooij
Import upstream version 2.2.13~rc1
140
	if (*name_parts != NULL) {
141
		/* namespace prefix found with a mailbox */
142
		return TRUE;
143
	}
144
	if (*prefix == '\0') {
145
		/* namespace prefix itself matched */
146
		return TRUE;
147
	}
148
	return FALSE;
1.13.12 by Jaldhar H. Vyas
Import upstream version 2.2.5
149
}
150
151
static struct mail_namespace *
152
dsync_find_namespace(struct dsync_brain *brain, const char *const *name_parts)
153
{
154
	struct mail_namespace *ns, *best_ns = NULL;
155
156
	for (ns = brain->user->namespaces; ns != NULL; ns = ns->next) {
157
		if (!dsync_brain_want_namespace(brain, ns))
158
			continue;
159
160
		if (ns->prefix_len == 0) {
161
			/* prefix="" is the fallback namespace */
162
			if (best_ns == NULL)
163
				best_ns = ns;
164
		} else if (dsync_namespace_match_parts(ns, name_parts)) {
165
			if (best_ns == NULL ||
166
			    best_ns->prefix_len < ns->prefix_len)
167
				best_ns = ns;
168
		}
169
	}
170
	return best_ns;
171
}
172
173
static bool
174
dsync_is_valid_name(struct mail_namespace *ns, const char *vname)
175
{
176
	struct mailbox *box;
177
	bool ret;
178
1.13.16 by Jelmer Vernooij
Import upstream version 2.2.16
179
	box = mailbox_alloc(ns->list, vname, MAILBOX_FLAG_READONLY);
1.13.12 by Jaldhar H. Vyas
Import upstream version 2.2.5
180
	ret = mailbox_verify_create_name(box) == 0;
181
	mailbox_free(&box);
182
	return ret;
183
}
184
185
static void
1.13.16 by Jelmer Vernooij
Import upstream version 2.2.16
186
dsync_fix_mailbox_name(struct mail_namespace *ns, string_t *vname_str,
1.13.12 by Jaldhar H. Vyas
Import upstream version 2.2.5
187
		       char alt_char)
188
{
189
	const char *old_vname;
1.13.16 by Jelmer Vernooij
Import upstream version 2.2.16
190
	char *vname, list_sep = mailbox_list_get_hierarchy_sep(ns->list);
1.13.12 by Jaldhar H. Vyas
Import upstream version 2.2.5
191
	guid_128_t guid;
1.13.16 by Jelmer Vernooij
Import upstream version 2.2.16
192
	unsigned int i, start_pos;
193
194
	vname = str_c_modifiable(vname_str);
195
	if (strncmp(vname, ns->prefix, ns->prefix_len) == 0)
196
		start_pos = ns->prefix_len;
197
	else
198
		start_pos = 0;
1.13.12 by Jaldhar H. Vyas
Import upstream version 2.2.5
199
200
	/* replace control chars */
1.13.16 by Jelmer Vernooij
Import upstream version 2.2.16
201
	for (i = start_pos; vname[i] != '\0'; i++) {
202
		if ((unsigned char)vname[i] < ' ')
203
			vname[i] = alt_char;
1.13.12 by Jaldhar H. Vyas
Import upstream version 2.2.5
204
	}
205
	/* make it valid UTF8 */
1.13.16 by Jelmer Vernooij
Import upstream version 2.2.16
206
	if (!uni_utf8_str_is_valid(vname)) {
207
		old_vname = t_strdup(vname + start_pos);
208
		str_truncate(vname_str, start_pos);
1.13.12 by Jaldhar H. Vyas
Import upstream version 2.2.5
209
		if (uni_utf8_get_valid_data((const void *)old_vname,
1.13.16 by Jelmer Vernooij
Import upstream version 2.2.16
210
					    strlen(old_vname), vname_str))
1.13.12 by Jaldhar H. Vyas
Import upstream version 2.2.5
211
			i_unreached();
1.13.16 by Jelmer Vernooij
Import upstream version 2.2.16
212
		vname = str_c_modifiable(vname_str);
1.13.12 by Jaldhar H. Vyas
Import upstream version 2.2.5
213
	}
1.13.16 by Jelmer Vernooij
Import upstream version 2.2.16
214
	if (dsync_is_valid_name(ns, vname))
1.13.12 by Jaldhar H. Vyas
Import upstream version 2.2.5
215
		return;
216
217
	/* 1) change any real separators to alt separators (this wouldn't
218
	   be necessary with listescape, but don't bother detecting it) */
219
	if (list_sep != mail_namespace_get_sep(ns)) {
1.13.16 by Jelmer Vernooij
Import upstream version 2.2.16
220
		for (i = start_pos; vname[i] != '\0'; i++) {
221
			if (vname[i] == list_sep)
222
				vname[i] = alt_char;
1.13.12 by Jaldhar H. Vyas
Import upstream version 2.2.5
223
		}
1.13.16 by Jelmer Vernooij
Import upstream version 2.2.16
224
		if (dsync_is_valid_name(ns, vname))
1.13.12 by Jaldhar H. Vyas
Import upstream version 2.2.5
225
			return;
226
	}
227
	/* 2) '/' characters aren't valid without listescape */
228
	if (mail_namespace_get_sep(ns) != '/' && list_sep != '/') {
1.13.16 by Jelmer Vernooij
Import upstream version 2.2.16
229
		for (i = start_pos; vname[i] != '\0'; i++) {
230
			if (vname[i] == '/')
231
				vname[i] = alt_char;
1.13.12 by Jaldhar H. Vyas
Import upstream version 2.2.5
232
		}
1.13.16 by Jelmer Vernooij
Import upstream version 2.2.16
233
		if (dsync_is_valid_name(ns, vname))
1.13.12 by Jaldhar H. Vyas
Import upstream version 2.2.5
234
			return;
235
	}
236
	/* 3) probably some reserved name (e.g. dbox-Mails) */
1.13.16 by Jelmer Vernooij
Import upstream version 2.2.16
237
	str_insert(vname_str, ns->prefix_len, "_");
238
	if (dsync_is_valid_name(ns, str_c(vname_str)))
1.13.12 by Jaldhar H. Vyas
Import upstream version 2.2.5
239
		return;
240
241
	/* 4) name is too long? just give up and generate a unique name */
242
	guid_128_generate(guid);
1.13.16 by Jelmer Vernooij
Import upstream version 2.2.16
243
	str_truncate(vname_str, 0);
244
	str_append(vname_str, ns->prefix);
245
	str_append(vname_str, guid_128_to_string(guid));
246
	i_assert(dsync_is_valid_name(ns, str_c(vname_str)));
1.13.12 by Jaldhar H. Vyas
Import upstream version 2.2.5
247
}
248
249
static int
250
dsync_get_mailbox_name(struct dsync_brain *brain, const char *const *name_parts,
251
		       const char **name_r, struct mail_namespace **ns_r)
252
{
253
	struct mail_namespace *ns;
254
	const char *p;
255
	string_t *vname;
1.13.16 by Jelmer Vernooij
Import upstream version 2.2.16
256
	char ns_sep;
1.13.12 by Jaldhar H. Vyas
Import upstream version 2.2.5
257
258
	i_assert(*name_parts != NULL);
259
260
	ns = dsync_find_namespace(brain, name_parts);
261
	if (ns == NULL)
262
		return -1;
263
	ns_sep = mail_namespace_get_sep(ns);
264
265
	/* build the mailbox name */
266
	vname = t_str_new(128);
267
	for (; *name_parts != NULL; name_parts++) {
268
		for (p = *name_parts; *p != '\0'; p++) {
269
			if (*p != ns_sep)
270
				str_append_c(vname, *p);
271
			else
1.13.16 by Jelmer Vernooij
Import upstream version 2.2.16
272
				str_append_c(vname, brain->alt_char);
1.13.12 by Jaldhar H. Vyas
Import upstream version 2.2.5
273
		}
274
		str_append_c(vname, ns_sep);
275
	}
276
	str_truncate(vname, str_len(vname)-1);
277
1.13.16 by Jelmer Vernooij
Import upstream version 2.2.16
278
	dsync_fix_mailbox_name(ns, vname, brain->alt_char);
1.13.12 by Jaldhar H. Vyas
Import upstream version 2.2.5
279
	*name_r = str_c(vname);
280
	*ns_r = ns;
281
	return 0;
282
}
283
284
static void dsync_brain_mailbox_trees_sync(struct dsync_brain *brain)
285
{
286
	struct dsync_mailbox_tree_sync_ctx *ctx;
287
	const struct dsync_mailbox_tree_sync_change *change;
288
	enum dsync_mailbox_trees_sync_type sync_type;
1.16.1 by Jaldhar H. Vyas
Import upstream version 2.2.9
289
	enum dsync_mailbox_trees_sync_flags sync_flags =
290
		(brain->debug ? DSYNC_MAILBOX_TREES_SYNC_FLAG_DEBUG : 0) |
291
		(brain->master_brain ? DSYNC_MAILBOX_TREES_SYNC_FLAG_MASTER_BRAIN : 0);
1.13.12 by Jaldhar H. Vyas
Import upstream version 2.2.5
292
293
	if (brain->no_backup_overwrite)
294
		sync_type = DSYNC_MAILBOX_TREES_SYNC_TYPE_TWOWAY;
295
	else if (brain->backup_send)
296
		sync_type = DSYNC_MAILBOX_TREES_SYNC_TYPE_PRESERVE_LOCAL;
297
	else if (brain->backup_recv)
298
		sync_type = DSYNC_MAILBOX_TREES_SYNC_TYPE_PRESERVE_REMOTE;
299
	else
300
		sync_type = DSYNC_MAILBOX_TREES_SYNC_TYPE_TWOWAY;
301
302
	ctx = dsync_mailbox_trees_sync_init(brain->local_mailbox_tree,
303
					    brain->remote_mailbox_tree,
1.16.1 by Jaldhar H. Vyas
Import upstream version 2.2.9
304
					    sync_type, sync_flags);
1.13.12 by Jaldhar H. Vyas
Import upstream version 2.2.5
305
	while ((change = dsync_mailbox_trees_sync_next(ctx)) != NULL) {
1.13.17 by Jelmer Vernooij
Import upstream version 2.2.18
306
		if (dsync_brain_mailbox_tree_sync_change(brain, change,
307
							 &brain->mail_error) < 0) {
1.13.12 by Jaldhar H. Vyas
Import upstream version 2.2.5
308
			brain->failed = TRUE;
1.13.17 by Jelmer Vernooij
Import upstream version 2.2.18
309
			break;
310
		}
1.13.12 by Jaldhar H. Vyas
Import upstream version 2.2.5
311
	}
312
	dsync_mailbox_trees_sync_deinit(&ctx);
313
}
314
315
bool dsync_brain_recv_mailbox_tree(struct dsync_brain *brain)
316
{
317
	const struct dsync_mailbox_node *remote_node;
318
	struct dsync_mailbox_node *node, *dup_node1, *dup_node2;
319
	const char *const *parts, *name;
320
	struct mail_namespace *ns;
321
	enum dsync_ibc_recv_ret ret;
322
	char sep[2];
323
	bool changed = FALSE;
324
1.13.16 by Jelmer Vernooij
Import upstream version 2.2.16
325
	sep[0] = brain->hierarchy_sep; sep[1] = '\0';
1.13.12 by Jaldhar H. Vyas
Import upstream version 2.2.5
326
	while ((ret = dsync_ibc_recv_mailbox_tree_node(brain->ibc, &parts,
327
						       &remote_node)) > 0) {
328
		if (dsync_get_mailbox_name(brain, parts, &name, &ns) < 0) {
329
			i_error("Couldn't find namespace for mailbox %s",
330
				t_strarray_join(parts, sep));
331
			brain->failed = TRUE;
332
			return TRUE;
333
		}
1.13.16 by Jelmer Vernooij
Import upstream version 2.2.16
334
		if (brain->debug) {
335
			i_debug("brain %c: Remote mailbox tree: %s %s",
336
				brain->master_brain ? 'M' : 'S',
337
				t_strarray_join(parts, sep),
338
				dsync_mailbox_node_to_string(remote_node));
339
		}
1.13.12 by Jaldhar H. Vyas
Import upstream version 2.2.5
340
		node = dsync_mailbox_tree_get(brain->remote_mailbox_tree, name);
341
		node->ns = ns;
342
		dsync_mailbox_node_copy_data(node, remote_node);
343
	}
344
	if (ret != DSYNC_IBC_RECV_RET_FINISHED)
345
		return changed;
346
347
	if (dsync_mailbox_tree_build_guid_hash(brain->remote_mailbox_tree,
348
					       &dup_node1, &dup_node2) < 0) {
349
		i_error("Remote sent duplicate mailbox GUID %s for mailboxes %s and %s",
350
			guid_128_to_string(dup_node1->mailbox_guid),
351
			dsync_mailbox_node_get_full_name(brain->remote_mailbox_tree,
352
							 dup_node1),
353
			dsync_mailbox_node_get_full_name(brain->remote_mailbox_tree,
354
							 dup_node2));
355
		brain->failed = TRUE;
356
	}
357
358
	brain->state = DSYNC_STATE_RECV_MAILBOX_TREE_DELETES;
359
	return TRUE;
360
}
361
362
static void
363
dsync_brain_mailbox_tree_add_delete(struct dsync_mailbox_tree *tree,
364
				    struct dsync_mailbox_tree *other_tree,
1.13.16 by Jelmer Vernooij
Import upstream version 2.2.16
365
				    const struct dsync_mailbox_delete *other_del,
366
				    const struct dsync_mailbox_node **node_r,
367
				    const char **status_r)
1.13.12 by Jaldhar H. Vyas
Import upstream version 2.2.5
368
{
369
	const struct dsync_mailbox_node *node;
370
	struct dsync_mailbox_node *other_node, *old_node;
371
	const char *name;
372
373
	/* see if we can find the deletion based on mailbox tree that should
374
	   still have the mailbox */
1.13.16 by Jelmer Vernooij
Import upstream version 2.2.16
375
	node = *node_r = dsync_mailbox_tree_find_delete(tree, other_del);
376
	if (node == NULL) {
377
		*status_r = "not found";
1.13.12 by Jaldhar H. Vyas
Import upstream version 2.2.5
378
		return;
1.13.16 by Jelmer Vernooij
Import upstream version 2.2.16
379
	}
1.13.12 by Jaldhar H. Vyas
Import upstream version 2.2.5
380
381
	switch (other_del->type) {
382
	case DSYNC_MAILBOX_DELETE_TYPE_MAILBOX:
383
		/* mailbox is always deleted */
384
		break;
385
	case DSYNC_MAILBOX_DELETE_TYPE_DIR:
386
		if (other_del->timestamp <= node->last_renamed_or_created) {
387
			/* we don't want to delete this directory, we already
388
			   have a newer timestamp for it */
1.13.16 by Jelmer Vernooij
Import upstream version 2.2.16
389
			*status_r = "keep directory, we have a newer timestamp";
1.13.12 by Jaldhar H. Vyas
Import upstream version 2.2.5
390
			return;
391
		}
392
		break;
393
	case DSYNC_MAILBOX_DELETE_TYPE_UNSUBSCRIBE:
394
		if (other_del->timestamp <= node->last_subscription_change) {
395
			/* we don't want to unsubscribe, since we already have
396
			   a newer subscription timestamp */
1.13.16 by Jelmer Vernooij
Import upstream version 2.2.16
397
			*status_r = "keep subscription, we have a newer timestamp";
1.13.12 by Jaldhar H. Vyas
Import upstream version 2.2.5
398
			return;
399
		}
400
		break;
401
	}
402
403
	/* make a node for it in the other mailbox tree */
404
	name = dsync_mailbox_node_get_full_name(tree, node);
405
	other_node = dsync_mailbox_tree_get(other_tree, name);
406
407
	if (other_node->existence == DSYNC_MAILBOX_NODE_EXISTS &&
408
	    (!guid_128_is_empty(other_node->mailbox_guid) ||
409
	     other_del->type != DSYNC_MAILBOX_DELETE_TYPE_MAILBOX)) {
410
		/* other side has already created a new mailbox or
411
		   directory with this name, we can't delete it */
1.13.16 by Jelmer Vernooij
Import upstream version 2.2.16
412
		*status_r = "name has already been recreated";
1.13.12 by Jaldhar H. Vyas
Import upstream version 2.2.5
413
		return;
414
	}
415
416
	/* ok, mark the other node deleted */
417
	if (other_del->type == DSYNC_MAILBOX_DELETE_TYPE_MAILBOX) {
418
		memcpy(other_node->mailbox_guid, node->mailbox_guid,
419
		       sizeof(other_node->mailbox_guid));
420
	}
1.13.14 by Jelmer Vernooij
Import upstream version 2.2.13~rc1
421
	if (other_node->ns != node->ns && other_node->ns != NULL) {
422
		/* namespace mismatch for this node. this shouldn't happen
423
		   normally, but especially during some misconfigurations it's
424
		   possible that one side has created mailboxes that conflict
425
		   with another namespace's prefix. since we're here because
426
		   one of the mailboxes was deleted, we'll just ignore this. */
1.13.16 by Jelmer Vernooij
Import upstream version 2.2.16
427
		*status_r = "namespace mismatch";
1.13.14 by Jelmer Vernooij
Import upstream version 2.2.13~rc1
428
		return;
429
	}
1.13.12 by Jaldhar H. Vyas
Import upstream version 2.2.5
430
	other_node->ns = node->ns;
1.13.16 by Jelmer Vernooij
Import upstream version 2.2.16
431
	if (other_del->type != DSYNC_MAILBOX_DELETE_TYPE_UNSUBSCRIBE) {
1.13.12 by Jaldhar H. Vyas
Import upstream version 2.2.5
432
		other_node->existence = DSYNC_MAILBOX_NODE_DELETED;
1.13.16 by Jelmer Vernooij
Import upstream version 2.2.16
433
		*status_r = "marked as deleted";
434
	} else {
1.13.12 by Jaldhar H. Vyas
Import upstream version 2.2.5
435
		other_node->last_subscription_change = other_del->timestamp;
436
		other_node->subscribed = FALSE;
1.13.16 by Jelmer Vernooij
Import upstream version 2.2.16
437
		*status_r = "marked as unsubscribed";
1.13.12 by Jaldhar H. Vyas
Import upstream version 2.2.5
438
	}
439
440
	if (dsync_mailbox_tree_guid_hash_add(other_tree, other_node,
441
					     &old_node) < 0)
442
		i_unreached();
443
}
444
445
bool dsync_brain_recv_mailbox_tree_deletes(struct dsync_brain *brain)
446
{
1.13.16 by Jelmer Vernooij
Import upstream version 2.2.16
447
	const struct dsync_mailbox_node *node;
448
	const char *status;
1.13.12 by Jaldhar H. Vyas
Import upstream version 2.2.5
449
	const struct dsync_mailbox_delete *deletes;
450
	unsigned int i, count;
451
	char sep;
452
453
	if (dsync_ibc_recv_mailbox_deletes(brain->ibc, &deletes, &count,
454
					   &sep) == 0)
455
		return FALSE;
456
457
	/* apply remote's mailbox deletions based on our local tree */
458
	dsync_mailbox_tree_set_remote_sep(brain->local_mailbox_tree, sep);
459
	for (i = 0; i < count; i++) {
460
		dsync_brain_mailbox_tree_add_delete(brain->local_mailbox_tree,
461
						    brain->remote_mailbox_tree,
1.13.16 by Jelmer Vernooij
Import upstream version 2.2.16
462
						    &deletes[i], &node, &status);
463
		if (brain->debug) {
464
			const char *node_name = node == NULL ? "" :
465
				dsync_mailbox_node_get_full_name(brain->local_mailbox_tree, node);
466
			i_debug("brain %c: Remote mailbox tree deletion: guid=%s type=%s timestamp=%ld name=%s local update=%s",
467
				brain->master_brain ? 'M' : 'S',
468
				guid_128_to_string(deletes[i].guid),
469
				dsync_mailbox_delete_type_to_string(deletes[i].type),
470
				deletes[i].timestamp, node_name, status);
471
		}
1.13.12 by Jaldhar H. Vyas
Import upstream version 2.2.5
472
	}
473
474
	/* apply local mailbox deletions based on remote tree */
475
	deletes = dsync_mailbox_tree_get_deletes(brain->local_mailbox_tree,
476
						 &count);
477
	dsync_mailbox_tree_set_remote_sep(brain->remote_mailbox_tree,
478
					  brain->hierarchy_sep);
479
	for (i = 0; i < count; i++) {
480
		dsync_brain_mailbox_tree_add_delete(brain->remote_mailbox_tree,
481
						    brain->local_mailbox_tree,
1.13.16 by Jelmer Vernooij
Import upstream version 2.2.16
482
						    &deletes[i], &node, &status);
1.13.12 by Jaldhar H. Vyas
Import upstream version 2.2.5
483
	}
484
485
	dsync_brain_mailbox_trees_sync(brain);
486
	brain->state = brain->master_brain ?
487
		DSYNC_STATE_MASTER_SEND_MAILBOX :
488
		DSYNC_STATE_SLAVE_RECV_MAILBOX;
489
	i_assert(brain->local_tree_iter == NULL);
490
	brain->local_tree_iter =
491
		dsync_mailbox_tree_iter_init(brain->local_mailbox_tree);
492
	return TRUE;
493
}