load-fragment: ignore ENOTDIR/EACCES errors (#3510)
authorZbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>
Wed, 15 Jun 2016 21:02:27 +0000 (17:02 -0400)
committerLennart Poettering <lennart@poettering.net>
Wed, 15 Jun 2016 21:02:27 +0000 (23:02 +0200)
If for whatever reason the file system is "corrupted", we want
to be resilient and ignore the error, as long as we can load the units
from a different place.

Arch bug https://bugs.archlinux.org/task/49547.

A user had an ntfs symlink (essentially a file) instead of a directory after
restoring from backup. We should just ignore that like we would treat a missing
directory, for general resiliency.

We should treat permission errors similarly. For example an unreadable
/usr/local/lib directory would prevent (user) instances of systemd from
loading any units. It seems better to continue.

src/core/load-fragment.c
src/shared/install.c

index 17c72ae..d42f517 100644 (file)
@@ -3830,7 +3830,15 @@ static int load_from_path(Unit *u, const char *path) {
                         if (r >= 0)
                                 break;
                         filename = mfree(filename);
-                        if (r != -ENOENT)
+
+                        /* ENOENT means that the file is missing or is a dangling symlink.
+                         * ENOTDIR means that one of paths we expect to be is a directory
+                         * is not a directory, we should just ignore that.
+                         * EACCES means that the directory or file permissions are wrong.
+                         */
+                        if (r == -EACCES)
+                                log_debug_errno(r, "Cannot access \"%s\": %m", filename);
+                        else if (!IN_SET(r, -ENOENT, -ENOTDIR))
                                 return r;
 
                         /* Empty the symlink names for the next run */
index 64d66a4..23cab96 100644 (file)
@@ -779,7 +779,7 @@ static int find_symlinks(
 
         fd = open(config_path, O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC|O_NOFOLLOW);
         if (fd < 0) {
-                if (errno == ENOENT)
+                if (IN_SET(errno, ENOENT, ENOTDIR, EACCES))
                         return 0;
                 return -errno;
         }
@@ -1271,7 +1271,7 @@ static int unit_file_search(
                         info->path = path;
                         path = NULL;
                         return r;
-                } else if (r != -ENOENT)
+                } else if (!IN_SET(r, -ENOENT, -ENOTDIR, -EACCES))
                         return r;
         }
 
@@ -1296,7 +1296,7 @@ static int unit_file_search(
                                 info->path = path;
                                 path = NULL;
                                 return r;
-                        } else if (r != -ENOENT)
+                        } else if (!IN_SET(r, -ENOENT, -ENOTDIR, -EACCES))
                                 return r;
                 }
         }
@@ -2870,6 +2870,10 @@ int unit_file_get_list(
                 if (!d) {
                         if (errno == ENOENT)
                                 continue;
+                        if (IN_SET(errno, ENOTDIR, EACCES)) {
+                                log_debug("Failed to open \"%s\": %m", *i);
+                                continue;
+                        }
 
                         return -errno;
                 }