#ifndef UTIL_LINUX_STRUTILS #define UTIL_LINUX_STRUTILS #include #include #include #include #include #include #include /* initialize a custom exit code for all *_or_err functions */ extern void strutils_set_exitcode(int exit_code); extern int parse_size(const char *str, uintmax_t *res, int *power); extern int strtosize(const char *str, uintmax_t *res); extern uintmax_t strtosize_or_err(const char *str, const char *errmesg); extern int16_t strtos16_or_err(const char *str, const char *errmesg); extern uint16_t strtou16_or_err(const char *str, const char *errmesg); extern uint16_t strtox16_or_err(const char *str, const char *errmesg); extern int32_t strtos32_or_err(const char *str, const char *errmesg); extern uint32_t strtou32_or_err(const char *str, const char *errmesg); extern uint32_t strtox32_or_err(const char *str, const char *errmesg); extern int64_t strtos64_or_err(const char *str, const char *errmesg); extern uint64_t strtou64_or_err(const char *str, const char *errmesg); extern uint64_t strtox64_or_err(const char *str, const char *errmesg); extern double strtod_or_err(const char *str, const char *errmesg); extern long strtol_or_err(const char *str, const char *errmesg); extern unsigned long strtoul_or_err(const char *str, const char *errmesg); extern void strtotimeval_or_err(const char *str, struct timeval *tv, const char *errmesg); extern int isdigit_strend(const char *str, const char **end); #define isdigit_string(_s) isdigit_strend(_s, NULL) extern int isxdigit_strend(const char *str, const char **end); #define isxdigit_string(_s) isxdigit_strend(_s, NULL) extern int parse_switch(const char *arg, const char *errmesg, ...); #ifndef HAVE_MEMPCPY extern void *mempcpy(void *restrict dest, const void *restrict src, size_t n); #endif #ifndef HAVE_STRNLEN extern size_t strnlen(const char *s, size_t maxlen); #endif #ifndef HAVE_STRNDUP extern char *strndup(const char *s, size_t n); #endif #ifndef HAVE_STRNCHR extern char *strnchr(const char *s, size_t maxlen, int c); #endif /* caller guarantees n > 0 */ static inline void xstrncpy(char *dest, const char *src, size_t n) { strncpy(dest, src, n-1); dest[n-1] = 0; } /* This is like strncpy(), but based on memcpy(), so compilers and static * analyzers do not complain when sizeof(destination) is the same as 'n' and * result is not terminated by zero. * * Use this function to copy string to logs with fixed sizes (wtmp/utmp. ...) * where string terminator is optional. */ static inline void *str2memcpy(void *dest, const char *src, size_t n) { size_t bytes = strlen(src) + 1; if (bytes > n) bytes = n; memcpy(dest, src, bytes); return dest; } static inline char *mem2strcpy(char *dest, const void *src, size_t n, size_t nmax) { if (n + 1 > nmax) n = nmax - 1; memcpy(dest, src, n); dest[nmax-1] = '\0'; return dest; } static inline int strdup_to_offset(void *stru, size_t offset, const char *str) { char *n = NULL; char **o; if (!stru) return -EINVAL; o = (char **) ((char *) stru + offset); if (str) { n = strdup(str); if (!n) return -ENOMEM; } free(*o); *o = n; return 0; } #define strdup_to_struct_member(_s, _m, _str) \ strdup_to_offset((void *) _s, offsetof(__typeof__(*(_s)), _m), _str) extern char *xstrmode(mode_t mode, char *str); /* Options for size_to_human_string() */ enum { SIZE_SUFFIX_1LETTER = 0, SIZE_SUFFIX_3LETTER = (1 << 0), SIZE_SUFFIX_SPACE = (1 << 1), SIZE_DECIMAL_2DIGITS = (1 << 2) }; extern char *size_to_human_string(int options, uint64_t bytes); extern int string_to_idarray(const char *list, int ary[], size_t arysz, int (name2id)(const char *, size_t)); extern int string_add_to_idarray(const char *list, int ary[], size_t arysz, size_t *ary_pos, int (name2id)(const char *, size_t)); extern int string_to_bitarray(const char *list, char *ary, int (*name2bit)(const char *, size_t)); extern int string_to_bitmask(const char *list, unsigned long *mask, long (*name2flag)(const char *, size_t)); extern int parse_range(const char *str, int *lower, int *upper, int def); extern int streq_paths(const char *a, const char *b); /* * Match string beginning. */ static inline const char *startswith(const char *s, const char *prefix) { size_t sz = prefix ? strlen(prefix) : 0; if (s && sz && strncmp(s, prefix, sz) == 0) return s + sz; return NULL; } /* * Case insensitive match string beginning. */ static inline const char *startswith_no_case(const char *s, const char *prefix) { size_t sz = prefix ? strlen(prefix) : 0; if (s && sz && strncasecmp(s, prefix, sz) == 0) return s + sz; return NULL; } /* * Match string ending. */ static inline const char *endswith(const char *s, const char *postfix) { size_t sl = s ? strlen(s) : 0; size_t pl = postfix ? strlen(postfix) : 0; if (pl == 0) return s + sl; if (sl < pl) return NULL; if (memcmp(s + sl - pl, postfix, pl) != 0) return NULL; return s + sl - pl; } /* * Skip leading white space. */ static inline const char *skip_space(const char *p) { while (isspace(*p)) ++p; return p; } static inline const char *skip_blank(const char *p) { while (isblank(*p)) ++p; return p; } /* Removes whitespace from the right-hand side of a string (trailing * whitespace). * * Returns size of the new string (without \0). */ static inline size_t rtrim_whitespace(unsigned char *str) { size_t i; if (!str) return 0; i = strlen((char *) str); while (i) { i--; if (!isspace(str[i])) { i++; break; } } str[i] = '\0'; return i; } /* Removes whitespace from the left-hand side of a string. * * Returns size of the new string (without \0). */ static inline size_t ltrim_whitespace(unsigned char *str) { size_t len; unsigned char *p; if (!str) return 0; for (p = str; *p && isspace(*p); p++); len = strlen((char *) p); if (p > str) memmove(str, p, len + 1); return len; } static inline void strrep(char *s, int find, int replace) { while (s && *s && (s = strchr(s, find)) != NULL) *s++ = replace; } static inline void strrem(char *s, int rem) { char *p; if (!s) return; for (p = s; *s; s++) { if (*s != rem) *p++ = *s; } *p = '\0'; } extern char *strnappend(const char *s, const char *suffix, size_t b); extern char *strappend(const char *s, const char *suffix); extern char *strfappend(const char *s, const char *format, ...) __attribute__ ((__format__ (__printf__, 2, 0))); extern const char *split(const char **state, size_t *l, const char *separator, int quoted); extern int skip_fline(FILE *fp); #endif