dovecot-2.0: Added mailbox_list_get_guid() to get/create directo...

dovecot at dovecot.org dovecot at dovecot.org
Thu Aug 6 03:30:51 EEST 2009


details:   http://hg.dovecot.org/dovecot-2.0/rev/73daab8251eb
changeset: 9730:73daab8251eb
user:      Timo Sirainen <tss at iki.fi>
date:      Wed Aug 05 20:23:46 2009 -0400
description:
Added mailbox_list_get_guid() to get/create directory GUID.
Directory GUIDs are mainly useful for dsync to identify \Noselect mailboxes.

diffstat:

8 files changed, 119 insertions(+)
src/lib-storage/index/cydir/cydir-storage.c     |    2 
src/lib-storage/index/cydir/cydir-storage.h     |    1 
src/lib-storage/index/dbox/dbox-storage.c       |    2 
src/lib-storage/index/dbox/dbox-storage.h       |    1 
src/lib-storage/index/maildir/maildir-storage.c |    2 
src/lib-storage/index/maildir/maildir-storage.h |    1 
src/lib-storage/mailbox-list.c                  |  105 +++++++++++++++++++++++
src/lib-storage/mailbox-list.h                  |    5 +

diffs (220 lines):

diff -r 7315aa70dfcf -r 73daab8251eb src/lib-storage/index/cydir/cydir-storage.c
--- a/src/lib-storage/index/cydir/cydir-storage.c	Wed Aug 05 20:17:13 2009 -0400
+++ b/src/lib-storage/index/cydir/cydir-storage.c	Wed Aug 05 20:23:46 2009 -0400
@@ -46,6 +46,8 @@ cydir_storage_get_list_settings(const st
 		set->layout = MAILBOX_LIST_NAME_FS;
 	if (set->subscription_fname == NULL)
 		set->subscription_fname = CYDIR_SUBSCRIPTION_FILE_NAME;
+	if (set->dir_guid_fname == NULL)
+		set->dir_guid_fname = CYDIR_DIR_GUID_FILE_NAME;
 }
 
 static int create_cydir(struct mail_storage *storage, struct mailbox_list *list,
diff -r 7315aa70dfcf -r 73daab8251eb src/lib-storage/index/cydir/cydir-storage.h
--- a/src/lib-storage/index/cydir/cydir-storage.h	Wed Aug 05 20:17:13 2009 -0400
+++ b/src/lib-storage/index/cydir/cydir-storage.h	Wed Aug 05 20:23:46 2009 -0400
@@ -7,6 +7,7 @@
 #define CYDIR_STORAGE_NAME "cydir"
 #define CYDIR_SUBSCRIPTION_FILE_NAME "subscriptions."
 #define CYDIR_INDEX_PREFIX "dovecot.index"
+#define CYDIR_DIR_GUID_FILE_NAME "dovecot.dir.guid."
 
 struct cydir_storage {
 	struct mail_storage storage;
diff -r 7315aa70dfcf -r 73daab8251eb src/lib-storage/index/dbox/dbox-storage.c
--- a/src/lib-storage/index/dbox/dbox-storage.c	Wed Aug 05 20:17:13 2009 -0400
+++ b/src/lib-storage/index/dbox/dbox-storage.c	Wed Aug 05 20:23:46 2009 -0400
@@ -109,6 +109,8 @@ dbox_storage_get_list_settings(const str
 		set->layout = MAILBOX_LIST_NAME_FS;
 	if (set->subscription_fname == NULL)
 		set->subscription_fname = DBOX_SUBSCRIPTION_FILE_NAME;
+	if (set->dir_guid_fname == NULL)
+		set->dir_guid_fname = DBOX_DIR_GUID_FILE_NAME;
 	if (set->maildir_name == NULL)
 		set->maildir_name = DBOX_MAILDIR_NAME;
 	if (set->mailbox_dir_name == NULL)
diff -r 7315aa70dfcf -r 73daab8251eb src/lib-storage/index/dbox/dbox-storage.h
--- a/src/lib-storage/index/dbox/dbox-storage.h	Wed Aug 05 20:17:13 2009 -0400
+++ b/src/lib-storage/index/dbox/dbox-storage.h	Wed Aug 05 20:23:46 2009 -0400
@@ -9,6 +9,7 @@
 #define DBOX_SUBSCRIPTION_FILE_NAME "subscriptions"
 #define DBOX_UIDVALIDITY_FILE_NAME "dovecot-uidvalidity"
 #define DBOX_INDEX_PREFIX "dovecot.index"
+#define DBOX_DIR_GUID_FILE_NAME "dbox-GUID"
 
 #define DBOX_MAILBOX_DIR_NAME "mailboxes"
 #define DBOX_TRASH_DIR_NAME "trash"
diff -r 7315aa70dfcf -r 73daab8251eb src/lib-storage/index/maildir/maildir-storage.c
--- a/src/lib-storage/index/maildir/maildir-storage.c	Wed Aug 05 20:17:13 2009 -0400
+++ b/src/lib-storage/index/maildir/maildir-storage.c	Wed Aug 05 20:23:46 2009 -0400
@@ -140,6 +140,8 @@ static void maildir_storage_get_list_set
 		set->layout = MAILBOX_LIST_NAME_MAILDIRPLUSPLUS;
 	if (set->subscription_fname == NULL)
 		set->subscription_fname = MAILDIR_SUBSCRIPTION_FILE_NAME;
+	if (set->dir_guid_fname == NULL)
+		set->dir_guid_fname = MAILDIR_DIR_GUID_FILE_NAME;
 
 	if (set->inbox_path == NULL &&
 	    (strcmp(set->layout, MAILBOX_LIST_NAME_MAILDIRPLUSPLUS) == 0 ||
diff -r 7315aa70dfcf -r 73daab8251eb src/lib-storage/index/maildir/maildir-storage.h
--- a/src/lib-storage/index/maildir/maildir-storage.h	Wed Aug 05 20:17:13 2009 -0400
+++ b/src/lib-storage/index/maildir/maildir-storage.h	Wed Aug 05 20:23:46 2009 -0400
@@ -8,6 +8,7 @@
 #define MAILDIR_INDEX_PREFIX "dovecot.index"
 #define MAILDIR_UNLINK_DIRNAME "DOVECOT-TRASHED"
 #define MAILDIR_UIDVALIDITY_FNAME "dovecot-uidvalidity"
+#define MAILDIR_DIR_GUID_FILE_NAME "dovecot-dir-guid"
 
 /* "base,S=123:2," means:
    <base> [<extra sep> <extra data> [..]] <info sep> 2 <flags sep> */
diff -r 7315aa70dfcf -r 73daab8251eb src/lib-storage/mailbox-list.c
--- a/src/lib-storage/mailbox-list.c	Wed Aug 05 20:17:13 2009 -0400
+++ b/src/lib-storage/mailbox-list.c	Wed Aug 05 20:23:46 2009 -0400
@@ -131,6 +131,8 @@ int mailbox_list_create(const char *driv
 	list->set.inbox_path = p_strdup(list->pool, set->inbox_path);
 	list->set.subscription_fname =
 		p_strdup(list->pool, set->subscription_fname);
+	list->set.dir_guid_fname =
+		p_strdup(list->pool, set->dir_guid_fname);
 	list->set.maildir_name = set->maildir_name == NULL ||
 		(list->props & MAILBOX_LIST_PROP_NO_MAILDIR_NAME) != 0 ? "" :
 		p_strdup(list->pool, set->maildir_name);
@@ -729,6 +731,109 @@ int mailbox_list_rename_mailbox(struct m
 
 	return oldlist->v.rename_mailbox(oldlist, oldname, newlist, newname,
 					 rename_children);
+}
+
+static int mailbox_list_read_guid(struct mailbox_list *list, const char *path,
+				  uint8_t mailbox_guid[MAIL_GUID_128_SIZE])
+{
+	int fd, ret;
+
+	fd = open(path, O_RDONLY);
+	if (fd != -1) {
+		ret = read_full(fd, mailbox_guid, MAIL_GUID_128_SIZE);
+		close_keep_errno(fd);
+		if (ret > 0)
+			return 1;
+		if (ret < 0) {
+			mailbox_list_set_critical(list, "read(%s) failed: %m",
+						  path);
+			return -1;
+		}
+		/* recreate it */
+		mailbox_list_set_critical(list, "Corrupted mailbox GUID in %s",
+					  path);
+		(void)unlink(path);
+		return 0;
+	} else if (errno == ENOENT) {
+		return 0;
+	} else if (errno == EACCES) {
+		mailbox_list_set_critical(list, "%s",
+					  eacces_error_get("open", path));
+		return -1;
+	} else {
+		mailbox_list_set_critical(list, "open(%s) failed: %m", path);
+		return -1;
+	}
+}
+
+static int
+mailbox_list_get_guid_real(struct mailbox_list *list, const char *name,
+			   uint8_t mailbox_guid[MAIL_GUID_128_SIZE])
+{
+	string_t *temp_path;
+	const char *dir, *path;
+	int fd, ret;
+
+	memset(mailbox_guid, 0, MAIL_GUID_128_SIZE);
+	if (list->set.dir_guid_fname == NULL) {
+		mailbox_list_set_error(list, MAIL_ERROR_NOTPOSSIBLE,
+			"Storage doesn't support mailbox GUIDs");
+		return -1;
+	}
+
+	dir = mailbox_list_get_path(list, name, MAILBOX_LIST_PATH_TYPE_DIR);
+	path = t_strconcat(dir, "/", list->set.dir_guid_fname, NULL);
+
+	/* try reading the GUID from the file */
+	if ((ret = mailbox_list_read_guid(list, path, mailbox_guid)) < 0)
+		return -1;
+
+	/* create temp file containing a new GUID. the file must never be
+	   modified and it doesn't contain anything sensitive, so just make
+	   it world-readable. */
+	temp_path = t_str_new(256);
+	str_append(temp_path, path);
+	fd = safe_mkstemp_hostpid_group(temp_path, 0644, (gid_t)-1, NULL);
+	if (fd == -1) {
+		mailbox_list_set_critical(list,
+			"safe_mkstemp(%s) failed: %m", str_c(temp_path));
+		return -1;
+	}
+
+	mail_generate_guid_128(mailbox_guid);
+	ret = write_full(fd, mailbox_guid, MAIL_GUID_128_SIZE);
+	close_keep_errno(fd);
+	if (ret < 0) {
+		mailbox_list_set_critical(list,
+			"write(%s) failed: %m", str_c(temp_path));
+	} else if (link(str_c(temp_path), path) == 0) {
+		/* success */
+	} else if (errno == EEXIST) {
+		/* someone else just created the GUID, read it. */
+		ret = mailbox_list_read_guid(list, path, mailbox_guid);
+		if (ret == 0) {
+			/* broken? shouldn't really happen. we anyway deleted
+			   it already, so try again. */
+			return mailbox_list_get_guid(list, name, mailbox_guid);
+		}
+	} else {
+		mailbox_list_set_critical(list, "link(%s, %s) failed: %m",
+					  str_c(temp_path), path);
+		ret = -1;
+	}
+	(void)unlink(str_c(temp_path));
+	return ret < 0 ? -1 : 0;
+}
+
+int mailbox_list_get_guid(struct mailbox_list *list, const char *name,
+			  uint8_t mailbox_guid[MAIL_GUID_128_SIZE])
+{
+	int ret;
+
+	T_BEGIN {
+		ret = mailbox_list_get_guid_real(list, name, mailbox_guid);
+	} T_END;
+	return ret;
 }
 
 static int mailbox_list_try_delete(struct mailbox_list *list, const char *dir)
diff -r 7315aa70dfcf -r 73daab8251eb src/lib-storage/mailbox-list.h
--- a/src/lib-storage/mailbox-list.h	Wed Aug 05 20:17:13 2009 -0400
+++ b/src/lib-storage/mailbox-list.h	Wed Aug 05 20:23:46 2009 -0400
@@ -1,6 +1,7 @@
 #ifndef MAILBOX_LIST_H
 #define MAILBOX_LIST_H
 
+#include "mail-types.h"
 #include "mail-error.h"
 
 struct mail_namespace;
@@ -94,6 +95,7 @@ struct mailbox_list_settings {
 
 	const char *inbox_path;
 	const char *subscription_fname;
+	const char *dir_guid_fname;
 	/* If non-empty, it means that mails exist in a maildir_name
 	   subdirectory. eg. if you have a directory containing directories:
 
@@ -181,6 +183,9 @@ int mailbox_list_get_mailbox_name_status
 int mailbox_list_get_mailbox_name_status(struct mailbox_list *list,
 					 const char *name,
 					 enum mailbox_name_status *status);
+/* Get 128bit mailbox directory GUID, creating it if necessary. */
+int mailbox_list_get_guid(struct mailbox_list *list, const char *name,
+			  uint8_t mailbox_guid[MAIL_GUID_128_SIZE]);
 
 /* Returns a prefix that temporary files should use without conflicting
    with the namespace. */


More information about the dovecot-cvs mailing list