Mercurial > dovecot > original-hg > dovecot-1.2
view src/lib-storage/index/maildir/maildir-save.c @ 817:86cf24da85f1 HEAD
Added :INDEX=<dir> for both Maildir and mbox to specify different location
where to store index files. This would allow keeping mailboxes accessible
through NFS but still keep the indexes in fast local disk.
Did also some other related cleanups and minor fixes.
author | Timo Sirainen <tss@iki.fi> |
---|---|
date | Fri, 20 Dec 2002 09:53:51 +0200 |
parents | 35abd7a5d381 |
children | fd8888f6f037 |
line wrap: on
line source
/* Copyright (C) 2002 Timo Sirainen */ #include "lib.h" #include "ioloop.h" #include "hostpid.h" #include "ostream.h" #include "maildir-index.h" #include "maildir-storage.h" #include <stdio.h> #include <unistd.h> #include <fcntl.h> #include <utime.h> const char *maildir_generate_tmp_filename(void) { static unsigned int create_count = 0; hostpid_init(); return t_strdup_printf("%s.%s_%u.%s", dec2str(ioloop_time), my_pid, create_count++, my_hostname); } static int maildir_create_tmp(MailStorage *storage, const char *dir, const char **fname) { const char *path; int fd; *fname = maildir_generate_tmp_filename(); path = t_strconcat(dir, "/", *fname, NULL); fd = open(path, O_WRONLY | O_CREAT | O_EXCL, 0660); if (fd == -1) { if (errno == ENOSPC) { mail_storage_set_error(storage, "Not enough disk space"); } else { /* don't bother checking if it was because file existed - if that happens it's itself an error. */ mail_storage_set_critical(storage, "Can't create file " "%s: %m", path); } } return fd; } static const char *maildir_read_into_tmp(MailStorage *storage, const char *dir, IStream *input, uoff_t data_size) { const char *fname, *path; OStream *output; int fd; fd = maildir_create_tmp(storage, dir, &fname); if (fd == -1) return NULL; t_push(); output = o_stream_create_file(fd, data_stack_pool, 4096, IO_PRIORITY_DEFAULT, FALSE); o_stream_set_blocking(output, 60000, NULL, NULL); path = t_strconcat(dir, "/", fname, NULL); if (!index_storage_save(storage, path, input, output, data_size)) fname = NULL; o_stream_unref(output); if (close(fd) < 0) fname = NULL; if (fname == NULL) (void)unlink(path); t_pop(); return fname; } int maildir_storage_save(Mailbox *box, MailFlags flags, const char *custom_flags[], time_t internal_date, int timezone_offset __attr_unused__, IStream *data, uoff_t data_size) { IndexMailbox *ibox = (IndexMailbox *) box; struct utimbuf buf; const char *tmpdir, *fname, *tmp_path, *new_path; int failed; if (box->readonly) { mail_storage_set_error(box->storage, "Mailbox is read-only"); return FALSE; } if (!index_mailbox_fix_custom_flags(ibox, &flags, custom_flags)) return FALSE; t_push(); /* create the file into tmp/ directory */ tmpdir = t_strconcat(ibox->index->mailbox_path, "/tmp", NULL); fname = maildir_read_into_tmp(box->storage, tmpdir, data, data_size); if (fname == NULL) { t_pop(); return FALSE; } tmp_path = t_strconcat(tmpdir, "/", fname, NULL); fname = maildir_filename_set_flags(fname, flags); new_path = t_strconcat(ibox->index->mailbox_path, "/new/", fname, NULL); /* set the internal_date by modifying mtime */ buf.actime = ioloop_time; buf.modtime = internal_date; if (utime(tmp_path, &buf) < 0) { /* just warn, don't bother actually failing */ mail_storage_set_critical(box->storage, "utime() failed for " "%s: %m", tmp_path); } /* move the file into new/ directory - syncing will pick it up from there */ if (rename(tmp_path, new_path) == 0) failed = FALSE; else { if (errno == ENOSPC) { mail_storage_set_error(box->storage, "Not enough disk space"); } else { mail_storage_set_critical(box->storage, "rename(%s, %s) failed: %m", tmp_path, new_path); } (void)unlink(tmp_path); failed = TRUE; } t_pop(); return !failed; }