1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
6 #define PATH_SPLIT_BIN(x) x "sbin:" x "bin"
7 #define PATH_SPLIT_BIN_NULSTR(x) x "sbin\0" x "bin\0"
9 #define PATH_MERGED_BIN(x) x "bin"
10 #define PATH_MERGED_BIN_NULSTR(x) x "bin\0"
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/")
15 #define DEFAULT_PATH_COMPAT PATH_SPLIT_BIN("/usr/local/") ":" PATH_SPLIT_BIN("/usr/") ":" PATH_SPLIT_BIN("/")
17 const char* default_PATH(void);
19 static inline const char* default_user_PATH(void) {
20 #ifdef DEFAULT_USER_PATH
21 return DEFAULT_USER_PATH
;
23 return default_PATH();
27 bool is_path(const char *p
) _pure_
;
29 static inline bool path_is_absolute(const char *p
) {
30 if (!p
) /* A NULL pointer is definitely not an absolute path */
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
);
43 typedef enum PathStartWithFlags
{
44 PATH_STARTSWITH_REFUSE_DOT_DOT
= 1U << 0,
45 PATH_STARTSWITH_RETURN_LEADING_SLASH
= 1U << 1,
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);
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;
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;
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;
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)
72 char* skip_leading_slash(const char *p
) _pure_
;
74 typedef enum PathSimplifyFlags
{
75 PATH_SIMPLIFY_KEEP_TRAILING_SLASH
= 1 << 0,
78 char* path_simplify_full(char *path
, PathSimplifyFlags flags
);
79 static inline char* path_simplify(char *path
) {
80 return path_simplify_full(path
, 0);
83 int path_simplify_alloc(const char *path
, char **ret
);
85 /* Note: the search terminates on the first NULL item. */
86 #define PATH_IN_SET(p, ...) path_strv_contains(STRV_MAKE(__VA_ARGS__), p)
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__))
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
);
95 int open_and_check_executable(const char *name
, const char *root
, char **ret_path
, int *ret_fd
);
96 int find_executable_full(
99 char * const *exec_search_path
,
100 bool use_path_envvar
,
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
);
107 bool paths_check_timestamp(const char* const* paths
, usec_t
*paths_ts_usec
, bool update
);
109 int fsck_exists(void);
110 int fsck_exists_for_fstype(const char *fstype
);
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, '/'); \
120 _slash && ((*_slash = 0), true); \
121 _slash = strrchr((prefix), '/'))
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, "/")) \
129 strrchr(prefix, 0); \
131 _slash && ((*_slash = 0), true); \
132 _slash = strrchr((prefix), '/'))
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
);
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);
146 static inline bool path_is_safe(const char *p
) {
147 return path_is_valid_full(p
, /* accept_dot_dot= */ false);
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
);
154 return filename_is_valid(p
);
157 int file_in_same_dir(const char *path
, const char *filename
, char **ret
);
159 bool hidden_or_backup_file(const char *filename
) _pure_
;
161 bool is_device_path(const char *path
) _pure_
;
163 bool valid_device_node_path(const char *path
) _pure_
;
164 bool valid_device_allow_pattern(const char *path
) _pure_
;
166 bool dot_or_dot_dot(const char *path
) _pure_
;
168 bool path_implies_directory(const char *path
) _pure_
;
170 static inline const char* skip_dev_prefix(const char *p
) {
173 /* Drop any /dev prefix if there is any */
175 e
= path_startswith(p
, "/dev/");
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
);
184 bool path_strv_contains(char * const *l
, const char *path
);
185 bool prefixed_path_strv_contains(char * const *l
, const char *path
);
187 int path_glob_can_match(const char *pattern
, const char *prefix
, char **ret
);