]>
Commit | Line | Data |
---|---|---|
1 | /* SPDX-License-Identifier: LGPL-2.1+ */ | |
2 | ||
3 | #ifndef __LXC_STRING_UTILS_H | |
4 | #define __LXC_STRING_UTILS_H | |
5 | ||
6 | #include "config.h" | |
7 | ||
8 | #include <stdarg.h> | |
9 | ||
10 | #include "initutils.h" | |
11 | #include "macro.h" | |
12 | ||
13 | #if !HAVE_STRLCAT | |
14 | #include "strlcat.h" | |
15 | #endif | |
16 | ||
17 | #if !HAVE_STRLCPY | |
18 | #include "strlcpy.h" | |
19 | #endif | |
20 | ||
21 | #if !HAVE_STRCHRNUL | |
22 | #include "strchrnul.h" | |
23 | #endif | |
24 | ||
25 | /* convert variadic argument lists to arrays (for execl type argument lists) */ | |
26 | __hidden extern char **lxc_va_arg_list_to_argv(va_list ap, size_t skip, int do_strdup); | |
27 | __hidden extern const char **lxc_va_arg_list_to_argv_const(va_list ap, size_t skip); | |
28 | ||
29 | /* | |
30 | * Some simple string functions; if they return pointers, they are allocated | |
31 | * buffers. | |
32 | */ | |
33 | __hidden extern char *lxc_string_replace(const char *needle, const char *replacement, | |
34 | const char *haystack); | |
35 | __hidden extern bool lxc_string_in_array(const char *needle, const char **haystack); | |
36 | __hidden extern char *lxc_string_join(const char *sep, const char **parts, bool use_as_prefix); | |
37 | ||
38 | __hidden extern char *lxc_append_paths(const char *first, const char *second); | |
39 | ||
40 | /* | |
41 | * Note: the following two functions use strtok(), so they will never | |
42 | * consider an empty element, even if two delimiters are next to | |
43 | * each other. | |
44 | */ | |
45 | __hidden extern bool lxc_string_in_list(const char *needle, const char *haystack, char sep); | |
46 | __hidden extern char **lxc_string_split(const char *string, char sep); | |
47 | __hidden extern char **lxc_string_split_and_trim(const char *string, char sep); | |
48 | __hidden extern char **lxc_string_split_quoted(char *string); | |
49 | ||
50 | /* Append string to NULL-terminated string array. */ | |
51 | __hidden extern int lxc_append_string(char ***list, char *entry); | |
52 | ||
53 | /* Some simple array manipulation utilities */ | |
54 | typedef void (*lxc_free_fn)(void *); | |
55 | typedef void *(*lxc_dup_fn)(void *); | |
56 | __hidden extern int lxc_grow_array(void ***array, size_t *capacity, size_t new_size, | |
57 | size_t capacity_increment); | |
58 | __hidden extern void lxc_free_array(void **array, lxc_free_fn element_free_fn); | |
59 | __hidden extern size_t lxc_array_len(void **array); | |
60 | ||
61 | __hidden extern void **lxc_append_null_to_array(void **array, size_t count); | |
62 | __hidden extern void remove_trailing_newlines(char *l); | |
63 | ||
64 | /* Helper functions to parse numbers. */ | |
65 | __hidden extern int lxc_safe_uint(const char *numstr, unsigned int *converted); | |
66 | __hidden extern int lxc_safe_int(const char *numstr, int *converted); | |
67 | __hidden extern int lxc_safe_long(const char *numstr, long int *converted); | |
68 | __hidden extern int lxc_safe_long_long(const char *numstr, long long int *converted); | |
69 | __hidden extern int lxc_safe_ulong(const char *numstr, unsigned long *converted); | |
70 | __hidden extern int lxc_safe_uint64(const char *numstr, uint64_t *converted, int base); | |
71 | __hidden extern int lxc_safe_int64_residual(const char *restrict numstr, | |
72 | int64_t *restrict converted, | |
73 | int base, char *restrict residual, | |
74 | size_t residual_len); | |
75 | /* Handles B, kb, MB, GB. Detects overflows and reports -ERANGE. */ | |
76 | __hidden extern int parse_byte_size_string(const char *s, long long int *converted); | |
77 | ||
78 | /* | |
79 | * Concatenate all passed-in strings into one path. Do not fail. If any piece | |
80 | * is not prefixed with '/', add a '/'. | |
81 | */ | |
82 | __hidden __attribute__((sentinel)) extern char *must_concat(size_t *len, const char *first, ...); | |
83 | __hidden __attribute__((sentinel)) extern char *must_make_path(const char *first, ...); | |
84 | __hidden __attribute__((sentinel)) extern char *must_append_path(char *first, ...); | |
85 | ||
86 | #define must_make_path_relative(__first__, ...) \ | |
87 | ({ \ | |
88 | char *__ptr__; \ | |
89 | if (*__first__ == '/') \ | |
90 | __ptr__ = must_make_path(".", __first__, __VA_ARGS__); \ | |
91 | else \ | |
92 | __ptr__ = must_make_path(__first__, __VA_ARGS__); \ | |
93 | __ptr__; \ | |
94 | }) | |
95 | ||
96 | /* Return copy of string @entry. Do not fail. */ | |
97 | __hidden extern char *must_copy_string(const char *entry); | |
98 | ||
99 | /* Re-allocate a pointer, do not fail */ | |
100 | __hidden extern void *must_realloc(void *orig, size_t sz); | |
101 | ||
102 | __hidden extern int lxc_char_left_gc(const char *buffer, size_t len); | |
103 | ||
104 | __hidden extern int lxc_char_right_gc(const char *buffer, size_t len); | |
105 | ||
106 | __hidden extern char *lxc_trim_whitespace_in_place(char *buffer); | |
107 | ||
108 | __hidden extern int lxc_is_line_empty(const char *line); | |
109 | __hidden extern void remove_trailing_slashes(char *p); | |
110 | ||
111 | static inline bool is_empty_string(const char *s) | |
112 | { | |
113 | return !s || strcmp(s, "") == 0; | |
114 | } | |
115 | ||
116 | #define maybe_empty(s) ((!is_empty_string(s)) ? (s) : ("(null)")) | |
117 | ||
118 | static inline ssize_t safe_strlcat(char *src, const char *append, size_t len) | |
119 | { | |
120 | size_t new_len; | |
121 | ||
122 | new_len = strlcat(src, append, len); | |
123 | if (new_len >= len) | |
124 | return ret_errno(EINVAL); | |
125 | ||
126 | return (ssize_t)new_len; | |
127 | } | |
128 | ||
129 | static inline bool strnequal(const char *str, const char *eq, size_t len) | |
130 | { | |
131 | return strncmp(str, eq, len) == 0; | |
132 | } | |
133 | ||
134 | static inline bool strequal(const char *str, const char *eq) | |
135 | { | |
136 | return strcmp(str, eq) == 0; | |
137 | } | |
138 | ||
139 | static inline bool dotdot(const char *str) | |
140 | { | |
141 | return !!strstr(str, ".."); | |
142 | } | |
143 | ||
144 | static inline bool abspath(const char *str) | |
145 | { | |
146 | return *str == '/'; | |
147 | } | |
148 | ||
149 | static inline char *deabs(char *str) | |
150 | { | |
151 | return str + strspn(str, "/"); | |
152 | } | |
153 | ||
154 | #define strnprintf(buf, buf_size, ...) \ | |
155 | ({ \ | |
156 | int __ret_strnprintf; \ | |
157 | __ret_strnprintf = snprintf(buf, buf_size, ##__VA_ARGS__); \ | |
158 | if (__ret_strnprintf < 0 || (size_t)__ret_strnprintf >= (size_t)buf_size) \ | |
159 | __ret_strnprintf = ret_errno(EIO); \ | |
160 | __ret_strnprintf; \ | |
161 | }) | |
162 | ||
163 | static inline const char *proc_self_fd(int fd) | |
164 | { | |
165 | static const char *invalid_fd_path = "/proc/self/fd/-EBADF"; | |
166 | static char buf[LXC_PROC_SELF_FD_LEN] = "/proc/self/fd/"; | |
167 | ||
168 | if (strnprintf(buf + STRLITERALLEN("/proc/self/fd/"), | |
169 | INTTYPE_TO_STRLEN(int), "%d", fd) < 0) | |
170 | return invalid_fd_path; | |
171 | ||
172 | return buf; | |
173 | } | |
174 | ||
175 | static inline const char *fdstr(__s64 fd) | |
176 | { | |
177 | static const char *fdstr_invalid = "-EBADF"; | |
178 | static char buf[INTTYPE_TO_STRLEN(__s64)]; | |
179 | ||
180 | if (strnprintf(buf, sizeof(buf), "%lld", (long long signed int)fd) < 0) | |
181 | return fdstr_invalid; | |
182 | ||
183 | return buf; | |
184 | } | |
185 | ||
186 | #define lxc_iterate_parts(__iterator, __splitme, __separators) \ | |
187 | for (char *__p = NULL, *__it = strtok_r(__splitme, __separators, &__p); \ | |
188 | (__iterator = __it); \ | |
189 | __iterator = __it = strtok_r(NULL, __separators, &__p)) | |
190 | ||
191 | __hidden extern char *lxc_path_simplify(const char *path); | |
192 | ||
193 | #endif /* __LXC_STRING_UTILS_H */ |