#include "config.h"

#include <stdio.h>
#include "utils.h"

/* Global state */
bool opt_verbose = 0;

__attribute__((__format__(printf, 1, 2))) void
verbose(const char *format, ...)
{
    if (opt_verbose) {
	va_list args;
	va_start(args, format);
	vprintf(format, args);
	va_end(args);
    }
}

__attribute__((__format__(printf, 1, 2))) void
error(const char *format, ...)
{
    va_list args;

    va_start(args, format);
    vfprintf(stderr, format, args);
    va_end(args);
}

__attribute__((__noreturn__)) __attribute__((__format__(printf, 1, 2))) void
fatal(const char *format, ...)
{
    va_list args;

    va_start(args, format);
    vfprintf(stderr, format, args);
    va_end(args);

    exit(1);
}

__attribute__((__noreturn__)) void
oom()
{
    fatal("Out of memory");
}

uint32_t
crc32(const uint8_t *data, size_t len)
{
    size_t i;
    ssize_t j;
    uint32_t byte, crc, mask;

    i = 0;
    crc = 0xFFFFFFFF;
    while (i < len) {
	byte = data[i]; // Get next byte.
	crc = crc ^ byte;
	for (j = 7; j >= 0; j--) { // Do eight times.
	    mask = -(crc & 1);
	    crc = (crc >> 1) ^ (0xEDB88320 & mask);
	}
	i = i + 1;
    }
    return ~crc;
}

char *
read_proc_cmdline(void)
{
    FILE *f = fopen("/proc/cmdline", "r");
    char *cmdline = NULL;
    size_t len;

    if (!f)
	goto out;

    /* Note that /proc/cmdline will not end in a newline, so getline
     * will fail unelss we provide a length.
     */
    if (getline(&cmdline, &len, f) < 0)
	goto out;
    /* ... but the length will be the size of the malloc buffer, not
     * strlen().  Fix that.
     */
    len = strlen(cmdline);

    if (cmdline[len - 1] == '\n')
	cmdline[len - 1] = '\0';
out:
    if (f)
	fclose(f);
    return cmdline;
}

char *
find_proc_cmdline_key(const char *cmdline, const char *key)
{
    const size_t key_len = strlen(key);
    for (const char *iter = cmdline; iter;) {
	const char *next = strchr(iter, ' ');
	if (strncmp(iter, key, key_len) == 0 && iter[key_len] == '=') {
	    const char *start = iter + key_len + 1;
	    if (next)
		return strndup(start, next - start);

	    return strdup(start);
	}

	if (next)
	    next += strspn(next, " ");

	iter = next;
    }

    return NULL;
}
