Fix for mbox (Renaming mailbox under newly created dir didn't move

index directory). From upstream via Brad.
This commit is contained in:
sthen 2010-07-05 21:54:28 +00:00
parent b114a07f75
commit 0e50d5fc42
2 changed files with 89 additions and 2 deletions

View File

@ -1,4 +1,4 @@
# $OpenBSD: Makefile,v 1.140 2010/06/27 09:46:18 sthen Exp $
# $OpenBSD: Makefile,v 1.141 2010/07/05 21:54:28 sthen Exp $
SHARED_ONLY= Yes
@ -11,7 +11,7 @@ V_SIEVE= 0.1.17
V_MANAGESIEVE= 0.11.11
PKGNAME= dovecot-${V_DOVECOT}
PKGNAME-server= dovecot-${V_DOVECOT}p0
PKGNAME-server= dovecot-${V_DOVECOT}p1
FULLPKGNAME-sieve= dovecot-sieve-${V_SIEVE}v0
FULLPKGPATH-sieve= ${PKGPATH},-sieve

View File

@ -0,0 +1,87 @@
$OpenBSD: patch-src_lib-storage_list_mailbox-list-fs_c,v 1.1 2010/07/05 21:54:28 sthen Exp $
--- src/lib-storage/list/mailbox-list-fs.c.orig Sat Feb 6 18:55:17 2010
+++ src/lib-storage/list/mailbox-list-fs.c Mon Jul 5 16:06:11 2010
@@ -279,6 +279,31 @@ static int fs_list_delete_mailbox(struct mailbox_list
return mailbox_list_delete_index_control(list, name);
}
+static int
+mailbox_list_mkdir_parent(struct mailbox_list *list, const char *path)
+{
+ const char *p, *parent, *origin;
+ mode_t mode;
+ gid_t gid;
+
+ p = strrchr(path, '/');
+ if (p == NULL)
+ return 0;
+
+ mailbox_list_get_dir_permissions(list, NULL, &mode, &gid, &origin);
+ parent = t_strdup_until(path, p);
+ if (mkdir_parents_chgrp(parent, mode, gid, origin) < 0 &&
+ errno != EEXIST) {
+ if (mailbox_list_set_error_from_errno(list))
+ return -1;
+
+ mailbox_list_set_critical(list, "mkdir_parents(%s) failed: %m",
+ parent);
+ return -1;
+ }
+ return 0;
+}
+
static int rename_dir(struct mailbox_list *list,
enum mailbox_list_path_type type,
const char *oldname, const char *newname)
@@ -291,7 +316,14 @@ static int rename_dir(struct mailbox_list *list,
if (strcmp(oldpath, newpath) == 0)
return 0;
- if (rename(oldpath, newpath) < 0 && errno != ENOENT) {
+ if (rename(oldpath, newpath) < 0) {
+ if (errno == ENOENT) {
+ /* maybe the parent directory doesn't exist. */
+ if (mailbox_list_mkdir_parent(list, newpath) < 0)
+ return -1;
+ if (rename(oldpath, newpath) == 0 || errno == ENOENT)
+ return 0;
+ }
mailbox_list_set_critical(list, "rename(%s, %s) failed: %m",
oldpath, newpath);
return -1;
@@ -302,10 +334,8 @@ static int rename_dir(struct mailbox_list *list,
static int fs_list_rename_mailbox(struct mailbox_list *list,
const char *oldname, const char *newname)
{
- const char *oldpath, *newpath, *p, *origin;
+ const char *oldpath, *newpath;
struct stat st;
- mode_t mode;
- gid_t gid;
oldpath = mailbox_list_get_path(list, oldname,
MAILBOX_LIST_PATH_TYPE_DIR);
@@ -313,21 +343,8 @@ static int fs_list_rename_mailbox(struct mailbox_list
MAILBOX_LIST_PATH_TYPE_DIR);
/* create the hierarchy */
- p = strrchr(newpath, '/');
- if (p != NULL) {
- mailbox_list_get_dir_permissions(list, NULL, &mode,
- &gid, &origin);
- p = t_strdup_until(newpath, p);
- if (mkdir_parents_chgrp(p, mode, gid, origin) < 0 &&
- errno != EEXIST) {
- if (mailbox_list_set_error_from_errno(list))
- return -1;
-
- mailbox_list_set_critical(list,
- "mkdir_parents(%s) failed: %m", p);
- return -1;
- }
- }
+ if (mailbox_list_mkdir_parent(list, newpath) < 0)
+ return -1;
/* first check that the destination mailbox doesn't exist.
this is racy, but we need to be atomic and there's hardly any