1 /* SPDX-License-Identifier: LGPL-2.1+ */
3 #ifndef __LXC_STRING_UTILS_H
4 #define __LXC_STRING_UTILS_H
10 #include "initutils.h"
22 #include "strchrnul.h"
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
);
30 * Some simple string functions; if they return pointers, they are allocated
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
);
38 __hidden
extern char *lxc_append_paths(const char *first
, const char *second
);
41 * Note: the following two functions use strtok(), so they will never
42 * consider an empty element, even if two delimiters are next to
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
);
50 /* Append string to NULL-terminated string array. */
51 __hidden
extern int lxc_append_string(char ***list
, char *entry
);
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
);
61 __hidden
extern void **lxc_append_null_to_array(void **array
, size_t count
);
62 __hidden
extern void remove_trailing_newlines(char *l
);
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
,
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
);
79 * Concatenate all passed-in strings into one path. Do not fail. If any piece
80 * is not prefixed with '/', add a '/'.
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
, ...);
86 #define must_make_path_relative(__first__, ...) \
89 if (*__first__ == '/') \
90 __ptr__ = must_make_path(".", __first__, __VA_ARGS__); \
92 __ptr__ = must_make_path(__first__, __VA_ARGS__); \
96 /* Return copy of string @entry. Do not fail. */
97 __hidden
extern char *must_copy_string(const char *entry
);
99 /* Re-allocate a pointer, do not fail */
100 __hidden
extern void *must_realloc(void *orig
, size_t sz
);
102 __hidden
extern int lxc_char_left_gc(const char *buffer
, size_t len
);
104 __hidden
extern int lxc_char_right_gc(const char *buffer
, size_t len
);
106 __hidden
extern char *lxc_trim_whitespace_in_place(char *buffer
);
108 __hidden
extern int lxc_is_line_empty(const char *line
);
109 __hidden
extern void remove_trailing_slashes(char *p
);
111 static inline bool is_empty_string(const char *s
)
113 return !s
|| strcmp(s
, "") == 0;
116 #define maybe_empty(s) ((!is_empty_string(s)) ? (s) : ("(null)"))
118 static inline ssize_t
safe_strlcat(char *src
, const char *append
, size_t len
)
122 new_len
= strlcat(src
, append
, len
);
124 return ret_errno(EINVAL
);
126 return (ssize_t
)new_len
;
129 static inline bool strnequal(const char *str
, const char *eq
, size_t len
)
131 return strncmp(str
, eq
, len
) == 0;
134 static inline bool strequal(const char *str
, const char *eq
)
136 return strcmp(str
, eq
) == 0;
139 static inline bool dotdot(const char *str
)
141 return !!strstr(str
, "..");
144 static inline bool abspath(const char *str
)
149 static inline char *deabs(char *str
)
151 return str
+ strspn(str
, "/");
154 #define strnprintf(buf, buf_size, ...) \
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); \
163 static inline const char *proc_self_fd(int fd
)
165 static const char *invalid_fd_path
= "/proc/self/fd/-EBADF";
166 static char buf
[LXC_PROC_SELF_FD_LEN
] = "/proc/self/fd/";
168 if (strnprintf(buf
+ STRLITERALLEN("/proc/self/fd/"),
169 INTTYPE_TO_STRLEN(int), "%d", fd
) < 0)
170 return invalid_fd_path
;
175 static inline const char *fdstr(__s64 fd
)
177 static const char *fdstr_invalid
= "-EBADF";
178 static char buf
[INTTYPE_TO_STRLEN(__s64
)];
180 if (strnprintf(buf
, sizeof(buf
), "%lld", (long long signed int)fd
) < 0)
181 return fdstr_invalid
;
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))
191 __hidden
extern char *path_simplify(const char *path
);
193 #endif /* __LXC_STRING_UTILS_H */