/* 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); }