/* * Basic wrapper around mmap(2) that gives you the file length so you can * safely treat it as an ordinary buffer. Only gives you read access. */ static char *read_file(char *path, size_t *length) { int fd; char buf[4096], *copy = NULL; if (!length) return NULL; fd = open(path, O_RDONLY | O_CLOEXEC); if (fd < 0) return NULL; *length = 0; for (;;) { int n; n = read(fd, buf, sizeof(buf)); if (n < 0) goto error; if (!n) break; copy = must_realloc(copy, (*length + n) * sizeof(*copy)); memcpy(copy + *length, buf, n); *length += n; } close(fd); return copy; error: close(fd); free(copy); return NULL; }
static void batch_realloc(char **mem, size_t oldlen, size_t newlen) { int newbatches = (newlen / BATCH_SIZE) + 1; int oldbatches = (oldlen / BATCH_SIZE) + 1; if (!*mem || newbatches > oldbatches) { *mem = must_realloc(*mem, newbatches * BATCH_SIZE); } }
/* * Given a pointer to a null-terminated array of pointers, realloc to * add one entry, and point the new entry to NULL. Do not fail. Return * the index to the second-to-last entry - that is, the one which is * now available for use (keeping the list null-terminated). */ static int append_null_to_list(void ***list) { int newentry = 0; if (*list) for (; (*list)[newentry]; newentry++); *list = must_realloc(*list, (newentry + 2) * sizeof(void **)); (*list)[newentry + 1] = NULL; return newentry; }
/* * A poor-man's version of "xargs -0". Basically parses a given block of * NUL-delimited data, within the given length and adds a pointer to each entry * to the array of pointers. */ static int parse_xargs(char *data, int data_length, char ***output) { int num = 0; char *cur = data; if (!data || *output != NULL) return -1; while (cur < data + data_length) { num++; *output = must_realloc(*output, (num + 1) * sizeof(**output)); (*output)[num - 1] = cur; cur += strlen(cur) + 1; } (*output)[num] = NULL; return num; }
/* Allocate a pointer, do not fail */ static void *must_alloc(size_t sz) { return must_realloc(NULL, sz); }