]> git.ipfire.org Git - thirdparty/util-linux.git/blame - include/strutils.h
login: reduce file-descriptors cleanup overhead
[thirdparty/util-linux.git] / include / strutils.h
CommitLineData
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 */
13extern void strutils_set_exitcode(int exit_code);
a99c9130 14
23106a29 15extern int parse_size(const char *str, uintmax_t *res, int *power);
8abcf290 16extern int strtosize(const char *str, uintmax_t *res);
551dae40
KZ
17extern uintmax_t strtosize_or_err(const char *str, const char *errmesg);
18
19extern int16_t strtos16_or_err(const char *str, const char *errmesg);
20extern uint16_t strtou16_or_err(const char *str, const char *errmesg);
54394eab 21extern uint16_t strtox16_or_err(const char *str, const char *errmesg);
551dae40
KZ
22
23extern int32_t strtos32_or_err(const char *str, const char *errmesg);
24extern uint32_t strtou32_or_err(const char *str, const char *errmesg);
54394eab 25extern uint32_t strtox32_or_err(const char *str, const char *errmesg);
551dae40
KZ
26
27extern int64_t strtos64_or_err(const char *str, const char *errmesg);
28extern uint64_t strtou64_or_err(const char *str, const char *errmesg);
54394eab 29extern uint64_t strtox64_or_err(const char *str, const char *errmesg);
551dae40 30
a9f97001 31extern double strtod_or_err(const char *str, const char *errmesg);
551dae40 32
8abcf290 33extern long strtol_or_err(const char *str, const char *errmesg);
e53bc960 34extern unsigned long strtoul_or_err(const char *str, const char *errmesg);
8abcf290 35
477254da
KZ
36extern void strtotimeval_or_err(const char *str, struct timeval *tv,
37 const char *errmesg);
38
61cbc8a3
KZ
39extern int isdigit_strend(const char *str, const char **end);
40#define isdigit_string(_s) isdigit_strend(_s, NULL)
41
42extern int isxdigit_strend(const char *str, const char **end);
43#define isxdigit_string(_s) isxdigit_strend(_s, NULL)
44
416c43a9 45
30b294c4 46extern int parse_switch(const char *arg, const char *errmesg, ...);
e5cf1476 47
02887b73
DT
48#ifndef HAVE_MEMPCPY
49extern void *mempcpy(void *restrict dest, const void *restrict src, size_t n);
50#endif
8abcf290
DB
51#ifndef HAVE_STRNLEN
52extern size_t strnlen(const char *s, size_t maxlen);
53#endif
54#ifndef HAVE_STRNDUP
55extern char *strndup(const char *s, size_t n);
56#endif
57#ifndef HAVE_STRNCHR
58extern char *strnchr(const char *s, size_t maxlen, int c);
59#endif
60
61/* caller guarantees n > 0 */
62static 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 */
75static 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
86static 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 */
97static inline char * __attribute__((warn_unused_result))
98strrealloc(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
122nothing:
123 free(str);
124 return NULL;
125}
126
deb1c903 127static 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 150extern char *xstrmode(mode_t mode, char *str);
5d2a9849
FC
151
152/* Options for size_to_human_string() */
153enum
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
161extern char *size_to_human_string(int options, uint64_t bytes);
ce877f2d 162
c87638ad
KZ
163extern int string_to_idarray(const char *list, int ary[], size_t arysz,
164 int (name2id)(const char *, size_t));
f5077b51 165extern 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
169extern int string_to_bitarray(const char *list, char *ary,
170 int (*name2bit)(const char *, size_t));
171
5ef16771
KZ
172extern int string_to_bitmask(const char *list,
173 unsigned long *mask,
174 long (*name2flag)(const char *, size_t));
af7df9ee 175extern int parse_range(const char *str, int *lower, int *upper, int def);
a883c634 176
d4e89dea 177extern int streq_paths(const char *a, const char *b);
b106d052 178
646e159a
KZ
179/*
180 * Match string beginning.
181 */
182static 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 */
194static 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 */
206static 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 */
223static inline const char *skip_space(const char *p)
224{
225 while (isspace(*p))
226 ++p;
227 return p;
228}
229
230static 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 */
243static 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 */
265static 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
282static inline void strrep(char *s, int find, int replace)
283{
284 while (s && *s && (s = strchr(s, find)) != NULL)
285 *s++ = replace;
286}
287
288static 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
301extern char *strnappend(const char *s, const char *suffix, size_t b);
302extern char *strappend(const char *s, const char *suffix);
3c201431
KZ
303extern char *strfappend(const char *s, const char *format, ...)
304 __attribute__ ((__format__ (__printf__, 2, 0)));
548b9714
KZ
305extern const char *split(const char **state, size_t *l, const char *separator, int quoted);
306
3e5a5455
SK
307extern int skip_fline(FILE *fp);
308
8abcf290 309#endif