]> git.ipfire.org Git - thirdparty/util-linux.git/blame - include/strutils.h
taskset: Accept 0 pid for current process
[thirdparty/util-linux.git] / include / strutils.h
CommitLineData
faeb1b64
KZ
1/*
2 * No copyright is claimed. This code is in the public domain; do with
3 * it what you wish.
4 */
8abcf290
DB
5#ifndef UTIL_LINUX_STRUTILS
6#define UTIL_LINUX_STRUTILS
7
23106a29 8#include <stdlib.h>
8abcf290
DB
9#include <inttypes.h>
10#include <string.h>
42a7b48f 11#include <strings.h>
ce877f2d 12#include <sys/types.h>
675de3f5 13#include <ctype.h>
3e5a5455 14#include <stdio.h>
deb1c903 15#include <errno.h>
35c84bf7 16#include <time.h>
28453bcc 17#include <stdbool.h>
8abcf290 18
ad265938
KZ
19#include "c.h"
20
9c8b9fba
RM
21/* initialize a custom exit code for all *_or_err functions */
22extern void strutils_set_exitcode(int exit_code);
a99c9130 23
c6b3e988 24extern int ul_parse_size(const char *str, uintmax_t *res, int *power);
8abcf290 25extern int strtosize(const char *str, uintmax_t *res);
551dae40
KZ
26extern uintmax_t strtosize_or_err(const char *str, const char *errmesg);
27
84825b16
KZ
28extern int ul_strtos64(const char *str, int64_t *num, int base);
29extern int ul_strtou64(const char *str, uint64_t *num, int base);
9fc0f69c
KZ
30extern int ul_strtos32(const char *str, int32_t *num, int base);
31extern int ul_strtou32(const char *str, uint32_t *num, int base);
b82e008d
KZ
32extern int ul_strtou16(const char *str, uint16_t *num, int base);
33
a57de0ef 34extern int ul_strtold(const char *str, long double *num);
84825b16 35
9fc0f69c
KZ
36extern int64_t str2num_or_err(const char *str, int base, const char *errmesg, int64_t low, int64_t up);
37extern uint64_t str2unum_or_err(const char *str, int base, const char *errmesg, uint64_t up);
551dae40 38
9fc0f69c
KZ
39#define strtos64_or_err(_s, _e) str2num_or_err(_s, 10, _e, 0, 0)
40#define strtou64_or_err(_s, _e) str2unum_or_err(_s, 10, _e, 0)
41#define strtox64_or_err(_s, _e) str2unum_or_err(_s, 16, _e, 0)
551dae40 42
9fc0f69c
KZ
43#define strtos32_or_err(_s, _e) (int32_t) str2num_or_err(_s, 10, _e, INT32_MIN, INT32_MAX)
44#define strtou32_or_err(_s, _e) (uint32_t) str2unum_or_err(_s, 10, _e, UINT32_MAX)
45#define strtox32_or_err(_s, _e) (uint32_t) str2unum_or_err(_s, 16, _e, UINT32_MAX)
46
47#define strtos16_or_err(_s, _e) (int16_t) str2num_or_err(_s, 10, _e, INT16_MIN, INT16_MAX)
48#define strtou16_or_err(_s, _e) (uint16_t) str2unum_or_err(_s, 10, _e, UINT16_MAX)
49#define strtox16_or_err(_s, _e) (uint16_t) str2unum_or_err(_s, 16, _e, UINT16_MAX)
551dae40 50
a9f97001 51extern double strtod_or_err(const char *str, const char *errmesg);
35c84bf7 52extern long double strtold_or_err(const char *str, const char *errmesg);
551dae40 53
3b888573 54#define strtol_or_err(_s, _e) (long) str2num_or_err(_s, 10, _e, LONG_MIN, LONG_MAX)
550d32c4 55#define strtopid_or_err(_s, _e) (pid_t) str2num_or_err(_s, 10, _e, 1, SINT_MAX(pid_t))
3b888573 56#define strtoul_or_err(_s, _e) (unsigned long) str2unum_or_err(_s, 10, _e, ULONG_MAX)
8abcf290 57
477254da
KZ
58extern void strtotimeval_or_err(const char *str, struct timeval *tv,
59 const char *errmesg);
937cd872
TW
60extern void strtotimespec_or_err(const char *str, struct timespec *ts,
61 const char *errmesg);
35c84bf7 62extern time_t strtotime_or_err(const char *str, const char *errmesg);
477254da 63
8a2c604c 64extern bool hyperlinkwanted(const char *mode);
28453bcc 65
61cbc8a3
KZ
66extern int isdigit_strend(const char *str, const char **end);
67#define isdigit_string(_s) isdigit_strend(_s, NULL)
68
69extern int isxdigit_strend(const char *str, const char **end);
70#define isxdigit_string(_s) isxdigit_strend(_s, NULL)
71
416c43a9 72
818341be 73extern int ul_parse_switch(const char *arg, ...);
e5cf1476 74
02887b73
DT
75#ifndef HAVE_MEMPCPY
76extern void *mempcpy(void *restrict dest, const void *restrict src, size_t n);
77#endif
8abcf290
DB
78#ifndef HAVE_STRNLEN
79extern size_t strnlen(const char *s, size_t maxlen);
80#endif
81#ifndef HAVE_STRNDUP
82extern char *strndup(const char *s, size_t n);
83#endif
84#ifndef HAVE_STRNCHR
85extern char *strnchr(const char *s, size_t maxlen, int c);
86#endif
87
88/* caller guarantees n > 0 */
df67bcc1 89static inline int xstrncpy(char *dest, const char *src, size_t n)
8abcf290 90{
ad265938
KZ
91 size_t len = src ? strlen(src) : 0;
92
93 if (!len)
df67bcc1 94 return 0;
ad265938
KZ
95 len = min(len, n - 1);
96 memcpy(dest, src, len);
97 dest[len] = 0;
df67bcc1 98 return len;
8abcf290 99}
ce877f2d 100
a338eb4a
KZ
101/* This is like strncpy(), but based on memcpy(), so compilers and static
102 * analyzers do not complain when sizeof(destination) is the same as 'n' and
103 * result is not terminated by zero.
104 *
105 * Use this function to copy string to logs with fixed sizes (wtmp/utmp. ...)
106 * where string terminator is optional.
107 */
d57672e2
KZ
108static inline void * __attribute__((nonnull (1)))
109str2memcpy(void *dest, const char *src, size_t n)
a338eb4a
KZ
110{
111 size_t bytes = strlen(src) + 1;
112
113 if (bytes > n)
114 bytes = n;
115
116 memcpy(dest, src, bytes);
117 return dest;
118}
119
d57672e2
KZ
120static inline char * __attribute__((nonnull (1)))
121mem2strcpy(char *dest, const void *src, size_t n, size_t nmax)
a338eb4a
KZ
122{
123 if (n + 1 > nmax)
124 n = nmax - 1;
125
9c05f4b6 126 memset(dest, '\0', nmax);
a338eb4a 127 memcpy(dest, src, n);
a338eb4a
KZ
128 return dest;
129}
130
01aedbec
KZ
131/* Reallocate @str according to @newstr and copy @newstr to @str; returns new @str.
132 * The @str is not modified if reallocation failed (like classic realloc()).
133 */
23afadca
KZ
134static inline char * __attribute__((warn_unused_result))
135strrealloc(char *str, const char *newstr)
136{
137 size_t nsz, osz;
138
139 if (!str)
140 return newstr ? strdup(newstr) : NULL;
01aedbec
KZ
141 if (!newstr)
142 return NULL;
23afadca
KZ
143
144 osz = strlen(str);
145 nsz = strlen(newstr);
146
01aedbec
KZ
147 if (nsz > osz)
148 str = realloc(str, nsz + 1);
149 if (str)
150 memcpy(str, newstr, nsz + 1);
23afadca 151 return str;
23afadca
KZ
152}
153
787226dc 154/* Copy string @str to struct @stru to member addressed by @offset */
deb1c903 155static inline int strdup_to_offset(void *stru, size_t offset, const char *str)
23106a29 156{
deb1c903 157 char **o;
787226dc 158 char *p = NULL;
23106a29 159
deb1c903
KZ
160 if (!stru)
161 return -EINVAL;
162
163 o = (char **) ((char *) stru + offset);
23106a29 164 if (str) {
787226dc
KZ
165 p = strdup(str);
166 if (!p)
deb1c903 167 return -ENOMEM;
23106a29
KZ
168 }
169
170 free(*o);
787226dc 171 *o = p;
deb1c903 172 return 0;
23106a29
KZ
173}
174
787226dc 175/* Copy string __str to struct member _m of the struct _s */
23106a29
KZ
176#define strdup_to_struct_member(_s, _m, _str) \
177 strdup_to_offset((void *) _s, offsetof(__typeof__(*(_s)), _m), _str)
178
787226dc
KZ
179/* Copy string addressed by @offset between two structs */
180static inline int strdup_between_offsets(void *stru_dst, void *stru_src, size_t offset)
181{
182 char **src;
183 char **dst;
184 char *p = NULL;
185
186 if (!stru_src || !stru_dst)
187 return -EINVAL;
188
189 src = (char **) ((char *) stru_src + offset);
190 dst = (char **) ((char *) stru_dst + offset);
191
192 if (*src) {
193 p = strdup(*src);
194 if (!p)
195 return -ENOMEM;
196 }
197
198 free(*dst);
199 *dst = p;
200 return 0;
201}
202
203/* Copy string addressed by struct member between two instances of the same
204 * struct type */
205#define strdup_between_structs(_dst, _src, _m) \
206 strdup_between_offsets((void *)_dst, (void *)_src, offsetof(__typeof__(*(_src)), _m))
207
eb6514b4
KZ
208static inline int is_nonnull_offset(const void *stru, size_t offset)
209{
210 const char **o;
211
212 if (!stru)
213 return -EINVAL;
214
215 o = (const char **) ((const char *) stru + offset);
216 return *o != NULL;
217}
218
219#define is_nonnull_member(_stru, _m) \
220 is_nonnull_offset((void *) _stru, offsetof(__typeof__(*(_stru)), _m))
221
222static inline int strcmp_offsets(const void *sa, const void *sb, size_t offset)
223{
224 const char **a = (const char **) ((const char *) sa + offset),
225 **b = (const char **) ((const char *) sb + offset);
226
227 if (!*a && !*b)
228 return 0;
229 if (!*a)
230 return -1;
231 if (!*b)
232 return 1;
233 return strcmp(*a, *b);
234}
235
236#define strcmp_members(_a, _b, _m) \
237 strcmp_offsets((void *) _a, (void *) _b, offsetof(__typeof__(*(_a)), _m))
787226dc 238
5b82289b 239extern char *xstrmode(mode_t mode, char *str);
5d2a9849
FC
240
241/* Options for size_to_human_string() */
242enum
243{
07b94c9f
KZ
244 SIZE_SUFFIX_1LETTER = 0,
245 SIZE_SUFFIX_3LETTER = (1 << 0),
246 SIZE_SUFFIX_SPACE = (1 << 1),
247 SIZE_DECIMAL_2DIGITS = (1 << 2)
5d2a9849
FC
248};
249
250extern char *size_to_human_string(int options, uint64_t bytes);
ce877f2d 251
c87638ad
KZ
252extern int string_to_idarray(const char *list, int ary[], size_t arysz,
253 int (name2id)(const char *, size_t));
f5077b51 254extern int string_add_to_idarray(const char *list, int ary[],
40b17508 255 size_t arysz, size_t *ary_pos,
f5077b51
MB
256 int (name2id)(const char *, size_t));
257
c87638ad 258extern int string_to_bitarray(const char *list, char *ary,
73a96af6
TW
259 int (*name2bit)(const char *, size_t),
260 size_t allow_range);
c87638ad 261
5ef16771
KZ
262extern int string_to_bitmask(const char *list,
263 unsigned long *mask,
264 long (*name2flag)(const char *, size_t));
dbbe9e7d 265extern int ul_parse_range(const char *str, int *lower, int *upper, int def);
a883c634 266
d4e89dea 267extern int streq_paths(const char *a, const char *b);
b106d052 268
646e159a
KZ
269/*
270 * Match string beginning.
271 */
aa07db0a 272static inline const char *ul_startswith(const char *s, const char *prefix)
646e159a
KZ
273{
274 size_t sz = prefix ? strlen(prefix) : 0;
275
276 if (s && sz && strncmp(s, prefix, sz) == 0)
277 return s + sz;
278 return NULL;
279}
280
281/*
282 * Case insensitive match string beginning.
283 */
284static inline const char *startswith_no_case(const char *s, const char *prefix)
285{
286 size_t sz = prefix ? strlen(prefix) : 0;
287
288 if (s && sz && strncasecmp(s, prefix, sz) == 0)
289 return s + sz;
290 return NULL;
291}
292
10f0de32
KZ
293/*
294 * Match path beginning
295 */
296static inline const char *startswithpath(const char *s, const char *prefix)
297{
aa07db0a 298 const char *p = ul_startswith(s, prefix);
10f0de32
KZ
299
300 if (p && (*p == '/' || *p == '\0'))
301 return p;
302
303 return NULL;
304}
305
646e159a
KZ
306/*
307 * Match string ending.
308 */
aa07db0a 309static inline const char *ul_endswith(const char *s, const char *postfix)
646e159a
KZ
310{
311 size_t sl = s ? strlen(s) : 0;
312 size_t pl = postfix ? strlen(postfix) : 0;
313
314 if (pl == 0)
8a7aeeda 315 return s + sl;
646e159a
KZ
316 if (sl < pl)
317 return NULL;
318 if (memcmp(s + sl - pl, postfix, pl) != 0)
319 return NULL;
8a7aeeda 320 return s + sl - pl;
646e159a 321}
199e939d 322
675de3f5
OO
323/*
324 * Skip leading white space.
325 */
326static inline const char *skip_space(const char *p)
327{
328 while (isspace(*p))
329 ++p;
330 return p;
331}
332
333static inline const char *skip_blank(const char *p)
334{
335 while (isblank(*p))
336 ++p;
337 return p;
338}
339
22e9e9c8
KZ
340
341/* Removes whitespace from the right-hand side of a string (trailing
342 * whitespace).
343 *
344 * Returns size of the new string (without \0).
345 */
346static inline size_t rtrim_whitespace(unsigned char *str)
347{
0b404f08 348 size_t i;
22e9e9c8 349
0b404f08
SK
350 if (!str)
351 return 0;
352 i = strlen((char *) str);
2f8610ee
SK
353 while (i) {
354 i--;
355 if (!isspace(str[i])) {
356 i++;
22e9e9c8 357 break;
2f8610ee 358 }
22e9e9c8 359 }
2f8610ee 360 str[i] = '\0';
22e9e9c8
KZ
361 return i;
362}
363
364/* Removes whitespace from the left-hand side of a string.
365 *
366 * Returns size of the new string (without \0).
367 */
368static inline size_t ltrim_whitespace(unsigned char *str)
369{
370 size_t len;
371 unsigned char *p;
372
0b404f08
SK
373 if (!str)
374 return 0;
375 for (p = str; *p && isspace(*p); p++);
22e9e9c8
KZ
376
377 len = strlen((char *) p);
378
6c183c28 379 if (p > str)
22e9e9c8
KZ
380 memmove(str, p, len + 1);
381
382 return len;
383}
384
5d68f974
KZ
385/* Removes left-hand, right-hand and repeating whitespaces.
386 */
c862d0e1
KZ
387static inline size_t __normalize_whitespace(
388 const unsigned char *src,
389 size_t sz,
390 unsigned char *dst,
391 size_t len)
5d68f974 392{
c862d0e1 393 size_t i, x = 0;
5d68f974
KZ
394 int nsp = 0, intext = 0;
395
396 if (!sz)
c862d0e1 397 goto done;
5d68f974 398
c862d0e1
KZ
399 for (i = 0, x = 0; i < sz && x < len - 1; ) {
400 if (isspace(src[i]))
5d68f974
KZ
401 nsp++;
402 else
403 nsp = 0, intext = 1;
404
405 if (nsp > 1 || (nsp && !intext))
406 i++;
407 else
c862d0e1 408 dst[x++] = src[i++];
5d68f974 409 }
67e194ae 410 if (nsp && x > 0) /* trailing space */
5d68f974 411 x--;
c862d0e1
KZ
412done:
413 dst[x] = '\0';
5d68f974
KZ
414 return x;
415}
416
c862d0e1
KZ
417static inline size_t normalize_whitespace(unsigned char *str)
418{
419 size_t sz = strlen((char *) str);
420 return __normalize_whitespace(str, sz, str, sz + 1);
421}
422
7bb1151e 423static inline void ul_strrep(char *s, int find, int replace)
3c4ff2dc
KZ
424{
425 while (s && *s && (s = strchr(s, find)) != NULL)
426 *s++ = replace;
427}
428
7bb1151e 429static inline void ul_strrem(char *s, int rem)
3c4ff2dc
KZ
430{
431 char *p;
432
d2a1ee4e
SK
433 if (!s)
434 return;
435 for (p = s; *s; s++) {
3c4ff2dc
KZ
436 if (*s != rem)
437 *p++ = *s;
438 }
b94acada 439 *p = '\0';
3c4ff2dc
KZ
440}
441
357e6a0e
KZ
442/* returns next string after \0 if before @end */
443static inline char *ul_next_string(char *p, char *end)
444{
445 char *last;
446
447 if (!p || !end || p >= end)
448 return NULL;
449
450 for (last = p; p < end; p++) {
451 if (*last == '\0' && p != last)
452 return p;
453 last = p;
454 }
455
456 return NULL;
457}
458
c128ee3e
KZ
459extern char *ul_strnconcat(const char *s, const char *suffix, size_t b);
460extern char *ul_strconcat(const char *s, const char *suffix);
461extern char *ul_strfconcat(const char *s, const char *format, ...)
40b55f5a 462 __attribute__ ((__format__ (__printf__, 2, 3)));
2e03758d 463
d42e5e4b 464extern int ul_strappend(char **a, const char *b);
25a5cff8
MY
465extern int strfappend(char **a, const char *format, ...)
466 __attribute__ ((__format__ (__printf__, 2, 3)));
d42e5e4b 467extern int ul_strvfappend(char **a, const char *format, va_list ap)
25a5cff8 468 __attribute__ ((__format__ (__printf__, 2, 0)));
2e03758d 469
6b627aa3 470extern const char *ul_split(const char **state, size_t *l, const char *separator, int quoted);
548b9714 471
63bb0450
KZ
472extern char *ul_strchr_escaped(const char *s, int c);
473
3e5a5455 474extern int skip_fline(FILE *fp);
27e6b3a9 475extern int ul_stralnumcmp(const char *p1, const char *p2);
3e5a5455 476
6c513f3c 477extern int ul_optstr_next(char **optstr, char **name, size_t *namesz, char **value, size_t *valsz);
02defa3e 478extern int ul_optstr_is_valid(const char *optstr);
6c513f3c 479
8abcf290 480#endif