diff options
Diffstat (limited to 'src/basic/path-util.c')
-rw-r--r-- | src/basic/path-util.c | 80 |
1 files changed, 68 insertions, 12 deletions
diff --git a/src/basic/path-util.c b/src/basic/path-util.c index 6810bf6..068fb42 100644 --- a/src/basic/path-util.c +++ b/src/basic/path-util.c @@ -217,8 +217,10 @@ int path_make_relative_parent(const char *from_child, const char *to, char **ret return path_make_relative(from, to, ret); } -char* path_startswith_strv(const char *p, char **set) { - STRV_FOREACH(s, set) { +char* path_startswith_strv(const char *p, char * const *strv) { + assert(p); + + STRV_FOREACH(s, strv) { char *t; t = path_startswith(p, *s); @@ -525,6 +527,18 @@ int path_compare_filename(const char *a, const char *b) { return strcmp(fa, fb); } +int path_equal_or_inode_same_full(const char *a, const char *b, int flags) { + /* Returns true if paths are of the same entry, false if not, <0 on error. */ + + if (path_equal(a, b)) + return 1; + + if (!a || !b) + return 0; + + return inode_same(a, b, flags); +} + char* path_extend_internal(char **x, ...) { size_t sz, old_sz; char *q, *nx; @@ -684,7 +698,7 @@ int find_executable_full( * binary. */ p = getenv("PATH"); if (!p) - p = DEFAULT_PATH; + p = default_PATH(); if (exec_search_path) { STRV_FOREACH(element, exec_search_path) { @@ -1094,7 +1108,6 @@ int path_extract_filename(const char *path, char **ret) { } int path_extract_directory(const char *path, char **ret) { - _cleanup_free_ char *a = NULL; const char *c, *next = NULL; int r; @@ -1118,14 +1131,10 @@ int path_extract_directory(const char *path, char **ret) { if (*path != '/') /* filename only */ return -EDESTADDRREQ; - a = strdup("/"); - if (!a) - return -ENOMEM; - *ret = TAKE_PTR(a); - return 0; + return strdup_to(ret, "/"); } - a = strndup(path, next - path); + _cleanup_free_ char *a = strndup(path, next - path); if (!a) return -ENOMEM; @@ -1336,6 +1345,20 @@ bool dot_or_dot_dot(const char *path) { return path[2] == 0; } +bool path_implies_directory(const char *path) { + + /* Sometimes, if we look at a path we already know it must refer to a directory, because it is + * suffixed with a slash, or its last component is "." or ".." */ + + if (!path) + return false; + + if (dot_or_dot_dot(path)) + return true; + + return ENDSWITH_SET(path, "/", "/.", "/.."); +} + bool empty_or_root(const char *path) { /* For operations relative to some root directory, returns true if the specified root directory is @@ -1347,7 +1370,9 @@ bool empty_or_root(const char *path) { return path_equal(path, "/"); } -bool path_strv_contains(char **l, const char *path) { +bool path_strv_contains(char * const *l, const char *path) { + assert(path); + STRV_FOREACH(i, l) if (path_equal(*i, path)) return true; @@ -1355,7 +1380,9 @@ bool path_strv_contains(char **l, const char *path) { return false; } -bool prefixed_path_strv_contains(char **l, const char *path) { +bool prefixed_path_strv_contains(char * const *l, const char *path) { + assert(path); + STRV_FOREACH(i, l) { const char *j = *i; @@ -1363,6 +1390,7 @@ bool prefixed_path_strv_contains(char **l, const char *path) { j++; if (*j == '+') j++; + if (path_equal(j, path)) return true; } @@ -1432,3 +1460,31 @@ int path_glob_can_match(const char *pattern, const char *prefix, char **ret) { *ret = NULL; return false; } + +const char* default_PATH(void) { +#if HAVE_SPLIT_BIN + static int split = -1; + 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; +#endif + return DEFAULT_PATH_WITHOUT_SBIN; +} |