]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/basic/path-util.h
io.systemd.Unit.List fix context/runtime split (#38172)
[thirdparty/systemd.git] / src / basic / path-util.h
1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
2 #pragma once
3
4 #include "forward.h"
5
6 #define PATH_SPLIT_BIN(x) x "sbin:" x "bin"
7 #define PATH_SPLIT_BIN_NULSTR(x) x "sbin\0" x "bin\0"
8
9 #define PATH_MERGED_BIN(x) x "bin"
10 #define PATH_MERGED_BIN_NULSTR(x) x "bin\0"
11
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/")
14
15 #define DEFAULT_PATH_COMPAT PATH_SPLIT_BIN("/usr/local/") ":" PATH_SPLIT_BIN("/usr/") ":" PATH_SPLIT_BIN("/")
16
17 const char* default_PATH(void);
18
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();
24 #endif
25 }
26
27 bool is_path(const char *p) _pure_;
28
29 static inline bool path_is_absolute(const char *p) {
30 if (!p) /* A NULL pointer is definitely not an absolute path */
31 return false;
32
33 return p[0] == '/';
34 }
35
36 int path_split_and_make_absolute(const char *p, char ***ret);
37 char* path_make_absolute(const char *p, const char *prefix);
38 int safe_getcwd(char **ret);
39 int path_make_absolute_cwd(const char *p, char **ret);
40 int path_make_relative(const char *from, const char *to, char **ret);
41 int path_make_relative_parent(const char *from_child, const char *to, char **ret);
42
43 typedef enum PathStartWithFlags {
44 PATH_STARTSWITH_REFUSE_DOT_DOT = 1U << 0,
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_;
49 static inline char* path_startswith(const char *path, const char *prefix) {
50 return path_startswith_full(path, prefix, 0);
51 }
52
53 int path_compare(const char *a, const char *b) _pure_;
54 static inline bool path_equal(const char *a, const char *b) {
55 return path_compare(a, b) == 0;
56 }
57
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
63 int path_equal_or_inode_same_full(const char *a, const char *b, int flags);
64 static inline bool path_equal_or_inode_same(const char *a, const char *b, int flags) {
65 return path_equal_or_inode_same_full(a, b, flags) > 0;
66 }
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)
71
72 char* skip_leading_slash(const char *p) _pure_;
73
74 typedef enum PathSimplifyFlags {
75 PATH_SIMPLIFY_KEEP_TRAILING_SLASH = 1 << 0,
76 } PathSimplifyFlags;
77
78 char* path_simplify_full(char *path, PathSimplifyFlags flags);
79 static inline char* path_simplify(char *path) {
80 return path_simplify_full(path, 0);
81 }
82
83 int path_simplify_alloc(const char *path, char **ret);
84
85 /* Note: the search terminates on the first NULL item. */
86 #define PATH_IN_SET(p, ...) path_strv_contains(STRV_MAKE(__VA_ARGS__), p)
87
88 char* path_startswith_strv(const char *p, char * const *strv);
89 #define PATH_STARTSWITH_SET(p, ...) path_startswith_strv(p, STRV_MAKE(__VA_ARGS__))
90
91 int path_strv_make_absolute_cwd(char **l);
92 char** path_strv_resolve(char **l, const char *root);
93 char** path_strv_resolve_uniq(char **l, const char *root);
94
95 int open_and_check_executable(const char *name, const char *root, char **ret_path, int *ret_fd);
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);
103 static inline int find_executable(const char *name, char **ret_filename) {
104 return find_executable_full(name, /* root= */ NULL, NULL, true, ret_filename, NULL);
105 }
106
107 bool paths_check_timestamp(const char* const* paths, usec_t *paths_ts_usec, bool update);
108
109 int fsck_exists(void);
110 int fsck_exists_for_fstype(const char *fstype);
111
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 */
115 #define PATH_FOREACH_PREFIX(prefix, path) \
116 for (char *_slash = ({ \
117 path_simplify(strcpy(prefix, path)); \
118 streq(prefix, "/") ? NULL : strrchr(prefix, '/'); \
119 }); \
120 _slash && ((*_slash = 0), true); \
121 _slash = strrchr((prefix), '/'))
122
123 /* Same as PATH_FOREACH_PREFIX but also includes the specified path itself */
124 #define PATH_FOREACH_PREFIX_MORE(prefix, path) \
125 for (char *_slash = ({ \
126 path_simplify(strcpy(prefix, path)); \
127 if (streq(prefix, "/")) \
128 prefix[0] = 0; \
129 strrchr(prefix, 0); \
130 }); \
131 _slash && ((*_slash = 0), true); \
132 _slash = strrchr((prefix), '/'))
133
134 int path_find_first_component(const char **p, bool accept_dot_dot, const char **ret);
135 int path_find_last_component(const char *path, bool accept_dot_dot, const char **next, const char **ret);
136 const char* last_path_component(const char *path);
137 int path_extract_filename(const char *path, char **ret);
138 int path_extract_directory(const char *path, char **ret);
139
140 bool filename_part_is_valid(const char *p) _pure_;
141 bool filename_is_valid(const char *p) _pure_;
142 bool path_is_valid_full(const char *p, bool accept_dot_dot) _pure_;
143 static inline bool path_is_valid(const char *p) {
144 return path_is_valid_full(p, /* accept_dot_dot= */ true);
145 }
146 static inline bool path_is_safe(const char *p) {
147 return path_is_valid_full(p, /* accept_dot_dot= */ false);
148 }
149 bool path_is_normalized(const char *p) _pure_;
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 }
156
157 int file_in_same_dir(const char *path, const char *filename, char **ret);
158
159 bool hidden_or_backup_file(const char *filename) _pure_;
160
161 bool is_device_path(const char *path) _pure_;
162
163 bool valid_device_node_path(const char *path) _pure_;
164 bool valid_device_allow_pattern(const char *path) _pure_;
165
166 bool dot_or_dot_dot(const char *path) _pure_;
167
168 bool path_implies_directory(const char *path) _pure_;
169
170 static inline const char* skip_dev_prefix(const char *p) {
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 }
179
180 bool empty_or_root(const char *path) _pure_;
181 const char* empty_to_root(const char *path) _pure_;
182 int empty_or_root_harder_to_null(const char **path);
183
184 bool path_strv_contains(char * const *l, const char *path);
185 bool prefixed_path_strv_contains(char * const *l, const char *path);
186
187 int path_glob_can_match(const char *pattern, const char *prefix, char **ret);