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