1 /* SPDX-License-Identifier: LGPL-2.1+ */
3 This file is part of systemd.
5 Copyright 2010-2012 Lennart Poettering
7 systemd is free software; you can redistribute it and/or modify it
8 under the terms of the GNU Lesser General Public License as published by
9 the Free Software Foundation; either version 2.1 of the License, or
10 (at your option) any later version.
12 systemd is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 Lesser General Public License for more details.
17 You should have received a copy of the GNU Lesser General Public License
18 along with systemd; If not, see <http://www.gnu.org/licenses/>.
29 /* When we include libgen.h because we need dirname() we immediately
30 * undefine basename() since libgen.h defines it as a macro to the
31 * POSIX version which is really broken. We prefer GNU basename(). */
35 #include "alloc-util.h"
36 #include "extract-word.h"
38 //#include "glob-util.h"
42 #include "parse-util.h"
43 #include "path-util.h"
44 #include "stat-util.h"
45 #include "string-util.h"
47 #include "time-util.h"
49 bool path_is_absolute(const char *p) {
53 bool is_path(const char *p) {
54 return !!strchr(p, '/');
57 #if 0 /// UNNEEDED by elogind
58 int path_split_and_make_absolute(const char *p, char ***ret) {
65 l = strv_split(p, ":");
69 r = path_strv_make_absolute_cwd(l);
79 char *path_make_absolute(const char *p, const char *prefix) {
82 /* Makes every item in the list an absolute path by prepending
83 * the prefix, if specified and necessary */
85 if (path_is_absolute(p) || isempty(prefix))
88 if (endswith(prefix, "/"))
89 return strjoin(prefix, p);
91 return strjoin(prefix, "/", p);
95 int path_make_absolute_cwd(const char *p, char **ret) {
101 /* Similar to path_make_absolute(), but prefixes with the
102 * current working directory. */
104 if (path_is_absolute(p))
107 _cleanup_free_ char *cwd = NULL;
109 cwd = get_current_dir_name();
111 return negative_errno();
113 c = strjoin(cwd, "/", p);
122 #if 0 /// UNNEEDED by elogind
123 int path_make_relative(const char *from_dir, const char *to_path, char **_r) {
131 /* Strips the common part, and adds ".." elements as necessary. */
133 if (!path_is_absolute(from_dir))
136 if (!path_is_absolute(to_path))
139 /* Skip the common part. */
143 from_dir += strspn(from_dir, "/");
144 to_path += strspn(to_path, "/");
148 /* from_dir equals to_path. */
151 /* from_dir is a parent directory of to_path. */
156 path_kill_slashes(r);
165 a = strcspn(from_dir, "/");
166 b = strcspn(to_path, "/");
171 if (memcmp(from_dir, to_path, a) != 0)
178 /* If we're here, then "from_dir" has one or more elements that need to
179 * be replaced with "..". */
181 /* Count the number of necessary ".." elements. */
182 for (n_parents = 0;;) {
185 from_dir += strspn(from_dir, "/");
190 w = strcspn(from_dir, "/");
192 /* If this includes ".." we can't do a simple series of "..", refuse */
193 if (w == 2 && from_dir[0] == '.' && from_dir[1] == '.')
196 /* Count number of elements, except if they are "." */
197 if (w != 1 || from_dir[0] != '.')
203 r = new(char, n_parents * 3 + strlen(to_path) + 1);
207 for (p = r; n_parents > 0; n_parents--)
208 p = mempcpy(p, "../", 3);
211 path_kill_slashes(r);
217 int path_strv_make_absolute_cwd(char **l) {
221 /* Goes through every item in the string list and makes it
222 * absolute. This works in place and won't rollback any
223 * changes on failure. */
228 r = path_make_absolute_cwd(*s, &t);
232 path_kill_slashes(t);
233 free_and_replace(*s, t);
240 char **path_strv_resolve(char **l, const char *root) {
249 /* Goes through every item in the string list and canonicalize
250 * the path. This works in place and won't rollback any
251 * changes on failure. */
254 _cleanup_free_ char *orig = NULL;
257 if (!path_is_absolute(*s)) {
264 t = prefix_root(root, orig);
272 r = chase_symlinks(t, root, 0, &u);
291 x = path_startswith(u, root);
293 /* restore the slash if it was lost */
294 if (!startswith(x, "/"))
305 /* canonicalized path goes outside of
306 * prefix, keep the original path instead */
307 free_and_replace(u, orig);
323 char **path_strv_resolve_uniq(char **l, const char *root) {
328 if (!path_strv_resolve(l, root))
334 char *path_kill_slashes(char *path) {
338 /* Removes redundant inner and trailing slashes. Modifies the
339 * passed string in-place.
341 * ///foo///bar/ becomes /foo/bar
344 for (f = path, t = path; *f; f++) {
359 /* Special rule, if we are talking of the root directory, a
360 trailing slash is good */
362 if (t == path && slash)
369 char* path_startswith(const char *path, const char *prefix) {
373 /* Returns a pointer to the start of the first component after the parts matched by
375 * - both paths are absolute or both paths are relative,
377 * - each component in prefix in turn matches a component in path at the same position.
378 * An empty string will be returned when the prefix and path are equivalent.
380 * Returns NULL otherwise.
383 if ((path[0] == '/') != (prefix[0] == '/'))
389 path += strspn(path, "/");
390 prefix += strspn(prefix, "/");
398 a = strcspn(path, "/");
399 b = strcspn(prefix, "/");
404 if (memcmp(path, prefix, a) != 0)
412 int path_compare(const char *a, const char *b) {
418 /* A relative path and an abolute path must not compare as equal.
419 * Which one is sorted before the other does not really matter.
420 * Here a relative path is ordered before an absolute path. */
421 d = (a[0] == '/') - (b[0] == '/');
431 if (*a == 0 && *b == 0)
434 /* Order prefixes first: "/foo" before "/foo/bar" */
443 /* Alphabetical sort: "/foo/aaa" before "/foo/b" */
444 d = memcmp(a, b, MIN(j, k));
446 return (d > 0) - (d < 0); /* sign of d */
448 /* Sort "/foo/a" before "/foo/aaa" */
449 d = (j > k) - (j < k); /* sign of (j - k) */
458 bool path_equal(const char *a, const char *b) {
459 return path_compare(a, b) == 0;
462 bool path_equal_or_files_same(const char *a, const char *b, int flags) {
463 return path_equal(a, b) || files_same(a, b, flags) > 0;
466 char* path_join(const char *root, const char *path, const char *rest) {
470 return strjoin(root, endswith(root, "/") ? "" : "/",
471 path[0] == '/' ? path+1 : path,
472 rest ? (endswith(path, "/") ? "" : "/") : NULL,
473 rest && rest[0] == '/' ? rest+1 : rest);
476 rest ? (endswith(path, "/") ? "" : "/") : NULL,
477 rest && rest[0] == '/' ? rest+1 : rest);
480 int find_binary(const char *name, char **ret) {
487 if (access(name, X_OK) < 0)
491 r = path_make_absolute_cwd(name, ret);
500 * Plain getenv, not secure_getenv, because we want
501 * to actually allow the user to pick the binary.
507 last_error = -ENOENT;
510 _cleanup_free_ char *j = NULL, *element = NULL;
512 r = extract_first_word(&p, &element, ":", EXTRACT_RELAX|EXTRACT_DONT_COALESCE_SEPARATORS);
518 if (!path_is_absolute(element))
521 j = strjoin(element, "/", name);
525 if (access(j, X_OK) >= 0) {
529 *ret = path_kill_slashes(j);
542 #if 0 /// UNNEEDED by elogind
543 bool paths_check_timestamp(const char* const* paths, usec_t *timestamp, bool update) {
544 bool changed = false;
545 const char* const* i;
552 STRV_FOREACH(i, paths) {
556 if (stat(*i, &stats) < 0)
559 u = timespec_load(&stats.st_mtim);
565 log_debug("timestamp of '%s' changed", *i);
567 /* update timestamp */
578 static int binary_is_good(const char *binary) {
579 _cleanup_free_ char *p = NULL, *d = NULL;
582 r = find_binary(binary, &p);
588 /* An fsck that is linked to /bin/true is a non-existent
591 r = readlink_malloc(p, &d);
592 if (r == -EINVAL) /* not a symlink */
597 return !PATH_IN_SET(d, "true"
603 int fsck_exists(const char *fstype) {
608 if (streq(fstype, "auto"))
611 checker = strjoina("fsck.", fstype);
612 return binary_is_good(checker);
615 int mkfs_exists(const char *fstype) {
620 if (streq(fstype, "auto"))
623 mkfs = strjoina("mkfs.", fstype);
624 return binary_is_good(mkfs);
628 char *prefix_root(const char *root, const char *path) {
632 /* If root is passed, prefixes path with it. Otherwise returns
637 /* First, drop duplicate prefixing slashes from the path */
638 while (path[0] == '/' && path[1] == '/')
641 if (isempty(root) || path_equal(root, "/"))
644 l = strlen(root) + 1 + strlen(path) + 1;
652 while (p > n && p[-1] == '/')
662 #if 0 /// UNNEEDED by elogind
663 int parse_path_argument_and_warn(const char *path, bool suppress_root, char **arg) {
668 * This function is intended to be used in command line
669 * parsers, to handle paths that are passed in. It makes the
670 * path absolute, and reduces it to NULL if omitted or
671 * root (the latter optionally).
673 * NOTE THAT THIS WILL FREE THE PREVIOUS ARGUMENT POINTER ON
674 * SUCCESS! Hence, do not pass in uninitialized pointers.
682 r = path_make_absolute_cwd(path, &p);
684 return log_error_errno(r, "Failed to parse path \"%s\" and make it absolute: %m", path);
686 path_kill_slashes(p);
687 if (suppress_root && path_equal(p, "/"))
696 char* dirname_malloc(const char *path) {
697 char *d, *dir, *dir2;
717 const char *last_path_component(const char *path) {
718 /* Finds the last component of the path, preserving the
719 * optional trailing slash that signifies a directory.
726 * This is different than basename, which returns "" when
727 * a trailing slash is present.
732 l = k = strlen(path);
733 if (l == 0) /* special case — an empty string */
736 while (k > 0 && path[k-1] == '/')
739 if (k == 0) /* the root directory */
742 while (k > 0 && path[k-1] != '/')
748 bool filename_is_valid(const char *p) {
754 if (dot_or_dot_dot(p))
757 e = strchrnul(p, '/');
761 if (e - p > FILENAME_MAX)
767 bool path_is_normalized(const char *p) {
772 if (dot_or_dot_dot(p))
775 if (startswith(p, "../") || endswith(p, "/..") || strstr(p, "/../"))
778 if (strlen(p)+1 > PATH_MAX)
781 if (startswith(p, "./") || endswith(p, "/.") || strstr(p, "/./"))
790 char *file_in_same_dir(const char *path, const char *filename) {
797 /* This removes the last component of path and appends
798 * filename, unless the latter is absolute anyway or the
801 if (path_is_absolute(filename))
802 return strdup(filename);
804 e = strrchr(path, '/');
806 return strdup(filename);
808 k = strlen(filename);
809 ret = new(char, (e + 1 - path) + k + 1);
813 memcpy(mempcpy(ret, path, e + 1 - path), filename, k + 1);
817 bool hidden_or_backup_file(const char *filename) {
822 if (filename[0] == '.' ||
823 streq(filename, "lost+found") ||
824 streq(filename, "aquota.user") ||
825 streq(filename, "aquota.group") ||
826 endswith(filename, "~"))
829 p = strrchr(filename, '.');
833 /* Please, let's not add more entries to the list below. If external projects think it's a good idea to come up
834 * with always new suffixes and that everybody else should just adjust to that, then it really should be on
835 * them. Hence, in future, let's not add any more entries. Instead, let's ask those packages to instead adopt
836 * one of the generic suffixes/prefixes for hidden files or backups, possibly augmented with an additional
837 * string. Specifically: there's now:
839 * The generic suffixes "~" and ".bak" for backup files
840 * The generic prefix "." for hidden files
842 * Thus, if a new package manager "foopkg" wants its own set of ".foopkg-new", ".foopkg-old", ".foopkg-dist"
843 * or so registered, let's refuse that and ask them to use ".foopkg.new", ".foopkg.old" or ".foopkg~" instead.
846 return STR_IN_SET(p + 1,
866 #if 0 /// UNNEEDED by elogind
867 bool is_device_path(const char *path) {
869 /* Returns true on paths that refer to a device, either in
870 * sysfs or in /dev */
872 return path_startswith(path, "/dev/") ||
873 path_startswith(path, "/sys/");
876 bool is_deviceallow_pattern(const char *path) {
877 return path_startswith(path, "/dev/") ||
878 startswith(path, "block-") ||
879 startswith(path, "char-");
882 int systemd_installation_has_version(const char *root, unsigned minimal_version) {
886 /* Try to guess if systemd installation is later than the specified version. This
887 * is hacky and likely to yield false negatives, particularly if the installation
888 * is non-standard. False positives should be relatively rare.
891 NULSTR_FOREACH(pattern,
892 /* /lib works for systems without usr-merge, and for systems with a sane
893 * usr-merge, where /lib is a symlink to /usr/lib. /usr/lib is necessary
894 * for Gentoo which does a merge without making /lib a symlink.
896 "lib/systemd/libsystemd-shared-*.so\0"
897 "lib64/systemd/libsystemd-shared-*.so\0"
898 "usr/lib/systemd/libsystemd-shared-*.so\0"
899 "usr/lib64/systemd/libsystemd-shared-*.so\0") {
901 _cleanup_strv_free_ char **names = NULL;
902 _cleanup_free_ char *path = NULL;
905 path = prefix_root(root, pattern);
909 r = glob_extend(&names, path);
915 assert_se((c = endswith(path, "*.so")));
916 *c = '\0'; /* truncate the glob part */
918 STRV_FOREACH(name, names) {
919 /* This is most likely to run only once, hence let's not optimize anything. */
923 t = startswith(*name, path);
927 t2 = endswith(t, ".so");
931 t2[0] = '\0'; /* truncate the suffix */
933 r = safe_atou(t, &version);
935 log_debug_errno(r, "Found libsystemd shared at \"%s.so\", but failed to parse version: %m", *name);
939 log_debug("Found libsystemd shared at \"%s.so\", version %u (%s).",
941 version >= minimal_version ? "OK" : "too old");
942 if (version >= minimal_version)
951 bool dot_or_dot_dot(const char *path) {