]>
Commit | Line | Data |
---|---|---|
db9ecf05 | 1 | /* SPDX-License-Identifier: LGPL-2.1-or-later */ |
76877b46 | 2 | #pragma once |
9eb977db | 3 | |
11c3a366 | 4 | #include <alloca.h> |
44a6b1b6 | 5 | #include <stdbool.h> |
11c3a366 | 6 | #include <stddef.h> |
9eb977db | 7 | |
44a6b1b6 | 8 | #include "macro.h" |
e3c9e093 | 9 | #include "stat-util.h" |
a6f72863 | 10 | #include "string-util.h" |
f5a9bd21 | 11 | #include "strv.h" |
8e184852 | 12 | #include "time-util.h" |
44a6b1b6 | 13 | |
0c300adf LP |
14 | #define PATH_SPLIT_SBIN_BIN(x) x "sbin:" x "bin" |
15 | #define PATH_SPLIT_SBIN_BIN_NULSTR(x) x "sbin\0" x "bin\0" | |
16 | ||
17 | #define PATH_NORMAL_SBIN_BIN(x) x "bin" | |
18 | #define PATH_NORMAL_SBIN_BIN_NULSTR(x) x "bin\0" | |
19 | ||
671f0f8d | 20 | #if HAVE_SPLIT_BIN |
0c300adf LP |
21 | # define PATH_SBIN_BIN(x) PATH_SPLIT_SBIN_BIN(x) |
22 | # define PATH_SBIN_BIN_NULSTR(x) PATH_SPLIT_SBIN_BIN_NULSTR(x) | |
671f0f8d | 23 | #else |
0c300adf LP |
24 | # define PATH_SBIN_BIN(x) PATH_NORMAL_SBIN_BIN(x) |
25 | # define PATH_SBIN_BIN_NULSTR(x) PATH_NORMAL_SBIN_BIN_NULSTR(x) | |
671f0f8d ZJS |
26 | #endif |
27 | ||
b0d3095f LB |
28 | #define DEFAULT_PATH PATH_SBIN_BIN("/usr/local/") ":" PATH_SBIN_BIN("/usr/") |
29 | #define DEFAULT_PATH_NULSTR PATH_SBIN_BIN_NULSTR("/usr/local/") PATH_SBIN_BIN_NULSTR("/usr/") | |
0c300adf | 30 | #define DEFAULT_PATH_COMPAT PATH_SPLIT_SBIN_BIN("/usr/local/") ":" PATH_SPLIT_SBIN_BIN("/usr/") ":" PATH_SPLIT_SBIN_BIN("/") |
e10a55fd | 31 | |
3602ca6f ZJS |
32 | #ifndef DEFAULT_USER_PATH |
33 | # define DEFAULT_USER_PATH DEFAULT_PATH | |
34 | #endif | |
35 | ||
cd4ff5aa | 36 | static inline bool is_path(const char *p) { |
70980a39 LP |
37 | if (!p) /* A NULL pointer is definitely not a path */ |
38 | return false; | |
39 | ||
cd4ff5aa ZJS |
40 | return strchr(p, '/'); |
41 | } | |
42 | ||
43 | static inline bool path_is_absolute(const char *p) { | |
70980a39 LP |
44 | if (!p) /* A NULL pointer is definitely not an absolute path */ |
45 | return false; | |
46 | ||
cd4ff5aa ZJS |
47 | return p[0] == '/'; |
48 | } | |
49 | ||
0f474365 | 50 | int path_split_and_make_absolute(const char *p, char ***ret); |
44a6b1b6 | 51 | char* path_make_absolute(const char *p, const char *prefix); |
a2556d25 | 52 | int safe_getcwd(char **ret); |
0f474365 | 53 | int path_make_absolute_cwd(const char *p, char **ret); |
fe69c41e | 54 | int path_make_relative(const char *from, const char *to, char **ret); |
d4f60bdc | 55 | int path_make_relative_parent(const char *from_child, const char *to, char **ret); |
00d811a5 | 56 | char* path_startswith_full(const char *path, const char *prefix, bool accept_dot_dot) _pure_; |
63f11e35 YW |
57 | static inline char* path_startswith(const char *path, const char *prefix) { |
58 | return path_startswith_full(path, prefix, true); | |
59 | } | |
1a27c323 | 60 | |
6808e004 | 61 | int path_compare(const char *a, const char *b) _pure_; |
1a27c323 LP |
62 | static inline bool path_equal(const char *a, const char *b) { |
63 | return path_compare(a, b) == 0; | |
64 | } | |
65 | ||
6808e004 YW |
66 | int path_compare_filename(const char *a, const char *b); |
67 | static inline bool path_equal_filename(const char *a, const char *b) { | |
68 | return path_compare_filename(a, b) == 0; | |
69 | } | |
70 | ||
e3c9e093 MY |
71 | static inline bool path_equal_or_inode_same(const char *a, const char *b, int flags) { |
72 | return path_equal(a, b) || inode_same(a, b, flags) > 0; | |
73 | } | |
7ae27680 LP |
74 | |
75 | char* path_extend_internal(char **x, ...); | |
76 | #define path_extend(x, ...) path_extend_internal(x, __VA_ARGS__, POINTER_MAX) | |
77 | #define path_join(...) path_extend_internal(NULL, __VA_ARGS__, POINTER_MAX) | |
cd8194a3 | 78 | |
baaca3db MY |
79 | static inline char* skip_leading_slash(const char *p) { |
80 | return skip_leading_chars(p, "/"); | |
81 | } | |
82 | ||
4541d045 DDM |
83 | typedef enum PathSimplifyFlags { |
84 | PATH_SIMPLIFY_KEEP_TRAILING_SLASH = 1 << 0, | |
85 | } PathSimplifyFlags; | |
86 | ||
00d811a5 | 87 | char* path_simplify_full(char *path, PathSimplifyFlags flags); |
4541d045 DDM |
88 | static inline char* path_simplify(char *path) { |
89 | return path_simplify_full(path, 0); | |
90 | } | |
44a6b1b6 | 91 | |
660087dc ZJS |
92 | static inline int path_simplify_alloc(const char *path, char **ret) { |
93 | assert(ret); | |
94 | ||
95 | if (!path) { | |
96 | *ret = NULL; | |
97 | return 0; | |
98 | } | |
99 | ||
100 | char *t = strdup(path); | |
101 | if (!t) | |
102 | return -ENOMEM; | |
103 | ||
104 | *ret = path_simplify(t); | |
105 | return 0; | |
106 | } | |
107 | ||
3ae5990c | 108 | /* Note: the search terminates on the first NULL item. */ |
3593fa60 | 109 | #define PATH_IN_SET(p, ...) path_strv_contains(STRV_MAKE(__VA_ARGS__), p) |
3ae5990c | 110 | |
cc4d7d81 ZJS |
111 | char* path_startswith_strv(const char *p, char **set); |
112 | #define PATH_STARTSWITH_SET(p, ...) path_startswith_strv(p, STRV_MAKE(__VA_ARGS__)) | |
ad2706db | 113 | |
0f474365 | 114 | int path_strv_make_absolute_cwd(char **l); |
e1873695 LP |
115 | char** path_strv_resolve(char **l, const char *root); |
116 | char** path_strv_resolve_uniq(char **l, const char *root); | |
9eb977db | 117 | |
8c35c10d | 118 | int find_executable_full(const char *name, const char *root, char **exec_search_path, bool use_path_envvar, char **ret_filename, int *ret_fd); |
5ca9139a | 119 | static inline int find_executable(const char *name, char **ret_filename) { |
8c35c10d | 120 | return find_executable_full(name, /* root= */ NULL, NULL, true, ret_filename, NULL); |
92673045 | 121 | } |
fecffe5d | 122 | |
2ad8416d | 123 | bool paths_check_timestamp(const char* const* paths, usec_t *paths_ts_usec, bool update); |
8e184852 | 124 | |
13556724 JK |
125 | int fsck_exists(void); |
126 | int fsck_exists_for_fstype(const char *fstype); | |
eb66db55 | 127 | |
e203f7c3 LP |
128 | /* Iterates through the path prefixes of the specified path, going up |
129 | * the tree, to root. Also returns "" (and not "/"!) for the root | |
130 | * directory. Excludes the specified directory itself */ | |
f8703ed7 ZJS |
131 | #define PATH_FOREACH_PREFIX(prefix, path) \ |
132 | for (char *_slash = ({ \ | |
4ff361cc | 133 | path_simplify(strcpy(prefix, path)); \ |
f8703ed7 ZJS |
134 | streq(prefix, "/") ? NULL : strrchr(prefix, '/'); \ |
135 | }); \ | |
136 | _slash && ((*_slash = 0), true); \ | |
137 | _slash = strrchr((prefix), '/')) | |
e203f7c3 LP |
138 | |
139 | /* Same as PATH_FOREACH_PREFIX but also includes the specified path itself */ | |
f8703ed7 ZJS |
140 | #define PATH_FOREACH_PREFIX_MORE(prefix, path) \ |
141 | for (char *_slash = ({ \ | |
4ff361cc | 142 | path_simplify(strcpy(prefix, path)); \ |
f8703ed7 ZJS |
143 | if (streq(prefix, "/")) \ |
144 | prefix[0] = 0; \ | |
145 | strrchr(prefix, 0); \ | |
146 | }); \ | |
147 | _slash && ((*_slash = 0), true); \ | |
148 | _slash = strrchr((prefix), '/')) | |
1d13f648 | 149 | |
c6134d3e | 150 | /* Similar to path_join(), but only works for two components, and only the first one may be NULL and returns |
95bbf19e | 151 | * an alloca() buffer, or possibly a const pointer into the path parameter. */ |
2e76ca79 | 152 | /* DEPRECATED: use path_join() instead */ |
1d13f648 LP |
153 | #define prefix_roota(root, path) \ |
154 | ({ \ | |
155 | const char* _path = (path), *_root = (root), *_ret; \ | |
156 | char *_p, *_n; \ | |
157 | size_t _l; \ | |
158 | while (_path[0] == '/' && _path[1] == '/') \ | |
b3a9d980 | 159 | _path++; \ |
95bbf19e | 160 | if (isempty(_root)) \ |
1d13f648 LP |
161 | _ret = _path; \ |
162 | else { \ | |
163 | _l = strlen(_root) + 1 + strlen(_path) + 1; \ | |
6e9417f5 | 164 | _n = newa(char, _l); \ |
1d13f648 LP |
165 | _p = stpcpy(_n, _root); \ |
166 | while (_p > _n && _p[-1] == '/') \ | |
167 | _p--; \ | |
168 | if (_path[0] != '/') \ | |
169 | *(_p++) = '/'; \ | |
170 | strcpy(_p, _path); \ | |
171 | _ret = _n; \ | |
172 | } \ | |
173 | _ret; \ | |
174 | }) | |
0f03c2a4 | 175 | |
0ee54dd4 | 176 | int path_find_first_component(const char **p, bool accept_dot_dot, const char **ret); |
484cd43c | 177 | int path_find_last_component(const char *path, bool accept_dot_dot, const char **next, const char **ret); |
00d811a5 | 178 | const char* last_path_component(const char *path); |
01950464 YW |
179 | int path_extract_filename(const char *path, char **ret); |
180 | int path_extract_directory(const char *path, char **ret); | |
bb15fafe | 181 | |
ec926463 | 182 | bool filename_part_is_valid(const char *p) _pure_; |
bb15fafe | 183 | bool filename_is_valid(const char *p) _pure_; |
32df2e14 YW |
184 | bool path_is_valid_full(const char *p, bool accept_dot_dot) _pure_; |
185 | static inline bool path_is_valid(const char *p) { | |
39e419a2 | 186 | return path_is_valid_full(p, /* accept_dot_dot= */ true); |
32df2e14 YW |
187 | } |
188 | static inline bool path_is_safe(const char *p) { | |
39e419a2 | 189 | return path_is_valid_full(p, /* accept_dot_dot= */ false); |
32df2e14 | 190 | } |
99be45a4 | 191 | bool path_is_normalized(const char *p) _pure_; |
a0956174 | 192 | |
162f6477 | 193 | int file_in_same_dir(const char *path, const char *filename, char **ret); |
a0956174 | 194 | |
55cdd057 | 195 | bool hidden_or_backup_file(const char *filename) _pure_; |
a0956174 LP |
196 | |
197 | bool is_device_path(const char *path); | |
57e84e75 LP |
198 | |
199 | bool valid_device_node_path(const char *path); | |
200 | bool valid_device_allow_pattern(const char *path); | |
5a46d55f | 201 | |
49bfc877 | 202 | bool dot_or_dot_dot(const char *path); |
a119ec7c | 203 | |
dd92ba8a LP |
204 | bool path_implies_directory(const char *path); |
205 | ||
a119ec7c LP |
206 | static inline const char *skip_dev_prefix(const char *p) { |
207 | const char *e; | |
208 | ||
209 | /* Drop any /dev prefix if there is any */ | |
210 | ||
211 | e = path_startswith(p, "/dev/"); | |
212 | ||
213 | return e ?: p; | |
214 | } | |
57ea45e1 | 215 | |
15bac3e8 | 216 | bool empty_or_root(const char *path); |
00d811a5 | 217 | static inline const char* empty_to_root(const char *path) { |
945403e6 YW |
218 | return isempty(path) ? "/" : path; |
219 | } | |
3841fee8 LP |
220 | |
221 | bool path_strv_contains(char **l, const char *path); | |
de46b2be | 222 | bool prefixed_path_strv_contains(char **l, const char *path); |
3b703fe2 YW |
223 | |
224 | int path_glob_can_match(const char *pattern, const char *prefix, char **ret); |