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);
const char *name, bool set)
{
uint8_t guid[MAIL_GUID_128_SIZE];
- unsigned char sha[SHA1_RESULTLEN];
if (list->v.set_subscribed(list, name, set) < 0)
return -1;
to have a subscription to non-existing mailbox. renames also don't
change subscriptions. so instead of using actual GUIDs, we'll use
hash of the name. */
- sha1_get_digest(name, strlen(name), sha);
- memcpy(guid, sha, I_MIN(sizeof(guid), sizeof(sha)));
+ mailbox_name_get_sha128(name, guid);
mailbox_list_add_change(list, set ? MAILBOX_LOG_RECORD_SUBSCRIBE :
MAILBOX_LOG_RECORD_UNSUBSCRIBE, guid);
return 0;
return -1;
}
- (void)mailbox_list_get_guid(oldlist, oldname, guid);
if (oldlist->v.rename_mailbox(oldlist, oldname, newlist, newname,
rename_children) < 0)
return -1;
+
+ /* we'll track mailbox names, instead of GUIDs. We may be renaming a
+ non-selectable mailbox (directory), which doesn't even have a GUID */
+ mailbox_name_get_sha128(newname, guid);
mailbox_list_add_change(oldlist, MAILBOX_LOG_RECORD_RENAME, guid);
return 0;
}
-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;
- }
-}
-
-int mailbox_list_get_guid_path(struct mailbox_list *list, const char *path,
- uint8_t mailbox_guid[MAIL_GUID_128_SIZE])
+void mailbox_name_get_sha128(const char *name, uint8_t guid[MAIL_GUID_128_SIZE])
{
- string_t *temp_path;
- int fd, ret;
-
- /* 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_path(list, path,
- 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;
-}
-
-static int
-mailbox_list_get_guid_default(struct mailbox_list *list, const char *name,
- uint8_t mailbox_guid[MAIL_GUID_128_SIZE])
-{
- const char *dir, *path;
-
- 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);
-
- return mailbox_list_get_guid_path(list, path, mailbox_guid);
-}
-
-int mailbox_list_get_guid(struct mailbox_list *list, const char *name,
- uint8_t mailbox_guid[MAIL_GUID_128_SIZE])
-{
- int ret;
+ unsigned char sha[SHA1_RESULTLEN];
- T_BEGIN {
- ret = list->v.get_guid != NULL ?
- list->v.get_guid(list, name, mailbox_guid) :
- mailbox_list_get_guid_default(list, name, mailbox_guid);
- } T_END;
- return ret;
+ sha1_get_digest(name, strlen(name), sha);
+ memcpy(guid, sha, I_MIN(sizeof(guid), sizeof(sha)));
}
struct mailbox_log *mailbox_list_get_changelog(struct mailbox_list *list)