maildir-save.c revision a3d22d3cb0e5436128ca7287cedc921f1789b2c8
/* 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_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;
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_index_sync_context *sync_ctx,
struct maildir_filename *mf)
{
return NULL;
mf->keywords_count * sizeof(unsigned int));
}
static void
struct maildir_index_sync_context *sync_ctx,
struct maildir_filename *pos)
{
struct maildir_filename *mf;
/* try to unlink the mails already moved */
t_push();
else {
}
}
}
{
struct maildir_index_sync_context *sync_ctx;
struct maildir_filename *mf;
int ret;
return -1;
}
if (ret <= 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();
}
if (ret == 0) {
/* finish uidlist syncing, but keep it still locked */
}
if (ret < 0) {
/* deinit only if we failed. otherwise save_commit_post()
does it. */
ret = -1;
}
return ret;
}
{
/* can't do anything anymore if we fail */
}
{
struct maildir_filename *mf;
t_push();
/* clean up the temp files */
str_truncate(str, 0);
}
t_pop();
}