I've created a patch that adds a feature that is helpful to my setup. If
'parent_dir_umask' is set in the configuration file, any missing
directories in the home directory path are created.
The home directory itself is created according to the 'umask' setting,
'parent_dir_umask' is only used for intermediate directories that might
need creating.
This is useful to me, as I pull user information from a PostgreSQL
database. This allows a new account to be created just by populating the
database. The directory gets created the first time the user logs in (by
Dovecot) or mail is received (by the MTA).
As the patch is of modest length, I have included it below. I hope my
meager skills are not an insult to the beatiful Dovecot code base!
Thanks,
David
*** ./src/master/mail-process.c.orig Wed Sep 10 10:14:04 2003
--- ./src/master/mail-process.c Wed Sep 10 12:16:06 2003
***************
*** 95,100 ****
--- 95,136 ----
return str_c(str);
}
+ static int create_directories(const char *directory, mode_t mask) + {
+ char *chunk, *slash, *path;
+ mode_t oldmask;
+ int result;
+
+ if (mkdir(directory, 0777) == 0 || errno == EEXIST)
+ return TRUE;
+
+ if (errno != ENOENT)
+ return FALSE;
+
+ path = t_strdup_noconst(directory);
+
+ oldmask = umask(mask);
+
+ for (chunk = path; (slash = strchr(chunk, '/')); chunk = slash + 1) {
+
+ if (slash > chunk) {
+
+ *slash = '\0';
+ result = mkdir(path, 0777);
+ *slash = '/';
+
+ if (result != 0 && errno != EEXIST) {
+ umask(oldmask);
+ return FALSE;
+ }
+ }
+ }
+
+ umask(oldmask);
+
+ return (mkdir(path, 0777) == 0 || errno == EEXIST);
+ }
+
int create_mail_process(int socket, struct ip_addr *ip,
const char *executable, const char *module_dir,
unsigned int process_size, int process_type,
***************
*** 156,164 ****
--- 192,205 ----
restrict_process_size(process_size, (unsigned int)-1);
+ (void)umask(set->umask);
+
if (*home_dir != '\0') {
full_home_dir = *chroot_dir == '\0' ? home_dir :
t_strconcat(chroot_dir, "/", home_dir, NULL);
+ if (set->parent_dir_umask != 0777 &&
+ !create_directories(full_home_dir, set->parent_dir_umask)) +
i_fatal("mkdir(%s) failed: %m", full_home_dir);
if (chdir(full_home_dir) < 0)
i_fatal("chdir(%s) failed: %m", full_home_dir);
}
***************
*** 188,194 ****
env_put("MAILDIR_CHECK_CONTENT_CHANGES=1");
if (set->mail_full_filesystem_access)
env_put("FULL_FILESYSTEM_ACCESS=1");
- (void)umask(set->umask);
env_put(t_strconcat("MBOX_LOCKS=", set->mbox_locks, NULL));
env_put(t_strdup_printf("MBOX_LOCK_TIMEOUT=%u",
--- 229,234 ----
*** ./src/master/master-settings.h.orig Wed Sep 10 12:13:45 2003
--- ./src/master/master-settings.h Wed Sep 10 12:13:47 2003
***************
*** 51,56 ****
--- 51,57 ----
int mbox_read_dotlock;
unsigned int mbox_lock_timeout;
unsigned int mbox_dotlock_change_timeout;
+ unsigned int parent_dir_umask;
unsigned int umask;
int mail_drop_priv_before_exec;
*** ./src/master/master-settings.c.orig Wed Sep 10 12:13:59 2003
--- ./src/master/master-settings.c Wed Sep 10 12:14:40 2003
***************
*** 67,72 ****
--- 67,73 ----
DEF(SET_BOOL, mbox_read_dotlock),
DEF(SET_INT, mbox_lock_timeout),
DEF(SET_INT, mbox_dotlock_change_timeout),
+ DEF(SET_INT, parent_dir_umask),
DEF(SET_INT, umask),
DEF(SET_BOOL, mail_drop_priv_before_exec),
***************
*** 180,185 ****
--- 181,187 ----
MEMBER(mbox_read_dotlock) FALSE,
MEMBER(mbox_lock_timeout) 300,
MEMBER(mbox_dotlock_change_timeout) 30,
+ MEMBER(parent_dir_umask) 0777,
MEMBER(umask) 0077,
MEMBER(mail_drop_priv_before_exec) FALSE,