return false;
}
-const char* default_PATH(void) {
#if HAVE_SPLIT_BIN
- static int split = -1;
+static bool dir_is_split(const char *a, const char *b) {
int r;
- /* Check whether /usr/sbin is not a symlink and return the appropriate $PATH.
- * On error fall back to the safe value with both directories as configured… */
-
- if (split < 0)
- STRV_FOREACH_PAIR(bin, sbin, STRV_MAKE("/usr/bin", "/usr/sbin",
- "/usr/local/bin", "/usr/local/sbin")) {
- r = inode_same(*bin, *sbin, AT_NO_AUTOMOUNT);
- if (r > 0 || r == -ENOENT)
- continue;
- if (r < 0)
- log_debug_errno(r, "Failed to compare \"%s\" and \"%s\", using compat $PATH: %m",
- *bin, *sbin);
- split = true;
- break;
- }
- if (split < 0)
- split = false;
- if (split)
- return DEFAULT_PATH_WITH_SBIN;
+ r = inode_same(a, b, AT_NO_AUTOMOUNT);
+ if (r < 0 && r != -ENOENT) {
+ log_debug_errno(r, "Failed to compare \"%s\" and \"%s\", assuming split directories: %m", a, b);
+ return true;
+ }
+ return r == 0;
+}
#endif
+
+const char* default_PATH(void) {
+#if HAVE_SPLIT_BIN
+ static const char *default_path = NULL;
+
+ /* Return one of the three sets of paths:
+ * a) split /usr/s?bin, /usr/local/sbin doesn't matter.
+ * b) merged /usr/s?bin, /usr/sbin is a symlink, but /usr/local/sbin is not,
+ * c) fully merged, neither /usr/sbin nor /usr/local/sbin are symlinks,
+ *
+ * On error the fallback to the safe value with both directories as configured is returned.
+ */
+
+ if (default_path)
+ return default_path;
+
+ if (dir_is_split("/usr/sbin", "/usr/bin"))
+ return (default_path = DEFAULT_PATH_WITH_FULL_SBIN); /* a */
+ if (dir_is_split("/usr/local/sbin", "/usr/local/bin"))
+ return (default_path = DEFAULT_PATH_WITH_LOCAL_SBIN); /* b */
+ return (default_path = DEFAULT_PATH_WITHOUT_SBIN); /* c */
+#else
return DEFAULT_PATH_WITHOUT_SBIN;
+#endif
}
#define PATH_MERGED_BIN(x) x "bin"
#define PATH_MERGED_BIN_NULSTR(x) x "bin\0"
-#define DEFAULT_PATH_WITH_SBIN PATH_SPLIT_BIN("/usr/local/") ":" PATH_SPLIT_BIN("/usr/")
+#define DEFAULT_PATH_WITH_FULL_SBIN PATH_SPLIT_BIN("/usr/local/") ":" PATH_SPLIT_BIN("/usr/")
+#define DEFAULT_PATH_WITH_LOCAL_SBIN PATH_SPLIT_BIN("/usr/local/") ":" PATH_MERGED_BIN("/usr/")
#define DEFAULT_PATH_WITHOUT_SBIN PATH_MERGED_BIN("/usr/local/") ":" PATH_MERGED_BIN("/usr/")
-#define DEFAULT_PATH_COMPAT PATH_SPLIT_BIN("/usr/local/") ":" PATH_SPLIT_BIN("/usr/") ":" PATH_SPLIT_BIN("/")
+#define DEFAULT_PATH_COMPAT DEFAULT_PATH_WITH_FULL_SBIN ":" PATH_SPLIT_BIN("/")
const char* default_PATH(void);