]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/basic/path-util.h
man/systemd-sysext: list ephemeral/ephemeral-import in the list of options
[thirdparty/systemd.git] / src / basic / path-util.h
CommitLineData
db9ecf05 1/* SPDX-License-Identifier: LGPL-2.1-or-later */
76877b46 2#pragma once
9eb977db 3
0c15577a 4#include "forward.h"
44a6b1b6 5
0f36a4c8
ZJS
6#define PATH_SPLIT_BIN(x) x "sbin:" x "bin"
7#define PATH_SPLIT_BIN_NULSTR(x) x "sbin\0" x "bin\0"
0c300adf 8
0f36a4c8
ZJS
9#define PATH_MERGED_BIN(x) x "bin"
10#define PATH_MERGED_BIN_NULSTR(x) x "bin\0"
0c300adf 11
0f36a4c8
ZJS
12#define DEFAULT_PATH_WITH_SBIN PATH_SPLIT_BIN("/usr/local/") ":" PATH_SPLIT_BIN("/usr/")
13#define DEFAULT_PATH_WITHOUT_SBIN PATH_MERGED_BIN("/usr/local/") ":" PATH_MERGED_BIN("/usr/")
671f0f8d 14
0f36a4c8 15#define DEFAULT_PATH_COMPAT PATH_SPLIT_BIN("/usr/local/") ":" PATH_SPLIT_BIN("/usr/") ":" PATH_SPLIT_BIN("/")
e10a55fd 16
0f36a4c8 17const char* default_PATH(void);
e10a55fd 18
0f36a4c8
ZJS
19static inline const char* default_user_PATH(void) {
20#ifdef DEFAULT_USER_PATH
21 return DEFAULT_USER_PATH;
22#else
23 return default_PATH();
3602ca6f 24#endif
0f36a4c8 25}
3602ca6f 26
d9ccf6b3 27bool is_path(const char *p) _pure_;
cd4ff5aa
ZJS
28
29static inline bool path_is_absolute(const char *p) {
70980a39
LP
30 if (!p) /* A NULL pointer is definitely not an absolute path */
31 return false;
32
cd4ff5aa
ZJS
33 return p[0] == '/';
34}
35
0f474365 36int path_split_and_make_absolute(const char *p, char ***ret);
44a6b1b6 37char* path_make_absolute(const char *p, const char *prefix);
a2556d25 38int safe_getcwd(char **ret);
0f474365 39int path_make_absolute_cwd(const char *p, char **ret);
fe69c41e 40int path_make_relative(const char *from, const char *to, char **ret);
d4f60bdc 41int path_make_relative_parent(const char *from_child, const char *to, char **ret);
ee19edbb
LP
42
43typedef enum PathStartWithFlags {
ceed11e4 44 PATH_STARTSWITH_REFUSE_DOT_DOT = 1U << 0,
ee19edbb
LP
45 PATH_STARTSWITH_RETURN_LEADING_SLASH = 1U << 1,
46} PathStartWithFlags;
47
48char* path_startswith_full(const char *path, const char *prefix, PathStartWithFlags flags) _pure_;
63f11e35 49static inline char* path_startswith(const char *path, const char *prefix) {
ceed11e4 50 return path_startswith_full(path, prefix, 0);
63f11e35 51}
1a27c323 52
6808e004 53int path_compare(const char *a, const char *b) _pure_;
1a27c323
LP
54static inline bool path_equal(const char *a, const char *b) {
55 return path_compare(a, b) == 0;
56}
57
6808e004
YW
58int path_compare_filename(const char *a, const char *b);
59static inline bool path_equal_filename(const char *a, const char *b) {
60 return path_compare_filename(a, b) == 0;
61}
62
581d8a14 63int path_equal_or_inode_same_full(const char *a, const char *b, int flags);
e3c9e093 64static inline bool path_equal_or_inode_same(const char *a, const char *b, int flags) {
581d8a14 65 return path_equal_or_inode_same_full(a, b, flags) > 0;
e3c9e093 66}
7ae27680
LP
67
68char* path_extend_internal(char **x, ...);
69#define path_extend(x, ...) path_extend_internal(x, __VA_ARGS__, POINTER_MAX)
70#define path_join(...) path_extend_internal(NULL, __VA_ARGS__, POINTER_MAX)
cd8194a3 71
d9ccf6b3 72char* skip_leading_slash(const char *p) _pure_;
baaca3db 73
4541d045
DDM
74typedef enum PathSimplifyFlags {
75 PATH_SIMPLIFY_KEEP_TRAILING_SLASH = 1 << 0,
76} PathSimplifyFlags;
77
00d811a5 78char* path_simplify_full(char *path, PathSimplifyFlags flags);
4541d045
DDM
79static inline char* path_simplify(char *path) {
80 return path_simplify_full(path, 0);
81}
44a6b1b6 82
d9ccf6b3 83int path_simplify_alloc(const char *path, char **ret);
660087dc 84
3ae5990c 85/* Note: the search terminates on the first NULL item. */
3593fa60 86#define PATH_IN_SET(p, ...) path_strv_contains(STRV_MAKE(__VA_ARGS__), p)
3ae5990c 87
63a0e577 88char* path_startswith_strv(const char *p, char * const *strv);
cc4d7d81 89#define PATH_STARTSWITH_SET(p, ...) path_startswith_strv(p, STRV_MAKE(__VA_ARGS__))
ad2706db 90
0f474365 91int path_strv_make_absolute_cwd(char **l);
e1873695
LP
92char** path_strv_resolve(char **l, const char *root);
93char** path_strv_resolve_uniq(char **l, const char *root);
9eb977db 94
326d60a9 95int open_and_check_executable(const char *name, const char *root, char **ret_path, int *ret_fd);
51b271ea
MY
96int find_executable_full(
97 const char *name,
98 const char *root,
99 char * const *exec_search_path,
100 bool use_path_envvar,
101 char **ret_filename,
102 int *ret_fd);
5ca9139a 103static inline int find_executable(const char *name, char **ret_filename) {
8c35c10d 104 return find_executable_full(name, /* root= */ NULL, NULL, true, ret_filename, NULL);
92673045 105}
fecffe5d 106
2ad8416d 107bool paths_check_timestamp(const char* const* paths, usec_t *paths_ts_usec, bool update);
8e184852 108
13556724
JK
109int fsck_exists(void);
110int fsck_exists_for_fstype(const char *fstype);
eb66db55 111
e203f7c3
LP
112/* Iterates through the path prefixes of the specified path, going up
113 * the tree, to root. Also returns "" (and not "/"!) for the root
114 * directory. Excludes the specified directory itself */
f8703ed7
ZJS
115#define PATH_FOREACH_PREFIX(prefix, path) \
116 for (char *_slash = ({ \
4ff361cc 117 path_simplify(strcpy(prefix, path)); \
f8703ed7
ZJS
118 streq(prefix, "/") ? NULL : strrchr(prefix, '/'); \
119 }); \
120 _slash && ((*_slash = 0), true); \
121 _slash = strrchr((prefix), '/'))
e203f7c3
LP
122
123/* Same as PATH_FOREACH_PREFIX but also includes the specified path itself */
f8703ed7
ZJS
124#define PATH_FOREACH_PREFIX_MORE(prefix, path) \
125 for (char *_slash = ({ \
4ff361cc 126 path_simplify(strcpy(prefix, path)); \
f8703ed7
ZJS
127 if (streq(prefix, "/")) \
128 prefix[0] = 0; \
129 strrchr(prefix, 0); \
130 }); \
131 _slash && ((*_slash = 0), true); \
132 _slash = strrchr((prefix), '/'))
1d13f648 133
0ee54dd4 134int path_find_first_component(const char **p, bool accept_dot_dot, const char **ret);
484cd43c 135int path_find_last_component(const char *path, bool accept_dot_dot, const char **next, const char **ret);
00d811a5 136const char* last_path_component(const char *path);
01950464
YW
137int path_extract_filename(const char *path, char **ret);
138int path_extract_directory(const char *path, char **ret);
bb15fafe 139
ec926463 140bool filename_part_is_valid(const char *p) _pure_;
bb15fafe 141bool filename_is_valid(const char *p) _pure_;
32df2e14
YW
142bool path_is_valid_full(const char *p, bool accept_dot_dot) _pure_;
143static inline bool path_is_valid(const char *p) {
39e419a2 144 return path_is_valid_full(p, /* accept_dot_dot= */ true);
32df2e14
YW
145}
146static inline bool path_is_safe(const char *p) {
39e419a2 147 return path_is_valid_full(p, /* accept_dot_dot= */ false);
32df2e14 148}
99be45a4 149bool path_is_normalized(const char *p) _pure_;
398b3e44
MY
150static inline bool filename_or_absolute_path_is_valid(const char *p) {
151 if (path_is_absolute(p))
152 return path_is_valid(p);
153
154 return filename_is_valid(p);
155}
a0956174 156
162f6477 157int file_in_same_dir(const char *path, const char *filename, char **ret);
a0956174 158
55cdd057 159bool hidden_or_backup_file(const char *filename) _pure_;
a0956174 160
180341e7 161bool is_device_path(const char *path) _pure_;
57e84e75 162
180341e7
MY
163bool valid_device_node_path(const char *path) _pure_;
164bool valid_device_allow_pattern(const char *path) _pure_;
5a46d55f 165
180341e7 166bool dot_or_dot_dot(const char *path) _pure_;
a119ec7c 167
180341e7 168bool path_implies_directory(const char *path) _pure_;
dd92ba8a 169
bfd5a068 170static inline const char* skip_dev_prefix(const char *p) {
a119ec7c
LP
171 const char *e;
172
173 /* Drop any /dev prefix if there is any */
174
175 e = path_startswith(p, "/dev/");
176
177 return e ?: p;
178}
57ea45e1 179
180341e7 180bool empty_or_root(const char *path) _pure_;
d9ccf6b3 181const char* empty_to_root(const char *path) _pure_;
8ce46363 182int empty_or_root_harder_to_null(const char **path);
3841fee8 183
63a0e577
MY
184bool path_strv_contains(char * const *l, const char *path);
185bool prefixed_path_strv_contains(char * const *l, const char *path);
3b703fe2
YW
186
187int path_glob_can_match(const char *pattern, const char *prefix, char **ret);