]>
Commit | Line | Data |
---|---|---|
8abcf290 DB |
1 | #ifndef UTIL_LINUX_STRUTILS |
2 | #define UTIL_LINUX_STRUTILS | |
3 | ||
23106a29 | 4 | #include <stdlib.h> |
8abcf290 DB |
5 | #include <inttypes.h> |
6 | #include <string.h> | |
ce877f2d | 7 | #include <sys/types.h> |
675de3f5 | 8 | #include <ctype.h> |
3e5a5455 | 9 | #include <stdio.h> |
deb1c903 | 10 | #include <errno.h> |
8abcf290 | 11 | |
9c8b9fba RM |
12 | /* initialize a custom exit code for all *_or_err functions */ |
13 | extern void strutils_set_exitcode(int exit_code); | |
a99c9130 | 14 | |
23106a29 | 15 | extern int parse_size(const char *str, uintmax_t *res, int *power); |
8abcf290 | 16 | extern int strtosize(const char *str, uintmax_t *res); |
551dae40 KZ |
17 | extern uintmax_t strtosize_or_err(const char *str, const char *errmesg); |
18 | ||
19 | extern int16_t strtos16_or_err(const char *str, const char *errmesg); | |
20 | extern uint16_t strtou16_or_err(const char *str, const char *errmesg); | |
54394eab | 21 | extern uint16_t strtox16_or_err(const char *str, const char *errmesg); |
551dae40 KZ |
22 | |
23 | extern int32_t strtos32_or_err(const char *str, const char *errmesg); | |
24 | extern uint32_t strtou32_or_err(const char *str, const char *errmesg); | |
54394eab | 25 | extern uint32_t strtox32_or_err(const char *str, const char *errmesg); |
551dae40 KZ |
26 | |
27 | extern int64_t strtos64_or_err(const char *str, const char *errmesg); | |
28 | extern uint64_t strtou64_or_err(const char *str, const char *errmesg); | |
54394eab | 29 | extern uint64_t strtox64_or_err(const char *str, const char *errmesg); |
551dae40 | 30 | |
a9f97001 | 31 | extern double strtod_or_err(const char *str, const char *errmesg); |
551dae40 | 32 | |
8abcf290 | 33 | extern long strtol_or_err(const char *str, const char *errmesg); |
e53bc960 | 34 | extern unsigned long strtoul_or_err(const char *str, const char *errmesg); |
8abcf290 | 35 | |
477254da KZ |
36 | extern void strtotimeval_or_err(const char *str, struct timeval *tv, |
37 | const char *errmesg); | |
38 | ||
61cbc8a3 KZ |
39 | extern int isdigit_strend(const char *str, const char **end); |
40 | #define isdigit_string(_s) isdigit_strend(_s, NULL) | |
41 | ||
42 | extern int isxdigit_strend(const char *str, const char **end); | |
43 | #define isxdigit_string(_s) isxdigit_strend(_s, NULL) | |
44 | ||
416c43a9 | 45 | |
30b294c4 | 46 | extern int parse_switch(const char *arg, const char *errmesg, ...); |
e5cf1476 | 47 | |
02887b73 DT |
48 | #ifndef HAVE_MEMPCPY |
49 | extern void *mempcpy(void *restrict dest, const void *restrict src, size_t n); | |
50 | #endif | |
8abcf290 DB |
51 | #ifndef HAVE_STRNLEN |
52 | extern size_t strnlen(const char *s, size_t maxlen); | |
53 | #endif | |
54 | #ifndef HAVE_STRNDUP | |
55 | extern char *strndup(const char *s, size_t n); | |
56 | #endif | |
57 | #ifndef HAVE_STRNCHR | |
58 | extern char *strnchr(const char *s, size_t maxlen, int c); | |
59 | #endif | |
60 | ||
61 | /* caller guarantees n > 0 */ | |
62 | static inline void xstrncpy(char *dest, const char *src, size_t n) | |
63 | { | |
64 | strncpy(dest, src, n-1); | |
65 | dest[n-1] = 0; | |
66 | } | |
ce877f2d | 67 | |
a338eb4a KZ |
68 | /* This is like strncpy(), but based on memcpy(), so compilers and static |
69 | * analyzers do not complain when sizeof(destination) is the same as 'n' and | |
70 | * result is not terminated by zero. | |
71 | * | |
72 | * Use this function to copy string to logs with fixed sizes (wtmp/utmp. ...) | |
73 | * where string terminator is optional. | |
74 | */ | |
75 | static inline void *str2memcpy(void *dest, const char *src, size_t n) | |
76 | { | |
77 | size_t bytes = strlen(src) + 1; | |
78 | ||
79 | if (bytes > n) | |
80 | bytes = n; | |
81 | ||
82 | memcpy(dest, src, bytes); | |
83 | return dest; | |
84 | } | |
85 | ||
86 | static inline char *mem2strcpy(char *dest, const void *src, size_t n, size_t nmax) | |
87 | { | |
88 | if (n + 1 > nmax) | |
89 | n = nmax - 1; | |
90 | ||
91 | memcpy(dest, src, n); | |
92 | dest[nmax-1] = '\0'; | |
93 | return dest; | |
94 | } | |
95 | ||
23afadca KZ |
96 | /* Reallocate @str according to @newstr and copy @newstr to @str; returns new @str */ |
97 | static inline char * __attribute__((warn_unused_result)) | |
98 | strrealloc(char *str, const char *newstr) | |
99 | { | |
100 | size_t nsz, osz; | |
101 | ||
102 | if (!str) | |
103 | return newstr ? strdup(newstr) : NULL; | |
104 | if (!newstr) { | |
105 | free(str); | |
106 | goto nothing; | |
107 | } | |
108 | ||
109 | osz = strlen(str); | |
110 | nsz = strlen(newstr); | |
111 | ||
112 | if (nsz > osz) { | |
113 | char *tmp = realloc(str, nsz + 1); | |
114 | if (!tmp) | |
115 | goto nothing; | |
116 | str = tmp; | |
117 | } | |
118 | ||
119 | memcpy(str, newstr, nsz + 1); | |
120 | return str; | |
121 | ||
122 | nothing: | |
123 | free(str); | |
124 | return NULL; | |
125 | } | |
126 | ||
deb1c903 | 127 | static inline int strdup_to_offset(void *stru, size_t offset, const char *str) |
23106a29 KZ |
128 | { |
129 | char *n = NULL; | |
deb1c903 | 130 | char **o; |
23106a29 | 131 | |
deb1c903 KZ |
132 | if (!stru) |
133 | return -EINVAL; | |
134 | ||
135 | o = (char **) ((char *) stru + offset); | |
23106a29 KZ |
136 | if (str) { |
137 | n = strdup(str); | |
138 | if (!n) | |
deb1c903 | 139 | return -ENOMEM; |
23106a29 KZ |
140 | } |
141 | ||
142 | free(*o); | |
143 | *o = n; | |
deb1c903 | 144 | return 0; |
23106a29 KZ |
145 | } |
146 | ||
147 | #define strdup_to_struct_member(_s, _m, _str) \ | |
148 | strdup_to_offset((void *) _s, offsetof(__typeof__(*(_s)), _m), _str) | |
149 | ||
5b82289b | 150 | extern char *xstrmode(mode_t mode, char *str); |
5d2a9849 FC |
151 | |
152 | /* Options for size_to_human_string() */ | |
153 | enum | |
154 | { | |
07b94c9f KZ |
155 | SIZE_SUFFIX_1LETTER = 0, |
156 | SIZE_SUFFIX_3LETTER = (1 << 0), | |
157 | SIZE_SUFFIX_SPACE = (1 << 1), | |
158 | SIZE_DECIMAL_2DIGITS = (1 << 2) | |
5d2a9849 FC |
159 | }; |
160 | ||
161 | extern char *size_to_human_string(int options, uint64_t bytes); | |
ce877f2d | 162 | |
c87638ad KZ |
163 | extern int string_to_idarray(const char *list, int ary[], size_t arysz, |
164 | int (name2id)(const char *, size_t)); | |
f5077b51 | 165 | extern int string_add_to_idarray(const char *list, int ary[], |
40b17508 | 166 | size_t arysz, size_t *ary_pos, |
f5077b51 MB |
167 | int (name2id)(const char *, size_t)); |
168 | ||
c87638ad KZ |
169 | extern int string_to_bitarray(const char *list, char *ary, |
170 | int (*name2bit)(const char *, size_t)); | |
171 | ||
5ef16771 KZ |
172 | extern int string_to_bitmask(const char *list, |
173 | unsigned long *mask, | |
174 | long (*name2flag)(const char *, size_t)); | |
af7df9ee | 175 | extern int parse_range(const char *str, int *lower, int *upper, int def); |
a883c634 | 176 | |
d4e89dea | 177 | extern int streq_paths(const char *a, const char *b); |
b106d052 | 178 | |
646e159a KZ |
179 | /* |
180 | * Match string beginning. | |
181 | */ | |
182 | static inline const char *startswith(const char *s, const char *prefix) | |
183 | { | |
184 | size_t sz = prefix ? strlen(prefix) : 0; | |
185 | ||
186 | if (s && sz && strncmp(s, prefix, sz) == 0) | |
187 | return s + sz; | |
188 | return NULL; | |
189 | } | |
190 | ||
191 | /* | |
192 | * Case insensitive match string beginning. | |
193 | */ | |
194 | static inline const char *startswith_no_case(const char *s, const char *prefix) | |
195 | { | |
196 | size_t sz = prefix ? strlen(prefix) : 0; | |
197 | ||
198 | if (s && sz && strncasecmp(s, prefix, sz) == 0) | |
199 | return s + sz; | |
200 | return NULL; | |
201 | } | |
202 | ||
203 | /* | |
204 | * Match string ending. | |
205 | */ | |
206 | static inline const char *endswith(const char *s, const char *postfix) | |
207 | { | |
208 | size_t sl = s ? strlen(s) : 0; | |
209 | size_t pl = postfix ? strlen(postfix) : 0; | |
210 | ||
211 | if (pl == 0) | |
8a7aeeda | 212 | return s + sl; |
646e159a KZ |
213 | if (sl < pl) |
214 | return NULL; | |
215 | if (memcmp(s + sl - pl, postfix, pl) != 0) | |
216 | return NULL; | |
8a7aeeda | 217 | return s + sl - pl; |
646e159a | 218 | } |
199e939d | 219 | |
675de3f5 OO |
220 | /* |
221 | * Skip leading white space. | |
222 | */ | |
223 | static inline const char *skip_space(const char *p) | |
224 | { | |
225 | while (isspace(*p)) | |
226 | ++p; | |
227 | return p; | |
228 | } | |
229 | ||
230 | static inline const char *skip_blank(const char *p) | |
231 | { | |
232 | while (isblank(*p)) | |
233 | ++p; | |
234 | return p; | |
235 | } | |
236 | ||
22e9e9c8 KZ |
237 | |
238 | /* Removes whitespace from the right-hand side of a string (trailing | |
239 | * whitespace). | |
240 | * | |
241 | * Returns size of the new string (without \0). | |
242 | */ | |
243 | static inline size_t rtrim_whitespace(unsigned char *str) | |
244 | { | |
0b404f08 | 245 | size_t i; |
22e9e9c8 | 246 | |
0b404f08 SK |
247 | if (!str) |
248 | return 0; | |
249 | i = strlen((char *) str); | |
2f8610ee SK |
250 | while (i) { |
251 | i--; | |
252 | if (!isspace(str[i])) { | |
253 | i++; | |
22e9e9c8 | 254 | break; |
2f8610ee | 255 | } |
22e9e9c8 | 256 | } |
2f8610ee | 257 | str[i] = '\0'; |
22e9e9c8 KZ |
258 | return i; |
259 | } | |
260 | ||
261 | /* Removes whitespace from the left-hand side of a string. | |
262 | * | |
263 | * Returns size of the new string (without \0). | |
264 | */ | |
265 | static inline size_t ltrim_whitespace(unsigned char *str) | |
266 | { | |
267 | size_t len; | |
268 | unsigned char *p; | |
269 | ||
0b404f08 SK |
270 | if (!str) |
271 | return 0; | |
272 | for (p = str; *p && isspace(*p); p++); | |
22e9e9c8 KZ |
273 | |
274 | len = strlen((char *) p); | |
275 | ||
6c183c28 | 276 | if (p > str) |
22e9e9c8 KZ |
277 | memmove(str, p, len + 1); |
278 | ||
279 | return len; | |
280 | } | |
281 | ||
3c4ff2dc KZ |
282 | static inline void strrep(char *s, int find, int replace) |
283 | { | |
284 | while (s && *s && (s = strchr(s, find)) != NULL) | |
285 | *s++ = replace; | |
286 | } | |
287 | ||
288 | static inline void strrem(char *s, int rem) | |
289 | { | |
290 | char *p; | |
291 | ||
d2a1ee4e SK |
292 | if (!s) |
293 | return; | |
294 | for (p = s; *s; s++) { | |
3c4ff2dc KZ |
295 | if (*s != rem) |
296 | *p++ = *s; | |
297 | } | |
b94acada | 298 | *p = '\0'; |
3c4ff2dc KZ |
299 | } |
300 | ||
548b9714 KZ |
301 | extern char *strnappend(const char *s, const char *suffix, size_t b); |
302 | extern char *strappend(const char *s, const char *suffix); | |
3c201431 KZ |
303 | extern char *strfappend(const char *s, const char *format, ...) |
304 | __attribute__ ((__format__ (__printf__, 2, 0))); | |
548b9714 KZ |
305 | extern const char *split(const char **state, size_t *l, const char *separator, int quoted); |
306 | ||
3e5a5455 SK |
307 | extern int skip_fline(FILE *fp); |
308 | ||
8abcf290 | 309 | #endif |