blob: e4c784914e446d3a831ba15b95a4cff5a9aa1302 [file] [log] [blame]
// SPDX-License-Identifier: GPL-2.0-only
/* Copyright (C) 2019 Daniel Borkmann <daniel@iogearbox.net> */
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/syscall.h>
#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);
}
}