From 41f11239c0c83c378643fc4942c726a49025b3b8 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Mon, 17 Dec 2018 11:50:33 +0100 Subject: [PATCH] fileio: replace read_nul_string() by read_line() with a special flag read_line() is a lot more careful and optimized than read_nul_string() but does mostly the same thing. let's replace the latter by the former, just with a special flag that toggles between the slightly different EOL rules if both. --- src/basic/fileio.c | 58 +++++++------------------------------ src/basic/fileio.h | 14 +++++++-- src/machine/machined-dbus.c | 8 ++--- 3 files changed, 27 insertions(+), 53 deletions(-) diff --git a/src/basic/fileio.c b/src/basic/fileio.c index a119e831b4..febda0abfd 100644 --- a/src/basic/fileio.c +++ b/src/basic/fileio.c @@ -667,46 +667,6 @@ int fputs_with_space(FILE *f, const char *s, const char *separator, bool *space) return fputs(s, f); } -int read_nul_string(FILE *f, char **ret) { - _cleanup_free_ char *x = NULL; - size_t allocated = 0, n = 0; - - assert(f); - assert(ret); - - /* Reads a NUL-terminated string from the specified file. */ - - for (;;) { - int c; - - if (!GREEDY_REALLOC(x, allocated, n+2)) - return -ENOMEM; - - c = fgetc(f); - if (c == 0) /* Terminate at NUL byte */ - break; - if (c == EOF) { - if (ferror(f)) - return -errno; - break; /* Terminate at EOF */ - } - - x[n++] = (char) c; - } - - if (x) - x[n] = 0; - else { - x = new0(char, 1); - if (!x) - return -ENOMEM; - } - - *ret = TAKE_PTR(x); - - return 0; -} - /* A bitmask of the EOL markers we know */ typedef enum EndOfLineMarker { EOL_NONE = 0, @@ -715,11 +675,15 @@ typedef enum EndOfLineMarker { EOL_THIRTEEN = 1 << 2, /* \r (aka CR) */ } EndOfLineMarker; -static EndOfLineMarker categorize_eol(char c) { - if (c == '\n') - return EOL_TEN; - if (c == '\r') - return EOL_THIRTEEN; +static EndOfLineMarker categorize_eol(char c, ReadLineFlags flags) { + + if (!IN_SET(flags, READ_LINE_ONLY_NUL)) { + if (c == '\n') + return EOL_TEN; + if (c == '\r') + return EOL_THIRTEEN; + } + if (c == '\0') return EOL_ZERO; @@ -728,7 +692,7 @@ static EndOfLineMarker categorize_eol(char c) { DEFINE_TRIVIAL_CLEANUP_FUNC(FILE*, funlockfile); -int read_line(FILE *f, size_t limit, char **ret) { +int read_line_full(FILE *f, size_t limit, ReadLineFlags flags, char **ret) { size_t n = 0, allocated = 0, count = 0; _cleanup_free_ char *buffer = NULL; int r; @@ -787,7 +751,7 @@ int read_line(FILE *f, size_t limit, char **ret) { count++; - eol = categorize_eol(c); + eol = categorize_eol(c, flags); if (FLAGS_SET(previous_eol, EOL_ZERO) || (eol == EOL_NONE && previous_eol != EOL_NONE) || diff --git a/src/basic/fileio.h b/src/basic/fileio.h index 300d060cea..53e3f4ef5f 100644 --- a/src/basic/fileio.h +++ b/src/basic/fileio.h @@ -61,8 +61,18 @@ int read_timestamp_file(const char *fn, usec_t *ret); int fputs_with_space(FILE *f, const char *s, const char *separator, bool *space); -int read_nul_string(FILE *f, char **ret); +typedef enum ReadLineFlags { + READ_LINE_ONLY_NUL = 1 << 0, +} ReadLineFlags; -int read_line(FILE *f, size_t limit, char **ret); +int read_line_full(FILE *f, size_t limit, ReadLineFlags flags, char **ret); + +static inline int read_line(FILE *f, size_t limit, char **ret) { + return read_line_full(f, limit, 0, ret); +} + +static inline int read_nul_string(FILE *f, size_t limit, char **ret) { + return read_line_full(f, limit, READ_LINE_ONLY_NUL, ret); +} int safe_fgetc(FILE *f, char *ret); diff --git a/src/machine/machined-dbus.c b/src/machine/machined-dbus.c index 9afae72ae5..fea9cc2633 100644 --- a/src/machine/machined-dbus.c +++ b/src/machine/machined-dbus.c @@ -637,8 +637,8 @@ static int clean_pool_done(Operation *operation, int ret, sd_bus_error *error) { if (success) /* The resulting temporary file could not be updated, ignore it. */ return ret; - r = read_nul_string(f, &name); - if (r < 0 || isempty(name)) /* Same here... */ + r = read_nul_string(f, LONG_LINE_MAX, &name); + if (r <= 0) /* Same here... */ return ret; return sd_bus_error_set_errnof(error, ret, "Failed to remove image %s: %m", name); @@ -660,10 +660,10 @@ static int clean_pool_done(Operation *operation, int ret, sd_bus_error *error) { _cleanup_free_ char *name = NULL; uint64_t size; - r = read_nul_string(f, &name); + r = read_nul_string(f, LONG_LINE_MAX, &name); if (r < 0) return r; - if (isempty(name)) /* reached the end */ + if (r == 0) /* reached the end */ break; errno = 0;