// SPDX-License-Identifier: GPL-2.0-only /* Copyright (C) 2019 Daniel Borkmann */ #include #include #include #include #include #include #include #include #include #include #include "l2md.h" bool verbose_enabled; void *xmalloc(size_t size) { void *ptr; if (!size) panic("xmalloc: zero size\n"); ptr = malloc(size); if (ptr == NULL) panic("xmalloc: out of memory (allocating %zu bytes)\n", size); return ptr; } void *xzmalloc(size_t size) { void *ptr = xmalloc(size); memset(ptr, 0, size); return ptr; } void *xrealloc(void *old, size_t size) { void *new; if (size == 0) panic("xrealloc: zero size\n"); new = realloc(old, size); if (new == NULL) panic("xrealloc: out of memory (allocating %zu bytes)\n", size); return new; } void xfree(void *ptr) { free(ptr); } void xmkdir1(const char *path) { struct stat sb = {}; int ret; ret = stat(path, &sb); if (ret) { ret = mkdir(path, S_IRWXU); if (ret) panic("mkdir %s failed: %s\n", path, strerror(errno)); } } void xmkdir1_with_subdirs(const char *path) { char tmp[PATH_MAX], *ptr; size_t len; slprintf(tmp, sizeof(tmp),"%s", path); len = strlen(tmp); if (tmp[len - 1] == '/') tmp[len - 1] = 0; for (ptr = tmp + 1; *ptr; ptr++) { if (*ptr == '/') { *ptr = 0; xmkdir1(tmp); *ptr = '/'; } } xmkdir1(tmp); } void xmkdir2(const char *base, const char *name) { char path[PATH_MAX]; slprintf(path, sizeof(path), "%s/%s", base, name); xmkdir1(path); } typedef off_t loff_t; int xread_file(const char *file, char *to, size_t len, bool fatal) { loff_t ret; int fd; fd = open(file, O_RDONLY); if (fd < 0) { if (fatal) panic("Cannot open %s: %s\n", file, strerror(errno)); else return fd; } do { ret = read(fd, to, len); if (ret <= 0) { if (fatal) { if (ret) panic("Cannot read file %s: %s\n", file, strerror(errno)); else panic("Unexpected end of file %s\n", file); } else { if (!ret) warn("Unexpected end of file %s\n", file); close(fd); return -1; } } to += ret; len -= ret; } while (len > 0); close(fd); return 0; } int xwrite_file(const char *file, const char *to, size_t len, bool fatal) { loff_t ret; int fd; fd = open(file, O_CREAT | O_WRONLY | O_TRUNC, 0600); if (fd < 0) { if (fatal) panic("Cannot open %s: %s\n", file, strerror(errno)); else return fd; } do { ret = write(fd, to, len); if (ret < 0) { if (fatal) { panic("Cannot write file %s: %s\n", file, strerror(errno)); } else { close(fd); return -1; } } to += ret; len -= ret; } while (len > 0); close(fd); return 0; } void xpipe(int pipefd[2]) { if (pipe(pipefd) < 0) panic("Cannot create pipe: %s\n", strerror(errno)); } void xwrite(int fd, const char *to, size_t len) { loff_t ret; do { ret = write(fd, to, len); if (ret < 0) panic("Cannot write to file descriptor %d: %s", fd, strerror(errno)); to += ret; len -= ret; } while (len > 0); } int timeval_sub(struct timeval *res, struct timeval *x, struct timeval *y) { if (x->tv_usec < y->tv_usec) { int nsec = (y->tv_usec - x->tv_usec) / 1000000 + 1; y->tv_usec -= 1000000 * nsec; y->tv_sec += nsec; } if (x->tv_usec - y->tv_usec > 1000000) { int nsec = (x->tv_usec - y->tv_usec) / 1000000; y->tv_usec += 1000000 * nsec; y->tv_sec -= nsec; } res->tv_sec = x->tv_sec - y->tv_sec; res->tv_usec = x->tv_usec - y->tv_usec; return x->tv_sec < y->tv_sec; } size_t __strlcpy(char *dest, const char *src, size_t size) { size_t ret = strlen(src); if (size) { size_t len = (ret >= size) ? size - 1 : ret; memcpy(dest, src, len); dest[len] = '\0'; } return ret; } static inline int vslprintf(char *dst, size_t size, const char *fmt, va_list ap) { int ret; ret = vsnprintf(dst, size, fmt, ap); dst[size - 1] = '\0'; return ret; } int slprintf(char *dst, size_t size, const char *fmt, ...) { va_list ap; int ret; va_start(ap, fmt); ret = vslprintf(dst, size, fmt, ap); va_end(ap); return ret; } void die(void) { exit(EXIT_FAILURE); } void panic(const char *format, ...) { va_list vl; va_start(vl, format); vfprintf(stderr, format, vl); va_end(vl); die(); } void warn(const char *format, ...) { va_list vl; va_start(vl, format); vfprintf(stderr, format, vl); va_end(vl); } void verbose(const char *format, ...) { va_list vl; if (verbose_enabled) { va_start(vl, format); vfprintf(stderr, format, vl); va_end(vl); } }