Example #1
0
static int
index_storage_get_dict(struct mailbox *box, enum mail_attribute_type type,
		       struct dict **dict_r, const char **mailbox_prefix_r)
{
	struct mail_storage *storage = box->storage;
	struct mail_namespace *ns;
	struct mailbox_metadata metadata;
	struct dict_settings set;
	const char *error;

	if (mailbox_get_metadata(box, MAILBOX_METADATA_GUID, &metadata) < 0)
		return -1;
	*mailbox_prefix_r = guid_128_to_string(metadata.guid);

	ns = mailbox_get_namespace(box);
	if (type == MAIL_ATTRIBUTE_TYPE_PRIVATE) {
		/* private attributes are stored in user's own dict */
		return index_storage_get_user_dict(storage, storage->user, dict_r);
	} else if (ns->user == ns->owner) {
		/* user owns the mailbox. shared attributes are stored in
		   the same dict. */
		return index_storage_get_user_dict(storage, storage->user, dict_r);
	} else if (ns->owner != NULL) {
		/* accessing shared attribute of a shared mailbox.
		   use the owner's dict. */
		return index_storage_get_user_dict(storage, ns->owner, dict_r);
	}

	/* accessing shared attributes of a public mailbox. no user owns it,
	   so use the storage's dict. */
	if (storage->_shared_attr_dict != NULL) {
		*dict_r = storage->_shared_attr_dict;
		return 0;
	}
	if (*storage->set->mail_attribute_dict == '\0') {
		mail_storage_set_error(storage, MAIL_ERROR_NOTPOSSIBLE,
				       "Mailbox attributes not enabled");
		return -1;
	}
	if (storage->shared_attr_dict_failed) {
		mail_storage_set_internal_error(storage);
		return -1;
	}

	memset(&set, 0, sizeof(set));
	set.username = storage->user->username;
	set.base_dir = storage->user->set->base_dir;
	if (mail_user_get_home(storage->user, &set.home_dir) <= 0)
		set.home_dir = NULL;
	if (dict_init(storage->set->mail_attribute_dict, &set,
		      &storage->_shared_attr_dict, &error) < 0) {
		mail_storage_set_critical(storage,
			"mail_attribute_dict: dict_init(%s) failed: %s",
			storage->set->mail_attribute_dict, error);
		storage->shared_attr_dict_failed = TRUE;
		return -1;
	}
	*dict_r = storage->_shared_attr_dict;
	return 0;
}
Example #2
0
static int imapc_mail_failed(struct mail *mail, const char *field)
{
	struct imapc_mail *imail = (struct imapc_mail *)mail;
	struct imapc_mailbox *mbox = (struct imapc_mailbox *)mail->box;
	bool fix_broken_mail = FALSE;

	if (mail->expunged || imapc_mail_is_expunged(mail)) {
		mail_set_expunged(mail);
	} else if (!imapc_client_mailbox_is_opened(mbox->client_box)) {
		/* we've already logged a disconnection error */
		mail_storage_set_internal_error(mail->box->storage);
	} else {
		/* By default we'll assume that this is a critical failure,
		   because we don't want to lose any data. We can be here
		   either because it's a temporary failure on the server or
		   it's a permanent failure. Unfortunately we can't know
		   which case it is, so permanent failures need to be worked
		   around by setting imapc_features=fetch-fix-broken-mails.

		   One reason for permanent failures was that earlier Exchange
		   versions failed to return any data for messages in Calendars
		   mailbox. This seems to be fixed in newer versions.
		   */
		fix_broken_mail = imail->fetch_ignore_if_missing;
		mail_storage_set_critical(mail->box->storage,
			"imapc: Remote server didn't send %s for UID %u in %s%s (FETCH replied: %s)",
			field, mail->uid, mail->box->vname,
			fix_broken_mail ? " - treating it as empty" : "",
			imail->last_fetch_reply);
	}
	return fix_broken_mail ? 0 : -1;
}
Example #3
0
static int
acl_mailbox_rename(struct mailbox *src, struct mailbox *dest)
{
	struct acl_mailbox *abox = ACL_CONTEXT(src);
	int ret;

	/* renaming requires rights to delete the old mailbox */
	ret = acl_mailbox_right_lookup(src, ACL_STORAGE_RIGHT_DELETE);
	if (ret <= 0) {
		if (ret == 0)
			acl_mailbox_fail_not_found(src);
		return -1;
	}

	/* and create the new one under the parent mailbox */
	T_BEGIN {
		ret = acl_mailbox_list_have_right(dest->list, dest->name, TRUE,
						ACL_STORAGE_RIGHT_CREATE, NULL);
	} T_END;

	if (ret <= 0) {
		if (ret == 0) {
			/* Note that if the mailbox didn't have LOOKUP
			   permission, this now reveals to user the mailbox's
			   existence. Can't help it. */
			mail_storage_set_error(src->storage, MAIL_ERROR_PERM,
					       MAIL_ERRSTR_NO_PERMISSION);
		} else {
			mail_storage_set_internal_error(src->storage);
		}
		return -1;
	}

	return abox->module_ctx.super.rename_box(src, dest);
}
Example #4
0
static void imapc_sync_callback(const struct imapc_command_reply *reply,
				void *context)
{
	struct imapc_sync_command *cmd = context;
	struct imapc_sync_context *ctx = cmd->ctx;

	i_assert(ctx->sync_command_count > 0);

	if (reply->state == IMAPC_COMMAND_STATE_OK)
		;
	else if (reply->state == IMAPC_COMMAND_STATE_NO && cmd->ignore_no) {
		/* maybe the message was expunged already.
		   some servers fail STOREs with NO in such situation. */
	} else if (reply->state == IMAPC_COMMAND_STATE_DISCONNECTED) {
		/* the disconnection is already logged, don't flood
		   the logs unnecessarily */
		mail_storage_set_internal_error(&ctx->mbox->storage->storage);
		ctx->failed = TRUE;
	} else {
		mail_storage_set_critical(&ctx->mbox->storage->storage,
					  "imapc: Sync command '%s' failed: %s",
					  cmd->cmd_str, reply->text_full);
		ctx->failed = TRUE;
	}
	
	if (--ctx->sync_command_count == 0)
		imapc_client_stop(ctx->mbox->storage->client->client);
	i_free(cmd->cmd_str);
	i_free(cmd);
}
int index_storage_attribute_get(struct mailbox_transaction_context *t,
				enum mail_attribute_type type, const char *key,
				struct mail_attribute_value *value_r)
{
	struct dict *dict;
	const char *mailbox_prefix;
	int ret;

	memset(value_r, 0, sizeof(*value_r));

	if (strncmp(key, MAILBOX_ATTRIBUTE_PREFIX_DOVECOT_PVT,
		    strlen(MAILBOX_ATTRIBUTE_PREFIX_DOVECOT_PVT)) == 0)
		return 0;

	if (index_storage_get_dict(t->box, type, &dict, &mailbox_prefix) < 0)
		return -1;

	ret = dict_lookup(dict, pool_datastack_create(),
			  key_get_prefixed(type, mailbox_prefix, key),
			  &value_r->value);
	if (ret < 0) {
		mail_storage_set_internal_error(t->box->storage);
		return -1;
	}
	return ret;
}
Example #6
0
static int
sieve_attribute_get_active_script(struct mail_storage *storage,
			   struct sieve_storage *svstorage,
			   struct mail_attribute_value *value_r)
{
	struct sieve_script *script;
	const char *errstr;
	int ret;

	if ((ret=sieve_storage_is_singular(svstorage)) <= 0) {
		if (ret == 0 && sieve_storage_active_script_get_last_change
			(svstorage, &value_r->last_change) < 0) {
			ret = -1;
		}
		if (ret < 0)
			mail_storage_set_internal_error(storage);
		return ret;
	}

	if ((script=sieve_storage_active_script_open
		(svstorage, NULL)) == NULL)
		return 0;

	if ((ret=sieve_attribute_retrieve_script
		(storage, svstorage, script, TRUE, value_r, &errstr)) < 0) {
		mail_storage_set_critical(storage,
			"Failed to access active sieve script: %s", errstr);
	}
	return ret;
}
Example #7
0
static int
sieve_attribute_set_active(struct mail_storage *storage,
			   struct sieve_storage *svstorage,
			   const struct mail_attribute_value *value)
{
	const char *scriptname;
	struct sieve_script *script;
	int ret;

	if (mailbox_attribute_value_to_string(storage, value, &scriptname) < 0)
		return -1;

	if (scriptname == NULL) {
		/* don't affect non-link active script */
		if ((ret=sieve_storage_is_singular(svstorage)) != 0) {
			if (ret < 0) {
				mail_storage_set_internal_error(storage);
				return -1;
			}
			return 0;
		}

		/* deactivate current script */
		if (sieve_storage_deactivate(svstorage, value->last_change) < 0) {
			mail_storage_set_critical(storage,
				"Failed to deactivate Sieve: %s",
				sieve_storage_get_last_error(svstorage, NULL));
			return -1;
		}
		return 0;
	}
	i_assert(scriptname[0] == MAILBOX_ATTRIBUTE_SIEVE_DEFAULT_LINK);
	scriptname++;

	/* activate specified script */
	script = sieve_storage_open_script(svstorage, scriptname, NULL);
	ret = script == NULL ? -1 :
		sieve_script_activate(script, value->last_change);
	if (ret < 0) {
		mail_storage_set_critical(storage,
			"Failed to activate Sieve script '%s': %s", scriptname,
			sieve_storage_get_last_error(svstorage, NULL));
	}
	if (script != NULL)
		sieve_script_unref(&script);
	sieve_storage_set_modified(svstorage, value->last_change);
	return ret;
}
Example #8
0
int index_storage_attribute_iter_deinit(struct mailbox_attribute_iter *_iter)
{
	struct index_storage_attribute_iter *iter =
		(struct index_storage_attribute_iter *)_iter;
	int ret;

	if (iter->diter == NULL) {
		ret = iter->dict_disabled ? 0 : -1;
	} else {
		if ((ret = dict_iterate_deinit(&iter->diter)) < 0)
			mail_storage_set_internal_error(_iter->box->storage);
	}
	i_free(iter->prefix);
	i_free(iter);
	return ret;
}
Example #9
0
static int
index_storage_get_user_dict(struct mail_storage *err_storage,
			    struct mail_user *user, struct dict **dict_r)
{
	struct dict_settings dict_set;
	struct mail_namespace *ns;
	struct mail_storage *attr_storage;
	const char *error;

	if (user->_attr_dict != NULL) {
		*dict_r = user->_attr_dict;
		return 0;
	}
	if (user->attr_dict_failed) {
		mail_storage_set_internal_error(err_storage);
		return -1;
	}

	ns = mail_user_find_attribute_namespace(user);
	if (ns == NULL) {
		/* probably never happens? */
		mail_storage_set_error(err_storage, MAIL_ERROR_NOTPOSSIBLE,
			"Mailbox attributes not available for this mailbox");
		return -1;
	}
	attr_storage = mail_namespace_get_default_storage(ns);

	if (*attr_storage->set->mail_attribute_dict == '\0') {
		mail_storage_set_error(err_storage, MAIL_ERROR_NOTPOSSIBLE,
				       "Mailbox attributes not enabled");
		return -1;
	}

	memset(&dict_set, 0, sizeof(dict_set));
	dict_set.username = user->username;
	dict_set.base_dir = user->set->base_dir;
	if (dict_init(attr_storage->set->mail_attribute_dict, &dict_set,
		      &user->_attr_dict, &error) < 0) {
		mail_storage_set_critical(err_storage,
			"mail_attribute_dict: dict_init(%s) failed: %s",
			attr_storage->set->mail_attribute_dict, error);
		user->attr_dict_failed = TRUE;
		return -1;
	}
	*dict_r = user->_attr_dict;
	return 0;
}
Example #10
0
static int fts_mailbox_get_last_cached_seq(struct mailbox *box, uint32_t *seq_r)
{
	struct fts_mailbox_list *flist = FTS_LIST_CONTEXT(box->list);
	uint32_t seq1, seq2, last_uid;

	if (fts_backend_get_last_uid(flist->backend, box, &last_uid) < 0) {
		mail_storage_set_internal_error(box->storage);
		return -1;
	}

	if (last_uid == 0)
		*seq_r = 0;
	else {
		mailbox_get_seq_range(box, 1, last_uid, &seq1, &seq2);
		*seq_r = seq2;
	}
	return 0;
}
Example #11
0
static int imapc_mail_failed(struct mail *mail, const char *field)
{
	struct imapc_mailbox *mbox = (struct imapc_mailbox *)mail->box;

	if (mail->expunged || imapc_mail_is_expunged(mail)) {
		mail_set_expunged(mail);
		return -1;
	} else if (!imapc_client_mailbox_is_opened(mbox->client_box)) {
		/* we've already logged a disconnection error */
		mail_storage_set_internal_error(mail->box->storage);
		return -1;
	} else {
		mail_storage_set_critical(mail->box->storage,
			"imapc: Remote server didn't send %s for UID %u in %s",
			field, mail->uid, mail->box->vname);
		return 0;
	}
}
static int acl_attribute_get_acl(struct mailbox *box, const char *key,
				 struct mail_attribute_value *value_r)
{
	struct acl_object *aclobj = acl_mailbox_get_aclobj(box);
	struct acl_object_list_iter *iter;
	struct acl_rights rights, wanted_rights;
	const char *id;
	int ret;

	memset(value_r, 0, sizeof(*value_r));

	if (!box->storage->user->dsyncing) {
		mail_storage_set_error(box->storage, MAIL_ERROR_PERM,
				       MAIL_ERRSTR_NO_PERMISSION);
		return -1;
	}
	/* set last_change for all ACL objects, even if they don't exist
	   (because they could have been removed by the last change, and dsync
	   can use this information) */
	(void)acl_object_last_changed(aclobj, &value_r->last_change);

	memset(&wanted_rights, 0, sizeof(wanted_rights));
	id = key + strlen(MAILBOX_ATTRIBUTE_PREFIX_ACL);
	if (acl_identifier_parse(id, &wanted_rights) < 0) {
		mail_storage_set_error(box->storage, MAIL_ERROR_PARAMS,
				       t_strdup_printf("Invalid ID: %s", id));
		return -1;
	}

	iter = acl_object_list_init(aclobj);
	while ((ret = acl_object_list_next(iter, &rights)) > 0) {
		if (!rights.global &&
		    rights.id_type == wanted_rights.id_type &&
		    null_strcmp(rights.identifier, wanted_rights.identifier) == 0) {
			value_r->value = acl_rights_export(&rights);
			break;
		}
	}
	if (ret < 0)
		mail_storage_set_internal_error(box->storage);
	acl_object_list_deinit(&iter);
	return ret;
}
Example #13
0
static int
sieve_attribute_unset_active_script(struct mail_storage *storage,
			   struct sieve_storage *svstorage, time_t last_change)
{
	int ret;

	if ((ret=sieve_storage_is_singular(svstorage)) != 0) {
		if (ret < 0)
			mail_storage_set_internal_error(storage);
		return ret;
	}

	if (sieve_storage_deactivate(svstorage, last_change) < 0) {
		mail_storage_set_critical(storage,
			"Failed to deactivate sieve: %s",
			sieve_storage_get_last_error(svstorage, NULL));
		return -1;
	}
	return 0;
}
static const char *
acl_attribute_iter_next_acl(struct acl_mailbox_attribute_iter *aiter)
{
	struct acl_rights rights;
	int ret;

	while ((ret = acl_object_list_next(aiter->acl_iter, &rights)) > 0) {
		if (rights.global)
			continue;
		str_truncate(aiter->acl_name, strlen(MAILBOX_ATTRIBUTE_PREFIX_ACL));
		acl_rights_write_id(aiter->acl_name, &rights);
		return str_c(aiter->acl_name);
	}
	if (ret < 0) {
		mail_storage_set_internal_error(aiter->iter.box->storage);
		aiter->failed = TRUE;
		return NULL;
	}
	acl_object_list_deinit(&aiter->acl_iter);
	return NULL;
}
Example #15
0
void imapc_mailbox_set_corrupted(struct imapc_mailbox *mbox,
				 const char *reason, ...)
{
	va_list va;

	va_start(va, reason);
	i_error("imapc: Mailbox '%s' state corrupted: %s",
		mbox->box.name, t_strdup_vprintf(reason, va));
	va_end(va);

	mail_storage_set_internal_error(&mbox->storage->storage);

	if (!mbox->initial_sync_done) {
		/* we failed during initial sync. need to rebuild indexes if
		   we want to get this fixed */
		mail_index_mark_corrupted(mbox->box.index);
	} else {
		/* maybe the remote server is buggy and has become confused.
		   try reconnecting. */
	}
	imapc_client_mailbox_reconnect(mbox->client_box);
}
int acl_mailbox_right_lookup(struct mailbox *box, unsigned int right_idx)
{
	struct acl_mailbox *abox = ACL_CONTEXT(box);
	struct acl_mailbox_list *alist = ACL_LIST_CONTEXT(box->list);
	int ret;

	if (abox->skip_acl_checks)
		return 1;

	ret = acl_object_have_right(abox->aclobj,
			alist->rights.acl_storage_right_idx[right_idx]);
	if (ret > 0)
		return 1;
	if (ret < 0) {
		mail_storage_set_internal_error(box->storage);
		return -1;
	}

	mail_storage_set_error(box->storage, MAIL_ERROR_PERM,
			       MAIL_ERRSTR_NO_PERMISSION);
	return 0;
}
Example #17
0
static int
acl_mailbox_create(struct mailbox *box, const struct mailbox_update *update,
		   bool directory)
{
	struct acl_mailbox *abox = ACL_CONTEXT(box);
	int ret;

	if (!mailbox_is_autocreated(box)) {
		/* we're looking up CREATE permission from our parent's rights */
		ret = acl_mailbox_list_have_right(box->list, box->name, TRUE,
						  ACL_STORAGE_RIGHT_CREATE, NULL);
	} else {
		/* mailbox is autocreated, so we need to treat it as if it
		   already exists. ignore the "create" ACL here. */
		ret = 1;
	}
	if (ret <= 0) {
		if (ret < 0) {
			mail_storage_set_internal_error(box->storage);
			return -1;
		}
		/* Note that if user didn't have LOOKUP permission to parent
		   mailbox, this may reveal the mailbox's existence to user.
		   Can't help it. */
		mail_storage_set_error(box->storage, MAIL_ERROR_PERM,
				       MAIL_ERRSTR_NO_PERMISSION);
		return -1;
	}

	/* ignore ACLs in this mailbox until creation is complete, because
	   super.create() may call e.g. mailbox_open() which will fail since
	   we haven't yet copied ACLs to this mailbox. */
	abox->skip_acl_checks = TRUE;
	ret = abox->module_ctx.super.create_box(box, update, directory);
	abox->skip_acl_checks = FALSE;
	if (ret == 0)
		acl_mailbox_copy_acls_from_parent(box);
	return ret;
}
Example #18
0
static int
sieve_attribute_get_default(struct mail_storage *storage,
			    struct sieve_storage *svstorage,
			    struct mail_attribute_value *value_r)
{
	const char *scriptname;
	int ret;

	ret = sieve_storage_active_script_get_name(svstorage, &scriptname);
	if (ret == 0)
		return sieve_attribute_get_active_script(storage, svstorage, value_r);

	if (ret > 0) {
		value_r->value = t_strdup_printf("%c%s",
			MAILBOX_ATTRIBUTE_SIEVE_DEFAULT_LINK, scriptname);
		if (sieve_storage_active_script_get_last_change
				(svstorage, &value_r->last_change) < 0)
			ret = -1;
	}
	if (ret < 0)
		mail_storage_set_internal_error(storage);
	return ret;
}
Example #19
0
static void fts_mail_index(struct mail *_mail)
{
	struct fts_transaction_context *ft = FTS_CONTEXT(_mail->transaction);
	struct fts_mailbox_list *flist = FTS_LIST_CONTEXT(_mail->box->list);

	if (ft->failed)
		return;

	if (!ft->precached) {
		if (fts_mail_precache_init(_mail) < 0) {
			ft->failed = TRUE;
			return;
		}
	}
	if (ft->next_index_seq < _mail->seq) {
		/* most likely a virtual mailbox. we'll first need to
		   index all mails up to the current one. */
		fts_backend_update_set_mailbox(flist->update_ctx, _mail->box);
		if (fts_mail_precache_range(_mail->transaction,
					    flist->update_ctx,
					    ft->next_index_seq,
					    _mail->seq-1) < 0) {
			ft->failed = TRUE;
			return;
		}
	}

	if (ft->next_index_seq == _mail->seq) {
		fts_backend_update_set_mailbox(flist->update_ctx, _mail->box);
		if (fts_build_mail(flist->update_ctx, _mail) < 0) {
			mail_storage_set_internal_error(_mail->box->storage);
			ft->failed = TRUE;
		}
		ft->next_index_seq = _mail->seq + 1;
	}
}
Example #20
0
int fts_indexer_more(struct fts_indexer_context *ctx)
{
	int ret, diff;

	if ((ret = fts_indexer_more_int(ctx)) < 0) {
		mail_storage_set_internal_error(ctx->box->storage);
		ctx->failed = TRUE;
		return -1;
	}

	if (ctx->timeout_secs > 0) {
		diff = ioloop_time - ctx->search_start_time.tv_sec;
		if (diff > (int)ctx->timeout_secs) {
			mail_storage_set_error(ctx->box->storage,
				MAIL_ERROR_INUSE,
				"Timeout while waiting for indexing to finish");
			ctx->failed = TRUE;
			return -1;
		}
	}
	if (ret == 0)
		fts_indexer_notify(ctx);
	return ret;
}
static int
index_transaction_index_commit(struct mail_index_transaction *index_trans,
			       struct mail_index_transaction_commit_result *result_r)
{
	struct mailbox_transaction_context *t =
		MAIL_STORAGE_CONTEXT(index_trans);
	struct index_mailbox_sync_pvt_context *pvt_sync_ctx = NULL;
	int ret = 0;

	if (t->nontransactional_changes)
		t->changes->changed = TRUE;

	if (t->attr_pvt_trans != NULL) {
		if (dict_transaction_commit(&t->attr_pvt_trans) < 0) {
			mail_storage_set_internal_error(t->box->storage);
			ret = -1;
		}
	}
	if (t->attr_shared_trans != NULL) {
		if (dict_transaction_commit(&t->attr_shared_trans) < 0) {
			mail_storage_set_internal_error(t->box->storage);
			ret = -1;
		}
	}

	if (t->save_ctx != NULL) {
		if (ret < 0) {
			t->box->v.transaction_save_rollback(t->save_ctx);
			t->save_ctx = NULL;
		} else if (t->box->v.transaction_save_commit_pre(t->save_ctx) < 0) {
			t->save_ctx = NULL;
			ret = -1;
		} else {
			t->changes->changed = TRUE;
		}
	}

	if (array_is_created(&t->pvt_saves)) {
		if (index_mailbox_sync_pvt_init(t->box, TRUE, &pvt_sync_ctx) < 0)
			ret = -1;
	}

	i_assert(t->mail_ref_count == 0);
	if (ret < 0)
		t->super.rollback(index_trans);
	else {
		if (t->super.commit(index_trans, result_r) < 0) {
			mailbox_set_index_error(t->box);
			ret = -1;
		} else if (result_r->commit_size > 0) {
			/* something was written to the transaction log */
			t->changes->changed = TRUE;
		}
	}

	if (t->save_ctx != NULL)
		t->box->v.transaction_save_commit_post(t->save_ctx, result_r);

	if (pvt_sync_ctx != NULL) {
		if (index_mailbox_sync_pvt_newmails(pvt_sync_ctx, t) < 0) {
			/* failed to add private flags. a bit too late to
			   return failure though, so just ignore silently */
		}
		index_mailbox_sync_pvt_deinit(&pvt_sync_ctx);
	}

	index_transaction_free(t);
	return ret;
}
Example #22
0
static int mdbox_map_open_internal(struct mdbox_map *map, bool create_missing)
{
	enum mail_index_open_flags open_flags;
	struct mailbox_permissions perm;
	int ret = 0;

	if (map->view != NULL) {
		/* already opened */
		return 1;
	}

	mailbox_list_get_root_permissions(map->root_list, &perm);
	mail_index_set_permissions(map->index, perm.file_create_mode,
				   perm.file_create_gid,
				   perm.file_create_gid_origin);

	open_flags = MAIL_INDEX_OPEN_FLAG_NEVER_IN_MEMORY |
		mail_storage_settings_to_index_flags(MAP_STORAGE(map)->set);
	if (create_missing) {
		if ((ret = mdbox_map_mkdir_storage(map)) < 0)
			return -1;
		if (ret > 0) {
			/* storage/ directory already existed.
			   the index should exist also. */
		} else {
			open_flags |= MAIL_INDEX_OPEN_FLAG_CREATE;
		}
	}
	ret = mail_index_open(map->index, open_flags);
	if (ret == 0 && create_missing) {
		/* storage/ already existed, but indexes didn't. we'll need to
		   take extra steps to make sure we won't overwrite any m.*
		   files that may already exist. */
		map->verify_existing_file_ids = TRUE;
		open_flags |= MAIL_INDEX_OPEN_FLAG_CREATE;
		ret = mail_index_open(map->index, open_flags);
	}
	if (ret < 0) {
		mail_storage_set_internal_error(MAP_STORAGE(map));
		mail_index_reset_error(map->index);
		return -1;
	}
	if (ret == 0) {
		/* index not found - for now just return failure */
		i_assert(!create_missing);
		return 0;
	}

	map->view = mail_index_view_open(map->index);
	mdbox_map_cleanup(map);

	if (mail_index_get_header(map->view)->uid_validity == 0) {
		if (mdbox_map_generate_uid_validity(map) < 0 ||
		    mdbox_map_refresh(map) < 0) {
			mail_storage_set_internal_error(MAP_STORAGE(map));
			mail_index_reset_error(map->index);
			mail_index_close(map->index);
			return -1;
		}
	}
	return 1;
}