1 /* SPDX-License-Identifier: LGPL-2.1+ */
3 #ifndef __LXC_STRING_UTILS_H
4 #define __LXC_STRING_UTILS_H
10 #include "initutils.h"
14 #include "include/strlcat.h"
17 #ifndef HAVE_STRCHRNUL
18 #include "include/strchrnul.h"
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
);
26 * Some simple string functions; if they return pointers, they are allocated
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
);
34 __hidden
extern char *lxc_append_paths(const char *first
, const char *second
);
37 * Note: the following two functions use strtok(), so they will never
38 * consider an empty element, even if two delimiters are next to
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
);
46 /* Append string to NULL-terminated string array. */
47 __hidden
extern int lxc_append_string(char ***list
, char *entry
);
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
);
57 __hidden
extern void **lxc_append_null_to_array(void **array
, size_t count
);
58 __hidden
extern void remove_trailing_newlines(char *l
);
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
,
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
);
75 * Concatenate all passed-in strings into one path. Do not fail. If any piece
76 * is not prefixed with '/', add a '/'.
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
, ...);
82 #define must_make_path_relative(__first__, ...) \
85 if (*__first__ == '/') \
86 __ptr__ = must_make_path(".", __first__, __VA_ARGS__); \
88 __ptr__ = must_make_path(__first__, __VA_ARGS__); \
92 /* Return copy of string @entry. Do not fail. */
93 __hidden
extern char *must_copy_string(const char *entry
);
95 /* Re-allocate a pointer, do not fail */
96 __hidden
extern void *must_realloc(void *orig
, size_t sz
);
98 __hidden
extern int lxc_char_left_gc(const char *buffer
, size_t len
);
100 __hidden
extern int lxc_char_right_gc(const char *buffer
, size_t len
);
102 __hidden
extern char *lxc_trim_whitespace_in_place(char *buffer
);
104 __hidden
extern int lxc_is_line_empty(const char *line
);
105 __hidden
extern void remove_trailing_slashes(char *p
);
107 static inline bool is_empty_string(const char *s
)
109 return !s
|| strcmp(s
, "") == 0;
112 #define maybe_empty(s) ((!is_empty_string(s)) ? (s) : ("(null)"))
114 static inline ssize_t
safe_strlcat(char *src
, const char *append
, size_t len
)
118 new_len
= strlcat(src
, append
, len
);
120 return ret_errno(EINVAL
);
122 return (ssize_t
)new_len
;
125 static inline bool strnequal(const char *str
, const char *eq
, size_t len
)
127 return strncmp(str
, eq
, len
) == 0;
130 static inline bool strequal(const char *str
, const char *eq
)
132 return strcmp(str
, eq
) == 0;
135 static inline bool dotdot(const char *str
)
137 return !!strstr(str
, "..");
140 static inline bool abspath(const char *str
)
145 static inline char *deabs(char *str
)
147 return str
+ strspn(str
, "/");
150 #define strnprintf(buf, buf_size, ...) \
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); \
159 static inline const char *proc_self_fd(int fd
)
161 static const char *invalid_fd_path
= "/proc/self/fd/-EBADF";
162 static char buf
[LXC_PROC_SELF_FD_LEN
] = "/proc/self/fd/";
164 if (strnprintf(buf
+ STRLITERALLEN("/proc/self/fd/"),
165 INTTYPE_TO_STRLEN(int), "%d", fd
) < 0)
166 return invalid_fd_path
;
171 static inline const char *fdstr(int fd
)
173 static const char *fdstr_invalid
= "-EBADF";
174 static char buf
[INTTYPE_TO_STRLEN(int)];
176 if (strnprintf(buf
, sizeof(buf
), "%d", fd
) < 0)
177 return fdstr_invalid
;
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))
187 __hidden
extern char *path_simplify(const char *path
);
189 #endif /* __LXC_STRING_UTILS_H */