Mercurial > dovecot > core-2.2
changeset 9537:b373de4973cd HEAD
Whenever file's group changing fails, show the group origin in the error message.
line wrap: on
line diff
--- a/src/lda/main.c Sat Jun 27 19:55:44 2009 -0400 +++ b/src/lda/main.c Sat Jun 27 20:39:38 2009 -0400 @@ -90,6 +90,7 @@ static int deliver_create_dir(struct mail_user *user, const char *dir) { struct mail_namespace *ns; + const char *origin; mode_t mode; gid_t gid; @@ -97,8 +98,8 @@ if (ns == NULL) ns = user->namespaces; - mailbox_list_get_dir_permissions(ns->list, NULL, &mode, &gid); - if (mkdir_parents_chown(dir, mode, (uid_t)-1, gid) == 0) { + mailbox_list_get_dir_permissions(ns->list, NULL, &mode, &gid, &origin); + if (mkdir_parents_chgrp(dir, mode, gid, origin) == 0) { return 0; } else if (errno == EACCES) { i_error("%s", eacces_error_get_creating("mkdir_parents_chown",
--- a/src/lib-index/mail-index-private.h Sat Jun 27 19:55:44 2009 -0400 +++ b/src/lib-index/mail-index-private.h Sat Jun 27 20:39:38 2009 -0400 @@ -174,6 +174,7 @@ enum mail_index_sync_type fsync_mask; mode_t mode; gid_t gid; + char *gid_origin; pool_t extension_pool; ARRAY_DEFINE(extensions, struct mail_index_registered_ext);
--- a/src/lib-index/mail-index-strmap.c Sat Jun 27 19:55:44 2009 -0400 +++ b/src/lib-index/mail-index-strmap.c Sat Jun 27 20:39:38 2009 -0400 @@ -998,8 +998,9 @@ str = t_str_new(256); str_append(str, strmap->path); - fd = safe_mkstemp_hostpid(str, view->view->index->mode, - (uid_t)-1, view->view->index->gid); + fd = safe_mkstemp_hostpid_group(str, view->view->index->mode, + view->view->index->gid, + view->view->index->gid_origin); temp_path = str_c(str); if (fd == -1) {
--- a/src/lib-index/mail-index.c Sat Jun 27 19:55:44 2009 -0400 +++ b/src/lib-index/mail-index.c Sat Jun 27 20:39:38 2009 -0400 @@ -73,6 +73,7 @@ array_free(&index->keywords); array_free(&index->module_contexts); + i_free(index->gid_origin); i_free(index->error); i_free(index->dir); i_free(index->prefix); @@ -86,10 +87,13 @@ } void mail_index_set_permissions(struct mail_index *index, - mode_t mode, gid_t gid) + mode_t mode, gid_t gid, const char *gid_origin) { index->mode = mode & 0666; index->gid = gid; + + i_free(index->gid_origin); + index->gid_origin = i_strdup(gid_origin); } uint32_t mail_index_ext_register(struct mail_index *index, const char *name, @@ -662,7 +666,13 @@ really matter. ignore silently. */ return; } - mail_index_file_set_syscall_error(index, path, "fchown()"); + if (errno != EACCES) + mail_index_file_set_syscall_error(index, path, "fchown()"); + else { + mail_index_set_error(index, "%s", + eperm_error_get_chgrp("fchown", path, index->gid, + index->gid_origin)); + } /* continue, but change permissions so that only the common subset of group and world is used. this makes sure no one
--- a/src/lib-index/mail-index.h Sat Jun 27 19:55:44 2009 -0400 +++ b/src/lib-index/mail-index.h Sat Jun 27 20:39:38 2009 -0400 @@ -195,7 +195,7 @@ void mail_index_set_fsync_types(struct mail_index *index, enum mail_index_sync_type fsync_mask); void mail_index_set_permissions(struct mail_index *index, - mode_t mode, gid_t gid); + mode_t mode, gid_t gid, const char *gid_origin); /* Open index. Returns 1 if ok, 0 if index doesn't exist and CREATE flags wasn't given, -1 if error. */
--- a/src/lib-storage/index/cydir/cydir-storage.c Sat Jun 27 19:55:44 2009 -0400 +++ b/src/lib-storage/index/cydir/cydir-storage.c Sat Jun 27 20:39:38 2009 -0400 @@ -51,11 +51,12 @@ static int create_cydir(struct mail_storage *storage, struct mailbox_list *list, const char *path) { + const char *origin; mode_t mode; gid_t gid; - mailbox_list_get_dir_permissions(list, NULL, &mode, &gid); - if (mkdir_parents_chown(path, mode, (uid_t)-1, gid) < 0 && + mailbox_list_get_dir_permissions(list, NULL, &mode, &gid, &origin); + if (mkdir_parents_chgrp(path, mode, gid, origin) < 0 && errno != EEXIST) { if (!mail_storage_set_error_from_errno(storage)) { mail_storage_set_critical(storage,
--- a/src/lib-storage/index/dbox/dbox-file.c Sat Jun 27 19:55:44 2009 -0400 +++ b/src/lib-storage/index/dbox/dbox-file.c Sat Jun 27 20:39:38 2009 -0400 @@ -10,6 +10,7 @@ #include "file-lock.h" #include "mkdir-parents.h" #include "fdatasync-path.h" +#include "eacces-error.h" #include "str.h" #include "dbox-storage.h" #include "dbox-file.h" @@ -441,13 +442,20 @@ if (fd == -1) { mail_storage_set_critical(&storage->storage, "open(%s, O_CREAT) failed: %m", path); - } else if (storage->create_gid != (gid_t)-1) { - if (fchown(fd, (uid_t)-1, storage->create_gid) < 0) { + } else if (storage->create_gid == (gid_t)-1) { + /* no group change */ + } else if (fchown(fd, (uid_t)-1, storage->create_gid) < 0) { + if (errno == EPERM) { + mail_storage_set_critical(&storage->storage, "%s", + eperm_error_get_chgrp("fchown", path, + storage->create_gid, + storage->create_gid_origin)); + } else { mail_storage_set_critical(&storage->storage, "fchown(%s, -1, %ld) failed: %m", path, (long)storage->create_gid); - /* continue anyway */ } + /* continue anyway */ } return fd; }
--- a/src/lib-storage/index/dbox/dbox-map.c Sat Jun 27 19:55:44 2009 -0400 +++ b/src/lib-storage/index/dbox/dbox-map.c Sat Jun 27 20:39:38 2009 -0400 @@ -69,8 +69,9 @@ static int dbox_map_mkdir_storage(struct dbox_storage *storage) { - if (mkdir_parents_chown(storage->storage_dir, storage->create_mode, - (uid_t)-1, storage->create_gid) < 0 && + if (mkdir_parents_chgrp(storage->storage_dir, storage->create_mode, + storage->create_gid, + storage->create_gid_origin) < 0 && errno != EEXIST) { mail_storage_set_critical(&storage->storage, "mkdir(%s) failed: %m", storage->storage_dir);
--- a/src/lib-storage/index/dbox/dbox-storage.c Sat Jun 27 19:55:44 2009 -0400 +++ b/src/lib-storage/index/dbox/dbox-storage.c Sat Jun 27 20:39:38 2009 -0400 @@ -56,7 +56,7 @@ const char **error_r) { struct dbox_storage *storage = (struct dbox_storage *)_storage; - const char *dir; + const char *dir, *origin; storage->set = mail_storage_get_driver_settings(_storage); i_assert(storage->set->dbox_max_open_files >= 2); @@ -80,7 +80,8 @@ storage->map = dbox_map_init(storage); mailbox_list_get_dir_permissions(ns->list, NULL, &storage->create_mode, - &storage->create_gid); + &storage->create_gid, &origin); + storage->create_gid_origin = p_strdup(_storage->pool, origin); return 0; } @@ -282,12 +283,13 @@ const struct mailbox_update *update) { struct dbox_mailbox *mbox = (struct dbox_mailbox *)box; + const char *origin; mode_t mode; gid_t gid; int ret; - mailbox_list_get_dir_permissions(box->list, NULL, &mode, &gid); - if (mkdir_parents_chown(box->path, mode, (uid_t)-1, gid) == 0) { + mailbox_list_get_dir_permissions(box->list, NULL, &mode, &gid, &origin); + if (mkdir_parents_chgrp(box->path, mode, gid, origin) == 0) { /* create indexes immediately with the dbox header */ if (index_storage_mailbox_open(box) < 0) return -1; @@ -404,7 +406,7 @@ dbox_mailbox_create(struct mailbox *box, const struct mailbox_update *update, bool directory) { - const char *path, *alt_path; + const char *path, *alt_path, *origin; struct stat st; path = mailbox_list_get_path(box->list, box->name, @@ -420,8 +422,9 @@ mode_t mode; gid_t gid; - mailbox_list_get_dir_permissions(box->list, NULL, &mode, &gid); - if (mkdir_parents_chown(path, mode, (uid_t)-1, gid) == 0) + mailbox_list_get_dir_permissions(box->list, NULL, &mode, + &gid, &origin); + if (mkdir_parents_chgrp(path, mode, gid, origin) == 0) return 0; else if (errno == EEXIST) { mail_storage_set_error(box->storage, MAIL_ERROR_EXISTS, @@ -560,11 +563,13 @@ if (ret < 0 && errno == ENOENT) { /* either source mailbox doesn't exist or trash directory doesn't exist. try creating the trash and retrying. */ + const char *origin; mode_t mode; gid_t gid; - mailbox_list_get_dir_permissions(list, NULL, &mode, &gid); - if (mkdir_parents_chown(trash_dir, mode, (uid_t)-1, gid) < 0 && + mailbox_list_get_dir_permissions(list, NULL, &mode, + &gid, &origin); + if (mkdir_parents_chgrp(trash_dir, mode, gid, origin) < 0 && errno != EEXIST) { mailbox_list_set_critical(list, "mkdir(%s) failed: %m", trash_dir);
--- a/src/lib-storage/index/dbox/dbox-storage.h Sat Jun 27 19:55:44 2009 -0400 +++ b/src/lib-storage/index/dbox/dbox-storage.h Sat Jun 27 20:39:38 2009 -0400 @@ -51,6 +51,7 @@ /* mode/gid to use for new dbox storage files */ mode_t create_mode; gid_t create_gid; + const char *create_gid_origin; ARRAY_DEFINE(open_files, struct dbox_file *);
--- a/src/lib-storage/index/index-storage.c Sat Jun 27 19:55:44 2009 -0400 +++ b/src/lib-storage/index/index-storage.c Sat Jun 27 20:39:38 2009 -0400 @@ -73,6 +73,7 @@ static int create_missing_index_dir(struct mailbox *box) { const char *root_dir, *index_dir, *p, *parent_dir; + const char *origin, *parent_origin; mode_t mode, parent_mode; gid_t gid, parent_gid; int n = 0; @@ -84,8 +85,9 @@ if (strcmp(index_dir, root_dir) == 0 || *index_dir == '\0') return 0; - mailbox_list_get_dir_permissions(box->list, box->name, &mode, &gid); - while (mkdir_chown(index_dir, mode, (uid_t)-1, gid) < 0) { + mailbox_list_get_dir_permissions(box->list, box->name, &mode, + &gid, &origin); + while (mkdir_chgrp(index_dir, mode, gid, origin) < 0) { if (errno == EEXIST) break; @@ -97,10 +99,11 @@ } /* create the parent directory first */ mailbox_list_get_dir_permissions(box->list, NULL, - &parent_mode, &parent_gid); + &parent_mode, &parent_gid, + &parent_origin); parent_dir = t_strdup_until(index_dir, p); - if (mkdir_parents_chown(parent_dir, parent_mode, - (uid_t)-1, parent_gid) < 0 && + if (mkdir_parents_chgrp(parent_dir, parent_mode, + parent_gid, parent_origin) < 0 && errno != EEXIST) { mail_storage_set_critical(box->storage, "mkdir(%s) failed: %m", parent_dir); @@ -449,6 +452,7 @@ struct mailbox *box = &ibox->box; const char *path; gid_t dir_gid; + const char *origin, *dir_origin; if (name != NULL) box->name = p_strdup(box->pool, name); @@ -484,13 +488,14 @@ if (box->file_create_mode == 0) { mailbox_list_get_permissions(box->list, name, &box->file_create_mode, - &box->file_create_gid); + &box->file_create_gid, &origin); + box->file_create_gid_origin = p_strdup(box->pool, origin); mailbox_list_get_dir_permissions(box->list, name, &box->dir_create_mode, - &dir_gid); + &dir_gid, &dir_origin); mail_index_set_permissions(ibox->index, box->file_create_mode, - box->file_create_gid); + box->file_create_gid, origin); } }
--- a/src/lib-storage/index/maildir/maildir-keywords.c Sat Jun 27 19:55:44 2009 -0400 +++ b/src/lib-storage/index/maildir/maildir-keywords.c Sat Jun 27 20:39:38 2009 -0400 @@ -10,6 +10,7 @@ #include "hash.h" #include "str.h" #include "istream.h" +#include "eacces-error.h" #include "file-dotlock.h" #include "write-full.h" #include "nfs-workarounds.h" @@ -285,6 +286,7 @@ const char *path, int fd) { struct maildir_mailbox *mbox = mk->mbox; + struct mailbox *box = &mbox->ibox.box; const char *const *keywords; unsigned int i, count; string_t *str; @@ -308,11 +310,18 @@ return -1; } - if (st.st_gid != mbox->ibox.box.file_create_gid && - mbox->ibox.box.file_create_gid != (gid_t)-1) { - if (fchown(fd, (uid_t)-1, mbox->ibox.box.file_create_gid) < 0) { - mail_storage_set_critical(mk->storage, - "fchown(%s) failed: %m", path); + if (st.st_gid != box->file_create_gid && + box->file_create_gid != (gid_t)-1) { + if (fchown(fd, (uid_t)-1, box->file_create_gid) < 0) { + if (errno == EPERM) { + mail_storage_set_critical(mk->storage, "%s", + eperm_error_get_chgrp("fchown", path, + box->file_create_gid, + box->file_create_gid_origin)); + } else { + mail_storage_set_critical(mk->storage, + "fchown(%s) failed: %m", path); + } } }
--- a/src/lib-storage/index/maildir/maildir-save.c Sat Jun 27 19:55:44 2009 -0400 +++ b/src/lib-storage/index/maildir/maildir-save.c Sat Jun 27 20:39:38 2009 -0400 @@ -8,6 +8,7 @@ #include "istream-crlf.h" #include "ostream.h" #include "fdatasync-path.h" +#include "eacces-error.h" #include "str.h" #include "index-mail.h" #include "maildir-storage.h" @@ -340,8 +341,16 @@ } } else if (box->file_create_gid != (gid_t)-1) { if (fchown(fd, (uid_t)-1, box->file_create_gid) < 0) { - mail_storage_set_critical(box->storage, - "fchown(%s) failed: %m", str_c(path)); + if (errno == EPERM) { + mail_storage_set_critical(box->storage, "%s", + eperm_error_get_chgrp("fchown", + str_c(path), + box->file_create_gid, + box->file_create_gid_origin)); + } else { + mail_storage_set_critical(box->storage, + "fchown(%s) failed: %m", str_c(path)); + } } }
--- a/src/lib-storage/index/maildir/maildir-storage.c Sat Jun 27 19:55:44 2009 -0400 +++ b/src/lib-storage/index/maildir/maildir-storage.c Sat Jun 27 20:39:38 2009 -0400 @@ -6,6 +6,7 @@ #include "hostpid.h" #include "str.h" #include "mkdir-parents.h" +#include "eacces-error.h" #include "unlink-directory.h" #include "unlink-old-files.h" #include "mailbox-uidvalidity.h" @@ -213,8 +214,10 @@ return TRUE; } -static int mkdir_verify(struct mail_storage *storage, struct mail_namespace *ns, - const char *dir, mode_t mode, gid_t gid, bool verify) +static int +mkdir_verify(struct mail_storage *storage, struct mail_namespace *ns, + const char *dir, mode_t mode, gid_t gid, const char *gid_origin, + bool verify) { struct stat st; @@ -229,7 +232,7 @@ } } - if (mkdir_parents_chown(dir, mode, (uid_t)-1, gid) == 0) + if (mkdir_parents_chgrp(dir, mode, gid, gid_origin) == 0) return 0; if (errno == EEXIST) { @@ -289,7 +292,8 @@ /* create or fix maildir, ignore if it already exists */ static int create_maildir(struct mail_storage *storage, struct mail_namespace *ns, - const char *dir, mode_t mode, gid_t gid, bool verify) + const char *dir, mode_t mode, gid_t gid, const char *gid_origin, + bool verify) { const char *path; unsigned int i; @@ -308,7 +312,8 @@ for (i = 0; i < N_ELEMENTS(maildir_subdirs); i++) { path = t_strconcat(dir, "/", maildir_subdirs[i], NULL); - if (mkdir_verify(storage, ns, path, mode, gid, verify) < 0) + if (mkdir_verify(storage, ns, path, mode, gid, + gid_origin, verify) < 0) return -1; } return 0; @@ -360,21 +365,26 @@ { struct maildir_mailbox *mbox = (struct maildir_mailbox *)box; struct stat st; + const char *shared_path; /* for shared mailboxes get the create mode from the permissions of dovecot-shared file. */ - if (stat(t_strconcat(box->path, "/dovecot-shared", NULL), &st) == 0) { + shared_path = t_strconcat(box->path, "/dovecot-shared", NULL); + if (stat(shared_path, &st) == 0) { if ((st.st_mode & S_ISGID) != 0 || (st.st_mode & 0060) == 0) { /* Ignore GID */ st.st_gid = (gid_t)-1; } mail_index_set_permissions(mbox->ibox.index, - st.st_mode & 0666, st.st_gid); + st.st_mode & 0666, st.st_gid, + shared_path); box->file_create_mode = st.st_mode & 0666; box->dir_create_mode = get_dir_mode(st.st_mode & 0666); box->file_create_gid = st.st_gid; + mbox->ibox.box.file_create_gid_origin = + p_strdup(box->pool, shared_path); box->private_flags_mask = MAIL_SEEN; } @@ -395,6 +405,7 @@ static int maildir_mailbox_open(struct mailbox *box) { struct stat st; + const char *gid_origin; mode_t mode; gid_t gid; int ret; @@ -423,9 +434,9 @@ if (inbox || stat(box->path, &st) == 0) { /* yes, we'll need to create the missing dirs */ mailbox_list_get_dir_permissions(box->list, box->name, - &mode, &gid); + &mode, &gid, &gid_origin); if (create_maildir(box->storage, box->list->ns, box->path, - mode, gid, TRUE) < 0) + mode, gid, gid_origin, TRUE) < 0) return -1; return maildir_mailbox_open_existing(box); @@ -442,7 +453,8 @@ static int maildir_create_shared(struct mail_storage *storage, struct mail_namespace *ns, - const char *dir, mode_t mode, gid_t gid) + const char *dir, mode_t mode, gid_t gid, + const char *gid_origin) { const char *path; mode_t old_mask; @@ -453,7 +465,7 @@ if ((mode & 0060) != 0) mode |= 0010; if ((mode & 0006) != 0) mode |= 0001; - if (create_maildir(storage, ns, dir, mode, gid, FALSE) < 0) + if (create_maildir(storage, ns, dir, mode, gid, gid_origin, FALSE) < 0) return -1; old_mask = umask(0777 ^ mode); @@ -467,8 +479,14 @@ } if (fchown(fd, (uid_t)-1, gid) < 0) { - mail_storage_set_critical(storage, "fchown(%s) failed: %m", - path); + if (errno == EPERM) { + mail_storage_set_critical(storage, "%s", + eperm_error_get_chgrp("fchown", path, + gid, gid_origin)); + } else { + mail_storage_set_critical(storage, + "fchown(%s) failed: %m", path); + } } (void)close(fd); return 0; @@ -504,7 +522,7 @@ bool directory) { struct stat st; - const char *path, *root_dir, *shared_path; + const char *path, *root_dir, *shared_path, *gid_origin; mode_t old_mask; int fd; @@ -517,14 +535,17 @@ its permissions and gid, and copy the dovecot-shared inside it. */ shared_path = t_strconcat(root_dir, "/dovecot-shared", NULL); if (stat(shared_path, &st) == 0) { + gid_origin = shared_path; if (maildir_create_shared(box->storage, box->list->ns, path, - st.st_mode & 0666, st.st_gid) < 0) + st.st_mode & 0666, st.st_gid, + gid_origin) < 0) return -1; } else { - mailbox_list_get_dir_permissions(box->list, NULL, - &st.st_mode, &st.st_gid); + mailbox_list_get_dir_permissions(box->list, NULL, &st.st_mode, + &st.st_gid, &gid_origin); if (create_maildir(box->storage, box->list->ns, path, - st.st_mode, st.st_gid, FALSE) < 0) + st.st_mode, st.st_gid, gid_origin, + FALSE) < 0) return -1; } @@ -536,8 +557,15 @@ umask(old_mask); if (fd != -1) { /* if dovecot-shared exists, use the same group */ - if (st.st_gid != (gid_t)-1 && - fchown(fd, (uid_t)-1, st.st_gid) < 0) { + if (st.st_gid == (gid_t)-1) { + /* doesn't exist */ + } else if (fchown(fd, (uid_t)-1, st.st_gid) == 0) { + /* ok */ + } else if (errno == EPERM) { + mail_storage_set_critical(box->storage, "%s", + eperm_error_get_chgrp("fchown", path, + st.st_gid, gid_origin)); + } else { mail_storage_set_critical(box->storage, "fchown(%s) failed: %m", path); }
--- a/src/lib-storage/index/maildir/maildir-uidlist.c Sat Jun 27 19:55:44 2009 -0400 +++ b/src/lib-storage/index/maildir/maildir-uidlist.c Sat Jun 27 20:39:38 2009 -0400 @@ -1316,8 +1316,14 @@ return -1; } - if (box->file_create_gid != (gid_t)-1) { - if (fchown(fd, (uid_t)-1, box->file_create_gid) < 0) { + if (box->file_create_gid != (gid_t)-1 && + fchown(fd, (uid_t)-1, box->file_create_gid) < 0) { + if (errno == EPERM) { + mail_storage_set_critical(box->storage, "%s", + eperm_error_get_chgrp("fchown", temp_path, + box->file_create_gid, + box->file_create_gid_origin)); + } else { mail_storage_set_critical(box->storage, "fchown(%s) failed: %m", temp_path); }
--- a/src/lib-storage/index/maildir/maildir-util.c Sat Jun 27 19:55:44 2009 -0400 +++ b/src/lib-storage/index/maildir/maildir-util.c Sat Jun 27 20:39:38 2009 -0400 @@ -133,12 +133,12 @@ static int maildir_create_path(struct mailbox *box, const char *path, bool is_mail_dir) { - const char *p, *parent; + const char *p, *parent, *origin; mode_t parent_mode; gid_t parent_gid; - if (mkdir_chown(path, box->dir_create_mode, - (uid_t)-1, box->file_create_gid) == 0) + if (mkdir_chgrp(path, box->dir_create_mode, box->file_create_gid, + box->file_create_gid_origin) == 0) return 0; switch (errno) { @@ -153,10 +153,11 @@ } /* create index/control root directory */ parent = t_strdup_until(path, p); - mailbox_list_get_dir_permissions(box->list, NULL, - &parent_mode, &parent_gid); - if (mkdir_parents_chown(parent, parent_mode, (uid_t)-1, - parent_gid) == 0 || errno == EEXIST) { + mailbox_list_get_dir_permissions(box->list, NULL, &parent_mode, + &parent_gid, &origin); + if (mkdir_parents_chgrp(parent, parent_mode, parent_gid, + origin) == 0 || + errno == EEXIST) { /* should work now, try again */ return maildir_create_path(box, path, TRUE); }
--- a/src/lib-storage/index/mbox/mbox-storage.c Sat Jun 27 19:55:44 2009 -0400 +++ b/src/lib-storage/index/mbox/mbox-storage.c Sat Jun 27 20:39:38 2009 -0400 @@ -509,7 +509,7 @@ bool directory) { struct mail_storage *storage = box->storage; - const char *path, *p; + const char *path, *p, *origin; struct stat st; mode_t mode; gid_t gid; @@ -539,8 +539,9 @@ p = directory ? path + strlen(path) : strrchr(path, '/'); if (p != NULL) { p = t_strdup_until(path, p); - mailbox_list_get_dir_permissions(box->list, NULL, &mode, &gid); - if (mkdir_parents_chown(p, mode, (uid_t)-1, gid) < 0 && + mailbox_list_get_dir_permissions(box->list, NULL, &mode, &gid, + &origin); + if (mkdir_parents_chgrp(p, mode, gid, origin) < 0 && errno != EEXIST) { if (!mail_storage_set_error_from_errno(storage)) { mail_storage_set_critical(storage,
--- a/src/lib-storage/list/mailbox-list-fs.c Sat Jun 27 19:55:44 2009 -0400 +++ b/src/lib-storage/list/mailbox-list-fs.c Sat Jun 27 20:39:38 2009 -0400 @@ -314,7 +314,7 @@ const char *newname, bool rename_children) { struct mail_storage *oldstorage; - const char *oldpath, *newpath, *p; + const char *oldpath, *newpath, *p, *origin; enum mailbox_list_path_type path_type; struct stat st; mode_t mode; @@ -342,9 +342,10 @@ /* create the hierarchy */ p = strrchr(newpath, '/'); if (p != NULL) { - mailbox_list_get_dir_permissions(newlist, NULL, &mode, &gid); + mailbox_list_get_dir_permissions(newlist, NULL, &mode, + &gid, &origin); p = t_strdup_until(newpath, p); - if (mkdir_parents_chown(p, mode, (uid_t)-1, gid) < 0 && + if (mkdir_parents_chgrp(p, mode, gid, origin) < 0 && errno != EEXIST) { if (mailbox_list_set_error_from_errno(oldlist)) return -1;
--- a/src/lib-storage/list/subscription-file.c Sat Jun 27 19:55:44 2009 -0400 +++ b/src/lib-storage/list/subscription-file.c Sat Jun 27 20:39:38 2009 -0400 @@ -89,7 +89,7 @@ { struct dotlock_settings dotlock_set; struct dotlock *dotlock; - const char *line, *p, *dir; + const char *line, *p, *dir, *origin; struct istream *input; struct ostream *output; int fd_in, fd_out; @@ -107,22 +107,22 @@ dotlock_set.timeout = SUBSCRIPTION_FILE_LOCK_TIMEOUT; dotlock_set.stale_timeout = SUBSCRIPTION_FILE_CHANGE_TIMEOUT; - mailbox_list_get_permissions(list, NULL, &mode, &gid); - mailbox_list_get_dir_permissions(list, NULL, &dir_mode, &gid); - fd_out = file_dotlock_open_mode(&dotlock_set, path, 0, - mode, (uid_t)-1, gid, &dotlock); + mailbox_list_get_permissions(list, NULL, &mode, &gid, &origin); + mailbox_list_get_dir_permissions(list, NULL, &dir_mode, &gid, &origin); + fd_out = file_dotlock_open_group(&dotlock_set, path, 0, + mode, gid, origin, &dotlock); if (fd_out == -1 && errno == ENOENT) { /* directory hasn't been created yet. */ p = strrchr(path, '/'); dir = p == NULL ? NULL : t_strdup_until(path, p); if (dir != NULL && - mkdir_parents_chown(dir, dir_mode, (uid_t)-1, gid) < 0 && + mkdir_parents_chgrp(dir, dir_mode, gid, origin) < 0 && errno != EEXIST) { subswrite_set_syscall_error(list, "mkdir()", dir); return -1; } - fd_out = file_dotlock_open_mode(&dotlock_set, path, 0, - mode, (uid_t)-1, gid, &dotlock); + fd_out = file_dotlock_open_group(&dotlock_set, path, 0, + mode, gid, origin, &dotlock); } if (fd_out == -1) { if (errno == EAGAIN) {
--- a/src/lib-storage/mail-storage-private.h Sat Jun 27 19:55:44 2009 -0400 +++ b/src/lib-storage/mail-storage-private.h Sat Jun 27 20:39:38 2009 -0400 @@ -235,6 +235,8 @@ /* mode and GID to use for newly created files/dirs */ mode_t file_create_mode, dir_create_mode; gid_t file_create_gid; + /* origin (e.g. path) where the file_create_gid was got from */ + const char *file_create_gid_origin; /* Mailbox notification settings: */ unsigned int notify_min_interval;
--- a/src/lib-storage/mail-storage.c Sat Jun 27 19:55:44 2009 -0400 +++ b/src/lib-storage/mail-storage.c Sat Jun 27 20:39:38 2009 -0400 @@ -161,7 +161,7 @@ mail_storage_create_root(struct mailbox_list *list, enum mail_storage_flags flags, const char **error_r) { - const char *root_dir; + const char *root_dir, *origin; struct stat st; mode_t mode; gid_t gid; @@ -187,8 +187,8 @@ } /* we need to create the root directory. */ - mailbox_list_get_dir_permissions(list, NULL, &mode, &gid); - if (mkdir_parents_chown(root_dir, mode, (uid_t)-1, gid) < 0 && + mailbox_list_get_dir_permissions(list, NULL, &mode, &gid, &origin); + if (mkdir_parents_chgrp(root_dir, mode, gid, origin) < 0 && errno != EEXIST) { *error_r = mail_error_create_eacces_msg("mkdir", root_dir); return -1;
--- a/src/lib-storage/mailbox-list-private.h Sat Jun 27 19:55:44 2009 -0400 +++ b/src/lib-storage/mailbox-list-private.h Sat Jun 27 20:39:38 2009 -0400 @@ -92,6 +92,8 @@ /* -1 if not set yet. use mailbox_list_get_permissions() to set them */ mode_t file_create_mode, dir_create_mode; gid_t file_create_gid; + /* origin (e.g. path) where the file_create_gid was got from */ + const char *file_create_gid_origin; char *error_string; enum mail_error error;
--- a/src/lib-storage/mailbox-list.c Sat Jun 27 19:55:44 2009 -0400 +++ b/src/lib-storage/mailbox-list.c Sat Jun 27 20:39:38 2009 -0400 @@ -327,7 +327,7 @@ static void mailbox_list_get_permissions_full(struct mailbox_list *list, const char *name, mode_t *file_mode_r, mode_t *dir_mode_r, - gid_t *gid_r) + gid_t *gid_r, const char **gid_origin_r) { const char *path; struct stat st; @@ -345,16 +345,19 @@ /* return defaults */ mailbox_list_get_permissions_full(list, NULL, file_mode_r, - dir_mode_r, gid_r); + dir_mode_r, gid_r, + gid_origin_r); return; } /* return safe defaults */ *file_mode_r = 0600; *dir_mode_r = 0700; *gid_r = (gid_t)-1; + *gid_origin_r = "defaults"; } else { *file_mode_r = st.st_mode & 0666; *dir_mode_r = st.st_mode & 0777; + *gid_origin_r = path; if (!S_ISDIR(st.st_mode)) { /* we're getting permissions from a file. @@ -382,6 +385,8 @@ list->file_create_mode = *file_mode_r; list->dir_create_mode = *dir_mode_r; list->file_create_gid = *gid_r; + list->file_create_gid_origin = + p_strdup(list->pool, *gid_origin_r); } if (list->mail_set->mail_debug && name == NULL) { @@ -393,34 +398,40 @@ } } -void mailbox_list_get_permissions(struct mailbox_list *list, const char *name, - mode_t *mode_r, gid_t *gid_r) +void mailbox_list_get_permissions(struct mailbox_list *list, + const char *name, + mode_t *mode_r, gid_t *gid_r, + const char **gid_origin_r) { mode_t dir_mode; if (list->file_create_mode != (mode_t)-1 && name == NULL) { *mode_r = list->file_create_mode; *gid_r = list->file_create_gid; + *gid_origin_r = list->file_create_gid_origin; return; } - mailbox_list_get_permissions_full(list, name, mode_r, &dir_mode, gid_r); + mailbox_list_get_permissions_full(list, name, mode_r, &dir_mode, gid_r, + gid_origin_r); } void mailbox_list_get_dir_permissions(struct mailbox_list *list, const char *name, - mode_t *mode_r, gid_t *gid_r) + mode_t *mode_r, gid_t *gid_r, + const char **gid_origin_r) { mode_t file_mode; if (list->dir_create_mode != (mode_t)-1 && name == NULL) { *mode_r = list->dir_create_mode; *gid_r = list->file_create_gid; + *gid_origin_r = list->file_create_gid_origin; return; } mailbox_list_get_permissions_full(list, name, &file_mode, - mode_r, gid_r); + mode_r, gid_r, gid_origin_r); } bool mailbox_list_is_valid_pattern(struct mailbox_list *list,
--- a/src/lib-storage/mailbox-list.h Sat Jun 27 19:55:44 2009 -0400 +++ b/src/lib-storage/mailbox-list.h Sat Jun 27 20:39:38 2009 -0400 @@ -145,13 +145,16 @@ /* Returns the mode and GID that should be used when creating new files to the specified mailbox, or to mailbox list root if name is NULL. (gid_t)-1 is returned if it's not necessary to change the default gid. */ -void mailbox_list_get_permissions(struct mailbox_list *list, const char *name, - mode_t *mode_r, gid_t *gid_r); +void mailbox_list_get_permissions(struct mailbox_list *list, + const char *name, + mode_t *mode_r, gid_t *gid_r, + const char **gid_origin_r); /* Like mailbox_list_get_permissions(), but add execute-bits for mode if either read or write bit is set (e.g. 0640 -> 0750). */ void mailbox_list_get_dir_permissions(struct mailbox_list *list, const char *name, - mode_t *mode_r, gid_t *gid_r); + mode_t *mode_r, gid_t *gid_r, + const char **gid_origin_r); /* Returns TRUE if the name doesn't contain any invalid characters. The create name check can be more strict. */
--- a/src/lib/eacces-error.c Sat Jun 27 19:55:44 2009 -0400 +++ b/src/lib/eacces-error.c Sat Jun 27 20:39:38 2009 -0400 @@ -88,8 +88,9 @@ const struct group *group; string_t *errmsg; struct stat st, dir_st; - int ret = -1; + int orig_errno, ret = -1; + orig_errno = errno; errmsg = t_str_new(256); str_printfa(errmsg, "%s(%s) failed: Permission denied (euid=%s", func, path, dec2str(geteuid())); @@ -145,6 +146,7 @@ str_printfa(errmsg, " UNIX perms seem ok, ACL problem?"); } str_append_c(errmsg, ')'); + errno = orig_errno; return str_c(errmsg); } @@ -157,3 +159,29 @@ { return eacces_error_get_full(func, path, TRUE); } + +const char *eperm_error_get_chgrp(const char *func, const char *path, + gid_t gid, const char *gid_origin) +{ + string_t *errmsg; + const struct group *group; + int orig_errno = errno; + + errmsg = t_str_new(256); + + str_printfa(errmsg, "%s(%s, -1, %s", func, path, dec2str(gid)); + group = getgrgid(gid); + if (group != NULL) + str_printfa(errmsg, "(%s)", group->gr_name); + + str_printfa(errmsg, ") failed: Operation not permitted (egid=%s", + dec2str(getegid())); + group = getgrgid(getegid()); + if (group != NULL) + str_printfa(errmsg, "(%s)", group->gr_name); + if (gid_origin != NULL) + str_printfa(errmsg, ", group based on %s", gid_origin); + str_append_c(errmsg, ')'); + errno = orig_errno; + return str_c(errmsg); +}
--- a/src/lib/eacces-error.h Sat Jun 27 19:55:44 2009 -0400 +++ b/src/lib/eacces-error.h Sat Jun 27 20:39:38 2009 -0400 @@ -4,5 +4,10 @@ /* Return a user-friendly error message for EACCES failures. */ const char *eacces_error_get(const char *func, const char *path); const char *eacces_error_get_creating(const char *func, const char *path); +/* Return a user-friendly error message for fchown() or chown() EPERM + failures when only the group is being changed. gid_origin specifies why + exactly this group is being used. */ +const char *eperm_error_get_chgrp(const char *func, const char *path, + gid_t gid, const char *gid_origin); #endif
--- a/src/lib/file-dotlock.c Sat Jun 27 19:55:44 2009 -0400 +++ b/src/lib/file-dotlock.c Sat Jun 27 20:39:38 2009 -0400 @@ -6,6 +6,7 @@ #include "hex-binary.h" #include "hostpid.h" #include "randgen.h" +#include "eacces-error.h" #include "write-full.h" #include "safe-mkstemp.h" #include "nfs-workarounds.h" @@ -765,10 +766,11 @@ return dotlock->fd; } -int file_dotlock_open_mode(const struct dotlock_settings *set, const char *path, - enum dotlock_create_flags flags, - mode_t mode, uid_t uid, gid_t gid, - struct dotlock **dotlock_r) +static int +file_dotlock_open_mode_full(const struct dotlock_settings *set, const char *path, + enum dotlock_create_flags flags, + mode_t mode, uid_t uid, gid_t gid, + const char *gid_origin, struct dotlock **dotlock_r) { struct dotlock *dotlock; mode_t old_mask; @@ -780,9 +782,15 @@ if (fd != -1) { if (fchown(fd, uid, gid) < 0) { - i_error("fchown(%s, %ld, %ld) failed: %m", - file_dotlock_get_lock_path(dotlock), - (long)uid, (long)gid); + if (errno == EPERM && uid == (uid_t)-1) { + i_error("%s", eperm_error_get_chgrp("fchown", + file_dotlock_get_lock_path(dotlock), + gid, gid_origin)); + } else { + i_error("fchown(%s, %ld, %ld) failed: %m", + file_dotlock_get_lock_path(dotlock), + (long)uid, (long)gid); + } file_dotlock_delete(&dotlock); return -1; } @@ -791,6 +799,24 @@ return fd; } +int file_dotlock_open_mode(const struct dotlock_settings *set, const char *path, + enum dotlock_create_flags flags, + mode_t mode, uid_t uid, gid_t gid, + struct dotlock **dotlock_r) +{ + return file_dotlock_open_mode_full(set, path, flags, mode, uid, gid, + NULL, dotlock_r); +} + +int file_dotlock_open_group(const struct dotlock_settings *set, const char *path, + enum dotlock_create_flags flags, + mode_t mode, gid_t gid, const char *gid_origin, + struct dotlock **dotlock_r) +{ + return file_dotlock_open_mode_full(set, path, flags, mode, (uid_t)-1, + gid, gid_origin, dotlock_r); +} + int file_dotlock_replace(struct dotlock **dotlock_p, enum dotlock_replace_flags flags) {
--- a/src/lib/file-dotlock.h Sat Jun 27 19:55:44 2009 -0400 +++ b/src/lib/file-dotlock.h Sat Jun 27 20:39:38 2009 -0400 @@ -73,6 +73,10 @@ enum dotlock_create_flags flags, mode_t mode, uid_t uid, gid_t gid, struct dotlock **dotlock_r); +int file_dotlock_open_group(const struct dotlock_settings *set, const char *path, + enum dotlock_create_flags flags, + mode_t mode, gid_t gid, const char *gid_origin, + struct dotlock **dotlock_r); /* Replaces the file dotlock protects with the dotlock file itself. */ int file_dotlock_replace(struct dotlock **dotlock, enum dotlock_replace_flags flags);
--- a/src/lib/mkdir-parents.c Sat Jun 27 19:55:44 2009 -0400 +++ b/src/lib/mkdir-parents.c Sat Jun 27 20:39:38 2009 -0400 @@ -1,15 +1,22 @@ /* Copyright (c) 2003-2009 Dovecot authors, see the included COPYING file */ #include "lib.h" +#include "str.h" +#include "eacces-error.h" #include "mkdir-parents.h" #include <sys/stat.h> #include <unistd.h> +#include <pwd.h> +#include <grp.h> -int mkdir_chown(const char *path, mode_t mode, uid_t uid, gid_t gid) +static int +mkdir_chown_full(const char *path, mode_t mode, uid_t uid, + gid_t gid, const char *gid_origin) { + string_t *str; mode_t old_mask; - int ret; + int ret, orig_errno; old_mask = umask(0); ret = mkdir(path, mode); @@ -26,20 +33,57 @@ return -1; } if (chown(path, uid, gid) < 0) { - i_error("chown(%s, %ld, %ld) failed: %m", path, - uid == (uid_t)-1 ? -1L : (long)uid, - gid == (gid_t)-1 ? -1L : (long)gid); + if (errno == EPERM && uid == (uid_t)-1) { + i_error("%s", eperm_error_get_chgrp("chown", path, gid, + gid_origin)); + return -1; + } + orig_errno = errno; + + str = t_str_new(256); + str_printfa(str, "chown(%s, %ld", path, + uid == (uid_t)-1 ? -1L : (long)uid); + if (uid != (uid_t)-1) { + struct passwd *pw = getpwuid(uid); + + if (pw != NULL) + str_printfa(str, "(%s)", pw->pw_name); + + } + str_printfa(str, ", %ld", + gid == (gid_t)-1 ? -1L : (long)gid); + if (gid != (gid_t)-1) { + struct group *gr = getgrgid(uid); + + if (gr != NULL) + str_printfa(str, "(%s)", gr->gr_name); + } + errno = orig_errno; + i_error("%s) failed: %m", str_c(str)); return -1; } return 0; } -int mkdir_parents_chown(const char *path, mode_t mode, uid_t uid, gid_t gid) +int mkdir_chown(const char *path, mode_t mode, uid_t uid, gid_t gid) +{ + return mkdir_chown_full(path, mode, uid, gid, NULL); +} + +int mkdir_chgrp(const char *path, mode_t mode, + gid_t gid, const char *gid_origin) +{ + return mkdir_chown_full(path, mode, (uid_t)-1, gid, gid_origin); +} + +static int +mkdir_parents_chown_full(const char *path, mode_t mode, uid_t uid, gid_t gid, + const char *gid_origin) { const char *p; int ret; - if (mkdir_chown(path, mode, uid, gid) < 0) { + if (mkdir_chown_full(path, mode, uid, gid, gid_origin) < 0) { if (errno != ENOENT) return -1; @@ -49,19 +93,31 @@ return -1; /* shouldn't happen */ T_BEGIN { - ret = mkdir_parents_chown(t_strdup_until(path, p), - mode, uid, gid); + ret = mkdir_parents_chown_full(t_strdup_until(path, p), + mode, uid, + gid, gid_origin); } T_END; if (ret < 0) return -1; /* should work now */ - if (mkdir_chown(path, mode, uid, gid) < 0) + if (mkdir_chown_full(path, mode, uid, gid, gid_origin) < 0) return -1; } return 0; } +int mkdir_parents_chown(const char *path, mode_t mode, uid_t uid, gid_t gid) +{ + return mkdir_parents_chown_full(path, mode, uid, gid, NULL); +} + +int mkdir_parents_chgrp(const char *path, mode_t mode, + gid_t gid, const char *gid_origin) +{ + return mkdir_parents_chown_full(path, mode, (uid_t)-1, gid, gid_origin); +} + int mkdir_parents(const char *path, mode_t mode) { return mkdir_parents_chown(path, mode, (uid_t)-1, (gid_t)-1);
--- a/src/lib/mkdir-parents.h Sat Jun 27 19:55:44 2009 -0400 +++ b/src/lib/mkdir-parents.h Sat Jun 27 20:39:38 2009 -0400 @@ -7,10 +7,17 @@ int mkdir_parents(const char *path, mode_t mode); /* Like mkdir_parents(), but use the given uid/gid for newly created - directories. */ + directories. (uid_t)-1 or (gid_t)-1 can be used to indicate that it + doesn't need to be changed. */ int mkdir_parents_chown(const char *path, mode_t mode, uid_t uid, gid_t gid); +/* Like mkdir_parents_chown(), but change only group. If chown() fails with + EACCES, use gid_origin in the error message. */ +int mkdir_parents_chgrp(const char *path, mode_t mode, + gid_t gid, const char *gid_origin); /* Like mkdir_parents_chown(), but don't actually create any parents. */ int mkdir_chown(const char *path, mode_t mode, uid_t uid, gid_t gid); +int mkdir_chgrp(const char *path, mode_t mode, + gid_t gid, const char *gid_origin); #endif
--- a/src/lib/safe-mkstemp.c Sat Jun 27 19:55:44 2009 -0400 +++ b/src/lib/safe-mkstemp.c Sat Jun 27 20:39:38 2009 -0400 @@ -5,13 +5,16 @@ #include "hex-binary.h" #include "randgen.h" #include "hostpid.h" +#include "eacces-error.h" #include "safe-mkstemp.h" #include <unistd.h> #include <fcntl.h> #include <sys/stat.h> -int safe_mkstemp(string_t *prefix, mode_t mode, uid_t uid, gid_t gid) +static int +safe_mkstemp_full(string_t *prefix, mode_t mode, uid_t uid, gid_t gid, + const char *gid_origin) { size_t prefix_len; struct stat st; @@ -45,22 +48,46 @@ return -1; } } - if (uid != (uid_t)-1 || gid != (gid_t)-1) { - if (fchown(fd, uid, gid) < 0) { + if (uid == (uid_t)-1 && gid == (gid_t)-1) + return fd; + + if (fchown(fd, uid, gid) < 0) { + if (errno == EPERM) { + i_error("%s", eperm_error_get_chgrp("fchown", + str_c(prefix), gid, gid_origin)); + } else { i_error("fchown(%s, %ld, %ld) failed: %m", str_c(prefix), uid == (uid_t)-1 ? -1L : (long)uid, gid == (gid_t)-1 ? -1L : (long)gid); - (void)close(fd); - (void)unlink(str_c(prefix)); - return -1; } + (void)close(fd); + (void)unlink(str_c(prefix)); + return -1; } return fd; } +int safe_mkstemp(string_t *prefix, mode_t mode, uid_t uid, gid_t gid) +{ + return safe_mkstemp_full(prefix, mode, uid, gid, NULL); +} + +int safe_mkstemp_group(string_t *prefix, mode_t mode, + gid_t gid, const char *gid_origin) +{ + return safe_mkstemp_full(prefix, mode, (uid_t)-1, gid, gid_origin); +} + int safe_mkstemp_hostpid(string_t *prefix, mode_t mode, uid_t uid, gid_t gid) { str_printfa(prefix, "%s.%s.", my_hostname, my_pid); return safe_mkstemp(prefix, mode, uid, gid); } + +int safe_mkstemp_hostpid_group(string_t *prefix, mode_t mode, + gid_t gid, const char *gid_origin) +{ + str_printfa(prefix, "%s.%s.", my_hostname, my_pid); + return safe_mkstemp_group(prefix, mode, gid, gid_origin); +}
--- a/src/lib/safe-mkstemp.h Sat Jun 27 19:55:44 2009 -0400 +++ b/src/lib/safe-mkstemp.h Sat Jun 27 20:39:38 2009 -0400 @@ -5,7 +5,11 @@ created filename. uid and gid can be (uid_t)-1 and (gid_t)-1 to use the defaults. */ int safe_mkstemp(string_t *prefix, mode_t mode, uid_t uid, gid_t gid); +int safe_mkstemp_group(string_t *prefix, mode_t mode, + gid_t gid, const char *gid_origin); /* Append host and PID to the prefix. */ int safe_mkstemp_hostpid(string_t *prefix, mode_t mode, uid_t uid, gid_t gid); +int safe_mkstemp_hostpid_group(string_t *prefix, mode_t mode, + gid_t gid, const char *gid_origin); #endif
--- a/src/plugins/acl/acl-backend-vfile-acllist.c Sat Jun 27 19:55:44 2009 -0400 +++ b/src/plugins/acl/acl-backend-vfile-acllist.c Sat Jun 27 20:39:38 2009 -0400 @@ -171,7 +171,7 @@ struct mail_namespace *ns; struct mailbox_list_iterate_context *iter; const struct mailbox_info *info; - const char *rootdir, *acllist_path; + const char *rootdir, *acllist_path, *origin; struct ostream *output; struct stat st; string_t *path; @@ -198,8 +198,8 @@ /* Build it into a temporary file and rename() over. There's no need to use locking, because even if multiple processes are rebuilding the file at the same time the result should be the same. */ - mailbox_list_get_permissions(list, NULL, &mode, &gid); - fd = safe_mkstemp(path, mode, (uid_t)-1, gid); + mailbox_list_get_permissions(list, NULL, &mode, &gid, &origin); + fd = safe_mkstemp_group(path, mode, gid, origin); if (fd == -1) { if (errno == EACCES) { /* Ignore silently if we can't create it */
--- a/src/plugins/acl/acl-backend-vfile.c Sat Jun 27 19:55:44 2009 -0400 +++ b/src/plugins/acl/acl-backend-vfile.c Sat Jun 27 20:39:38 2009 -0400 @@ -846,18 +846,18 @@ struct dotlock **dotlock_r) { struct acl_object *_aclobj = &aclobj->aclobj; + const char *gid_origin; mode_t mode; gid_t gid; int fd; /* first lock the ACL file */ mailbox_list_get_permissions(_aclobj->backend->list, _aclobj->name, - &mode, &gid); - fd = file_dotlock_open_mode(&dotlock_set, aclobj->local_path, 0, - mode, (uid_t)-1, gid, dotlock_r); + &mode, &gid, &gid_origin); + fd = file_dotlock_open_group(&dotlock_set, aclobj->local_path, 0, + mode, gid, gid_origin, dotlock_r); if (fd == -1) { - i_error("file_dotlock_open_mode(%s) failed: %m", - aclobj->local_path); + i_error("file_dotlock_open(%s) failed: %m", aclobj->local_path); return -1; }
--- a/src/plugins/lazy-expunge/lazy-expunge-plugin.c Sat Jun 27 19:55:44 2009 -0400 +++ b/src/plugins/lazy-expunge/lazy-expunge-plugin.c Sat Jun 27 20:39:38 2009 -0400 @@ -266,18 +266,18 @@ mailbox_move(struct mailbox_list *src_list, const char *src_name, struct mailbox_list *dest_list, const char **_dest_name) { - const char *dir, *dest_name = *_dest_name; + const char *dir, *origin, *dest_name = *_dest_name; enum mail_error error; mode_t mode; gid_t gid; /* make sure the destination root directory exists */ - mailbox_list_get_dir_permissions(dest_list, NULL, &mode, &gid); + mailbox_list_get_dir_permissions(dest_list, NULL, &mode, &gid, &origin); dir = mailbox_list_get_path(dest_list, NULL, MAILBOX_LIST_PATH_TYPE_DIR); - if (mkdir_parents_chown(dir, mode, (uid_t)-1, gid) < 0 && + if (mkdir_parents_chgrp(dir, mode, gid, origin) < 0 && errno != EEXIST) { mailbox_list_set_critical(src_list, - "mkdir_parents_chown(%s) failed: %m", dir); + "mkdir_parents(%s) failed: %m", dir); return -1; }
--- a/src/plugins/quota/quota-maildir.c Sat Jun 27 19:55:44 2009 -0400 +++ b/src/plugins/quota/quota-maildir.c Sat Jun 27 20:39:38 2009 -0400 @@ -222,7 +222,7 @@ struct mail_namespace *const *namespaces; unsigned int i, count; struct dotlock *dotlock; - const char *p, *dir; + const char *p, *dir, *gid_origin, *dir_gid_origin; string_t *str; mode_t mode, dir_mode; gid_t gid, dir_gid; @@ -232,43 +232,41 @@ /* figure out what permissions we should use for maildirsize. use the inbox namespace's permissions if possible. */ - mode = 0600; dir_mode = 0700; + mode = 0600; dir_mode = 0700; gid_origin = "default"; gid = dir_gid = (gid_t)-1; namespaces = array_get(&root->root.quota->namespaces, &count); i_assert(count > 0); for (i = 0; i < count; i++) { if ((namespaces[i]->flags & NAMESPACE_FLAG_INBOX) != 0) { mailbox_list_get_permissions(namespaces[i]->list, - NULL, &mode, &gid); + NULL, &mode, &gid, + &gid_origin); mailbox_list_get_dir_permissions(namespaces[i]->list, NULL, - &dir_mode, &dir_gid); + &dir_mode, &dir_gid, + &dir_gid_origin); break; } } dotlock_settings.use_excl_lock = set->dotlock_use_excl; dotlock_settings.nfs_flush = set->mail_nfs_storage; - fd = file_dotlock_open_mode(&dotlock_settings, path, - DOTLOCK_CREATE_FLAG_NONBLOCK, - mode, (uid_t)-1, gid, &dotlock); + fd = file_dotlock_open_group(&dotlock_settings, path, + DOTLOCK_CREATE_FLAG_NONBLOCK, + mode, gid, gid_origin, &dotlock); if (fd == -1 && errno == ENOENT) { /* the control directory doesn't exist yet? create it */ p = strrchr(path, '/'); dir = t_strdup_until(path, p); - if (mkdir_parents(dir, dir_mode) < 0 && errno != EEXIST) { + if (mkdir_parents_chgrp(dir, dir_mode, dir_gid, + dir_gid_origin) < 0 && + errno != EEXIST) { i_error("mkdir_parents(%s) failed: %m", dir); return -1; } - if (dir_gid != (gid_t)-1) { - if (chown(dir, (uid_t)-1, dir_gid) < 0) { - i_error("chown(%s,-1,%ld) failed: %m", - dir, (long)dir_gid); - } - } - fd = file_dotlock_open_mode(&dotlock_settings, path, - DOTLOCK_CREATE_FLAG_NONBLOCK, - mode, (uid_t)-1, gid, &dotlock); + fd = file_dotlock_open_group(&dotlock_settings, path, + DOTLOCK_CREATE_FLAG_NONBLOCK, + mode, gid, gid_origin, &dotlock); } if (fd == -1) { if (errno == EAGAIN) {