Eliminate fopen() in cfg.rl. Use unbuffered i/o instead.
This is fairly tricky, but fopen() almost surely interally calls malloc when it creates the FILE* that it returns. I did promise that ndhc doesn't call malloc after initialization, besides what libc may do internally, but it feels a bit dishonest given that fopen() is basically sure to do so on any general-purpose libc. Thus, eliminate it and just use direct POSIX i/o. With the previous pidfile changes, ndhc doesn't use C fopen() at all. In practice, this change won't really be noticeable as most libcs, particularly with dynamic linking, will end up calling malloc themselves during program initialization before main() is invoked.
This commit is contained in:
parent
04ec7c8f4b
commit
1fc7bd3144
52
src/cfg.rl
52
src/cfg.rl
@ -1,4 +1,7 @@
|
||||
#include <stdio.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <limits.h>
|
||||
@ -12,6 +15,7 @@
|
||||
#include "nk/log.h"
|
||||
#include "nk/privilege.h"
|
||||
#include "nk/copy_cmdarg.h"
|
||||
#include "nk/io.h"
|
||||
|
||||
struct cfgparse {
|
||||
char buf[MAX_BUF];
|
||||
@ -227,17 +231,35 @@ struct cfgparse {
|
||||
|
||||
static void parse_cfgfile(const char fname[static 1])
|
||||
{
|
||||
bool reached_eof = false;
|
||||
struct cfgparse ccfg;
|
||||
memset(&ccfg, 0, sizeof ccfg);
|
||||
FILE *f = fopen(fname, "r");
|
||||
if (!f)
|
||||
suicide("Unable to open config file '%s'.", fname);
|
||||
char l[MAX_BUF];
|
||||
size_t lc = 0;
|
||||
memset(l, 0, sizeof l);
|
||||
int fd = open(fname, O_RDONLY|O_CLOEXEC, 0);
|
||||
if (fd < 0)
|
||||
suicide("Unable to open config file '%s'.", fname);
|
||||
|
||||
size_t linenum = 0;
|
||||
while (linenum++, fgets(l, sizeof l, f)) {
|
||||
size_t llen = strlen(l);
|
||||
const char *p = l;
|
||||
const char *pe = l + llen;
|
||||
for (;;) {
|
||||
if (lc + 1 >= sizeof l) suicide("sizeof l - 1 - lc would underflow");
|
||||
ssize_t rc = safe_read(fd, l + lc, sizeof l - 1 - lc);
|
||||
if (rc < 0)
|
||||
suicide("Error reading config file '%s'.", fname);
|
||||
if (rc == 0) {
|
||||
l[lc] = '\n'; rc = 1; reached_eof = true; // Emulate a LF to terminate the line.
|
||||
}
|
||||
lc += rc;
|
||||
|
||||
size_t lstart = 0, lend = 0, consumed = 0;
|
||||
for (; lend < lc; ++lend) {
|
||||
if (l[lend] == '\n') {
|
||||
++linenum; consumed = lend;
|
||||
|
||||
size_t llen = lend - lstart;
|
||||
const char *p = l + lstart;
|
||||
const char *pe = l + lstart + llen + 1;
|
||||
%% write init;
|
||||
%% write exec;
|
||||
|
||||
@ -245,8 +267,22 @@ static void parse_cfgfile(const char fname[static 1])
|
||||
suicide("error parsing config file line %zu: malformed", linenum);
|
||||
if (ccfg.cs < file_cfg_first_final)
|
||||
suicide("error parsing config file line %zu: incomplete", linenum);
|
||||
lstart = lend + 1;
|
||||
}
|
||||
fclose(f);
|
||||
}
|
||||
if (reached_eof)
|
||||
break;
|
||||
if (!consumed && lend >= sizeof l - 1)
|
||||
suicide("Line %u in config file '%s' is too long: %u > %u.",
|
||||
linenum, fname, lend, sizeof l - 1);
|
||||
|
||||
if (consumed + 1 > lc) suicide("lc[%zu] - consumed[%zu] would underflow", lc, lend);
|
||||
if (consumed) {
|
||||
memmove(l, l + consumed + 1, lc - consumed - 1);
|
||||
lc -= consumed + 1;
|
||||
}
|
||||
}
|
||||
close(fd);
|
||||
}
|
||||
|
||||
%%{
|
||||
|
Loading…
Reference in New Issue
Block a user