]> git.proxmox.com Git - mirror_lxc.git/blob - src/lxc/string_utils.h
e64a66d0e38e6e42a58f496b8dbed6f5ed0e3b6b
[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 "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 *path_simplify(const char *path);
192
193 #endif /* __LXC_STRING_UTILS_H */