void io_loop_handler_run(struct ioloop *ioloop)
{
	struct ioloop_handler_context *ctx = ioloop->handler_context;
	struct kevent *events;
	const struct kevent *event;
	struct timeval tv;
	struct timespec ts;
	struct io_file *io;
	unsigned int events_count;
	int ret, i;

	/* get the time left for next timeout task */
	io_loop_get_wait_time(ioloop, &tv);
	ts.tv_sec = tv.tv_sec;
	ts.tv_nsec = tv.tv_usec * 1000;

	/* wait for events */
	events = array_get_modifiable(&ctx->events, &events_count);
	ret = kevent (ctx->kq, NULL, 0, events, events_count, &ts);
	if (ret < 0 && errno != EINTR)
		i_fatal("kevent(): %m");

	/* reference all IOs */
	for (i = 0; i < ret; i++) {
		io = (void *)events[i].udata;
		i_assert(io->refcount > 0);
		io->refcount++;
	}

	/* execute timeout handlers */
	io_loop_handle_timeouts(ioloop);

	for (i = 0; i < ret; i++) {
		/* io_loop_handle_add() may cause events array reallocation,
		   so we have use array_idx() */
		event = array_idx(&ctx->events, i);
		io = (void *)event->udata;

		/* callback is NULL if io_remove() was already called */
		if (io->io.callback != NULL)
			io_loop_call_io(&io->io);

		i_assert(io->refcount > 0);
		if (--io->refcount == 0)
			i_free(io);
	}
}
示例#2
0
static uoff_t
dump_size(struct istream *input, const char *name, const char *value)
{
	uoff_t size;

	if (strcmp(value, "0") == 0)
		size = 0;
	else {
		size = hex2dec((const void *)value, strlen(value));
		if (size == 0) {
			i_fatal("Invalid %s at %"PRIuUOFF_T": %s",
				name, input->v_offset, value);
		}
	}
	printf("%s = %"PRIuUOFF_T"\n", name, size);
	return size;
}
示例#3
0
static void ssl_params_rebuild(struct ssl_params *param)
{
	switch (fork()) {
	case -1:
		i_fatal("fork() failed: %m");
	case 0:
		/* child - close listener fds so a long-running ssl-params
		   doesn't cause Dovecot restart to fail */
		ssl_params_close_listeners();
		ssl_params_if_unchanged(param->path, param->last_mtime,
					param->set.ssl_dh_parameters_length);
		exit(0);
	default:
		/* parent */
		break;
	}
}
示例#4
0
static void cmd_dump_log(int argc ATTR_UNUSED, char *argv[])
{
	uint64_t modseq;
	int fd, ret;

	fd = open(argv[1], O_RDONLY);
	if (fd < 0)
		i_fatal("open(%s) failed: %m", argv[1]);

	dump_hdr(fd, &modseq);
	do {
		T_BEGIN {
			ret = dump_record(fd, &modseq);
		} T_END;
	} while (ret > 0);
	i_close_fd(&fd);
}
示例#5
0
struct ostream *sieve_tool_open_output_stream(const char *filename)
{
	struct ostream *outstream;
	int fd;

	if ( strcmp(filename, "-") == 0 )
		outstream = o_stream_create_fd(1, 0, FALSE);
	else {
		if ( (fd = open(filename, O_WRONLY | O_TRUNC | O_CREAT, 0600)) < 0 ) {
			i_fatal("failed to open file for writing: %m");
		}

		outstream = o_stream_create_fd_autoclose(&fd, 0);
	}

	return outstream;
}
示例#6
0
static struct passdb_module *
bsdauth_preinit(pool_t pool, const char *args)
{
	struct passdb_module *module;

	module = p_new(pool, struct passdb_module, 1);
	module->default_pass_scheme = "PLAIN"; /* same reason as PAM */
	module->blocking = TRUE;

	if (strcmp(args, "blocking=no") == 0)
		module->blocking = FALSE;
	else if (strncmp(args, "cache_key=", 10) == 0)
		module->cache_key = auth_cache_parse_key(pool, args + 10);
	else if (*args != '\0')
		i_fatal("passdb bsdauth: Unknown setting: %s", args);
	return module;
}
示例#7
0
文件: acl-backend.c 项目: bdraco/core
struct acl_backend *
acl_backend_init(const char *data, struct mailbox_list *list,
		 const char *acl_username, const char *const *groups,
		 bool owner)
{
	struct mail_user *user = mailbox_list_get_user(list);
	struct acl_backend *backend;
	unsigned int i, group_count;

	if (user->mail_debug) {
		i_debug("acl: initializing backend with data: %s", data);
		i_debug("acl: acl username = %s", acl_username);
		i_debug("acl: owner = %d", owner ? 1 : 0);
	}

	group_count = str_array_length(groups);

	if (strncmp(data, "vfile:", 6) == 0)
		data += 6;
	else if (strcmp(data, "vfile") == 0)
		data = "";
	else
		i_fatal("Unknown ACL backend: %s", t_strcut(data, ':'));

	backend = acl_backend_vfile.alloc();
	backend->debug = user->mail_debug;
	backend->v = acl_backend_vfile;
	backend->list = list;
	backend->username = p_strdup(backend->pool, acl_username);
	backend->owner = owner;
	backend->globals_only =
		mail_user_plugin_getenv_bool(user, "acl_globals_only");

	if (group_count > 0) {
		backend->group_count = group_count;
		backend->groups =
			p_new(backend->pool, const char *, group_count);
		for (i = 0; i < group_count; i++) {
			backend->groups[i] = p_strdup(backend->pool, groups[i]);
			if (user->mail_debug)
				i_debug("acl: group added: %s", groups[i]);
		}
		i_qsort(backend->groups, group_count, sizeof(const char *),
			i_strcmp_p);
	}
示例#8
0
static void
test_server_read_fd(struct istream *input, int wanted_fd, unsigned int idx)
{
	struct stat st1, st2;
	const unsigned char *data;
	size_t size;
	int recv_fd;

	test_assert_idx(i_stream_read_data(input, &data, &size, 0) == 1, idx);
	i_stream_skip(input, 1);
	test_assert_idx((recv_fd = i_stream_unix_get_read_fd(input)) != -1, idx);
	if (recv_fd != -1) {
		if (fstat(recv_fd, &st1) < 0 || fstat(wanted_fd, &st2) < 0)
			i_fatal("fstat() failed: %m");
		test_assert_idx(st1.st_ino == st2.st_ino, idx);
		i_close_fd(&recv_fd);
	}
}
示例#9
0
void sieve_tool_dump_binary_to
(struct sieve_binary *sbin, const char *filename, bool hexdump)
{
	struct ostream *dumpstream;

	if ( filename == NULL ) return;

	dumpstream = sieve_tool_open_output_stream(filename);
	if ( dumpstream != NULL ) {
		if ( hexdump )
			(void) sieve_hexdump(sbin, dumpstream);
		else
			(void) sieve_dump(sbin, dumpstream, FALSE);
		o_stream_destroy(&dumpstream);
	} else {
		i_fatal("Failed to create stream for sieve code dump.");
	}
}
示例#10
0
struct sql_db *sql_init(const char *db_driver, const char *connect_string)
{
	const struct sql_db *driver;
	struct sql_db *db;

	i_assert(connect_string != NULL);

	driver = sql_driver_lookup(db_driver);
	if (driver == NULL)
		i_fatal("Unknown database driver '%s'", db_driver);

	if ((driver->flags & SQL_DB_FLAG_POOLED) == 0)
		db = driver->v.init(connect_string);
	else
		db = driver_sqlpool_init(connect_string, driver);
	i_array_init(&db->module_contexts, 5);
	return db;
}
示例#11
0
void hostpid_init(void)
{
	static char hostname[256], pid[MAX_INT_STRLEN];

	if (gethostname(hostname, sizeof(hostname)-1) == -1)
		i_strocpy(hostname, "unknown", sizeof(hostname));
	hostname[sizeof(hostname)-1] = '\0';
	my_hostname = hostname;

	if (strchr(hostname, '/') != NULL)
		i_fatal("Invalid system hostname: %s", hostname);

	/* allow calling hostpid_init() multiple times to reset hostname */
	i_free_and_null(my_domain);

	i_strocpy(pid, dec2str(getpid()), sizeof(pid));
	my_pid = pid;
}
static void cmd_dump_fts_expunge_log(int argc ATTR_UNUSED, char *argv[])
{
	buffer_t *buf;
	int fd, ret;

	fd = open(argv[1], O_RDONLY);
	if (fd < 0)
		i_fatal("open(%s) failed: %m", argv[1]);

	buf = buffer_create_dynamic(default_pool, 1024);
	do {
		T_BEGIN {
			ret = dump_record(fd, buf);
		} T_END;
	} while (ret > 0);
	buffer_free(&buf);
	i_close_fd(&fd);
}
示例#13
0
static void doveadm_print_formatted_print(const char *value)
{
	if (ctx.format == NULL) {
		i_fatal("formatted formatter cannot be used without a format.");
	}
	const char *error;
	struct var_expand_table *entry = array_idx_modifiable(&ctx.headers, ctx.idx++);
	entry->value = value;

	if (ctx.idx >= array_count(&ctx.headers)) {
		if (var_expand(ctx.buf, ctx.format, array_idx(&ctx.headers,0), &error) <= 0) {
			i_error("Failed to expand print format '%s': %s",
				ctx.format, error);
		}
		doveadm_print_formatted_flush();
		ctx.idx = 0;
	}

}
示例#14
0
文件: askpass.c 项目: Raffprta/core
static void askpass_str(const char *prompt, buffer_t *pass)
{
        struct termios old_tio, tio;
	bool tty, restore_tio = FALSE;
	char ch;
	int fd;

	tty = isatty(STDIN_FILENO);
	if (tty) {
		fputs(prompt, stderr);
		fflush(stderr);

		fd = open("/dev/tty", O_RDONLY);
		if (fd < 0)
			i_fatal("open(/dev/tty) failed: %m");

		/* turn off echo */
		if (tcgetattr(fd, &old_tio) == 0) {
			restore_tio = TRUE;
			tio = old_tio;
			tio.c_lflag &= ~(ECHO | ECHONL);
			(void)tcsetattr(fd, TCSAFLUSH, &tio);
		}
	} else {
		/* read it from stdin without showing a prompt */
		fd = STDIN_FILENO;
	}

	/* read the password */
	while (read(fd, &ch, 1) > 0) {
		if (ch == '\n' || ch == '\r')
			break;
		buffer_append_c(pass, ch);
	}

	if (tty) {
		if (restore_tio)
			(void)tcsetattr(fd, TCSAFLUSH, &old_tio);

		fputs("\n", stderr); fflush(stderr);
		i_close_fd(&fd);
	}
}
示例#15
0
static struct fs *
fs_sis_init(const char *args, const struct fs_settings *set)
{
	struct sis_fs *fs;
	const char *p;

	fs = i_new(struct sis_fs, 1);
	fs->fs = fs_class_sis;

	if (*args == '\0')
		i_fatal("fs-sis: Parent filesystem not given as parameter");

	p = strchr(args, ':');
	if (p == NULL)
		fs->super = fs_init(args, "", set);
	else
		fs->super = fs_init(t_strdup_until(args, p), p+1, set);
	return &fs->fs;
}
示例#16
0
static void test_istream_unix_client(int fd)
{
	/* 1) */
	write_one(fd);
	read_one(fd);

	/* 2) */
	if (fd_send(fd, send_fd, "1", 1) < 0)
		i_fatal("fd_send() failed: %m");
	read_one(fd);

	/* 3) */
	write_one(fd);
	read_one(fd);

	/* 4) */
	if (fd_send(fd, send_fd2, "1", 1) < 0)
		i_fatal("fd_send() failed: %m");
	read_one(fd);

	/* 5) */
	write_one(fd);
	read_one(fd);

	/* 6) */
	if (fd_send(fd, send_fd, "1", 1) < 0)
		i_fatal("fd_send() failed: %m");
	read_one(fd);

	/* 7-8) */
	if (fd_send(fd, send_fd, "1", 1) < 0)
		i_fatal("fd_send() failed: %m");
	if (fd_send(fd, send_fd2, "1", 1) < 0)
		i_fatal("fd_send() failed: %m");
	read_one(fd);

	/* 9-10) */
	if (fd_send(fd, send_fd, "1", 1) < 0)
		i_fatal("fd_send() failed: %m");
	if (fd_send(fd, send_fd2, "1", 1) < 0)
		i_fatal("fd_send() failed: %m");
	read_one(fd);

	i_close_fd(&fd);
}
static bool stats_top_round(struct top_context *ctx)
{
#define TOP_CMD "EXPORT\tsession\tconnected\n"
	const char *const *args;
	pool_t tmp_pool;

	if (write_full(ctx->fd, TOP_CMD, strlen(TOP_CMD)) < 0)
		i_fatal("write(%s) failed: %m", ctx->path);

	/* read header */
	if (ctx->headers != NULL) {
		args = read_next_line(ctx->input);
		if (args == NULL)
			i_fatal("read(%s) unexpectedly disconnected", ctx->path);
		if (*args == NULL)
			return TRUE;
		if (str_array_length(args) != ctx->headers_count)
			i_fatal("headers changed");
	} else {
		ctx->headers = p_read_next_line(default_pool, ctx->input);
		if (ctx->headers == NULL)
			i_fatal("read(%s) unexpectedly disconnected", ctx->path);
		if (*ctx->headers == NULL) {
			i_free_and_null(ctx->headers);
			return FALSE;
		}
		ctx->headers_count = str_array_length((void *)ctx->headers);
		if (!stats_header_find(ctx, "last_update", &ctx->last_update_idx))
			i_fatal("last_update header missing");
		if (!stats_header_find(ctx, "user", &ctx->user_idx))
			i_fatal("user header missing");
		stats_top_get_sorting(ctx);
	}

	array_clear(&ctx->lines);
	p_clear(ctx->prev_pool);
	tmp_pool = ctx->prev_pool;
	ctx->prev_pool = ctx->cur_pool;
	ctx->cur_pool = tmp_pool;

	ctx->flip = !ctx->flip;
	stats_read(ctx);
	stats_drop_stale(ctx);

	sort_ctx = ctx;
	array_sort(&ctx->lines, *ctx->lines_sort);
	sort_ctx = NULL;
	return TRUE;
}
示例#18
0
void test_fs_async(const char *test_name, enum fs_properties properties,
		   const char *driver, const char *args)
{
	struct fs_settings fs_set;
	struct fs *fs;
	struct test_fs *test_fs;
	const char *error;

	i_zero(&fs_set);
	if (fs_init(driver, args, &fs_set, &fs, &error) < 0)
		i_fatal("fs_init() failed: %s", error);

	test_fs = test_fs_get(fs);
	test_fs->properties = properties;

	test_fs_async_write(test_name, fs);
	test_fs_async_copy(test_name, fs);

	fs_deinit(&fs);
}
void io_loop_handle_add(struct io_file *io)
{
	struct ioloop_handler_context *ctx = io->io.ioloop->handler_context;
	enum io_condition condition = io->io.condition;
	int fd = io->fd;

	i_assert(fd >= 0);

	if (fd >= FD_SETSIZE)
		i_fatal("fd %d too large for select()", fd);

        if ((condition & (IO_READ | IO_ERROR)) != 0)
		FD_SET(fd, &ctx->read_fds);
        if ((condition & IO_WRITE) != 0)
		FD_SET(fd, &ctx->write_fds);
	FD_SET(fd, &ctx->except_fds);

	if (io->fd > ctx->highest_fd)
		ctx->highest_fd = io->fd;
}
示例#20
0
void env_clean(void)
{
#ifdef HAVE_CLEARENV
	if (clearenv() < 0)
		i_fatal("clearenv() failed");
#else
	char ***environ_p = env_get_environ_p();

	/* Try to clear the environment.

	   a) environ = NULL crashes on OS X.
	   b) *environ = NULL doesn't work on FreeBSD 7.0.
	   c) environ = emptyenv doesn't work on Haiku OS
	   d) environ = calloc() should work everywhere
	*/
	*environ_p = calloc(1, sizeof(**environ_p));
#endif
	if (env_pool != NULL)
		p_clear(env_pool);
}
示例#21
0
struct sieve_binary *sieve_tool_script_open
(struct sieve_instance *svinst, const char *filename)
{
	struct sieve_error_handler *ehandler;
	struct sieve_binary *sbin;

	ehandler = sieve_stderr_ehandler_create(svinst, 0);
	sieve_error_handler_accept_infolog(ehandler, TRUE);

	if ( (sbin = sieve_open
		(svinst, filename, NULL, ehandler, 0, NULL)) == NULL ) {
		sieve_error_handler_unref(&ehandler);
		i_fatal("failed to compile sieve script");
	}

	sieve_error_handler_unref(&ehandler);

	sieve_save(sbin, FALSE, NULL);
	return sbin;
}
static void cmd_flags_init(struct doveadm_mail_cmd_context *_ctx,
			   const char *const args[])
{
	struct flags_cmd_context *ctx = (struct flags_cmd_context *)_ctx;
	const char *const *tmp;
	enum mail_flags flag;
	ARRAY_TYPE(const_string) keywords;

	if (args[0] == NULL || args[1] == NULL) {
		switch (ctx->modify_type) {
		case MODIFY_ADD:
			doveadm_mail_help_name("flags add");
		case MODIFY_REMOVE:
			doveadm_mail_help_name("flags remove");
		case MODIFY_REPLACE:
			doveadm_mail_help_name("flags replace");
		}
		i_unreached();
	}

	p_array_init(&keywords, _ctx->pool, 8);
	for (tmp = t_strsplit(args[0], " "); *tmp != NULL; tmp++) {
		const char *str = *tmp;

		if (str[0] == '\\') {
			flag = imap_parse_system_flag(str);
			if (flag == 0)
				i_fatal("Invalid system flag: %s", str);
			ctx->flags |= flag;
		} else {
			str = p_strdup(_ctx->pool, str);
			array_append(&keywords, &str, 1);
		}
	}
	if (array_count(&keywords) > 0 || ctx->modify_type == MODIFY_REPLACE) {
		array_append_zero(&keywords);
		ctx->keywords = array_idx(&keywords, 0);
	}

	_ctx->search_args = doveadm_mail_build_search_args(args+1);
}
示例#23
0
static void read_parameters(const char *fname)
{
	int fd;

	/* we'll wait until parameter file exists */
	for (;;) {
		fd = open(fname, O_RDONLY);
		if (fd != -1)
			break;

		if (errno != ENOENT)
			i_fatal("Can't open SSL parameter file %s: %m", fname);

		sleep(1);
	}

	read_dh_parameters(fd, fname);
	read_rsa_parameters(fd, fname);

	(void)close(fd);
}
示例#24
0
文件: context.c 项目: tonycoz/imager
im_slot_t
im_context_slot_new(im_slot_destroy_t destructor) {
  im_slot_t new_slot;
  im_slot_destroy_t *new_destructors;
  if (!slot_mutex)
    slot_mutex = i_mutex_new();

  i_mutex_lock(slot_mutex);

  new_slot = slot_count++;
  new_destructors = realloc(slot_destructors, sizeof(void *) * slot_count);
  if (!new_destructors)
    i_fatal(1, "Cannot allocate memory for slot destructors");
  slot_destructors = new_destructors;

  slot_destructors[new_slot] = destructor;

  i_mutex_unlock(slot_mutex);

  return new_slot;
}
示例#25
0
static void acl_mailbox_list_init_default(struct mailbox_list *list)
{
	struct mailbox_list_vfuncs *v = list->vlast;
	struct acl_mailbox_list *alist;

	if (list->mail_set->mail_full_filesystem_access) {
		/* not necessarily, but safer to do this for now. */
		i_fatal("mail_full_filesystem_access=yes is "
			"incompatible with ACLs");
	}

	alist = p_new(list->pool, struct acl_mailbox_list, 1);
	alist->module_ctx.super = *v;
	list->vlast = &alist->module_ctx.super;
	v->deinit = acl_mailbox_list_deinit;
	v->iter_init = acl_mailbox_list_iter_init;
	v->iter_next = acl_mailbox_list_iter_next;
	v->iter_deinit = acl_mailbox_list_iter_deinit;

	MODULE_CONTEXT_SET(list, acl_mailbox_list_module, alist);
}
示例#26
0
int main(int argc, char *argv[])
{
	const struct setting_parser_info *set_roots[] = {
		&doveadm_setting_parser_info,
		NULL
	};
	enum master_service_flags service_flags =
		MASTER_SERVICE_FLAG_KEEP_CONFIG_OPEN;
	const char *error;
	int c;

	master_service = master_service_init("doveadm", service_flags,
					     &argc, &argv, "D");
	while ((c = master_getopt(master_service)) > 0) {
		switch (c) {
		case 'D':
			doveadm_debug = TRUE;
			doveadm_verbose = TRUE;
			break;
		default:
			return FATAL_DEFAULT;
		}
	}

	if (master_service_settings_read_simple(master_service, set_roots,
						&error) < 0)
		i_fatal("Error reading configuration: %s", error);

	master_service_init_log(master_service, "doveadm: ");
	main_preinit();
	master_service_set_die_callback(master_service, doveadm_die);

	main_init();
	master_service_init_finish(master_service);
	master_service_run(master_service, client_connected);

	main_deinit();
	master_service_deinit(&master_service);
        return 0;
}
示例#27
0
void io_loop_handle_add(struct io_file *io)
{
	struct ioloop_handler_context *ctx = io->io.ioloop->handler_context;
	struct io_list **list;
	struct epoll_event event;
	int op;
	bool first;

	list = array_idx_modifiable(&ctx->fd_index, io->fd);
	if (*list == NULL)
		*list = i_new(struct io_list, 1);

	first = ioloop_iolist_add(*list, io);

	memset(&event, 0, sizeof(event));
	event.data.ptr = *list;
	event.events = epoll_event_mask(*list);

	op = first ? EPOLL_CTL_ADD : EPOLL_CTL_MOD;

	if (epoll_ctl(ctx->epfd, op, io->fd, &event) < 0) {
		if (errno == EPERM && op == EPOLL_CTL_ADD) {
			i_fatal("epoll_ctl(add, %d) failed: %m "
				"(fd doesn't support epoll%s)", io->fd,
				io->fd != STDIN_FILENO ? "" :
				" - instead of '<file', try 'cat file|'");
		}
		i_panic("epoll_ctl(%s, %d) failed: %m",
			op == EPOLL_CTL_ADD ? "add" : "mod", io->fd);
	}

	if (first) {
		/* allow epoll_wait() to return the maximum number of events
		   by keeping space allocated for each file descriptor */
		if (ctx->deleted_count > 0)
			ctx->deleted_count--;
		else
			array_append_zero(&ctx->events);
	}
}
示例#28
0
static void cmd_dump_dbox(int argc ATTR_UNUSED, char *argv[])
{
	struct istream *input;
	int fd;
	unsigned int hdr_size;
	bool ret;

	fd = open(argv[1], O_RDONLY);
	if (fd < 0)
		i_fatal("open(%s) failed: %m", argv[1]);

	input = i_stream_create_fd_autoclose(&fd, (size_t)-1);
	i_stream_set_name(input, argv[1]);
	hdr_size = dump_file_hdr(input);
	do {
		printf("\n");
		T_BEGIN {
			ret = dump_msg(input, hdr_size);
		} T_END;
	} while (ret);
	i_stream_destroy(&input);
}
示例#29
0
文件: ioloop.c 项目: aosm/dovecot
static void timeout_update_next(struct timeout *timeout, struct timeval *tv_now)
{
	if (tv_now == NULL) {
		if (gettimeofday(&timeout->next_run, NULL) < 0)
			i_fatal("gettimeofday(): %m");
	} else {
                timeout->next_run.tv_sec = tv_now->tv_sec;
                timeout->next_run.tv_usec = tv_now->tv_usec;
	}

	/* we don't want microsecond accuracy or this function will be
	   called all the time - millisecond is more than enough */
	timeout->next_run.tv_usec -= timeout->next_run.tv_usec % 1000;

	timeout->next_run.tv_sec += timeout->msecs/1000;
	timeout->next_run.tv_usec += (timeout->msecs%1000)*1000;

	if (timeout->next_run.tv_usec > 1000000) {
                timeout->next_run.tv_sec++;
                timeout->next_run.tv_usec -= 1000000;
	}
}
示例#30
0
文件: mbox-lock.c 项目: bdraco/core
static void mbox_init_lock_settings(struct mbox_storage *storage)
{
	enum mbox_lock_type read_locks[MBOX_LOCK_COUNT+1];
	enum mbox_lock_type write_locks[MBOX_LOCK_COUNT+1];
	int r, w;

	mbox_read_lock_methods(storage->set->mbox_read_locks,
			       "mbox_read_locks", read_locks);
	mbox_read_lock_methods(storage->set->mbox_write_locks,
			       "mbox_write_locks", write_locks);

	/* check that read/write list orders match. write_locks must contain
	   at least read_locks and possibly more. */
	for (r = w = 0; write_locks[w] != (enum mbox_lock_type)-1; w++) {
		if (read_locks[r] == (enum mbox_lock_type)-1)
			break;
		if (read_locks[r] == write_locks[w])
			r++;
	}
	if (read_locks[r] != (enum mbox_lock_type)-1) {
		i_fatal("mbox read/write lock list settings are invalid. "
			"Lock ordering must be the same with both, "
			"and write locks must contain all read locks "
			"(and possibly more)");
	}

	storage->read_locks = p_new(storage->storage.pool,
				    enum mbox_lock_type, MBOX_LOCK_COUNT+1);
	memcpy(storage->read_locks, read_locks,
	       sizeof(*storage->read_locks) * (MBOX_LOCK_COUNT+1));

	storage->write_locks = p_new(storage->storage.pool,
				     enum mbox_lock_type, MBOX_LOCK_COUNT+1);
	memcpy(storage->write_locks, write_locks,
	       sizeof(*storage->write_locks) * (MBOX_LOCK_COUNT+1));

        storage->lock_settings_initialized = TRUE;
}