diff src/lib-storage/mail-error.c @ 8642:dd53d40a2f09 HEAD

Permission denied error handling can now suggest missing +w permissions.
author Timo Sirainen <tss@iki.fi>
date Fri, 16 Jan 2009 12:45:06 -0500
parents 02ba04b6aa07
children 97a350198a4f
line wrap: on
line diff
--- a/src/lib-storage/mail-error.c	Fri Jan 16 12:29:30 2009 -0500
+++ b/src/lib-storage/mail-error.c	Fri Jan 16 12:45:06 2009 -0500
@@ -28,7 +28,8 @@
 	return TRUE;
 }
 
-const char *mail_error_eacces_msg(const char *func, const char *path)
+static const char *
+mail_error_eacces_msg_full(const char *func, const char *path, bool creating)
 {
 	const char *prev_path = path, *dir = "/", *p;
 	const struct passwd *pw;
@@ -53,21 +54,52 @@
 	while ((p = strrchr(prev_path, '/')) != NULL) {
 		dir = t_strdup_until(prev_path, p);
 		ret = stat(dir, &st);
-		if (ret == 0 || errno != EACCES)
+		if (ret == 0)
 			break;
+		if (errno == EACCES) {
+			/* see if we have access to parent directory */
+		} else if (errno == ENOENT && creating) {
+			/* probably mkdir_parents() failed here, find the first
+			   parent directory we couldn't create */
+		} else {
+			/* some other error, can't handle it */
+			str_printfa(errmsg, " stat(%s) failed: %m", dir);
+			break;
+		}
 		prev_path = dir;
 		dir = "/";
 	}
 
 	if (ret == 0) {
-		if (access(dir, X_OK) < 0 && errno == EACCES)
-			str_printfa(errmsg, " missing +x perm: %s", dir);
-		else if (prev_path == path &&
-			 access(path, R_OK) < 0 && errno == EACCES)
-			str_printfa(errmsg, " missing +r perm: %s", path);
-		else
+		/* dir is the first parent directory we can stat() */
+		if (access(dir, X_OK) < 0) {
+			if (errno == EACCES)
+				str_printfa(errmsg, " missing +x perm: %s", dir);
+			else
+				str_printfa(errmsg, " access(%s, x) failed: %m", dir);
+		} else if (prev_path == path && access(path, R_OK) < 0) {
+			if (errno == EACCES)
+				str_printfa(errmsg, " missing +r perm: %s", path);
+			else
+				str_printfa(errmsg, " access(%s, r) failed: %m", path);
+		} else if (creating && access(dir, W_OK) < 0) {
+			if (errno == EACCES)
+				str_printfa(errmsg, " missing +w perm: %s", dir);
+			else
+				str_printfa(errmsg, " access(%s, w) failed: %m", dir);
+		} else
 			str_printfa(errmsg, " UNIX perms seem ok, ACL problem?");
 	}
 	str_append_c(errmsg, ')');
 	return str_c(errmsg);
 }
+
+const char *mail_error_eacces_msg(const char *func, const char *path)
+{
+	return mail_error_eacces_msg_full(func, path, FALSE);
+}
+
+const char *mail_error_create_eacces_msg(const char *func, const char *path)
+{
+	return mail_error_eacces_msg_full(func, path, TRUE);
+}