1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
4 This file is part of systemd.
6 Copyright 2010-2012 Lennart Poettering
8 systemd is free software; you can redistribute it and/or modify it
9 under the terms of the GNU Lesser General Public License as published by
10 the Free Software Foundation; either version 2.1 of the License, or
11 (at your option) any later version.
13 systemd is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Lesser General Public License for more details.
18 You should have received a copy of the GNU Lesser General Public License
19 along with systemd; If not, see <http://www.gnu.org/licenses/>.
30 /* When we include libgen.h because we need dirname() we immediately
31 * undefine basename() since libgen.h defines it as a macro to the
32 * POSIX version which is really broken. We prefer GNU basename(). */
36 #include "alloc-util.h"
37 #include "extract-word.h"
42 #include "path-util.h"
43 #include "stat-util.h"
44 #include "string-util.h"
46 #include "time-util.h"
48 bool path_is_absolute(const char *p
) {
52 bool is_path(const char *p
) {
53 return !!strchr(p
, '/');
56 int path_split_and_make_absolute(const char *p
, char ***ret
) {
63 l
= strv_split(p
, ":");
67 r
= path_strv_make_absolute_cwd(l
);
77 char *path_make_absolute(const char *p
, const char *prefix
) {
80 /* Makes every item in the list an absolute path by prepending
81 * the prefix, if specified and necessary */
83 if (path_is_absolute(p
) || !prefix
)
86 return strjoin(prefix
, "/", p
, NULL
);
89 int path_make_absolute_cwd(const char *p
, char **ret
) {
95 /* Similar to path_make_absolute(), but prefixes with the
96 * current working directory. */
98 if (path_is_absolute(p
))
101 _cleanup_free_
char *cwd
= NULL
;
103 cwd
= get_current_dir_name();
107 c
= strjoin(cwd
, "/", p
, NULL
);
116 int path_make_relative(const char *from_dir
, const char *to_path
, char **_r
) {
124 /* Strips the common part, and adds ".." elements as necessary. */
126 if (!path_is_absolute(from_dir
))
129 if (!path_is_absolute(to_path
))
132 /* Skip the common part. */
137 from_dir
+= strspn(from_dir
, "/");
138 to_path
+= strspn(to_path
, "/");
142 /* from_dir equals to_path. */
145 /* from_dir is a parent directory of to_path. */
151 path_kill_slashes(r
);
160 a
= strcspn(from_dir
, "/");
161 b
= strcspn(to_path
, "/");
166 if (memcmp(from_dir
, to_path
, a
) != 0)
173 /* If we're here, then "from_dir" has one or more elements that need to
174 * be replaced with "..". */
176 /* Count the number of necessary ".." elements. */
177 for (n_parents
= 0;;) {
178 from_dir
+= strspn(from_dir
, "/");
183 from_dir
+= strcspn(from_dir
, "/");
187 r
= malloc(n_parents
* 3 + strlen(to_path
) + 1);
191 for (p
= r
; n_parents
> 0; n_parents
--, p
+= 3)
195 path_kill_slashes(r
);
201 int path_strv_make_absolute_cwd(char **l
) {
205 /* Goes through every item in the string list and makes it
206 * absolute. This works in place and won't rollback any
207 * changes on failure. */
212 r
= path_make_absolute_cwd(*s
, &t
);
223 char **path_strv_resolve(char **l
, const char *prefix
) {
231 /* Goes through every item in the string list and canonicalize
232 * the path. This works in place and won't rollback any
233 * changes on failure. */
237 _cleanup_free_
char *orig
= NULL
;
239 if (!path_is_absolute(*s
)) {
246 t
= strappend(prefix
, orig
);
255 u
= canonicalize_file_name(t
);
257 if (errno
== ENOENT
) {
266 if (errno
== ENOMEM
|| errno
== 0)
275 x
= path_startswith(u
, prefix
);
277 /* restore the slash if it was lost */
278 if (!startswith(x
, "/"))
289 /* canonicalized path goes outside of
290 * prefix, keep the original path instead */
309 char **path_strv_resolve_uniq(char **l
, const char *prefix
) {
314 if (!path_strv_resolve(l
, prefix
))
320 char *path_kill_slashes(char *path
) {
324 /* Removes redundant inner and trailing slashes. Modifies the
325 * passed string in-place.
327 * ///foo///bar/ becomes /foo/bar
330 for (f
= path
, t
= path
; *f
; f
++) {
345 /* Special rule, if we are talking of the root directory, a
346 trailing slash is good */
348 if (t
== path
&& slash
)
355 char* path_startswith(const char *path
, const char *prefix
) {
359 if ((path
[0] == '/') != (prefix
[0] == '/'))
365 path
+= strspn(path
, "/");
366 prefix
+= strspn(prefix
, "/");
374 a
= strcspn(path
, "/");
375 b
= strcspn(prefix
, "/");
380 if (memcmp(path
, prefix
, a
) != 0)
388 int path_compare(const char *a
, const char *b
) {
394 /* A relative path and an abolute path must not compare as equal.
395 * Which one is sorted before the other does not really matter.
396 * Here a relative path is ordered before an absolute path. */
397 d
= (a
[0] == '/') - (b
[0] == '/');
407 if (*a
== 0 && *b
== 0)
410 /* Order prefixes first: "/foo" before "/foo/bar" */
419 /* Alphabetical sort: "/foo/aaa" before "/foo/b" */
420 d
= memcmp(a
, b
, MIN(j
, k
));
422 return (d
> 0) - (d
< 0); /* sign of d */
424 /* Sort "/foo/a" before "/foo/aaa" */
425 d
= (j
> k
) - (j
< k
); /* sign of (j - k) */
434 bool path_equal(const char *a
, const char *b
) {
435 return path_compare(a
, b
) == 0;
438 bool path_equal_or_files_same(const char *a
, const char *b
) {
439 return path_equal(a
, b
) || files_same(a
, b
) > 0;
442 char* path_join(const char *root
, const char *path
, const char *rest
) {
446 return strjoin(root
, endswith(root
, "/") ? "" : "/",
447 path
[0] == '/' ? path
+1 : path
,
448 rest
? (endswith(path
, "/") ? "" : "/") : NULL
,
449 rest
&& rest
[0] == '/' ? rest
+1 : rest
,
453 rest
? (endswith(path
, "/") ? "" : "/") : NULL
,
454 rest
&& rest
[0] == '/' ? rest
+1 : rest
,
458 int find_binary(const char *name
, char **ret
) {
465 if (access(name
, X_OK
) < 0)
469 r
= path_make_absolute_cwd(name
, ret
);
478 * Plain getenv, not secure_getenv, because we want
479 * to actually allow the user to pick the binary.
485 last_error
= -ENOENT
;
488 _cleanup_free_
char *j
= NULL
, *element
= NULL
;
490 r
= extract_first_word(&p
, &element
, ":", EXTRACT_RELAX
|EXTRACT_DONT_COALESCE_SEPARATORS
);
496 if (!path_is_absolute(element
))
499 j
= strjoin(element
, "/", name
, NULL
);
503 if (access(j
, X_OK
) >= 0) {
507 *ret
= path_kill_slashes(j
);
520 bool paths_check_timestamp(const char* const* paths
, usec_t
*timestamp
, bool update
) {
521 bool changed
= false;
522 const char* const* i
;
529 STRV_FOREACH(i
, paths
) {
533 if (stat(*i
, &stats
) < 0)
536 u
= timespec_load(&stats
.st_mtim
);
542 log_debug("timestamp of '%s' changed", *i
);
544 /* update timestamp */
555 static int binary_is_good(const char *binary
) {
556 _cleanup_free_
char *p
= NULL
, *d
= NULL
;
559 r
= find_binary(binary
, &p
);
565 /* An fsck that is linked to /bin/true is a non-existent
568 r
= readlink_malloc(p
, &d
);
569 if (r
== -EINVAL
) /* not a symlink */
574 return !path_equal(d
, "true") &&
575 !path_equal(d
, "/bin/true") &&
576 !path_equal(d
, "/usr/bin/true") &&
577 !path_equal(d
, "/dev/null");
580 int fsck_exists(const char *fstype
) {
585 if (streq(fstype
, "auto"))
588 checker
= strjoina("fsck.", fstype
);
589 return binary_is_good(checker
);
592 int mkfs_exists(const char *fstype
) {
597 if (streq(fstype
, "auto"))
600 mkfs
= strjoina("mkfs.", fstype
);
601 return binary_is_good(mkfs
);
604 char *prefix_root(const char *root
, const char *path
) {
608 /* If root is passed, prefixes path with it. Otherwise returns
613 /* First, drop duplicate prefixing slashes from the path */
614 while (path
[0] == '/' && path
[1] == '/')
617 if (isempty(root
) || path_equal(root
, "/"))
620 l
= strlen(root
) + 1 + strlen(path
) + 1;
628 while (p
> n
&& p
[-1] == '/')
638 int parse_path_argument_and_warn(const char *path
, bool suppress_root
, char **arg
) {
643 * This function is intended to be used in command line
644 * parsers, to handle paths that are passed in. It makes the
645 * path absolute, and reduces it to NULL if omitted or
646 * root (the latter optionally).
648 * NOTE THAT THIS WILL FREE THE PREVIOUS ARGUMENT POINTER ON
649 * SUCCESS! Hence, do not pass in uninitialized pointers.
657 r
= path_make_absolute_cwd(path
, &p
);
659 return log_error_errno(r
, "Failed to parse path \"%s\" and make it absolute: %m", path
);
661 path_kill_slashes(p
);
662 if (suppress_root
&& path_equal(p
, "/"))
670 char* dirname_malloc(const char *path
) {
671 char *d
, *dir
, *dir2
;
691 bool filename_is_valid(const char *p
) {
703 e
= strchrnul(p
, '/');
707 if (e
- p
> FILENAME_MAX
)
713 bool path_is_safe(const char *p
) {
718 if (streq(p
, "..") || startswith(p
, "../") || endswith(p
, "/..") || strstr(p
, "/../"))
721 if (strlen(p
)+1 > PATH_MAX
)
724 /* The following two checks are not really dangerous, but hey, they still are confusing */
725 if (streq(p
, ".") || startswith(p
, "./") || endswith(p
, "/.") || strstr(p
, "/./"))
734 char *file_in_same_dir(const char *path
, const char *filename
) {
741 /* This removes the last component of path and appends
742 * filename, unless the latter is absolute anyway or the
745 if (path_is_absolute(filename
))
746 return strdup(filename
);
748 e
= strrchr(path
, '/');
750 return strdup(filename
);
752 k
= strlen(filename
);
753 ret
= new(char, (e
+ 1 - path
) + k
+ 1);
757 memcpy(mempcpy(ret
, path
, e
+ 1 - path
), filename
, k
+ 1);
761 bool hidden_file_allow_backup(const char *filename
) {
765 filename
[0] == '.' ||
766 streq(filename
, "lost+found") ||
767 streq(filename
, "aquota.user") ||
768 streq(filename
, "aquota.group") ||
769 endswith(filename
, ".rpmnew") ||
770 endswith(filename
, ".rpmsave") ||
771 endswith(filename
, ".rpmorig") ||
772 endswith(filename
, ".dpkg-old") ||
773 endswith(filename
, ".dpkg-new") ||
774 endswith(filename
, ".dpkg-tmp") ||
775 endswith(filename
, ".dpkg-dist") ||
776 endswith(filename
, ".dpkg-bak") ||
777 endswith(filename
, ".dpkg-backup") ||
778 endswith(filename
, ".dpkg-remove") ||
779 endswith(filename
, ".swp");
782 bool hidden_file(const char *filename
) {
785 if (endswith(filename
, "~"))
788 return hidden_file_allow_backup(filename
);
791 bool is_device_path(const char *path
) {
793 /* Returns true on paths that refer to a device, either in
794 * sysfs or in /dev */
797 path_startswith(path
, "/dev/") ||
798 path_startswith(path
, "/sys/");