[dovecot-cvs] dovecot/src/lib-storage/index/maildir maildir-copy.c,1.22,1.23 maildir-expunge.c,1.10,1.11

cras at procontrol.fi cras at procontrol.fi
Sun May 18 16:26:08 EEST 2003


Update of /home/cvs/dovecot/src/lib-storage/index/maildir
In directory danu:/tmp/cvs-serv23020/lib-storage/index/maildir

Modified Files:
	maildir-copy.c maildir-expunge.c 
Log Message:
Maildir syncing updates: it's now faster, it handles read-only folders, it
handles many out of disk space conditions (uidlist doesn't) and all commands
finally handle the condition when maildir filename was renamed after
our syncing but before we had the chance to open it.



Index: maildir-copy.c
===================================================================
RCS file: /home/cvs/dovecot/src/lib-storage/index/maildir/maildir-copy.c,v
retrieving revision 1.22
retrieving revision 1.23
diff -u -d -r1.22 -r1.23
--- maildir-copy.c	5 Apr 2003 21:15:01 -0000	1.22
+++ maildir-copy.c	18 May 2003 12:26:06 -0000	1.23
@@ -16,6 +16,54 @@
 	const char *fname;
 };
 
+static int maildir_hardlink_file(struct mail_index *index,
+				 struct mail_index_record *rec,
+				 const char **fname, const char *new_path)
+{
+	const char *path;
+
+	*fname = maildir_get_location(index, rec);
+	if (*fname == NULL)
+		return -1;
+
+	if ((rec->index_flags & INDEX_MAIL_FLAG_MAILDIR_NEW) != 0) {
+		/* probably in new/ dir */
+		path = t_strconcat(index->mailbox_path, "/new/", *fname, NULL);
+		if (link(path, new_path) == 0)
+			return 1;
+
+		if (ENOSPACE(errno)) {
+			index->nodiskspace = TRUE;
+			return -1;
+		}
+		if (errno == EACCES || errno == EXDEV)
+			return -1;
+		if (errno != ENOENT) {
+			index_set_error(index, "link(%s, %s) failed: %m",
+					path, new_path);
+			return -1;
+		}
+	}
+
+	path = t_strconcat(index->mailbox_path, "/cur/", *fname, NULL);
+	if (link(path, new_path) == 0)
+		return 1;
+
+	if (ENOSPACE(errno)) {
+		index->nodiskspace = TRUE;
+		return -1;
+	}
+	if (errno == EACCES || errno == EXDEV)
+		return -1;
+	if (errno != ENOENT) {
+		index_set_error(index, "link(%s, %s) failed: %m",
+				path, new_path);
+		return -1;
+	}
+
+	return 0;
+}
+
 static int hardlink_messageset(struct messageset_context *ctx,
 			       struct index_mailbox *src,
 			       struct index_mailbox *dest)
@@ -27,7 +75,7 @@
 	enum mail_flags flags;
 	const char **custom_flags;
 	const char *fname, *src_path, *dest_fname, *dest_path;
-	int ret;
+	int ret, i, found;
 
 	pool = pool_alloconly_create("hard copy rollbacks", 2048);
 	rollbacks = NULL;
@@ -35,7 +83,7 @@
 	custom_flags = mail_custom_flags_list_get(index->custom_flags);
 
 	ret = 1;
-	while ((mail = index_messageset_next(ctx)) != NULL) {
+	while (ret > 0 && (mail = index_messageset_next(ctx)) != NULL) {
 		flags = mail->rec->msg_flags;
 		if (!index_mailbox_fix_custom_flags(dest, &flags,
 						    custom_flags,
@@ -45,16 +93,6 @@
 		}
 
 		/* link the file */
-		fname = index->lookup_field(index, mail->rec,
-					    DATA_FIELD_LOCATION);
-		if (fname == NULL) {
-			index_set_corrupted(index,
-				"Missing location field for record %u",
-				mail->rec->uid);
-			ret = -1;
-			break;
-		}
-
 		t_push();
 		src_path = t_strconcat(index->mailbox_path, "/cur/",
 				       fname, NULL);
@@ -64,23 +102,31 @@
 		dest_path = t_strconcat(dest->index->mailbox_path, "/new/",
 					dest_fname, NULL);
 
-		if (link(src_path, dest_path) == 0) {
-			rb = p_new(pool, struct rollback, 1);
-			rb->fname = p_strdup(pool, dest_fname);
-			rb->next = rollbacks;
-			rollbacks = rb;
-		} else {
-			if (errno != EXDEV) {
-				mail_storage_set_critical(src->box.storage,
-					"link(%s, %s) failed: %m",
-					src_path, dest_path);
-				t_pop();
-				ret = -1;
+		for (i = 0;; i++) {
+			ret = maildir_hardlink_file(index, mail->rec, &fname,
+						    dest_path);
+			if (ret > 0) {
+				rb = p_new(pool, struct rollback, 1);
+				rb->fname = p_strdup(pool, dest_fname);
+				rb->next = rollbacks;
+				rollbacks = rb;
 				break;
 			}
-			t_pop();
-			ret = 0;
-			break;
+			if (ret < 0)
+				break;
+
+			if (i == 10) {
+                                mail_storage_set_error(src->box.storage,
+					"File name keeps changing, "
+					"copy failed");
+				break;
+			}
+
+			if (!maildir_index_sync_readonly(index, fname, &found))
+				break;
+
+			if (!found)
+				break;
 		}
 		t_pop();
 	}
@@ -103,17 +149,20 @@
 			       const char *messageset, int uidset)
 {
         struct messageset_context *ctx;
-	int ret, ret2;
+	int exdev, ret, ret2;
 
 	if (!index_storage_sync_and_lock(src, TRUE, MAIL_LOCK_SHARED))
 		return -1;
 
 	ctx = index_messageset_init(src, messageset, uidset, FALSE);
 	ret = hardlink_messageset(ctx, src, dest);
+	exdev = ret < 0 && errno == EXDEV;
 	ret2 = index_messageset_deinit(ctx);
+
 	if (ret2 < 0)
 		ret = -1;
-	else if (ret2 == 0) {
+
+	if (ret == 0 || ret2 == 0) {
 		mail_storage_set_error(src->box.storage,
 			"Some of the requested messages no longer exist.");
 		ret = -1;
@@ -121,7 +170,7 @@
 
 	(void)index_storage_lock(src, MAIL_LOCK_UNLOCK);
 
-	return ret;
+	return exdev ? 0 : ret;
 }
 
 int maildir_storage_copy(struct mailbox *box, struct mailbox *destbox,

Index: maildir-expunge.c
===================================================================
RCS file: /home/cvs/dovecot/src/lib-storage/index/maildir/maildir-expunge.c,v
retrieving revision 1.10
retrieving revision 1.11
diff -u -d -r1.10 -r1.11
--- maildir-expunge.c	5 Jan 2003 13:09:52 -0000	1.10
+++ maildir-expunge.c	18 May 2003 12:26:06 -0000	1.11
@@ -1,60 +1,44 @@
 /* Copyright (C) 2002 Timo Sirainen */
 
 #include "lib.h"
+#include "maildir-index.h"
 #include "maildir-storage.h"
 
-#include <unistd.h>
-
-static int expunge_msg(struct index_mailbox *ibox,
-		       struct mail_index_record *rec)
-{
-	const char *fname;
-	char path[PATH_MAX];
-
-	fname = ibox->index->lookup_field(ibox->index, rec,
-					  DATA_FIELD_LOCATION);
-	if (fname != NULL) {
-		if (str_ppath(path, sizeof(path),
-			      ibox->index->mailbox_path, "cur/", fname) < 0) {
-			mail_storage_set_critical(ibox->box.storage,
-						  "Filename too long: %s",
-						  fname);
-			return FALSE;
-		}
-
-		if (unlink(path) < 0) {
-			/* if it didn't exist, someone just had either
-			   deleted it or changed it's flags */
-			mail_storage_set_error(ibox->box.storage,
-					       "unlink() failed for "
-					       "message file %s: %m", path);
-			return FALSE;
-		}
-	}
-
-	return TRUE;
-}
-
 int maildir_expunge_locked(struct index_mailbox *ibox, int notify)
 {
 	struct mail_index_record *rec;
 	unsigned int seq;
+	int ret, no_permission = FALSE;
 
 	if (!index_expunge_seek_first(ibox, &seq, &rec))
 		return FALSE;
 
 	while (rec != NULL) {
 		if (rec->msg_flags & MAIL_DELETED) {
-			if (!expunge_msg(ibox, rec))
-				return FALSE;
+			t_push();
+			ret = maildir_expunge_mail(ibox->index, rec);
+			t_pop();
 
-			if (!index_expunge_mail(ibox, rec, seq, notify))
-				return FALSE;
+			if (!ret) {
+				if (errno != EACCES)
+					return FALSE;
+				no_permission = TRUE;
+				seq++;
+			} else {
+				if (!index_expunge_mail(ibox, rec, seq, notify))
+					return FALSE;
+			}
 		} else {
 			seq++;
 		}
 
 		rec = ibox->index->next(ibox->index, rec);
+	}
+
+	if (no_permission) {
+		ibox->box.storage->callbacks->notify_no(&ibox->box,
+			"We didn't have permission to expunge all the mails",
+			ibox->box.storage->callback_context);
 	}
 
 	return TRUE;



More information about the dovecot-cvs mailing list