]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
Permission denied error handling can now suggest missing +w permissions.
authorTimo Sirainen <tss@iki.fi>
Fri, 16 Jan 2009 17:45:06 +0000 (12:45 -0500)
committerTimo Sirainen <tss@iki.fi>
Fri, 16 Jan 2009 17:45:06 +0000 (12:45 -0500)
--HG--
branch : HEAD

src/lib-storage/index/cydir/cydir-storage.c
src/lib-storage/index/dbox/dbox-storage.c
src/lib-storage/index/maildir/maildir-storage.c
src/lib-storage/index/mbox/mbox-storage.c
src/lib-storage/mail-error.c
src/lib-storage/mail-error.h

index e4e77afb8dee410ea094742f588db4ac0588505b..7af9bf98e8ed09179fb86370cb63450b4f271d2a 100644 (file)
@@ -106,7 +106,8 @@ static int cydir_create(struct mail_storage *_storage, const char *data,
        } else if (mkdir_parents(list_set.root_dir,
                                 CREATE_MODE) == 0 || errno == EEXIST) {
        } else if (errno == EACCES) {
-               *error_r = mail_error_eacces_msg("mkdir", list_set.root_dir);
+               *error_r = mail_error_create_eacces_msg("mkdir",
+                                                       list_set.root_dir);
                return -1;
        } else {
                *error_r = t_strdup_printf("mkdir(%s) failed: %m",
index 77a2e2f9033aba09630a6f5e1c9a05222f38262b..d29dfb72d15228a07918d3d9562b935bc4a6c5ab 100644 (file)
@@ -120,8 +120,8 @@ static int dbox_create(struct mail_storage *_storage, const char *data,
                                 CREATE_MODE) == 0 || errno == EEXIST) {
        } else if (errno == EACCES) {
                if (_storage->ns->type != NAMESPACE_SHARED) {
-                       *error_r = mail_error_eacces_msg("mkdir",
-                                                        list_set.root_dir);
+                       *error_r = mail_error_create_eacces_msg("mkdir",
+                                                       list_set.root_dir);
                        return -1;
                }
                /* can't create a new user, but we don't want to fail
index 5068bf2089bf20032b7e5400f921bf6bb524d264..71ea3bc9135998d83c38b22c5e0a9ecd246e1084 100644 (file)
@@ -317,11 +317,15 @@ static int mkdir_verify(struct mail_storage *storage,
        } else if (errno == ENOENT) {
                mail_storage_set_error(storage, MAIL_ERROR_NOTFOUND,
                        "Mailbox was deleted while it was being created");
-       } else if (errno == EACCES && storage->ns->type == NAMESPACE_SHARED) {
-               /* shared namespace, don't log permission errors */
-               mail_storage_set_error(storage, MAIL_ERROR_PERM,
-                                      MAIL_ERRSTR_NO_PERMISSION);
-               return -1;
+       } else if (errno == EACCES) {
+               if (storage->ns->type == NAMESPACE_SHARED) {
+                       /* shared namespace, don't log permission errors */
+                       mail_storage_set_error(storage, MAIL_ERROR_PERM,
+                                              MAIL_ERRSTR_NO_PERMISSION);
+                       return -1;
+               }
+               mail_storage_set_critical(storage, "%s",
+                       mail_error_create_eacces_msg("mkdir", dir));
        } else {
                mail_storage_set_critical(storage,
                                          "mkdir(%s) failed: %m", dir);
index 3324061a7eff00d171c0e29c7171c1061da92939..df24f2d129a8bda5050806b075cd27893bb085e3 100644 (file)
@@ -502,7 +502,7 @@ static int verify_inbox(struct mail_storage *storage)
                return -1;
        } else if (errno == EACCES) {
                mail_storage_set_critical(storage, "%s",
-                       mail_error_eacces_msg("open", inbox_path));
+                       mail_error_create_eacces_msg("open", inbox_path));
                return -1;
        } else if (errno != EEXIST) {
                mail_storage_set_critical(storage,
index dd1b6faaba146f92ade709ddee92a72586385671..92b21bd643e95943c2d3f525f885dbb1aa7f7c81 100644 (file)
@@ -28,7 +28,8 @@ bool mail_error_from_errno(enum mail_error *error_r,
        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 @@ const char *mail_error_eacces_msg(const char *func, const char *path)
        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);
+}
index 213cef3f12bac50bf8d4137491535bc02e5819f6..dc00e87b4f5a3628debc1d554216af5c90b22828 100644 (file)
@@ -48,7 +48,10 @@ enum mail_error {
 bool mail_error_from_errno(enum mail_error *error_r,
                           const char **error_string_r);
 
-/* Build a helpful error message for a failed EACCESS syscall. */
+/* Build a helpful error message for a failed EACCES syscall. */
 const char *mail_error_eacces_msg(const char *func, const char *path);
+/* Build a helpful error message for a failed EACCES syscall that tried to
+   write to directory (create, rename, etc). */
+const char *mail_error_create_eacces_msg(const char *func, const char *path);
 
 #endif