mbox-file.c revision b5e6f6f27c1461f0f9f202615eeb738a645188c3
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen/* Copyright (C) 2002-2003 Timo Sirainen */
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen#include "lib.h"
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen#include "istream.h"
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen#include "mbox-storage.h"
3343a61404603b21c246783a7963b77833095f31Timo Sirainen#include "mbox-sync-private.h"
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen#include "mbox-file.h"
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen#include "istream-raw-mbox.h"
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen#include <sys/stat.h>
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainenint mbox_file_open(struct mbox_mailbox *mbox)
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen{
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen struct stat st;
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen int fd;
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainen i_assert(mbox->mbox_fd == -1);
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainen if (mbox->mbox_file_stream != NULL) {
04ab375449dd97eed50ada88dd0df2abab01cfeeTimo Sirainen /* read-only mbox stream */
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainen i_assert(mbox->mbox_readonly);
04ab375449dd97eed50ada88dd0df2abab01cfeeTimo Sirainen return 0;
04ab375449dd97eed50ada88dd0df2abab01cfeeTimo Sirainen }
04ab375449dd97eed50ada88dd0df2abab01cfeeTimo Sirainen
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainen fd = open(mbox->path, mbox->mbox_readonly ? O_RDONLY : O_RDWR);
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainen if (fd == -1 && errno == EACCES && !mbox->mbox_readonly) {
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainen mbox->mbox_readonly = TRUE;
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainen fd = open(mbox->path, O_RDONLY);
3f190f4cbb9233a3a6830956cb5c7ae56a577b79Timo Sirainen }
3f190f4cbb9233a3a6830956cb5c7ae56a577b79Timo Sirainen
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen if (fd == -1) {
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainen mbox_set_syscall_error(mbox, "open()");
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen return -1;
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen }
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen if (fstat(fd, &st) < 0) {
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainen mbox_set_syscall_error(mbox, "fstat()");
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen (void)close(fd);
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen return -1;
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen }
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainen mbox->mbox_writeonly = S_ISFIFO(st.st_mode);
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainen mbox->mbox_fd = fd;
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainen mbox->mbox_dev = st.st_dev;
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainen mbox->mbox_ino = st.st_ino;
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen return 0;
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen}
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainenvoid mbox_file_close(struct mbox_mailbox *mbox)
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen{
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainen mbox_file_close_stream(mbox);
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainen if (mbox->mbox_fd != -1) {
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainen if (close(mbox->mbox_fd) < 0)
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen i_error("close(mbox) failed: %m");
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainen mbox->mbox_fd = -1;
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen }
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen}
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainenint mbox_file_open_stream(struct mbox_mailbox *mbox)
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen{
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainen if (mbox->mbox_stream != NULL)
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen return 0;
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainen if (mbox->mbox_file_stream != NULL) {
04ab375449dd97eed50ada88dd0df2abab01cfeeTimo Sirainen /* read-only mbox stream */
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainen i_assert(mbox->mbox_fd == -1 && mbox->mbox_readonly);
04ab375449dd97eed50ada88dd0df2abab01cfeeTimo Sirainen
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainen mbox->mbox_stream =
04ab375449dd97eed50ada88dd0df2abab01cfeeTimo Sirainen i_stream_create_raw_mbox(default_pool,
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainen mbox->mbox_file_stream);
04ab375449dd97eed50ada88dd0df2abab01cfeeTimo Sirainen return 0;
04ab375449dd97eed50ada88dd0df2abab01cfeeTimo Sirainen }
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainen if (mbox->mbox_fd == -1) {
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainen if (mbox_file_open(mbox) < 0)
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen return -1;
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen }
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainen if (mbox->mbox_writeonly) {
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainen mbox->mbox_file_stream =
709aa305126c32b49657e53d04826087b6838c16Timo Sirainen i_stream_create_from_data(default_pool, NULL, 0);
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainen } else if (mbox->ibox.mail_read_mmaped) {
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainen mbox->mbox_file_stream =
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainen i_stream_create_mmap(mbox->mbox_fd, default_pool,
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen MAIL_MMAP_BLOCK_SIZE,
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen 0, 0, FALSE);
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen } else {
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainen mbox->mbox_file_stream =
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainen i_stream_create_file(mbox->mbox_fd, default_pool,
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen MAIL_READ_BLOCK_SIZE, FALSE);
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen }
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainen mbox->mbox_stream =
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainen i_stream_create_raw_mbox(default_pool, mbox->mbox_file_stream);
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen return 0;
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen}
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainenvoid mbox_file_close_stream(struct mbox_mailbox *mbox)
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen{
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainen if (mbox->mbox_stream != NULL) {
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainen i_stream_unref(mbox->mbox_stream);
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainen mbox->mbox_stream = NULL;
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen }
04ab375449dd97eed50ada88dd0df2abab01cfeeTimo Sirainen
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainen if (mbox->mbox_file_stream != NULL) {
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainen if (mbox->mbox_fd == -1) {
04ab375449dd97eed50ada88dd0df2abab01cfeeTimo Sirainen /* read-only mbox stream */
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainen i_assert(mbox->mbox_readonly);
04ab375449dd97eed50ada88dd0df2abab01cfeeTimo Sirainen } else {
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainen i_stream_close(mbox->mbox_file_stream);
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainen i_stream_unref(mbox->mbox_file_stream);
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainen mbox->mbox_file_stream = NULL;
04ab375449dd97eed50ada88dd0df2abab01cfeeTimo Sirainen }
04ab375449dd97eed50ada88dd0df2abab01cfeeTimo Sirainen }
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen}
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainenint mbox_file_seek(struct mbox_mailbox *mbox, struct mail_index_view *view,
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen uint32_t seq, int *deleted_r)
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen{
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen const void *data;
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen uint64_t offset;
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen int ret;
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen *deleted_r = FALSE;
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainen ret = mail_index_lookup_ext(view, seq, mbox->mbox_ext_idx, &data);
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen if (ret <= 0) {
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen if (ret < 0)
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainen mail_storage_set_index_error(&mbox->ibox);
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen else
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen *deleted_r = TRUE;
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen return -1;
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen }
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen
7501b9f694460101b41d1d708ebc3ec2b0400b1cTimo Sirainen if (data == NULL) {
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainen mail_storage_set_critical(&mbox->storage->storage,
7501b9f694460101b41d1d708ebc3ec2b0400b1cTimo Sirainen "Cached message offset lost for seq %u in mbox file %s",
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainen seq, mbox->path);
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainen mail_index_mark_corrupted(mbox->ibox.index);
7501b9f694460101b41d1d708ebc3ec2b0400b1cTimo Sirainen return -1;
7501b9f694460101b41d1d708ebc3ec2b0400b1cTimo Sirainen }
7501b9f694460101b41d1d708ebc3ec2b0400b1cTimo Sirainen
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen offset = *((const uint64_t *)data);
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainen if (istream_raw_mbox_seek(mbox->mbox_stream, offset) < 0) {
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen if (offset == 0) {
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainen mail_storage_set_error(&mbox->storage->storage,
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen "Mailbox isn't a valid mbox file");
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen return -1;
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen }
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainen if (mbox->mbox_sync_dirty)
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen return 0;
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainen mail_storage_set_critical(&mbox->storage->storage,
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen "Cached message offset %s is invalid for mbox file %s",
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainen dec2str(offset), mbox->path);
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainen mail_index_mark_corrupted(mbox->ibox.index);
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen return -1;
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen }
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainen if (mbox->mbox_sync_dirty) {
3343a61404603b21c246783a7963b77833095f31Timo Sirainen /* we're dirty - make sure this is the correct mail */
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainen ret = mbox_sync_parse_match_mail(mbox, view, seq);
3343a61404603b21c246783a7963b77833095f31Timo Sirainen if (ret <= 0)
3343a61404603b21c246783a7963b77833095f31Timo Sirainen return ret;
3343a61404603b21c246783a7963b77833095f31Timo Sirainen
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainen ret = istream_raw_mbox_seek(mbox->mbox_stream, offset);
3343a61404603b21c246783a7963b77833095f31Timo Sirainen i_assert(ret == 0);
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen }
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen return 1;
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen}