예제 #1
0
static int maildir_keywords_commit(struct maildir_keywords *mk)
{
	const struct mailbox_permissions *perm;
	struct dotlock *dotlock;
	const char *lock_path;
	mode_t old_mask;
	int i, fd;

	mk->synced = FALSE;

	if (!mk->changed || mk->mbox == NULL)
		return 0;

	lock_path = t_strconcat(mk->path, ".lock", NULL);
	i_unlink_if_exists(lock_path);

	perm = mailbox_get_permissions(&mk->mbox->box);
	for (i = 0;; i++) {
		/* we could just create the temp file directly, but doing it
		   this ways avoids potential problems with overwriting
		   contents in malicious symlinks */
		old_mask = umask(0777 & ~perm->file_create_mode);
		fd = file_dotlock_open(&mk->dotlock_settings, mk->path,
				       DOTLOCK_CREATE_FLAG_NONBLOCK, &dotlock);
		umask(old_mask);
		if (fd != -1)
			break;

		if (errno != ENOENT || i == MAILDIR_DELETE_RETRY_COUNT) {
			mail_storage_set_critical(mk->storage,
				"file_dotlock_open(%s) failed: %m", mk->path);
			return -1;
		}
		/* the control dir doesn't exist. create it unless the whole
		   mailbox was just deleted. */
		if (!maildir_set_deleted(&mk->mbox->box))
			return -1;
	}

	if (maildir_keywords_write_fd(mk, lock_path, fd) < 0) {
		file_dotlock_delete(&dotlock);
		return -1;
	}

	if (file_dotlock_replace(&dotlock, 0) < 0) {
		mail_storage_set_critical(mk->storage,
			"file_dotlock_replace(%s) failed: %m", mk->path);
		return -1;
	}

	mk->changed = FALSE;
	return 0;
}
예제 #2
0
static int
maildir_stat(struct maildir_mailbox *mbox, const char *path, struct stat *st_r)
{
	struct mailbox *box = &mbox->box;
	int i;

	for (i = 0;; i++) {
		if (nfs_safe_stat(path, st_r) == 0)
			return 0;
		if (errno != ENOENT || i == MAILDIR_DELETE_RETRY_COUNT)
			break;

		if (!maildir_set_deleted(box))
			return -1;
		/* try again */
	}

	mail_storage_set_critical(box->storage, "stat(%s) failed: %m", path);
	return -1;
}