maildir-save.c revision e1ca7af110ea6eeb6303bdd8f07c172b11dff2fa
/* Copyright (C) 2002-2004 Timo Sirainen */
#include "lib.h"
#include "ioloop.h"
#include "array.h"
#include "buffer.h"
#include "ostream.h"
#include "ostream-crlf.h"
#include "str.h"
#include "maildir-storage.h"
#include "maildir-uidlist.h"
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <utime.h>
struct maildir_filename {
struct maildir_filename *next;
const char *basename;
enum mail_flags flags;
unsigned int keywords_count;
/* unsigned int keywords[]; */
};
struct maildir_save_context {
struct mail_save_context ctx;
struct maildir_mailbox *mbox;
struct mail_index_transaction *trans;
struct maildir_uidlist_sync_ctx *uidlist_sync_ctx;
struct maildir_index_sync_context *sync_ctx;
struct maildir_filename *files;
int fd;
unsigned int synced:1;
unsigned int failed:1;
};
{
int ret;
t_push();
/* if we have flags, we'll move it to cur/ directly, because files in
new/ directory can't have flags. alternative would be to write it
in new/ and set the flags dirty in index file, but in that case
external MUAs would see wrong flags. */
ret = 0;
else {
ret = -1;
"Not enough disk space");
} else {
}
}
"unlink(%s) failed: %m", tmp_path);
}
t_pop();
return ret;
}
static struct maildir_save_context *
{
struct maildir_save_context *ctx;
sizeof(unsigned int));
return ctx;
}
struct mail_save_context *
const char *from_envelope __attr_unused__,
{
struct maildir_transaction_context *t =
(struct maildir_transaction_context *)_t;
struct maildir_save_context *ctx;
struct maildir_filename *mf;
t_push();
t->save_ctx = maildir_save_transaction_init(t);
/* create a new file in tmp/ directory */
&path);
t_pop();
}
fname++;
MAIL_STORAGE_FLAG_SAVE_CRLF) != 0 ?
flags &= ~MAIL_RECENT;
flags |= MAIL_RECENT;
/* now, we want to be able to rollback the whole append session,
so we'll just store the name of this temp file and move it later
into new/ or cur/. */
/* @UNSAFE */
/* @UNSAFE */
}
if (maildir_storage_sync_force(mbox) < 0)
else
}
/* insert into index */
}
}
t_pop();
}
{
return -1;
"o_stream_send_istream(%s) failed: %m",
return -1;
}
return 0;
}
{
const char *path;
int output_errno;
/* tmp file creation failed */
return -1;
}
t_push();
/* set the received_date by modifying mtime */
"utime(%s) failed: %m", path);
}
}
/* FIXME: when saving multiple messages, we could get better
performance if we left the fd open and fsync()ed it later */
"fsync(%s) failed: %m", path);
}
"close(%s) failed: %m", path);
}
/* delete the tmp file */
"unlink(%s) failed: %m", path);
}
"Not enough disk space");
} else if (errno != 0) {
}
t_pop();
return -1;
}
return -1;
}
t_pop();
return 0;
}
{
}
static const char *
struct maildir_filename *mf)
{
return NULL;
mf->keywords_count * sizeof(unsigned int));
return maildir_filename_set_flags(
}
static void
struct maildir_filename *pos)
{
struct maildir_filename *mf;
/* try to unlink the mails already moved */
t_push();
else {
}
}
}
{
struct maildir_filename *mf;
int ret;
/* Start syncing so that keywords_sync_ctx gets set.. */
return -1;
}
&ctx->uidlist_sync_ctx) <= 0) {
/* error or timeout - our transaction is broken */
return -1;
}
}
/* move them into new/ */
ret = 0;
t_push();
t_pop();
ret = -1;
break;
}
t_pop();
}
ret = -1;
return ret;
}
{
/* since we've allocated more UIDs, the index must be kept locked
from that time until the changes are written to transaction log.
keeping the syncing open until here we also keep the lock open.
if the transaction log writer itself had to grab the lock, it'd
mean that there's a chance for another process to start maildir
sync and write the same UIDs twice for the transaction log. */
}
{
struct maildir_filename *mf;
t_push();
/* clean up the temp files */
}
t_pop();
}