]>
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 | ||
deb1c903 | 96 | static inline int strdup_to_offset(void *stru, size_t offset, const char *str) |
23106a29 KZ |
97 | { |
98 | char *n = NULL; | |
deb1c903 | 99 | char **o; |
23106a29 | 100 | |
deb1c903 KZ |
101 | if (!stru) |
102 | return -EINVAL; | |
103 | ||
104 | o = (char **) ((char *) stru + offset); | |
23106a29 KZ |
105 | if (str) { |
106 | n = strdup(str); | |
107 | if (!n) | |
deb1c903 | 108 | return -ENOMEM; |
23106a29 KZ |
109 | } |
110 | ||
111 | free(*o); | |
112 | *o = n; | |
deb1c903 | 113 | return 0; |
23106a29 KZ |
114 | } |
115 | ||
116 | #define strdup_to_struct_member(_s, _m, _str) \ | |
117 | strdup_to_offset((void *) _s, offsetof(__typeof__(*(_s)), _m), _str) | |
118 | ||
5b82289b | 119 | extern char *xstrmode(mode_t mode, char *str); |
5d2a9849 FC |
120 | |
121 | /* Options for size_to_human_string() */ | |
122 | enum | |
123 | { | |
07b94c9f KZ |
124 | SIZE_SUFFIX_1LETTER = 0, |
125 | SIZE_SUFFIX_3LETTER = (1 << 0), | |
126 | SIZE_SUFFIX_SPACE = (1 << 1), | |
127 | SIZE_DECIMAL_2DIGITS = (1 << 2) | |
5d2a9849 FC |
128 | }; |
129 | ||
130 | extern char *size_to_human_string(int options, uint64_t bytes); | |
ce877f2d | 131 | |
c87638ad KZ |
132 | extern int string_to_idarray(const char *list, int ary[], size_t arysz, |
133 | int (name2id)(const char *, size_t)); | |
f5077b51 | 134 | extern int string_add_to_idarray(const char *list, int ary[], |
40b17508 | 135 | size_t arysz, size_t *ary_pos, |
f5077b51 MB |
136 | int (name2id)(const char *, size_t)); |
137 | ||
c87638ad KZ |
138 | extern int string_to_bitarray(const char *list, char *ary, |
139 | int (*name2bit)(const char *, size_t)); | |
140 | ||
5ef16771 KZ |
141 | extern int string_to_bitmask(const char *list, |
142 | unsigned long *mask, | |
143 | long (*name2flag)(const char *, size_t)); | |
af7df9ee | 144 | extern int parse_range(const char *str, int *lower, int *upper, int def); |
a883c634 | 145 | |
d4e89dea | 146 | extern int streq_paths(const char *a, const char *b); |
b106d052 | 147 | |
646e159a KZ |
148 | /* |
149 | * Match string beginning. | |
150 | */ | |
151 | static inline const char *startswith(const char *s, const char *prefix) | |
152 | { | |
153 | size_t sz = prefix ? strlen(prefix) : 0; | |
154 | ||
155 | if (s && sz && strncmp(s, prefix, sz) == 0) | |
156 | return s + sz; | |
157 | return NULL; | |
158 | } | |
159 | ||
160 | /* | |
161 | * Case insensitive match string beginning. | |
162 | */ | |
163 | static inline const char *startswith_no_case(const char *s, const char *prefix) | |
164 | { | |
165 | size_t sz = prefix ? strlen(prefix) : 0; | |
166 | ||
167 | if (s && sz && strncasecmp(s, prefix, sz) == 0) | |
168 | return s + sz; | |
169 | return NULL; | |
170 | } | |
171 | ||
172 | /* | |
173 | * Match string ending. | |
174 | */ | |
175 | static inline const char *endswith(const char *s, const char *postfix) | |
176 | { | |
177 | size_t sl = s ? strlen(s) : 0; | |
178 | size_t pl = postfix ? strlen(postfix) : 0; | |
179 | ||
180 | if (pl == 0) | |
8a7aeeda | 181 | return s + sl; |
646e159a KZ |
182 | if (sl < pl) |
183 | return NULL; | |
184 | if (memcmp(s + sl - pl, postfix, pl) != 0) | |
185 | return NULL; | |
8a7aeeda | 186 | return s + sl - pl; |
646e159a | 187 | } |
199e939d | 188 | |
675de3f5 OO |
189 | /* |
190 | * Skip leading white space. | |
191 | */ | |
192 | static inline const char *skip_space(const char *p) | |
193 | { | |
194 | while (isspace(*p)) | |
195 | ++p; | |
196 | return p; | |
197 | } | |
198 | ||
199 | static inline const char *skip_blank(const char *p) | |
200 | { | |
201 | while (isblank(*p)) | |
202 | ++p; | |
203 | return p; | |
204 | } | |
205 | ||
22e9e9c8 KZ |
206 | |
207 | /* Removes whitespace from the right-hand side of a string (trailing | |
208 | * whitespace). | |
209 | * | |
210 | * Returns size of the new string (without \0). | |
211 | */ | |
212 | static inline size_t rtrim_whitespace(unsigned char *str) | |
213 | { | |
0b404f08 | 214 | size_t i; |
22e9e9c8 | 215 | |
0b404f08 SK |
216 | if (!str) |
217 | return 0; | |
218 | i = strlen((char *) str); | |
2f8610ee SK |
219 | while (i) { |
220 | i--; | |
221 | if (!isspace(str[i])) { | |
222 | i++; | |
22e9e9c8 | 223 | break; |
2f8610ee | 224 | } |
22e9e9c8 | 225 | } |
2f8610ee | 226 | str[i] = '\0'; |
22e9e9c8 KZ |
227 | return i; |
228 | } | |
229 | ||
230 | /* Removes whitespace from the left-hand side of a string. | |
231 | * | |
232 | * Returns size of the new string (without \0). | |
233 | */ | |
234 | static inline size_t ltrim_whitespace(unsigned char *str) | |
235 | { | |
236 | size_t len; | |
237 | unsigned char *p; | |
238 | ||
0b404f08 SK |
239 | if (!str) |
240 | return 0; | |
241 | for (p = str; *p && isspace(*p); p++); | |
22e9e9c8 KZ |
242 | |
243 | len = strlen((char *) p); | |
244 | ||
6c183c28 | 245 | if (p > str) |
22e9e9c8 KZ |
246 | memmove(str, p, len + 1); |
247 | ||
248 | return len; | |
249 | } | |
250 | ||
548b9714 KZ |
251 | extern char *strnappend(const char *s, const char *suffix, size_t b); |
252 | extern char *strappend(const char *s, const char *suffix); | |
3c201431 KZ |
253 | extern char *strfappend(const char *s, const char *format, ...) |
254 | __attribute__ ((__format__ (__printf__, 2, 0))); | |
548b9714 KZ |
255 | extern const char *split(const char **state, size_t *l, const char *separator, int quoted); |
256 | ||
3e5a5455 SK |
257 | extern int skip_fline(FILE *fp); |
258 | ||
8abcf290 | 259 | #endif |