fileio: replace read_nul_string() by read_line() with a special flag
authorLennart Poettering <lennart@poettering.net>
Mon, 17 Dec 2018 10:50:33 +0000 (11:50 +0100)
committerLennart Poettering <lennart@poettering.net>
Tue, 18 Dec 2018 14:03:05 +0000 (15:03 +0100)
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
src/basic/fileio.h
src/machine/machined-dbus.c

index a119e83..febda0a 100644 (file)
@@ -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) ||
index 300d060..53e3f4e 100644 (file)
@@ -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);
index 9afae72..fea9cc2 100644 (file)
@@ -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;