load-fragment: ignore ENOTDIR/EACCES errors (#3510)

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.
This commit is contained in:
Zbigniew Jędrzejewski-Szmek 2016-06-15 17:02:27 -04:00 committed by Lennart Poettering
parent 77d4acf332
commit a1feacf77f
2 changed files with 16 additions and 4 deletions

View 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 */

View 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;
}