maildir-index.c revision 934d42dec29def3fc2b070932f2a7247ec2eea8a
76b43e4417bab52e913da39b5f5bc2a130d3f149Timo Sirainen/* Copyright (C) 2002 Timo Sirainen */
67f1723e1685b4bf73c1cca0a1e08a0a87ffd410Timo Sirainen
67f1723e1685b4bf73c1cca0a1e08a0a87ffd410Timo Sirainen#include "lib.h"
67f1723e1685b4bf73c1cca0a1e08a0a87ffd410Timo Sirainen#include "ioloop.h"
f2f86ec77d1e4986e95990976447c2d1520a8357Timo Sirainen#include "hostpid.h"
67f1723e1685b4bf73c1cca0a1e08a0a87ffd410Timo Sirainen#include "str.h"
f2f86ec77d1e4986e95990976447c2d1520a8357Timo Sirainen#include "maildir-index.h"
67f1723e1685b4bf73c1cca0a1e08a0a87ffd410Timo Sirainen#include "mail-index-data.h"
67f1723e1685b4bf73c1cca0a1e08a0a87ffd410Timo Sirainen#include "mail-index-util.h"
67f1723e1685b4bf73c1cca0a1e08a0a87ffd410Timo Sirainen
67f1723e1685b4bf73c1cca0a1e08a0a87ffd410Timo Sirainen#include <stdio.h>
67f1723e1685b4bf73c1cca0a1e08a0a87ffd410Timo Sirainen#include <sys/stat.h>
67f1723e1685b4bf73c1cca0a1e08a0a87ffd410Timo Sirainen#include <sys/time.h>
67f1723e1685b4bf73c1cca0a1e08a0a87ffd410Timo Sirainen#include <time.h>
67f1723e1685b4bf73c1cca0a1e08a0a87ffd410Timo Sirainen
67f1723e1685b4bf73c1cca0a1e08a0a87ffd410Timo Sirainenextern struct mail_index maildir_index;
67f1723e1685b4bf73c1cca0a1e08a0a87ffd410Timo Sirainen
67f1723e1685b4bf73c1cca0a1e08a0a87ffd410Timo Sirainenstatic int maildir_index_open(struct mail_index *index,
c8b5a21a139992e66b4ad02adb69eaf929b3d024Timo Sirainen enum mail_index_open_flags flags)
67f1723e1685b4bf73c1cca0a1e08a0a87ffd410Timo Sirainen{
67f1723e1685b4bf73c1cca0a1e08a0a87ffd410Timo Sirainen maildir_clean_tmp(t_strconcat(index->mailbox_path, "/tmp", NULL));
67f1723e1685b4bf73c1cca0a1e08a0a87ffd410Timo Sirainen return mail_index_open(index, flags);
67f1723e1685b4bf73c1cca0a1e08a0a87ffd410Timo Sirainen}
67f1723e1685b4bf73c1cca0a1e08a0a87ffd410Timo Sirainen
c8b5a21a139992e66b4ad02adb69eaf929b3d024Timo Sirainenconst char *maildir_get_location(struct mail_index *index,
c8b5a21a139992e66b4ad02adb69eaf929b3d024Timo Sirainen struct mail_index_record *rec)
c8b5a21a139992e66b4ad02adb69eaf929b3d024Timo Sirainen{
67f1723e1685b4bf73c1cca0a1e08a0a87ffd410Timo Sirainen const char *fname;
67f1723e1685b4bf73c1cca0a1e08a0a87ffd410Timo Sirainen
67f1723e1685b4bf73c1cca0a1e08a0a87ffd410Timo Sirainen fname = index->lookup_field(index, rec, DATA_FIELD_LOCATION);
67f1723e1685b4bf73c1cca0a1e08a0a87ffd410Timo Sirainen if (fname == NULL) {
67f1723e1685b4bf73c1cca0a1e08a0a87ffd410Timo Sirainen index_data_set_corrupted(index->data,
67f1723e1685b4bf73c1cca0a1e08a0a87ffd410Timo Sirainen "Missing location field for record %u", rec->uid);
67f1723e1685b4bf73c1cca0a1e08a0a87ffd410Timo Sirainen }
67f1723e1685b4bf73c1cca0a1e08a0a87ffd410Timo Sirainen return fname;
67f1723e1685b4bf73c1cca0a1e08a0a87ffd410Timo Sirainen}
67f1723e1685b4bf73c1cca0a1e08a0a87ffd410Timo Sirainen
67f1723e1685b4bf73c1cca0a1e08a0a87ffd410Timo Sirainenconst char *maildir_generate_tmp_filename(const struct timeval *tv)
67f1723e1685b4bf73c1cca0a1e08a0a87ffd410Timo Sirainen{
67f1723e1685b4bf73c1cca0a1e08a0a87ffd410Timo Sirainen static unsigned int create_count = 0;
67f1723e1685b4bf73c1cca0a1e08a0a87ffd410Timo Sirainen
67f1723e1685b4bf73c1cca0a1e08a0a87ffd410Timo Sirainen return t_strdup_printf("%s.P%sQ%uM%s.%s",
67f1723e1685b4bf73c1cca0a1e08a0a87ffd410Timo Sirainen dec2str(tv->tv_sec), my_pid, create_count++,
67f1723e1685b4bf73c1cca0a1e08a0a87ffd410Timo Sirainen dec2str(tv->tv_usec), my_hostname);
67f1723e1685b4bf73c1cca0a1e08a0a87ffd410Timo Sirainen}
67f1723e1685b4bf73c1cca0a1e08a0a87ffd410Timo Sirainen
67f1723e1685b4bf73c1cca0a1e08a0a87ffd410Timo Sirainenint maildir_create_tmp(struct mail_index *index, const char *dir,
67f1723e1685b4bf73c1cca0a1e08a0a87ffd410Timo Sirainen const char **fname)
67f1723e1685b4bf73c1cca0a1e08a0a87ffd410Timo Sirainen{
f2f86ec77d1e4986e95990976447c2d1520a8357Timo Sirainen const char *path, *tmp_fname;
f2f86ec77d1e4986e95990976447c2d1520a8357Timo Sirainen struct stat st;
f2f86ec77d1e4986e95990976447c2d1520a8357Timo Sirainen struct timeval *tv, tv_now;
67f1723e1685b4bf73c1cca0a1e08a0a87ffd410Timo Sirainen pool_t pool;
67f1723e1685b4bf73c1cca0a1e08a0a87ffd410Timo Sirainen int fd;
67f1723e1685b4bf73c1cca0a1e08a0a87ffd410Timo Sirainen
67f1723e1685b4bf73c1cca0a1e08a0a87ffd410Timo Sirainen tv = &ioloop_timeval;
67f1723e1685b4bf73c1cca0a1e08a0a87ffd410Timo Sirainen pool = pool_alloconly_create("maildir_tmp", 4096);
67f1723e1685b4bf73c1cca0a1e08a0a87ffd410Timo Sirainen for (;;) {
67f1723e1685b4bf73c1cca0a1e08a0a87ffd410Timo Sirainen p_clear(pool);
67f1723e1685b4bf73c1cca0a1e08a0a87ffd410Timo Sirainen tmp_fname = maildir_generate_tmp_filename(tv);
67f1723e1685b4bf73c1cca0a1e08a0a87ffd410Timo Sirainen
67f1723e1685b4bf73c1cca0a1e08a0a87ffd410Timo Sirainen path = p_strconcat(pool, dir, "/", tmp_fname, NULL);
67f1723e1685b4bf73c1cca0a1e08a0a87ffd410Timo Sirainen if (stat(path, &st) < 0 && errno == ENOENT) {
67f1723e1685b4bf73c1cca0a1e08a0a87ffd410Timo Sirainen /* doesn't exist */
67f1723e1685b4bf73c1cca0a1e08a0a87ffd410Timo Sirainen fd = open(path, O_WRONLY | O_CREAT | O_EXCL, 0600);
67f1723e1685b4bf73c1cca0a1e08a0a87ffd410Timo Sirainen if (fd != -1 || errno != EEXIST)
67f1723e1685b4bf73c1cca0a1e08a0a87ffd410Timo Sirainen break;
67f1723e1685b4bf73c1cca0a1e08a0a87ffd410Timo Sirainen }
67f1723e1685b4bf73c1cca0a1e08a0a87ffd410Timo Sirainen
67f1723e1685b4bf73c1cca0a1e08a0a87ffd410Timo Sirainen /* wait and try again - very unlikely */
67f1723e1685b4bf73c1cca0a1e08a0a87ffd410Timo Sirainen sleep(2);
67f1723e1685b4bf73c1cca0a1e08a0a87ffd410Timo Sirainen tv = &tv_now;
67f1723e1685b4bf73c1cca0a1e08a0a87ffd410Timo Sirainen if (gettimeofday(&tv_now, NULL) < 0)
67f1723e1685b4bf73c1cca0a1e08a0a87ffd410Timo Sirainen i_fatal("gettimeofday(): %m");
67f1723e1685b4bf73c1cca0a1e08a0a87ffd410Timo Sirainen }
67f1723e1685b4bf73c1cca0a1e08a0a87ffd410Timo Sirainen
67f1723e1685b4bf73c1cca0a1e08a0a87ffd410Timo Sirainen *fname = t_strdup(path);
67f1723e1685b4bf73c1cca0a1e08a0a87ffd410Timo Sirainen if (fd == -1)
67f1723e1685b4bf73c1cca0a1e08a0a87ffd410Timo Sirainen index_file_set_syscall_error(index, path, "open()");
67f1723e1685b4bf73c1cca0a1e08a0a87ffd410Timo Sirainen
67f1723e1685b4bf73c1cca0a1e08a0a87ffd410Timo Sirainen pool_unref(pool);
67f1723e1685b4bf73c1cca0a1e08a0a87ffd410Timo Sirainen return fd;
67f1723e1685b4bf73c1cca0a1e08a0a87ffd410Timo Sirainen}
67f1723e1685b4bf73c1cca0a1e08a0a87ffd410Timo Sirainen
67f1723e1685b4bf73c1cca0a1e08a0a87ffd410Timo Sirainenenum mail_flags maildir_filename_get_flags(const char *fname,
67f1723e1685b4bf73c1cca0a1e08a0a87ffd410Timo Sirainen enum mail_flags default_flags)
f2f86ec77d1e4986e95990976447c2d1520a8357Timo Sirainen{
f2f86ec77d1e4986e95990976447c2d1520a8357Timo Sirainen const char *info;
f2f86ec77d1e4986e95990976447c2d1520a8357Timo Sirainen enum mail_flags flags;
f2f86ec77d1e4986e95990976447c2d1520a8357Timo Sirainen
f2f86ec77d1e4986e95990976447c2d1520a8357Timo Sirainen info = strchr(fname, ':');
f2f86ec77d1e4986e95990976447c2d1520a8357Timo Sirainen if (info == NULL || info[1] != '2' || info[2] != ',')
f2f86ec77d1e4986e95990976447c2d1520a8357Timo Sirainen return default_flags;
f2f86ec77d1e4986e95990976447c2d1520a8357Timo Sirainen
f2f86ec77d1e4986e95990976447c2d1520a8357Timo Sirainen flags = 0;
f2f86ec77d1e4986e95990976447c2d1520a8357Timo Sirainen for (info += 3; *info != '\0' && *info != ','; info++) {
f2f86ec77d1e4986e95990976447c2d1520a8357Timo Sirainen switch (*info) {
f2f86ec77d1e4986e95990976447c2d1520a8357Timo Sirainen case 'R': /* replied */
f2f86ec77d1e4986e95990976447c2d1520a8357Timo Sirainen flags |= MAIL_ANSWERED;
f2f86ec77d1e4986e95990976447c2d1520a8357Timo Sirainen break;
f2f86ec77d1e4986e95990976447c2d1520a8357Timo Sirainen case 'S': /* seen */
67f1723e1685b4bf73c1cca0a1e08a0a87ffd410Timo Sirainen flags |= MAIL_SEEN;
f2f86ec77d1e4986e95990976447c2d1520a8357Timo Sirainen break;
f2f86ec77d1e4986e95990976447c2d1520a8357Timo Sirainen case 'T': /* trashed */
f2f86ec77d1e4986e95990976447c2d1520a8357Timo Sirainen flags |= MAIL_DELETED;
67f1723e1685b4bf73c1cca0a1e08a0a87ffd410Timo Sirainen break;
f2f86ec77d1e4986e95990976447c2d1520a8357Timo Sirainen case 'D': /* draft */
67f1723e1685b4bf73c1cca0a1e08a0a87ffd410Timo Sirainen flags |= MAIL_DRAFT;
67f1723e1685b4bf73c1cca0a1e08a0a87ffd410Timo Sirainen break;
67f1723e1685b4bf73c1cca0a1e08a0a87ffd410Timo Sirainen case 'F': /* flagged */
67f1723e1685b4bf73c1cca0a1e08a0a87ffd410Timo Sirainen flags |= MAIL_FLAGGED;
67f1723e1685b4bf73c1cca0a1e08a0a87ffd410Timo Sirainen break;
67f1723e1685b4bf73c1cca0a1e08a0a87ffd410Timo Sirainen default:
67f1723e1685b4bf73c1cca0a1e08a0a87ffd410Timo Sirainen if (*info >= 'a' && *info <= 'z') {
67f1723e1685b4bf73c1cca0a1e08a0a87ffd410Timo Sirainen /* custom flag */
67f1723e1685b4bf73c1cca0a1e08a0a87ffd410Timo Sirainen flags |= 1 << (MAIL_CUSTOM_FLAG_1_BIT +
67f1723e1685b4bf73c1cca0a1e08a0a87ffd410Timo Sirainen *info-'a');
67f1723e1685b4bf73c1cca0a1e08a0a87ffd410Timo Sirainen break;
67f1723e1685b4bf73c1cca0a1e08a0a87ffd410Timo Sirainen }
67f1723e1685b4bf73c1cca0a1e08a0a87ffd410Timo Sirainen
67f1723e1685b4bf73c1cca0a1e08a0a87ffd410Timo Sirainen /* unknown flag - ignore */
19e8adccba16ff419f5675b1575358c2956dce83Timo Sirainen break;
eddd9bf1a1369aea4a2715f6be1137da6d17d293Timo Sirainen }
19e8adccba16ff419f5675b1575358c2956dce83Timo Sirainen }
67f1723e1685b4bf73c1cca0a1e08a0a87ffd410Timo Sirainen
67f1723e1685b4bf73c1cca0a1e08a0a87ffd410Timo Sirainen return flags;
eddd9bf1a1369aea4a2715f6be1137da6d17d293Timo Sirainen}
19e8adccba16ff419f5675b1575358c2956dce83Timo Sirainen
eddd9bf1a1369aea4a2715f6be1137da6d17d293Timo Sirainenconst char *maildir_filename_set_flags(const char *fname, enum mail_flags flags)
19e8adccba16ff419f5675b1575358c2956dce83Timo Sirainen{
eddd9bf1a1369aea4a2715f6be1137da6d17d293Timo Sirainen string_t *flags_str;
67f1723e1685b4bf73c1cca0a1e08a0a87ffd410Timo Sirainen const char *info, *oldflags;
67f1723e1685b4bf73c1cca0a1e08a0a87ffd410Timo Sirainen int i, nextflag;
67f1723e1685b4bf73c1cca0a1e08a0a87ffd410Timo Sirainen
67f1723e1685b4bf73c1cca0a1e08a0a87ffd410Timo Sirainen /* remove the old :info from file name, and get the old flags */
67f1723e1685b4bf73c1cca0a1e08a0a87ffd410Timo Sirainen info = strrchr(fname, ':');
67f1723e1685b4bf73c1cca0a1e08a0a87ffd410Timo Sirainen if (info != NULL && strrchr(fname, '/') > info)
67f1723e1685b4bf73c1cca0a1e08a0a87ffd410Timo Sirainen info = NULL;
67f1723e1685b4bf73c1cca0a1e08a0a87ffd410Timo Sirainen
67f1723e1685b4bf73c1cca0a1e08a0a87ffd410Timo Sirainen oldflags = "";
67f1723e1685b4bf73c1cca0a1e08a0a87ffd410Timo Sirainen if (info != NULL) {
67f1723e1685b4bf73c1cca0a1e08a0a87ffd410Timo Sirainen fname = t_strdup_until(fname, info);
67f1723e1685b4bf73c1cca0a1e08a0a87ffd410Timo Sirainen if (info[1] == '2' && info[2] == ',')
67f1723e1685b4bf73c1cca0a1e08a0a87ffd410Timo Sirainen oldflags = info+3;
67f1723e1685b4bf73c1cca0a1e08a0a87ffd410Timo Sirainen }
67f1723e1685b4bf73c1cca0a1e08a0a87ffd410Timo Sirainen
67f1723e1685b4bf73c1cca0a1e08a0a87ffd410Timo Sirainen /* insert the new flags between old flags. flags must be sorted by
67f1723e1685b4bf73c1cca0a1e08a0a87ffd410Timo Sirainen their ASCII code. unknown flags are kept. */
67f1723e1685b4bf73c1cca0a1e08a0a87ffd410Timo Sirainen flags_str = t_str_new(256);
67f1723e1685b4bf73c1cca0a1e08a0a87ffd410Timo Sirainen str_append(flags_str, fname);
67f1723e1685b4bf73c1cca0a1e08a0a87ffd410Timo Sirainen str_append(flags_str, ":2,");
67f1723e1685b4bf73c1cca0a1e08a0a87ffd410Timo Sirainen for (;;) {
67f1723e1685b4bf73c1cca0a1e08a0a87ffd410Timo Sirainen /* skip all known flags */
67f1723e1685b4bf73c1cca0a1e08a0a87ffd410Timo Sirainen while (*oldflags == 'D' || *oldflags == 'F' ||
67f1723e1685b4bf73c1cca0a1e08a0a87ffd410Timo Sirainen *oldflags == 'R' || *oldflags == 'S' ||
67f1723e1685b4bf73c1cca0a1e08a0a87ffd410Timo Sirainen *oldflags == 'T' ||
67f1723e1685b4bf73c1cca0a1e08a0a87ffd410Timo Sirainen (*oldflags >= 'a' && *oldflags <= 'z'))
67f1723e1685b4bf73c1cca0a1e08a0a87ffd410Timo Sirainen oldflags++;
67f1723e1685b4bf73c1cca0a1e08a0a87ffd410Timo Sirainen
67f1723e1685b4bf73c1cca0a1e08a0a87ffd410Timo Sirainen nextflag = *oldflags == '\0' || *oldflags == ',' ? 256 :
67f1723e1685b4bf73c1cca0a1e08a0a87ffd410Timo Sirainen (unsigned char) *oldflags;
67f1723e1685b4bf73c1cca0a1e08a0a87ffd410Timo Sirainen
67f1723e1685b4bf73c1cca0a1e08a0a87ffd410Timo Sirainen if ((flags & MAIL_DRAFT) && nextflag > 'D') {
67f1723e1685b4bf73c1cca0a1e08a0a87ffd410Timo Sirainen str_append_c(flags_str, 'D');
67f1723e1685b4bf73c1cca0a1e08a0a87ffd410Timo Sirainen flags &= ~MAIL_DRAFT;
67f1723e1685b4bf73c1cca0a1e08a0a87ffd410Timo Sirainen }
67f1723e1685b4bf73c1cca0a1e08a0a87ffd410Timo Sirainen if ((flags & MAIL_FLAGGED) && nextflag > 'F') {
67f1723e1685b4bf73c1cca0a1e08a0a87ffd410Timo Sirainen str_append_c(flags_str, 'F');
67f1723e1685b4bf73c1cca0a1e08a0a87ffd410Timo Sirainen flags &= ~MAIL_FLAGGED;
67f1723e1685b4bf73c1cca0a1e08a0a87ffd410Timo Sirainen }
67f1723e1685b4bf73c1cca0a1e08a0a87ffd410Timo Sirainen if ((flags & MAIL_ANSWERED) && nextflag > 'R') {
67f1723e1685b4bf73c1cca0a1e08a0a87ffd410Timo Sirainen str_append_c(flags_str, 'R');
67f1723e1685b4bf73c1cca0a1e08a0a87ffd410Timo Sirainen flags &= ~MAIL_ANSWERED;
67f1723e1685b4bf73c1cca0a1e08a0a87ffd410Timo Sirainen }
67f1723e1685b4bf73c1cca0a1e08a0a87ffd410Timo Sirainen if ((flags & MAIL_SEEN) && nextflag > 'S') {
67f1723e1685b4bf73c1cca0a1e08a0a87ffd410Timo Sirainen str_append_c(flags_str, 'S');
67f1723e1685b4bf73c1cca0a1e08a0a87ffd410Timo Sirainen flags &= ~MAIL_SEEN;
67f1723e1685b4bf73c1cca0a1e08a0a87ffd410Timo Sirainen }
67f1723e1685b4bf73c1cca0a1e08a0a87ffd410Timo Sirainen if ((flags & MAIL_DELETED) && nextflag > 'T') {
67f1723e1685b4bf73c1cca0a1e08a0a87ffd410Timo Sirainen str_append_c(flags_str, 'T');
67f1723e1685b4bf73c1cca0a1e08a0a87ffd410Timo Sirainen flags &= ~MAIL_DELETED;
67f1723e1685b4bf73c1cca0a1e08a0a87ffd410Timo Sirainen }
67f1723e1685b4bf73c1cca0a1e08a0a87ffd410Timo Sirainen
67f1723e1685b4bf73c1cca0a1e08a0a87ffd410Timo Sirainen if ((flags & MAIL_CUSTOM_FLAGS_MASK) && nextflag > 'a') {
67f1723e1685b4bf73c1cca0a1e08a0a87ffd410Timo Sirainen for (i = 0; i < MAIL_CUSTOM_FLAGS_COUNT; i++) {
67f1723e1685b4bf73c1cca0a1e08a0a87ffd410Timo Sirainen if (flags & (1 << (i + MAIL_CUSTOM_FLAG_1_BIT)))
67f1723e1685b4bf73c1cca0a1e08a0a87ffd410Timo Sirainen str_append_c(flags_str, 'a' + i);
67f1723e1685b4bf73c1cca0a1e08a0a87ffd410Timo Sirainen }
67f1723e1685b4bf73c1cca0a1e08a0a87ffd410Timo Sirainen flags &= ~MAIL_CUSTOM_FLAGS_MASK;
67f1723e1685b4bf73c1cca0a1e08a0a87ffd410Timo Sirainen }
67f1723e1685b4bf73c1cca0a1e08a0a87ffd410Timo Sirainen
67f1723e1685b4bf73c1cca0a1e08a0a87ffd410Timo Sirainen if (*oldflags == '\0' || *oldflags == ',')
67f1723e1685b4bf73c1cca0a1e08a0a87ffd410Timo Sirainen break;
67f1723e1685b4bf73c1cca0a1e08a0a87ffd410Timo Sirainen
67f1723e1685b4bf73c1cca0a1e08a0a87ffd410Timo Sirainen str_append_c(flags_str, *oldflags);
67f1723e1685b4bf73c1cca0a1e08a0a87ffd410Timo Sirainen oldflags++;
67f1723e1685b4bf73c1cca0a1e08a0a87ffd410Timo Sirainen }
67f1723e1685b4bf73c1cca0a1e08a0a87ffd410Timo Sirainen
67f1723e1685b4bf73c1cca0a1e08a0a87ffd410Timo Sirainen if (*oldflags == ',') {
67f1723e1685b4bf73c1cca0a1e08a0a87ffd410Timo Sirainen /* another flagset, we don't know about these, just keep them */
67f1723e1685b4bf73c1cca0a1e08a0a87ffd410Timo Sirainen while (*oldflags != '\0')
67f1723e1685b4bf73c1cca0a1e08a0a87ffd410Timo Sirainen str_append_c(flags_str, *oldflags++);
67f1723e1685b4bf73c1cca0a1e08a0a87ffd410Timo Sirainen }
67f1723e1685b4bf73c1cca0a1e08a0a87ffd410Timo Sirainen
67f1723e1685b4bf73c1cca0a1e08a0a87ffd410Timo Sirainen return str_c(flags_str);
67f1723e1685b4bf73c1cca0a1e08a0a87ffd410Timo Sirainen}
67f1723e1685b4bf73c1cca0a1e08a0a87ffd410Timo Sirainen
67f1723e1685b4bf73c1cca0a1e08a0a87ffd410Timo Sirainenstruct mail_index *
67f1723e1685b4bf73c1cca0a1e08a0a87ffd410Timo Sirainenmaildir_index_alloc(const char *maildir, const char *index_dir,
67f1723e1685b4bf73c1cca0a1e08a0a87ffd410Timo Sirainen const char *control_dir)
{
struct mail_index *index;
i_assert(maildir != NULL);
index = i_new(struct mail_index, 1);
memcpy(index, &maildir_index, sizeof(struct mail_index));
index->maildir_lock_fd = -1;
index->mailbox_path = i_strdup(maildir);
index->control_dir = i_strdup(control_dir);
mail_index_init(index, index_dir);
return index;
}
static void maildir_index_free(struct mail_index *index)
{
mail_index_close(index);
i_free(index->dir);
i_free(index->mailbox_path);
i_free(index);
}
static time_t maildir_get_internal_date(struct mail_index *index,
struct mail_index_record *rec)
{
struct stat st;
const char *fname;
time_t date;
/* try getting it from cache */
date = mail_get_internal_date(index, rec);
if (date != (time_t)-1)
return date;
/* stat() gives it */
fname = maildir_get_location(index, rec);
if (fname == NULL)
return (time_t)-1;
if (stat(fname, &st) < 0) {
index_file_set_syscall_error(index, fname, "stat()");
return (time_t)-1;
}
return st.st_mtime;
}
static int maildir_index_update_flags(struct mail_index *index,
struct mail_index_record *rec,
unsigned int seq, enum mail_flags flags,
int external_change)
{
struct mail_index_update *update;
const char *old_fname, *new_fname;
const char *old_path, *new_path;
/* we need to update the flags in the file name */
old_fname = maildir_get_location(index, rec);
if (old_fname == NULL)
return FALSE;
new_fname = maildir_filename_set_flags(old_fname, flags);
if (strcmp(old_fname, new_fname) != 0) {
old_path = t_strconcat(index->mailbox_path,
"/cur/", old_fname, NULL);
new_path = t_strconcat(index->mailbox_path,
"/cur/", new_fname, NULL);
/* minor problem: new_path is overwritten if it exists.. */
if (rename(old_path, new_path) < 0) {
if (ENOSPACE(errno))
index->nodiskspace = TRUE;
index_set_error(index, "maildir flags update: "
"rename(%s, %s) failed: %m",
old_path, new_path);
return FALSE;
}
/* update the filename in index */
update = index->update_begin(index, rec);
index->update_field(update, DATA_FIELD_LOCATION, new_fname, 0);
if (!index->update_end(update))
return FALSE;
}
if (!mail_index_update_flags(index, rec, seq, flags, external_change))
return FALSE;
return TRUE;
}
struct mail_index maildir_index = {
maildir_index_open,
maildir_index_free,
mail_index_set_lock,
mail_index_try_lock,
mail_index_set_lock_notify_callback,
maildir_index_rebuild,
mail_index_fsck,
maildir_index_sync,
mail_index_get_header,
mail_index_lookup,
mail_index_next,
mail_index_lookup_uid_range,
mail_index_lookup_field,
mail_index_lookup_field_raw,
mail_index_cache_fields_later,
maildir_open_mail,
maildir_get_internal_date,
mail_index_expunge,
maildir_index_update_flags,
mail_index_append_begin,
mail_index_append_end,
mail_index_append_abort,
mail_index_update_begin,
mail_index_update_end,
mail_index_update_abort,
mail_index_update_field,
mail_index_update_field_raw,
mail_index_get_last_error,
mail_index_get_last_error_text,
MAIL_INDEX_PRIVATE_FILL
};