maildir-util.c revision 825f6569a5276488133796c2f529c65128a09ba0
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen/* Copyright (C) 2004 Timo Sirainen */
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "lib.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "hostpid.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "ioloop.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "str.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "maildir-storage.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "maildir-uidlist.h"
cce169a321c9c629e4f2db1a69dae3b75bbcb27aTimo Sirainen#include "maildir-keywords.h"
5fb3bff645380804c9db2510940c41db6b8fdb01Timo Sirainen#include "maildir-sync.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include <unistd.h>
73a552a9ed06cd6017ad4ee4b252a8b38c8ac42dTimo Sirainen#include <dirent.h>
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include <fcntl.h>
73a552a9ed06cd6017ad4ee4b252a8b38c8ac42dTimo Sirainen#include <utime.h>
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include <sys/stat.h>
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainenstatic int maildir_file_do_try(struct maildir_mailbox *mbox, uint32_t uid,
00efa7d99981e18e286c02b18c1163dde18ee521Timo Sirainen maildir_file_do_func *callback, void *context)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen{
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen const char *fname, *path;
641f0c0900ee6e7cf9667f4b40ed95cec7d0cdcaTimo Sirainen enum maildir_uidlist_rec_flag flags;
641f0c0900ee6e7cf9667f4b40ed95cec7d0cdcaTimo Sirainen int ret;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainen fname = maildir_uidlist_lookup(mbox->uidlist, uid, &flags);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (fname == NULL)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return -2; /* expunged */
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
2f2823ad8928654ed405467c6c1f4fd4c6f5cf7cTimo Sirainen t_push();
641f0c0900ee6e7cf9667f4b40ed95cec7d0cdcaTimo Sirainen if ((flags & MAILDIR_UIDLIST_REC_FLAG_NEW_DIR) != 0) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen /* probably in new/ dir */
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainen path = t_strconcat(mbox->path, "/new/", fname, NULL);
00efa7d99981e18e286c02b18c1163dde18ee521Timo Sirainen ret = callback(mbox, path, context);
2f2823ad8928654ed405467c6c1f4fd4c6f5cf7cTimo Sirainen if (ret != 0) {
2f2823ad8928654ed405467c6c1f4fd4c6f5cf7cTimo Sirainen t_pop();
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return ret;
2f2823ad8928654ed405467c6c1f4fd4c6f5cf7cTimo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainen path = t_strconcat(mbox->path, "/cur/", fname, NULL);
00efa7d99981e18e286c02b18c1163dde18ee521Timo Sirainen ret = callback(mbox, path, context);
2f2823ad8928654ed405467c6c1f4fd4c6f5cf7cTimo Sirainen t_pop();
2f2823ad8928654ed405467c6c1f4fd4c6f5cf7cTimo Sirainen return ret;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen}
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
825f6569a5276488133796c2f529c65128a09ba0Timo Sirainenstatic int do_racecheck(struct maildir_mailbox *mbox, const char *path,
825f6569a5276488133796c2f529c65128a09ba0Timo Sirainen void *context __attr_unused__)
825f6569a5276488133796c2f529c65128a09ba0Timo Sirainen{
825f6569a5276488133796c2f529c65128a09ba0Timo Sirainen struct stat st;
825f6569a5276488133796c2f529c65128a09ba0Timo Sirainen
825f6569a5276488133796c2f529c65128a09ba0Timo Sirainen if (lstat(path, &st) == 0 && (st.st_mode & S_IFLNK) != 0) {
825f6569a5276488133796c2f529c65128a09ba0Timo Sirainen /* most likely a symlink pointing to a non-existing file */
825f6569a5276488133796c2f529c65128a09ba0Timo Sirainen mail_storage_set_critical(&mbox->storage->storage,
825f6569a5276488133796c2f529c65128a09ba0Timo Sirainen "Maildir: Symlink destination doesn't exist: %s", path);
825f6569a5276488133796c2f529c65128a09ba0Timo Sirainen return -2;
825f6569a5276488133796c2f529c65128a09ba0Timo Sirainen } else {
825f6569a5276488133796c2f529c65128a09ba0Timo Sirainen mail_storage_set_critical(&mbox->storage->storage,
825f6569a5276488133796c2f529c65128a09ba0Timo Sirainen "maildir_file_do(%s): Filename keeps changing", path);
825f6569a5276488133796c2f529c65128a09ba0Timo Sirainen return -1;
825f6569a5276488133796c2f529c65128a09ba0Timo Sirainen }
825f6569a5276488133796c2f529c65128a09ba0Timo Sirainen}
825f6569a5276488133796c2f529c65128a09ba0Timo Sirainen
59151b71059df1190acd75d8717ed04a7920c862Timo Sirainen#undef maildir_file_do
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainenint maildir_file_do(struct maildir_mailbox *mbox, uint32_t uid,
00efa7d99981e18e286c02b18c1163dde18ee521Timo Sirainen maildir_file_do_func *callback, void *context)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen{
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen int i, ret;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
00efa7d99981e18e286c02b18c1163dde18ee521Timo Sirainen ret = maildir_file_do_try(mbox, uid, callback, context);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen for (i = 0; i < 10 && ret == 0; i++) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen /* file is either renamed or deleted. sync the maildir and
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen see which one. if file appears to be renamed constantly,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen don't try to open it more than 10 times. */
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainen if (maildir_storage_sync_force(mbox) < 0)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return -1;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
00efa7d99981e18e286c02b18c1163dde18ee521Timo Sirainen ret = maildir_file_do_try(mbox, uid, callback, context);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
825f6569a5276488133796c2f529c65128a09ba0Timo Sirainen if (i == 10)
825f6569a5276488133796c2f529c65128a09ba0Timo Sirainen ret = maildir_file_do_try(mbox, uid, do_racecheck, context);
039e42997fe5e0d1c5ad9306dc0ae69bf0e1ca10Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return ret == -2 ? 0 : ret;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen}
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenconst char *maildir_generate_tmp_filename(const struct timeval *tv)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen{
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen static unsigned int create_count = 0;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen static time_t first_stamp = 0;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (first_stamp == 0 || first_stamp == ioloop_time) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen /* it's possible that within last second another process had
4c176a543191e4572910401c218a63306ed68784Timo Sirainen the same PID as us. Use usecs to make sure we don't create
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen duplicate base name. */
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen first_stamp = ioloop_time;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return t_strdup_printf("%s.P%sQ%uM%s.%s",
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen dec2str(tv->tv_sec), my_pid,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen create_count++,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen dec2str(tv->tv_usec), my_hostname);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen } else {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen /* Don't bother with usecs. Saves a bit space :) */
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return t_strdup_printf("%s.P%sQ%u.%s",
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen dec2str(tv->tv_sec), my_pid,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen create_count++, my_hostname);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen}
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainenint maildir_create_tmp(struct maildir_mailbox *mbox, const char *dir,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen mode_t mode, const char **fname_r)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen{
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen struct stat st;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen struct timeval *tv, tv_now;
c44e6b4d3522b6accba426e1e3f64c2e2d860d92Timo Sirainen unsigned int prefix_len;
c44e6b4d3522b6accba426e1e3f64c2e2d860d92Timo Sirainen const char *tmp_fname = NULL;
c44e6b4d3522b6accba426e1e3f64c2e2d860d92Timo Sirainen string_t *path;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen int fd;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen tv = &ioloop_timeval;
c44e6b4d3522b6accba426e1e3f64c2e2d860d92Timo Sirainen path = t_str_new(256);
c44e6b4d3522b6accba426e1e3f64c2e2d860d92Timo Sirainen str_append(path, dir);
c44e6b4d3522b6accba426e1e3f64c2e2d860d92Timo Sirainen str_append_c(path, '/');
c44e6b4d3522b6accba426e1e3f64c2e2d860d92Timo Sirainen prefix_len = str_len(path);
c44e6b4d3522b6accba426e1e3f64c2e2d860d92Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen for (;;) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen tmp_fname = maildir_generate_tmp_filename(tv);
c44e6b4d3522b6accba426e1e3f64c2e2d860d92Timo Sirainen str_truncate(path, prefix_len);
c44e6b4d3522b6accba426e1e3f64c2e2d860d92Timo Sirainen str_append(path, tmp_fname);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
c44e6b4d3522b6accba426e1e3f64c2e2d860d92Timo Sirainen /* stat() first to see if it exists. pretty much the only
c44e6b4d3522b6accba426e1e3f64c2e2d860d92Timo Sirainen possibility of that happening is if time had moved
c44e6b4d3522b6accba426e1e3f64c2e2d860d92Timo Sirainen backwards, but even then it's highly unlikely. */
c44e6b4d3522b6accba426e1e3f64c2e2d860d92Timo Sirainen if (stat(str_c(path), &st) < 0 && errno == ENOENT) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen /* doesn't exist */
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen mode_t old_mask = umask(0);
c44e6b4d3522b6accba426e1e3f64c2e2d860d92Timo Sirainen fd = open(str_c(path), O_WRONLY | O_CREAT | O_EXCL,
c44e6b4d3522b6accba426e1e3f64c2e2d860d92Timo Sirainen mode);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen umask(old_mask);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (fd != -1 || errno != EEXIST)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen break;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen sleep(2);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen tv = &tv_now;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (gettimeofday(&tv_now, NULL) < 0)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen i_fatal("gettimeofday(): %m");
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
c44e6b4d3522b6accba426e1e3f64c2e2d860d92Timo Sirainen *fname_r = tmp_fname;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (fd == -1) {
102c6b4e47a0d17699004e48740f651153fb8b76Timo Sirainen if (ENOSPACE(errno)) {
ccc895c0358108d2304239063e940b7d75f364abTimo Sirainen mail_storage_set_error(&mbox->storage->storage,
ff7056842f14fd3b30a2d327dfab165b9d15dd30Timo Sirainen MAIL_ERROR_NOSPACE, MAIL_ERRSTR_NO_SPACE);
102c6b4e47a0d17699004e48740f651153fb8b76Timo Sirainen } else {
ccc895c0358108d2304239063e940b7d75f364abTimo Sirainen mail_storage_set_critical(&mbox->storage->storage,
c44e6b4d3522b6accba426e1e3f64c2e2d860d92Timo Sirainen "open(%s) failed: %m", str_c(path));
102c6b4e47a0d17699004e48740f651153fb8b76Timo Sirainen }
b17f1f82de846c6f0ba40a86659c3e64d4c1b1f6Timo Sirainen } else if (mbox->mail_create_gid != (gid_t)-1) {
8a6fc472a12c5ec09e2bd19f1b3acd553d75ff91Timo Sirainen if (fchown(fd, (uid_t)-1, mbox->mail_create_gid) < 0) {
ccc895c0358108d2304239063e940b7d75f364abTimo Sirainen mail_storage_set_critical(&mbox->storage->storage,
c44e6b4d3522b6accba426e1e3f64c2e2d860d92Timo Sirainen "fchown(%s) failed: %m", str_c(path));
8a6fc472a12c5ec09e2bd19f1b3acd553d75ff91Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return fd;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen}
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
73a552a9ed06cd6017ad4ee4b252a8b38c8ac42dTimo Sirainenvoid maildir_tmp_cleanup(struct mail_storage *storage, const char *dir)
73a552a9ed06cd6017ad4ee4b252a8b38c8ac42dTimo Sirainen{
73a552a9ed06cd6017ad4ee4b252a8b38c8ac42dTimo Sirainen DIR *dirp;
73a552a9ed06cd6017ad4ee4b252a8b38c8ac42dTimo Sirainen struct dirent *d;
73a552a9ed06cd6017ad4ee4b252a8b38c8ac42dTimo Sirainen struct stat st;
73a552a9ed06cd6017ad4ee4b252a8b38c8ac42dTimo Sirainen string_t *path;
73a552a9ed06cd6017ad4ee4b252a8b38c8ac42dTimo Sirainen unsigned int dir_len;
73a552a9ed06cd6017ad4ee4b252a8b38c8ac42dTimo Sirainen
73a552a9ed06cd6017ad4ee4b252a8b38c8ac42dTimo Sirainen dirp = opendir(dir);
73a552a9ed06cd6017ad4ee4b252a8b38c8ac42dTimo Sirainen if (dirp == NULL) {
73a552a9ed06cd6017ad4ee4b252a8b38c8ac42dTimo Sirainen if (errno != ENOENT) {
73a552a9ed06cd6017ad4ee4b252a8b38c8ac42dTimo Sirainen mail_storage_set_critical(storage,
73a552a9ed06cd6017ad4ee4b252a8b38c8ac42dTimo Sirainen "opendir(%s) failed: %m", dir);
73a552a9ed06cd6017ad4ee4b252a8b38c8ac42dTimo Sirainen }
73a552a9ed06cd6017ad4ee4b252a8b38c8ac42dTimo Sirainen return;
73a552a9ed06cd6017ad4ee4b252a8b38c8ac42dTimo Sirainen }
73a552a9ed06cd6017ad4ee4b252a8b38c8ac42dTimo Sirainen
73a552a9ed06cd6017ad4ee4b252a8b38c8ac42dTimo Sirainen t_push();
73a552a9ed06cd6017ad4ee4b252a8b38c8ac42dTimo Sirainen path = t_str_new(256);
73a552a9ed06cd6017ad4ee4b252a8b38c8ac42dTimo Sirainen str_printfa(path, "%s/", dir);
73a552a9ed06cd6017ad4ee4b252a8b38c8ac42dTimo Sirainen dir_len = str_len(path);
73a552a9ed06cd6017ad4ee4b252a8b38c8ac42dTimo Sirainen
73a552a9ed06cd6017ad4ee4b252a8b38c8ac42dTimo Sirainen while ((d = readdir(dirp)) != NULL) {
73a552a9ed06cd6017ad4ee4b252a8b38c8ac42dTimo Sirainen if (d->d_name[0] == '.' &&
73a552a9ed06cd6017ad4ee4b252a8b38c8ac42dTimo Sirainen (d->d_name[1] == '\0' ||
73a552a9ed06cd6017ad4ee4b252a8b38c8ac42dTimo Sirainen (d->d_name[1] == '.' && d->d_name[2] == '\0'))) {
73a552a9ed06cd6017ad4ee4b252a8b38c8ac42dTimo Sirainen /* skip . and .. */
73a552a9ed06cd6017ad4ee4b252a8b38c8ac42dTimo Sirainen continue;
73a552a9ed06cd6017ad4ee4b252a8b38c8ac42dTimo Sirainen }
73a552a9ed06cd6017ad4ee4b252a8b38c8ac42dTimo Sirainen
73a552a9ed06cd6017ad4ee4b252a8b38c8ac42dTimo Sirainen str_truncate(path, dir_len);
73a552a9ed06cd6017ad4ee4b252a8b38c8ac42dTimo Sirainen str_append(path, d->d_name);
73a552a9ed06cd6017ad4ee4b252a8b38c8ac42dTimo Sirainen if (stat(str_c(path), &st) < 0) {
73a552a9ed06cd6017ad4ee4b252a8b38c8ac42dTimo Sirainen if (errno != ENOENT) {
73a552a9ed06cd6017ad4ee4b252a8b38c8ac42dTimo Sirainen mail_storage_set_critical(storage,
73a552a9ed06cd6017ad4ee4b252a8b38c8ac42dTimo Sirainen "stat(%s) failed: %m", str_c(path));
73a552a9ed06cd6017ad4ee4b252a8b38c8ac42dTimo Sirainen }
73a552a9ed06cd6017ad4ee4b252a8b38c8ac42dTimo Sirainen } else if (st.st_ctime <=
73a552a9ed06cd6017ad4ee4b252a8b38c8ac42dTimo Sirainen ioloop_time - MAILDIR_TMP_DELETE_SECS) {
73a552a9ed06cd6017ad4ee4b252a8b38c8ac42dTimo Sirainen if (unlink(str_c(path)) < 0 && errno != ENOENT) {
73a552a9ed06cd6017ad4ee4b252a8b38c8ac42dTimo Sirainen mail_storage_set_critical(storage,
73a552a9ed06cd6017ad4ee4b252a8b38c8ac42dTimo Sirainen "unlink(%s) failed: %m", str_c(path));
73a552a9ed06cd6017ad4ee4b252a8b38c8ac42dTimo Sirainen }
73a552a9ed06cd6017ad4ee4b252a8b38c8ac42dTimo Sirainen }
73a552a9ed06cd6017ad4ee4b252a8b38c8ac42dTimo Sirainen }
73a552a9ed06cd6017ad4ee4b252a8b38c8ac42dTimo Sirainen t_pop();
73a552a9ed06cd6017ad4ee4b252a8b38c8ac42dTimo Sirainen
73a552a9ed06cd6017ad4ee4b252a8b38c8ac42dTimo Sirainen#ifdef HAVE_DIRFD
73a552a9ed06cd6017ad4ee4b252a8b38c8ac42dTimo Sirainen if (fstat(dirfd(dirp), &st) < 0) {
73a552a9ed06cd6017ad4ee4b252a8b38c8ac42dTimo Sirainen mail_storage_set_critical(storage,
73a552a9ed06cd6017ad4ee4b252a8b38c8ac42dTimo Sirainen "fstat(%s) failed: %m", dir);
73a552a9ed06cd6017ad4ee4b252a8b38c8ac42dTimo Sirainen }
73a552a9ed06cd6017ad4ee4b252a8b38c8ac42dTimo Sirainen#else
73a552a9ed06cd6017ad4ee4b252a8b38c8ac42dTimo Sirainen if (stat(dir, &st) < 0) {
73a552a9ed06cd6017ad4ee4b252a8b38c8ac42dTimo Sirainen mail_storage_set_critical(storage,
73a552a9ed06cd6017ad4ee4b252a8b38c8ac42dTimo Sirainen "stat(%s) failed: %m", dir);
73a552a9ed06cd6017ad4ee4b252a8b38c8ac42dTimo Sirainen }
73a552a9ed06cd6017ad4ee4b252a8b38c8ac42dTimo Sirainen#endif
73a552a9ed06cd6017ad4ee4b252a8b38c8ac42dTimo Sirainen else if (st.st_atime < ioloop_time) {
73a552a9ed06cd6017ad4ee4b252a8b38c8ac42dTimo Sirainen /* mounted with noatime. update it ourself. */
73a552a9ed06cd6017ad4ee4b252a8b38c8ac42dTimo Sirainen struct utimbuf ut;
73a552a9ed06cd6017ad4ee4b252a8b38c8ac42dTimo Sirainen
73a552a9ed06cd6017ad4ee4b252a8b38c8ac42dTimo Sirainen ut.actime = ioloop_time;
73a552a9ed06cd6017ad4ee4b252a8b38c8ac42dTimo Sirainen ut.modtime = st.st_mtime;
73a552a9ed06cd6017ad4ee4b252a8b38c8ac42dTimo Sirainen
73a552a9ed06cd6017ad4ee4b252a8b38c8ac42dTimo Sirainen if (utime(dir, &ut) < 0 && errno != ENOENT) {
73a552a9ed06cd6017ad4ee4b252a8b38c8ac42dTimo Sirainen mail_storage_set_critical(storage,
73a552a9ed06cd6017ad4ee4b252a8b38c8ac42dTimo Sirainen "utime(%s) failed: %m", dir);
73a552a9ed06cd6017ad4ee4b252a8b38c8ac42dTimo Sirainen }
73a552a9ed06cd6017ad4ee4b252a8b38c8ac42dTimo Sirainen }
73a552a9ed06cd6017ad4ee4b252a8b38c8ac42dTimo Sirainen
73a552a9ed06cd6017ad4ee4b252a8b38c8ac42dTimo Sirainen if (closedir(dirp) < 0) {
73a552a9ed06cd6017ad4ee4b252a8b38c8ac42dTimo Sirainen mail_storage_set_critical(storage,
73a552a9ed06cd6017ad4ee4b252a8b38c8ac42dTimo Sirainen "closedir(%s) failed: %m", dir);
73a552a9ed06cd6017ad4ee4b252a8b38c8ac42dTimo Sirainen }
73a552a9ed06cd6017ad4ee4b252a8b38c8ac42dTimo Sirainen}
73a552a9ed06cd6017ad4ee4b252a8b38c8ac42dTimo Sirainen
677e22747b82bf15b339e31d1d0106d62bf806daTimo Sirainenbool maildir_filename_get_size(const char *fname, char type, uoff_t *size_r)
677e22747b82bf15b339e31d1d0106d62bf806daTimo Sirainen{
677e22747b82bf15b339e31d1d0106d62bf806daTimo Sirainen uoff_t size = 0;
677e22747b82bf15b339e31d1d0106d62bf806daTimo Sirainen
677e22747b82bf15b339e31d1d0106d62bf806daTimo Sirainen for (; *fname != '\0'; fname++) {
b142deb9a831c89b1bb9129ada655f3e56b9d4ccTimo Sirainen i_assert(*fname != '/');
677e22747b82bf15b339e31d1d0106d62bf806daTimo Sirainen if (*fname == ',' && fname[1] == type && fname[2] == '=') {
677e22747b82bf15b339e31d1d0106d62bf806daTimo Sirainen fname += 3;
677e22747b82bf15b339e31d1d0106d62bf806daTimo Sirainen break;
677e22747b82bf15b339e31d1d0106d62bf806daTimo Sirainen }
677e22747b82bf15b339e31d1d0106d62bf806daTimo Sirainen }
677e22747b82bf15b339e31d1d0106d62bf806daTimo Sirainen
677e22747b82bf15b339e31d1d0106d62bf806daTimo Sirainen if (*fname == '\0')
677e22747b82bf15b339e31d1d0106d62bf806daTimo Sirainen return FALSE;
677e22747b82bf15b339e31d1d0106d62bf806daTimo Sirainen
677e22747b82bf15b339e31d1d0106d62bf806daTimo Sirainen while (*fname >= '0' && *fname <= '9') {
677e22747b82bf15b339e31d1d0106d62bf806daTimo Sirainen size = size * 10 + (*fname - '0');
677e22747b82bf15b339e31d1d0106d62bf806daTimo Sirainen fname++;
677e22747b82bf15b339e31d1d0106d62bf806daTimo Sirainen }
677e22747b82bf15b339e31d1d0106d62bf806daTimo Sirainen
677e22747b82bf15b339e31d1d0106d62bf806daTimo Sirainen if (*fname != MAILDIR_INFO_SEP &&
677e22747b82bf15b339e31d1d0106d62bf806daTimo Sirainen *fname != MAILDIR_EXTRA_SEP &&
677e22747b82bf15b339e31d1d0106d62bf806daTimo Sirainen *fname != '\0')
677e22747b82bf15b339e31d1d0106d62bf806daTimo Sirainen return FALSE;
677e22747b82bf15b339e31d1d0106d62bf806daTimo Sirainen
677e22747b82bf15b339e31d1d0106d62bf806daTimo Sirainen *size_r = size;
677e22747b82bf15b339e31d1d0106d62bf806daTimo Sirainen return TRUE;
677e22747b82bf15b339e31d1d0106d62bf806daTimo Sirainen}
677e22747b82bf15b339e31d1d0106d62bf806daTimo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen/* a char* hash function from ASU -- from glib */
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenunsigned int maildir_hash(const void *p)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen{
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen const unsigned char *s = p;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen unsigned int g, h = 0;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
8754bb7a1f24705ffa5434f9e10d57e0b3b88d6eTimo Sirainen while (*s != MAILDIR_INFO_SEP && *s != '\0') {
b142deb9a831c89b1bb9129ada655f3e56b9d4ccTimo Sirainen i_assert(*s != '/');
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen h = (h << 4) + *s;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if ((g = h & 0xf0000000UL)) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen h = h ^ (g >> 24);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen h = h ^ g;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen s++;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return h;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen}
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenint maildir_cmp(const void *p1, const void *p2)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen{
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen const char *s1 = p1, *s2 = p2;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
8754bb7a1f24705ffa5434f9e10d57e0b3b88d6eTimo Sirainen while (*s1 == *s2 && *s1 != MAILDIR_INFO_SEP && *s1 != '\0') {
b142deb9a831c89b1bb9129ada655f3e56b9d4ccTimo Sirainen i_assert(*s1 != '/');
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen s1++; s2++;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
8754bb7a1f24705ffa5434f9e10d57e0b3b88d6eTimo Sirainen if ((*s1 == '\0' || *s1 == MAILDIR_INFO_SEP) &&
8754bb7a1f24705ffa5434f9e10d57e0b3b88d6eTimo Sirainen (*s2 == '\0' || *s2 == MAILDIR_INFO_SEP))
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return 0;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return *s1 - *s2;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen}