changeset 9085:36d823adb302 HEAD

deliver: If temp file can't be created because home dir doesn't exist, create it.
author Timo Sirainen <tss@iki.fi>
date Mon, 25 May 2009 22:34:38 -0400
parents 82949209612e
children c7db09d796b9
files src/deliver/deliver.c
diffstat 1 files changed, 37 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- a/src/deliver/deliver.c	Mon May 25 22:18:55 2009 -0400
+++ b/src/deliver/deliver.c	Mon May 25 22:34:38 2009 -0400
@@ -20,6 +20,8 @@
 #include "str-sanitize.h"
 #include "strescape.h"
 #include "safe-mkstemp.h"
+#include "mkdir-parents.h"
+#include "eacces-error.h"
 #include "close-keep-errno.h"
 #include "var-expand.h"
 #include "rfc822-parser.h"
@@ -611,15 +613,50 @@
 	return ret;
 }
 
+static int deliver_create_dir(struct mail_user *user, const char *dir)
+{
+	struct mail_namespace *ns;
+	mode_t mode;
+	gid_t gid;
+
+	ns = mail_namespace_find_inbox(user->namespaces);
+	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) {
+		return 0;
+	} else if (errno == EACCES) {
+		i_error("%s", eacces_error_get_creating("mkdir_parents_chown",
+							dir));
+		return -1;
+	} else {
+		i_error("mkdir_parents_chown(%s, gid=%s) failed: %m",
+			dir, dec2str(gid));
+		return -1;
+	}
+}
+
 static int seekable_fd_callback(const char **path_r, void *context)
 {
 	struct mail_user *user = context;
+	const char *dir, *p;
 	string_t *path;
 	int fd;
 
 	path = t_str_new(128);
 	str_append(path, mail_user_get_temp_prefix(user));
 	fd = safe_mkstemp(path, 0600, (uid_t)-1, (gid_t)-1);
+	if (fd == -1 && errno == ENOENT) {
+		dir = str_c(path);
+		p = strrchr(dir, '/');
+		if (p != NULL) {
+			dir = t_strdup_until(dir, p);
+			if (deliver_create_dir(user, dir) < 0)
+				return -1;
+			fd = safe_mkstemp(path, 0600, (uid_t)-1, (gid_t)-1);
+		}
+	}
 	if (fd == -1) {
 		i_error("safe_mkstemp(%s) failed: %m", str_c(path));
 		return -1;