diff --git a/epicardium/modules/config.c b/epicardium/modules/config.c index 13ce3abaf12947237bf9963ad78af6e437e2c525..b1428dc3a8bda9a796a939d1a97a3ce48561123e 100644 --- a/epicardium/modules/config.c +++ b/epicardium/modules/config.c @@ -7,6 +7,7 @@ #include <ctype.h> #include <string.h> #include <stdlib.h> +#include <unistd.h> #define CONFIG_MAX_LINE_LENGTH 80 @@ -268,48 +269,77 @@ void load_config(void) return; } char buf[CONFIG_MAX_LINE_LENGTH]; - int nread = epic_file_read(fd, buf, sizeof(buf)); - if (nread < sizeof(buf)) { - //add fake EOL - buf[nread] = '\n'; - } int lineNumber = 0; - while (nread) { - char *line = buf; - char *eol = NULL; + int nread; + do { + //zero-terminate in case file is empty + buf[0] = '\0'; + nread = epic_file_read(fd, buf, sizeof(buf)); + if (nread < sizeof(buf)) { + //add fake EOL to ensure termination + buf[nread] = '\n'; + } + char *line = buf; + char *eol = NULL; + int last_eol = 0; while (line) { - eol = strchr(line, '\n'); - if (!eol) { - break; - } + //line points one character past the las (if any) '\n' hence '- 1' + last_eol = line - buf - 1; + eol = strchr(line, '\n'); ++lineNumber; - *eol = '\0'; - doline(line, eol, lineNumber); - line = eol + 1; - if (line - buf >= sizeof(buf)) { - //eol was right at the end of buf, - //break this loop and prevent memmove: - line = NULL; + if (eol) { + *eol = '\0'; + doline(line, eol, lineNumber); + line = eol + 1; + } else { + if (line == buf) { + //line did not fit into buf + LOG_WARN( + "card10.cfg", + "line:%d: too long - aborting", + lineNumber + ); + return; + } else { + int seek_back = last_eol - nread; + LOG_DEBUG( + "card10.cfg", + "nread, last_eol, seek_back: %d,%d,%d", + nread, + last_eol, + seek_back + ); + assert(seek_back <= 0); + if (seek_back) { + int rc = epic_file_seek( + fd, + seek_back, + SEEK_CUR + ); + if (rc < 0) { + LOG_ERR("card10.cfg", + "seek failed, aborting"); + return; + } + char newline; + rc = epic_file_read( + fd, &newline, 1 + ); + if (rc < 0 || newline != '\n') { + LOG_ERR("card10.cfg", + "seek failed, aborting"); + LOG_DEBUG( + "card10.cfg", + "seek failed at read-back of newline: rc: %d read: %d", + rc, + (int)newline + ); + return; + } + } + break; + } } } - if (line) { - int head = line - buf; - if (head == 0) { - //line did not fit into buf - LOG_WARN( - "card10.cfg", - "line:%d: too long", - lineNumber - ); - break; - } - int tail = (int)sizeof(buf) - head; - memmove(buf, line, tail); - nread = epic_file_read(fd, buf + tail, head); - if (nread < head) { - //add fake-eol in case of partial read - buf[tail + nread] = '\n'; - } - } - } + } while (nread == sizeof(buf)); }