mail-index-util.c revision 742111fa99a5b852c9645080573d5853be3907a7
285f3c4cf828ebe9ff345080aa1df3755613af29Timo Sirainen/* Copyright (C) 2002 Timo Sirainen */
285f3c4cf828ebe9ff345080aa1df3755613af29Timo Sirainen
285f3c4cf828ebe9ff345080aa1df3755613af29Timo Sirainen#include "lib.h"
285f3c4cf828ebe9ff345080aa1df3755613af29Timo Sirainen#include "istream.h"
285f3c4cf828ebe9ff345080aa1df3755613af29Timo Sirainen#include "hostpid.h"
285f3c4cf828ebe9ff345080aa1df3755613af29Timo Sirainen#include "file-lock.h"
285f3c4cf828ebe9ff345080aa1df3755613af29Timo Sirainen#include "message-size.h"
285f3c4cf828ebe9ff345080aa1df3755613af29Timo Sirainen#include "message-part-serialize.h"
285f3c4cf828ebe9ff345080aa1df3755613af29Timo Sirainen#include "mail-index.h"
285f3c4cf828ebe9ff345080aa1df3755613af29Timo Sirainen#include "mail-index-util.h"
285f3c4cf828ebe9ff345080aa1df3755613af29Timo Sirainen
285f3c4cf828ebe9ff345080aa1df3755613af29Timo Sirainen#include <unistd.h>
285f3c4cf828ebe9ff345080aa1df3755613af29Timo Sirainen#include <fcntl.h>
285f3c4cf828ebe9ff345080aa1df3755613af29Timo Sirainen
285f3c4cf828ebe9ff345080aa1df3755613af29Timo Sirainenint index_set_error(struct mail_index *index, const char *fmt, ...)
285f3c4cf828ebe9ff345080aa1df3755613af29Timo Sirainen{
285f3c4cf828ebe9ff345080aa1df3755613af29Timo Sirainen va_list va;
285f3c4cf828ebe9ff345080aa1df3755613af29Timo Sirainen
285f3c4cf828ebe9ff345080aa1df3755613af29Timo Sirainen i_free(index->error);
285f3c4cf828ebe9ff345080aa1df3755613af29Timo Sirainen
285f3c4cf828ebe9ff345080aa1df3755613af29Timo Sirainen if (fmt == NULL)
285f3c4cf828ebe9ff345080aa1df3755613af29Timo Sirainen index->error = NULL;
285f3c4cf828ebe9ff345080aa1df3755613af29Timo Sirainen else {
285f3c4cf828ebe9ff345080aa1df3755613af29Timo Sirainen va_start(va, fmt);
285f3c4cf828ebe9ff345080aa1df3755613af29Timo Sirainen index->error = i_strdup_vprintf(fmt, va);
285f3c4cf828ebe9ff345080aa1df3755613af29Timo Sirainen va_end(va);
285f3c4cf828ebe9ff345080aa1df3755613af29Timo Sirainen
285f3c4cf828ebe9ff345080aa1df3755613af29Timo Sirainen i_error("%s", index->error);
285f3c4cf828ebe9ff345080aa1df3755613af29Timo Sirainen }
285f3c4cf828ebe9ff345080aa1df3755613af29Timo Sirainen
285f3c4cf828ebe9ff345080aa1df3755613af29Timo Sirainen return FALSE;
285f3c4cf828ebe9ff345080aa1df3755613af29Timo Sirainen}
285f3c4cf828ebe9ff345080aa1df3755613af29Timo Sirainen
285f3c4cf828ebe9ff345080aa1df3755613af29Timo Sirainenint index_set_corrupted(struct mail_index *index, const char *fmt, ...)
285f3c4cf828ebe9ff345080aa1df3755613af29Timo Sirainen{
285f3c4cf828ebe9ff345080aa1df3755613af29Timo Sirainen va_list va;
285f3c4cf828ebe9ff345080aa1df3755613af29Timo Sirainen
285f3c4cf828ebe9ff345080aa1df3755613af29Timo Sirainen INDEX_MARK_CORRUPTED(index);
285f3c4cf828ebe9ff345080aa1df3755613af29Timo Sirainen index->inconsistent = TRUE;
285f3c4cf828ebe9ff345080aa1df3755613af29Timo Sirainen
285f3c4cf828ebe9ff345080aa1df3755613af29Timo Sirainen va_start(va, fmt);
285f3c4cf828ebe9ff345080aa1df3755613af29Timo Sirainen t_push();
285f3c4cf828ebe9ff345080aa1df3755613af29Timo Sirainen index_set_error(index, "Corrupted index file %s: %s",
285f3c4cf828ebe9ff345080aa1df3755613af29Timo Sirainen index->filepath, t_strdup_vprintf(fmt, va));
285f3c4cf828ebe9ff345080aa1df3755613af29Timo Sirainen t_pop();
285f3c4cf828ebe9ff345080aa1df3755613af29Timo Sirainen va_end(va);
285f3c4cf828ebe9ff345080aa1df3755613af29Timo Sirainen
285f3c4cf828ebe9ff345080aa1df3755613af29Timo Sirainen return FALSE;
285f3c4cf828ebe9ff345080aa1df3755613af29Timo Sirainen}
285f3c4cf828ebe9ff345080aa1df3755613af29Timo Sirainen
285f3c4cf828ebe9ff345080aa1df3755613af29Timo Sirainenint index_set_syscall_error(struct mail_index *index, const char *function)
285f3c4cf828ebe9ff345080aa1df3755613af29Timo Sirainen{
285f3c4cf828ebe9ff345080aa1df3755613af29Timo Sirainen i_assert(function != NULL);
285f3c4cf828ebe9ff345080aa1df3755613af29Timo Sirainen
285f3c4cf828ebe9ff345080aa1df3755613af29Timo Sirainen if (ENOSPACE(errno)) {
285f3c4cf828ebe9ff345080aa1df3755613af29Timo Sirainen index->nodiskspace = TRUE;
285f3c4cf828ebe9ff345080aa1df3755613af29Timo Sirainen return FALSE;
285f3c4cf828ebe9ff345080aa1df3755613af29Timo Sirainen }
285f3c4cf828ebe9ff345080aa1df3755613af29Timo Sirainen
285f3c4cf828ebe9ff345080aa1df3755613af29Timo Sirainen index_set_error(index, "%s failed with index file %s: %m",
285f3c4cf828ebe9ff345080aa1df3755613af29Timo Sirainen function, index->filepath);
285f3c4cf828ebe9ff345080aa1df3755613af29Timo Sirainen return FALSE;
285f3c4cf828ebe9ff345080aa1df3755613af29Timo Sirainen}
285f3c4cf828ebe9ff345080aa1df3755613af29Timo Sirainen
285f3c4cf828ebe9ff345080aa1df3755613af29Timo Sirainenint index_file_set_syscall_error(struct mail_index *index, const char *filepath,
285f3c4cf828ebe9ff345080aa1df3755613af29Timo Sirainen const char *function)
285f3c4cf828ebe9ff345080aa1df3755613af29Timo Sirainen{
285f3c4cf828ebe9ff345080aa1df3755613af29Timo Sirainen i_assert(filepath != NULL);
285f3c4cf828ebe9ff345080aa1df3755613af29Timo Sirainen i_assert(function != NULL);
285f3c4cf828ebe9ff345080aa1df3755613af29Timo Sirainen
285f3c4cf828ebe9ff345080aa1df3755613af29Timo Sirainen if (ENOSPACE(errno)) {
285f3c4cf828ebe9ff345080aa1df3755613af29Timo Sirainen index->nodiskspace = TRUE;
285f3c4cf828ebe9ff345080aa1df3755613af29Timo Sirainen return FALSE;
285f3c4cf828ebe9ff345080aa1df3755613af29Timo Sirainen }
285f3c4cf828ebe9ff345080aa1df3755613af29Timo Sirainen
285f3c4cf828ebe9ff345080aa1df3755613af29Timo Sirainen index_set_error(index, "%s failed with file %s: %m",
285f3c4cf828ebe9ff345080aa1df3755613af29Timo Sirainen function, filepath);
285f3c4cf828ebe9ff345080aa1df3755613af29Timo Sirainen
285f3c4cf828ebe9ff345080aa1df3755613af29Timo Sirainen return FALSE;
285f3c4cf828ebe9ff345080aa1df3755613af29Timo Sirainen}
285f3c4cf828ebe9ff345080aa1df3755613af29Timo Sirainen
285f3c4cf828ebe9ff345080aa1df3755613af29Timo Sirainenvoid index_reset_error(struct mail_index *index)
285f3c4cf828ebe9ff345080aa1df3755613af29Timo Sirainen{
285f3c4cf828ebe9ff345080aa1df3755613af29Timo Sirainen if (index->error != NULL) {
285f3c4cf828ebe9ff345080aa1df3755613af29Timo Sirainen i_free(index->error);
285f3c4cf828ebe9ff345080aa1df3755613af29Timo Sirainen index->error = NULL;
285f3c4cf828ebe9ff345080aa1df3755613af29Timo Sirainen }
285f3c4cf828ebe9ff345080aa1df3755613af29Timo Sirainen
285f3c4cf828ebe9ff345080aa1df3755613af29Timo Sirainen index->nodiskspace = FALSE;
285f3c4cf828ebe9ff345080aa1df3755613af29Timo Sirainen}
285f3c4cf828ebe9ff345080aa1df3755613af29Timo Sirainen
285f3c4cf828ebe9ff345080aa1df3755613af29Timo Sirainenint mail_index_create_temp_file(struct mail_index *index, const char **path)
285f3c4cf828ebe9ff345080aa1df3755613af29Timo Sirainen{
285f3c4cf828ebe9ff345080aa1df3755613af29Timo Sirainen int fd;
285f3c4cf828ebe9ff345080aa1df3755613af29Timo Sirainen
285f3c4cf828ebe9ff345080aa1df3755613af29Timo Sirainen /* use ".temp.host.pid" as temporary file name. unlink() it first,
285f3c4cf828ebe9ff345080aa1df3755613af29Timo Sirainen just to be sure it's not symlinked somewhere for some reason..
285f3c4cf828ebe9ff345080aa1df3755613af29Timo Sirainen FIXME: this function should rather be removed entirely. With
285f3c4cf828ebe9ff345080aa1df3755613af29Timo Sirainen in-memory indexes index->dir is NULL, so we fallback to /tmp
285f3c4cf828ebe9ff345080aa1df3755613af29Timo Sirainen so that mbox rewriting doesn't crash. */
285f3c4cf828ebe9ff345080aa1df3755613af29Timo Sirainen *path = t_strconcat(index->dir != NULL ? index->dir : "/tmp",
285f3c4cf828ebe9ff345080aa1df3755613af29Timo Sirainen "/.temp.", my_hostname, ".", my_pid, NULL);
285f3c4cf828ebe9ff345080aa1df3755613af29Timo Sirainen (void)unlink(*path);
/* usage of O_EXCL isn't exactly needed since the path should be
trusted, but it shouldn't hurt either - if creating file fails
because of it, it's because something must be wrong (race
condition). also, might not won't work through NFS but that
can't be helped. */
fd = open(*path, O_RDWR | O_CREAT | O_EXCL, 0660);
if (fd == -1) {
if (ENOSPACE(errno))
index->nodiskspace = TRUE;
else {
index_set_error(index, "Can't create temp index %s: %m",
*path);
}
}
return fd;
}
static void mail_index_lock_notify(unsigned int secs_left, void *context)
{
struct mail_index *index = context;
if (index->lock_notify_cb == NULL)
return;
index->lock_notify_cb(MAIL_LOCK_NOTIFY_INDEX_ABORT, secs_left,
index->lock_notify_context);
}
int mail_index_wait_lock(struct mail_index *index, int lock_type)
{
int ret;
ret = file_wait_lock_full(index->fd, lock_type, DEFAULT_LOCK_TIMEOUT,
mail_index_lock_notify, index);
if (ret < 0)
return index_set_syscall_error(index, "file_wait_lock()");
if (ret == 0) {
index_set_error(index, "Timeout while waiting for release of "
"fcntl() lock for index file %s",
index->filepath);
index->index_lock_timeout = TRUE;
return FALSE;
}
return TRUE;
}