[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