diff src/lib-storage/mail-error.c @ 8518:1e42b631f037 HEAD

Improved "Permission denied" error handling. It'll now show also the uid/gid name. Also moved the code to mail-error.c and used it when listing mailboxes.
author Timo Sirainen <tss@iki.fi>
date Sat, 06 Dec 2008 00:20:02 +0200
parents 7ed926ed7aa4
children b9faf4db2a9f
line wrap: on
line diff
--- a/src/lib-storage/mail-error.c	Sat Dec 06 00:08:01 2008 +0200
+++ b/src/lib-storage/mail-error.c	Sat Dec 06 00:20:02 2008 +0200
@@ -1,8 +1,14 @@
 /* Copyright (c) 2007-2008 Dovecot authors, see the included COPYING file */
 
 #include "lib.h"
+#include "str.h"
 #include "mail-error.h"
 
+#include <sys/stat.h>
+#include <unistd.h>
+#include <pwd.h>
+#include <grp.h>
+
 bool mail_error_from_errno(enum mail_error *error_r,
 			   const char **error_string_r)
 {
@@ -21,3 +27,45 @@
 	}
 	return TRUE;
 }
+
+const char *mail_error_eacces_msg(const char *func, const char *path)
+{
+	const char *prev_path = path, *dir = "/", *p;
+	const struct passwd *pw;
+	const struct group *group;
+	string_t *errmsg;
+	struct stat st;
+	int ret = -1;
+
+	errmsg = t_str_new(256);
+	str_printfa(errmsg, "%s(%s) failed: Permission denied (euid=%s",
+		    func, path, dec2str(geteuid()));
+
+	pw = getpwuid(geteuid());
+	if (pw != NULL)
+		str_printfa(errmsg, "(%s)", pw->pw_name);
+
+	str_printfa(errmsg, " egid=%s", dec2str(getegid()));
+	group = getgrgid(getegid());
+	if (group != NULL)
+		str_printfa(errmsg, "(%s)", group->gr_name);
+
+	while ((p = strrchr(prev_path, '/')) != NULL) {
+		dir = t_strdup_until(prev_path, p);
+		ret = stat(dir, &st);
+		if (ret == 0 || errno != EACCES)
+			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);
+	}
+	str_append_c(errmsg, ')');
+	return str_c(errmsg);
+}