]> git.proxmox.com Git - mirror_lxc.git/blame_incremental - src/lxc/string_utils.h
github: Update for main branch
[mirror_lxc.git] / src / lxc / string_utils.h
... / ...
CommitLineData
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 */
54typedef void (*lxc_free_fn)(void *);
55typedef 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
111static 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
118static 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
129static inline bool strnequal(const char *str, const char *eq, size_t len)
130{
131 return strncmp(str, eq, len) == 0;
132}
133
134static inline bool strequal(const char *str, const char *eq)
135{
136 return strcmp(str, eq) == 0;
137}
138
139static inline bool dotdot(const char *str)
140{
141 return !!strstr(str, "..");
142}
143
144static inline bool abspath(const char *str)
145{
146 return *str == '/';
147}
148
149static 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
163static 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
175static 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 */