]>
Commit | Line | Data |
---|---|---|
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 | 17 | const char* default_PATH(void); |
e10a55fd | 18 | |
0f36a4c8 ZJS |
19 | static 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 | 27 | bool is_path(const char *p) _pure_; |
cd4ff5aa ZJS |
28 | |
29 | static 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 | 36 | int path_split_and_make_absolute(const char *p, char ***ret); |
44a6b1b6 | 37 | char* path_make_absolute(const char *p, const char *prefix); |
a2556d25 | 38 | int safe_getcwd(char **ret); |
0f474365 | 39 | int path_make_absolute_cwd(const char *p, char **ret); |
fe69c41e | 40 | int path_make_relative(const char *from, const char *to, char **ret); |
d4f60bdc | 41 | int path_make_relative_parent(const char *from_child, const char *to, char **ret); |
ee19edbb LP |
42 | |
43 | typedef enum PathStartWithFlags { | |
ceed11e4 | 44 | PATH_STARTSWITH_REFUSE_DOT_DOT = 1U << 0, |
ee19edbb LP |
45 | PATH_STARTSWITH_RETURN_LEADING_SLASH = 1U << 1, |
46 | } PathStartWithFlags; | |
47 | ||
48 | char* path_startswith_full(const char *path, const char *prefix, PathStartWithFlags flags) _pure_; | |
63f11e35 | 49 | static inline char* path_startswith(const char *path, const char *prefix) { |
ceed11e4 | 50 | return path_startswith_full(path, prefix, 0); |
63f11e35 | 51 | } |
1a27c323 | 52 | |
6808e004 | 53 | int path_compare(const char *a, const char *b) _pure_; |
1a27c323 LP |
54 | static inline bool path_equal(const char *a, const char *b) { |
55 | return path_compare(a, b) == 0; | |
56 | } | |
57 | ||
6808e004 YW |
58 | int path_compare_filename(const char *a, const char *b); |
59 | static inline bool path_equal_filename(const char *a, const char *b) { | |
60 | return path_compare_filename(a, b) == 0; | |
61 | } | |
62 | ||
581d8a14 | 63 | int path_equal_or_inode_same_full(const char *a, const char *b, int flags); |
e3c9e093 | 64 | static 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 | |
68 | char* 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 | 72 | char* skip_leading_slash(const char *p) _pure_; |
baaca3db | 73 | |
4541d045 DDM |
74 | typedef enum PathSimplifyFlags { |
75 | PATH_SIMPLIFY_KEEP_TRAILING_SLASH = 1 << 0, | |
76 | } PathSimplifyFlags; | |
77 | ||
00d811a5 | 78 | char* path_simplify_full(char *path, PathSimplifyFlags flags); |
4541d045 DDM |
79 | static inline char* path_simplify(char *path) { |
80 | return path_simplify_full(path, 0); | |
81 | } | |
44a6b1b6 | 82 | |
d9ccf6b3 | 83 | int 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 | 88 | char* 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 | 91 | int path_strv_make_absolute_cwd(char **l); |
e1873695 LP |
92 | char** path_strv_resolve(char **l, const char *root); |
93 | char** path_strv_resolve_uniq(char **l, const char *root); | |
9eb977db | 94 | |
326d60a9 | 95 | int open_and_check_executable(const char *name, const char *root, char **ret_path, int *ret_fd); |
51b271ea MY |
96 | int 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 | 103 | static 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 | 107 | bool paths_check_timestamp(const char* const* paths, usec_t *paths_ts_usec, bool update); |
8e184852 | 108 | |
13556724 JK |
109 | int fsck_exists(void); |
110 | int 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 | 134 | int path_find_first_component(const char **p, bool accept_dot_dot, const char **ret); |
484cd43c | 135 | int path_find_last_component(const char *path, bool accept_dot_dot, const char **next, const char **ret); |
00d811a5 | 136 | const char* last_path_component(const char *path); |
01950464 YW |
137 | int path_extract_filename(const char *path, char **ret); |
138 | int path_extract_directory(const char *path, char **ret); | |
bb15fafe | 139 | |
ec926463 | 140 | bool filename_part_is_valid(const char *p) _pure_; |
bb15fafe | 141 | bool filename_is_valid(const char *p) _pure_; |
32df2e14 YW |
142 | bool path_is_valid_full(const char *p, bool accept_dot_dot) _pure_; |
143 | static inline bool path_is_valid(const char *p) { | |
39e419a2 | 144 | return path_is_valid_full(p, /* accept_dot_dot= */ true); |
32df2e14 YW |
145 | } |
146 | static inline bool path_is_safe(const char *p) { | |
39e419a2 | 147 | return path_is_valid_full(p, /* accept_dot_dot= */ false); |
32df2e14 | 148 | } |
99be45a4 | 149 | bool path_is_normalized(const char *p) _pure_; |
398b3e44 MY |
150 | static 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 | 157 | int file_in_same_dir(const char *path, const char *filename, char **ret); |
a0956174 | 158 | |
55cdd057 | 159 | bool hidden_or_backup_file(const char *filename) _pure_; |
a0956174 | 160 | |
180341e7 | 161 | bool is_device_path(const char *path) _pure_; |
57e84e75 | 162 | |
180341e7 MY |
163 | bool valid_device_node_path(const char *path) _pure_; |
164 | bool valid_device_allow_pattern(const char *path) _pure_; | |
5a46d55f | 165 | |
180341e7 | 166 | bool dot_or_dot_dot(const char *path) _pure_; |
a119ec7c | 167 | |
180341e7 | 168 | bool path_implies_directory(const char *path) _pure_; |
dd92ba8a | 169 | |
bfd5a068 | 170 | static 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 | 180 | bool empty_or_root(const char *path) _pure_; |
d9ccf6b3 | 181 | const char* empty_to_root(const char *path) _pure_; |
8ce46363 | 182 | int empty_or_root_harder_to_null(const char **path); |
3841fee8 | 183 | |
63a0e577 MY |
184 | bool path_strv_contains(char * const *l, const char *path); |
185 | bool prefixed_path_strv_contains(char * const *l, const char *path); | |
3b703fe2 YW |
186 | |
187 | int path_glob_can_match(const char *pattern, const char *prefix, char **ret); |