[dovecot-cvs] dovecot/src/lib-storage/index/maildir maildir-storage.c, 1.115.2.19, 1.115.2.20 maildir-storage.h, 1.49.2.4, 1.49.2.5 maildir-util.c, 1.14.2.2, 1.14.2.3
tss at dovecot.org
tss at dovecot.org
Tue Jan 16 16:59:04 UTC 2007
Update of /var/lib/cvs/dovecot/src/lib-storage/index/maildir
In directory talvi:/tmp/cvs-serv25452/src/lib-storage/index/maildir
Modified Files:
Tag: branch_1_0
maildir-storage.c maildir-storage.h maildir-util.c
Log Message:
When opening maildir, check if tmp/'s atime is over 8h old. If it is, delete
old files in it. However if atime - ctime > 36h, it means there's nothing to
be deleted so the scanning isn't done then. We update atime if filesystem is
mounted with noatime.
Index: maildir-storage.c
===================================================================
RCS file: /var/lib/cvs/dovecot/src/lib-storage/index/maildir/maildir-storage.c,v
retrieving revision 1.115.2.19
retrieving revision 1.115.2.20
diff -u -d -r1.115.2.19 -r1.115.2.20
--- maildir-storage.c 14 Jan 2007 01:47:17 -0000 1.115.2.19
+++ maildir-storage.c 16 Jan 2007 16:59:02 -0000 1.115.2.20
@@ -1,6 +1,7 @@
/* Copyright (C) 2002-2006 Timo Sirainen */
#include "lib.h"
+#include "ioloop.h"
#include "array.h"
#include "hostpid.h"
#include "home-expand.h"
@@ -34,8 +35,6 @@
extern struct mail_storage maildir_storage;
extern struct mailbox maildir_mailbox;
-static const char *maildirs[] = { "cur", "new", "tmp", NULL };
-
static int verify_inbox(struct maildir_storage *storage);
static void maildir_subscriptions_convert_099(struct maildir_storage *storage)
@@ -351,52 +350,58 @@
struct stat st;
if (verify) {
- if (lstat(dir, &st) == 0)
+ if (stat(dir, &st) == 0)
return 0;
if (errno != ENOENT) {
mail_storage_set_critical(&storage->storage,
- "lstat(%s) failed: %m", dir);
+ "stat(%s) failed: %m", dir);
return -1;
}
}
- if (mkdir_parents(dir, CREATE_MODE) < 0 &&
- (errno != EEXIST || !verify)) {
- if (errno != EEXIST && (!verify || errno != ENOENT)) {
+ if (mkdir_parents(dir, CREATE_MODE) < 0) {
+ if (errno == EEXIST) {
+ if (!verify)
+ return -1;
+ } else {
mail_storage_set_critical(&storage->storage,
"mkdir(%s) failed: %m", dir);
+ return -1;
}
- return -1;
}
-
return 0;
}
-/* create or fix maildir, ignore if it already exists */
static int create_maildir(struct index_storage *storage,
const char *dir, bool verify)
{
- const char **tmp, *path;
+ const char *path;
+ struct stat st;
- if (!verify && mkdir_verify(storage, dir, verify) < 0)
+ if (mkdir_verify(storage, t_strconcat(dir, "/cur", NULL), verify) < 0)
+ return -1;
+ if (mkdir_verify(storage, t_strconcat(dir, "/new", NULL), verify) < 0)
return -1;
- for (tmp = maildirs; *tmp != NULL; tmp++) {
- path = t_strconcat(dir, "/", *tmp, NULL);
-
- if (mkdir_verify(storage, path, verify) < 0) {
- if (!verify || errno != ENOENT)
- return -1;
-
- /* small optimization. if we're verifying, we don't
- check that the root dir actually exists unless we
- fail here. */
- if (mkdir_verify(storage, dir, verify) < 0)
- return -1;
- if (mkdir_verify(storage, path, verify) < 0)
- return -1;
+ /* if tmp/ directory exists, we need to clean it up once in a while */
+ path = t_strconcat(dir, "/tmp", NULL);
+ if (stat(path, &st) == 0) {
+ if (st.st_atime >
+ st.st_ctime + MAILDIR_TMP_DELETE_SECS) {
+ /* the directory should be empty. we won't do anything
+ until ctime changes. */
+ } else if (st.st_atime < ioloop_time - MAILDIR_TMP_SCAN_SECS) {
+ /* time to scan */
+ (void)maildir_tmp_cleanup(&storage->storage, path);
}
+ } else if (errno == ENOENT) {
+ if (mkdir_verify(storage, path, verify) < 0)
+ return -1;
+ } else {
+ mail_storage_set_critical(&storage->storage,
+ "stat(%s) failed: %m", path);
+ return -1;
}
return 0;
Index: maildir-storage.h
===================================================================
RCS file: /var/lib/cvs/dovecot/src/lib-storage/index/maildir/maildir-storage.h,v
retrieving revision 1.49.2.4
retrieving revision 1.49.2.5
diff -u -d -r1.49.2.4 -r1.49.2.5
--- maildir-storage.h 22 Dec 2006 14:20:31 -0000 1.49.2.4
+++ maildir-storage.h 16 Jan 2007 16:59:02 -0000 1.49.2.5
@@ -32,6 +32,11 @@
calculating file's virtual size (added missing CRs). */
#define MAILDIR_EXTRA_VIRTUAL_SIZE 'W'
+/* How often to scan tmp/ directory for old files (based on dir's atime) */
+#define MAILDIR_TMP_SCAN_SECS (8*60*60)
+/* Delete files having ctime older than this from tmp/. 36h is standard. */
+#define MAILDIR_TMP_DELETE_SECS (36*60*60)
+
#define MAILDIR_SAVE_FLAG_HARDLINK 0x10000000
#define MAILDIR_SAVE_FLAG_DELETED 0x20000000
@@ -91,6 +96,7 @@
const char *maildir_generate_tmp_filename(const struct timeval *tv);
int maildir_create_tmp(struct maildir_mailbox *mbox, const char *dir,
mode_t mode, const char **fname_r);
+void maildir_tmp_cleanup(struct mail_storage *storage, const char *dir);
bool maildir_filename_get_size(const char *fname, char type, uoff_t *size_r);
struct mailbox_list_context *
Index: maildir-util.c
===================================================================
RCS file: /var/lib/cvs/dovecot/src/lib-storage/index/maildir/maildir-util.c,v
retrieving revision 1.14.2.2
retrieving revision 1.14.2.3
diff -u -d -r1.14.2.2 -r1.14.2.3
--- maildir-util.c 27 Jun 2006 22:51:45 -0000 1.14.2.2
+++ maildir-util.c 16 Jan 2007 16:59:02 -0000 1.14.2.3
@@ -9,7 +9,9 @@
#include "maildir-keywords.h"
#include <unistd.h>
+#include <dirent.h>
#include <fcntl.h>
+#include <utime.h>
#include <sys/stat.h>
static int maildir_file_do_try(struct maildir_mailbox *mbox, uint32_t uid,
@@ -134,6 +136,83 @@
return fd;
}
+void maildir_tmp_cleanup(struct mail_storage *storage, const char *dir)
+{
+ DIR *dirp;
+ struct dirent *d;
+ struct stat st;
+ string_t *path;
+ unsigned int dir_len;
+
+ dirp = opendir(dir);
+ if (dirp == NULL) {
+ if (errno != ENOENT) {
+ mail_storage_set_critical(storage,
+ "opendir(%s) failed: %m", dir);
+ }
+ return;
+ }
+
+ t_push();
+ path = t_str_new(256);
+ str_printfa(path, "%s/", dir);
+ dir_len = str_len(path);
+
+ while ((d = readdir(dirp)) != NULL) {
+ if (d->d_name[0] == '.' &&
+ (d->d_name[1] == '\0' ||
+ (d->d_name[1] == '.' && d->d_name[2] == '\0'))) {
+ /* skip . and .. */
+ continue;
+ }
+
+ str_truncate(path, dir_len);
+ str_append(path, d->d_name);
+ if (stat(str_c(path), &st) < 0) {
+ if (errno != ENOENT) {
+ mail_storage_set_critical(storage,
+ "stat(%s) failed: %m", str_c(path));
+ }
+ } else if (st.st_ctime <=
+ ioloop_time - MAILDIR_TMP_DELETE_SECS) {
+ if (unlink(str_c(path)) < 0 && errno != ENOENT) {
+ mail_storage_set_critical(storage,
+ "unlink(%s) failed: %m", str_c(path));
+ }
+ }
+ }
+ t_pop();
+
+#ifdef HAVE_DIRFD
+ if (fstat(dirfd(dirp), &st) < 0) {
+ mail_storage_set_critical(storage,
+ "fstat(%s) failed: %m", dir);
+ }
+#else
+ if (stat(dir, &st) < 0) {
+ mail_storage_set_critical(storage,
+ "stat(%s) failed: %m", dir);
+ }
+#endif
+ else if (st.st_atime < ioloop_time) {
+ /* mounted with noatime. update it ourself. */
+ struct utimbuf ut;
+
+ ut.actime = ioloop_time;
+ ut.modtime = st.st_mtime;
+
+ if (utime(dir, &ut) < 0 && errno != ENOENT) {
+ mail_storage_set_critical(storage,
+ "utime(%s) failed: %m", dir);
+ }
+ }
+
+ if (closedir(dirp) < 0) {
+ mail_storage_set_critical(storage,
+ "closedir(%s) failed: %m", dir);
+ }
+}
+
bool maildir_filename_get_size(const char *fname, char type, uoff_t *size_r)
{
uoff_t size = 0;
More information about the dovecot-cvs
mailing list