dovecot-2.0-pigeonhole: sieve-storage: made auto-creation code m...
pigeonhole at rename-it.nl
pigeonhole at rename-it.nl
Sun May 2 10:30:46 EEST 2010
details: http://hg.rename-it.nl/dovecot-2.0-pigeonhole/rev/baf75b4123fe
changeset: 1266:baf75b4123fe
user: Stephan Bosch <stephan at rename-it.nl>
date: Sun May 02 09:30:37 2010 +0200
description:
sieve-storage: made auto-creation code match implementation of maildir storage from Dovecot.
diffstat:
src/lib-sievestorage/sieve-storage-private.h | 2 +-
src/lib-sievestorage/sieve-storage.c | 145 +++++++++++++++++++---------
2 files changed, 99 insertions(+), 48 deletions(-)
diffs (216 lines):
diff -r bc59d9d71029 -r baf75b4123fe src/lib-sievestorage/sieve-storage-private.h
--- a/src/lib-sievestorage/sieve-storage-private.h Sun May 02 09:29:54 2010 +0200
+++ b/src/lib-sievestorage/sieve-storage-private.h Sun May 02 09:30:37 2010 +0200
@@ -44,7 +44,7 @@
mode_t dir_create_mode;
mode_t file_create_mode;
- gid_t dir_create_gid;
+ gid_t file_create_gid;
uint64_t max_scripts;
uint64_t max_storage;
diff -r bc59d9d71029 -r baf75b4123fe src/lib-sievestorage/sieve-storage.c
--- a/src/lib-sievestorage/sieve-storage.c Sun May 02 09:29:54 2010 +0200
+++ b/src/lib-sievestorage/sieve-storage.c Sun May 02 09:30:37 2010 +0200
@@ -5,6 +5,7 @@
#include "home-expand.h"
#include "ioloop.h"
#include "mkdir-parents.h"
+#include "eacces-error.h"
#include "sieve.h"
#include "sieve-common.h"
@@ -70,59 +71,97 @@
return t_strdup(link_path);
}
-static int sieve_storage_verify_dir
-(const char *path, mode_t *mode_r, gid_t *gid_r)
+static mode_t get_dir_mode(mode_t mode)
+{
+ /* Add the execute bit if either read or write bit is set */
+
+ if ((mode & 0600) != 0) mode |= 0100;
+ if ((mode & 0060) != 0) mode |= 0010;
+ if ((mode & 0006) != 0) mode |= 0001;
+
+ return mode;
+}
+
+static void sieve_storage_get_permissions
+(const char *path, mode_t *file_mode_r, mode_t *dir_mode_r, gid_t *gid_r,
+ const char **gid_origin_r, bool debug)
{
struct stat st;
+ /* Use safe defaults */
+ *file_mode_r = 0600;
+ *dir_mode_r = 0700;
+ *gid_r = (gid_t)-1;
+ *gid_origin_r = "defaults";
+
if ( stat(path, &st) < 0 ) {
- const char *p;
- int ret;
+ if ( !ENOTFOUND(errno) ) {
+ i_error("sieve-storage: stat(%s) failed: %m", path);
+ } else if ( debug ) {
+ i_debug("sieve-storage: permission lookup failed from %s", path);
+ }
+ return;
- if ( errno != ENOENT )
- return -1;
+ } else {
+ *file_mode_r = (st.st_mode & 0666) | 0600;
+ *dir_mode_r = (st.st_mode & 0777) | 0700;
+ *gid_origin_r = path;
- /* Ascend to parent path element */
- p = strrchr(path, '/');
+ if ( !S_ISDIR(st.st_mode) ) {
+ /* We're getting permissions from a file. Apply +x modes as necessary. */
+ *dir_mode_r = get_dir_mode(*dir_mode_r);
+ }
- /* Path components exhausted? */
- if (p == NULL || p == path )
- return -1;
+ if (S_ISDIR(st.st_mode) && (st.st_mode & S_ISGID) != 0) {
+ /* Directory's GID is used automatically for new files */
+ *gid_r = (gid_t)-1;
+ } else if ((st.st_mode & 0070) >> 3 == (st.st_mode & 0007)) {
+ /* Group has same permissions as world, so don't bother changing it */
+ *gid_r = (gid_t)-1;
+ } else if (getegid() == st.st_gid) {
+ /* Using our own gid, no need to change it */
+ *gid_r = (gid_t)-1;
+ } else {
+ *gid_r = st.st_gid;
+ }
+ }
- /* Recurse */
- T_BEGIN {
- ret = sieve_storage_verify_dir(t_strdup_until(path, p), mode_r, gid_r);
- } T_END;
+ if ( debug ) {
+ i_debug("sieve-storage: using permissions from %s: mode=0%o gid=%ld",
+ path, (int)*dir_mode_r, *gid_r == (gid_t)-1 ? -1L : (long)*gid_r);
+ }
+}
- if ( ret < 0 )
- return -1;
+static int mkdir_verify
+(const char *dir, mode_t mode, gid_t gid, const char *gid_origin, bool debug)
+{
+ struct stat st;
- if ( mkdir_chown(path, *mode_r, (uid_t) -1, *gid_r) < 0 )
- return -1;
+ if ( stat(dir, &st) == 0 )
+ return 0;
- return 0;
- }
-
- /* Report back permission bits and group id back to caller */
-
- if ( !S_ISDIR(st.st_mode) ) {
- i_error("sieve-storage: Path is not a directory: %s", path);
+ if ( errno != ENOENT ) {
+ i_error("sieve-storage: stat(%s) failed: %m", dir);
return -1;
}
- *mode_r = st.st_mode & MAX_DIR_CREATE_MODE & 0777;
-
- /* Check whether changing GID will be necessary */
- if ( (st.st_mode & S_ISGID) != 0 ) {
- /* Setgid bit set */
- *gid_r = (gid_t) -1;
- } else if ( getegid() == st.st_gid ) {
- *gid_r = (gid_t) -1;
- } else {
- *gid_r = st.st_gid;
+ if ( mkdir_parents_chgrp(dir, mode, gid, gid_origin) == 0 ) {
+ if ( debug )
+ i_debug("sieve-storage: created storage directory %s", dir);
+ return 0;
}
- return 0;
+ if ( errno == EEXIST ) {
+ return 0;
+ } else if (errno == ENOENT) {
+ i_error("sieve-storage: storage was deleted while it was being created");
+ } else if (errno == EACCES) {
+ i_error("sieve-storage: %s", eacces_error_get_creating("mkdir", dir));
+ } else {
+ i_error("sieve-storage: mkdir(%s) failed: %m", dir);
+ }
+
+ return -1;
}
static struct sieve_storage *_sieve_storage_create
@@ -132,8 +171,9 @@
struct sieve_storage *storage;
const char *tmp_dir, *link_path;
const char *sieve_data, *active_path, *active_fname, *storage_dir;
- mode_t dir_mode;
- gid_t dir_gid;
+ mode_t dir_create_mode, file_create_mode;
+ gid_t file_create_gid;
+ const char *file_create_gid_origin;
unsigned long long int uint_setting;
size_t size_setting;
@@ -242,16 +282,27 @@
"using sieve script storage directory: %s", storage_dir);
}
+ /* Get permissions */
+
+ sieve_storage_get_permissions
+ (storage_dir, &file_create_mode, &dir_create_mode, &file_create_gid,
+ &file_create_gid_origin, debug);
+
/*
* Ensure sieve local directory structure exists (full autocreate):
* This currently currently only consists of a ./tmp direcory
*/
- tmp_dir = t_strconcat( storage_dir, "/tmp", NULL );
- if ( sieve_storage_verify_dir(tmp_dir, &dir_mode, &dir_gid) < 0 ) {
- i_error("sieve-storage: sieve_storage_verify_dir(%s) failed: %m", tmp_dir);
+
+ tmp_dir = t_strconcat(storage_dir, "/tmp", NULL);
+
+ /*ret = maildir_check_tmp(box->storage, box->path);
+ if (ret < 0)
+ return -1;*/
+
+ if ( mkdir_verify(tmp_dir, dir_create_mode, file_create_gid,
+ file_create_gid_origin, debug) < 0 )
return NULL;
- }
-
+
/*
* Create storage object
*/
@@ -266,9 +317,9 @@
storage->active_path = p_strdup(pool, active_path);
storage->active_fname = p_strdup(pool, active_fname);
- storage->dir_create_mode = dir_mode;
- storage->file_create_mode = dir_mode & 0666;
- storage->dir_create_gid = dir_gid;
+ storage->dir_create_mode = dir_create_mode;
+ storage->file_create_mode = file_create_mode;
+ storage->file_create_gid = file_create_gid;
/* Get the path to be prefixed to the script name in the symlink pointing
* to the active script.
More information about the dovecot-cvs
mailing list