diff options
Diffstat (limited to 'util.c')
| -rw-r--r-- | util.c | 144 |
1 files changed, 144 insertions, 0 deletions
@@ -0,0 +1,144 @@ +/* SPDX-License-Identifier: GPL-2.0 */ + +#include "tf.h" + +DEFINE_TF_ERRLIST; + +int atoi64(const char *str, int64_t *value) +{ + char *endptr; + long long tmp; + + errno = 0; /* To distinguish success/failure after call */ + tmp = strtoll(str, &endptr, 10); + if (errno == ERANGE && (tmp == LLONG_MAX || tmp == LLONG_MIN)) + return -E_ATOI_OVERFLOW; + /* + * If there were no digits at all, strtoll() stores the original value + * of str in *endptr. + */ + if (endptr == str) + return -E_ATOI_NO_DIGITS; + /* + * The implementation may also set errno and return 0 in case no + * conversion was performed. + */ + if (errno != 0 && tmp == 0) + return -E_ATOI_NO_DIGITS; + if (*endptr != '\0') /* Further characters after number */ + return -E_ATOI_JUNK_AT_END; + *value = tmp; + return 1; +} + +__attribute__ ((warn_unused_result)) +void *xrealloc(void *p, size_t size) +{ + /* + * No need to check for NULL pointers: If p is NULL, the call + * to realloc is equivalent to malloc(size) + */ + assert(size); + if (!(p = realloc(p, size))) { + EMERG_LOG("realloc failed (size = %zu), aborting\n", size); + exit(EXIT_FAILURE); + } + return p; +} + +__attribute__ ((warn_unused_result)) +void *xmalloc(size_t size) +{ + return xrealloc(NULL, size); +} + +__attribute__ ((warn_unused_result)) +void *xcalloc(size_t size) +{ + void *p = xmalloc(size); + memset(p, 0, size); + return p; +} + +/* + * Print a formated message to a dynamically allocated string. + * + * This function is similar to vasprintf(), a GNU extension which is not in C + * or POSIX. It allocates a string large enough to hold the output including + * the terminating null byte. The allocated string is returned via the first + * argument and must be freed by the caller. However, unlike vasprintf(), this + * function calls exit() if insufficient memory is available, while vasprintf() + * returns -1 in this case. + * + * It returns the number of bytes written, not including the terminating \p + * NULL character. + */ +__attribute__ ((format (printf, 2, 0))) +unsigned xvasprintf(char **result, const char *fmt, va_list ap) +{ + int ret; + size_t size = 150; + va_list aq; + + *result = xmalloc(size + 1); + va_copy(aq, ap); + ret = vsnprintf(*result, size, fmt, aq); + va_end(aq); + assert(ret >= 0); + if ((size_t)ret < size) + return ret; + size = ret + 1; + *result = xrealloc(*result, size); + va_copy(aq, ap); + ret = vsnprintf(*result, size, fmt, aq); + va_end(aq); + assert(ret >= 0 && (size_t)ret < size); + return ret; +} + +__attribute__ ((format (printf, 2, 3))) +/* Print to a dynamically allocated string, variable number of arguments. */ +unsigned xasprintf(char **result, const char *fmt, ...) +{ + va_list ap; + unsigned ret; + + va_start(ap, fmt); + ret = xvasprintf(result, fmt, ap); + va_end(ap); + return ret; +} + +/* + * Compile a regular expression. + * + * This simple wrapper calls regcomp(3) and logs a message on errors. + */ +int xregcomp(regex_t *preg, const char *regex, int cflags) +{ + char *buf; + size_t size; + int ret = regcomp(preg, regex, cflags); + + if (ret == 0) + return 1; + size = regerror(ret, preg, NULL, 0); + buf = xmalloc(size); + regerror(ret, preg, buf, size); + ERROR_LOG("%s\n", buf); + free(buf); + return -E_REGEX; +} + +static int loglevel_arg_val; + +__attribute__ ((format (printf, 2, 3))) +void txp_log(int ll, const char* fmt,...) +{ + va_list argp; + if (ll < loglevel_arg_val) + return; + va_start(argp, fmt); + vfprintf(stderr, fmt, argp); + va_end(argp); +} |
