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