diff -rup systemd-233/src/basic/fileio.c systemd-233-new/src/basic/fileio.c --- systemd-233/src/basic/fileio.c 2017-03-01 13:43:06.000000000 -0800 +++ systemd-233-new/src/basic/fileio.c 2019-01-04 11:20:06.383683271 -0800 @@ -164,21 +164,7 @@ int read_one_line_file(const char *fn, c if (!f) return -errno; - if (!fgets(t, sizeof(t), f)) { - - if (ferror(f)) - return errno > 0 ? -errno : -EIO; - - t[0] = 0; - } - - c = strdup(t); - if (!c) - return -ENOMEM; - truncate_nl(c); - - *line = c; - return 0; + return read_line(f, LONG_LINE_MAX, line); } int verify_file(const char *fn, const char *blob, bool accept_extra_nl) { @@ -1489,3 +1475,75 @@ int mkdtemp_malloc(const char *template, *ret = p; return 0; } + +DEFINE_TRIVIAL_CLEANUP_FUNC(FILE*, funlockfile); + +int read_line(FILE *f, size_t limit, char **ret) { + _cleanup_free_ char *buffer = NULL; + size_t n = 0, allocated = 0, count = 0; + + assert(f); + + /* Something like a bounded version of getline(). + * + * Considers EOF, \n and \0 end of line delimiters, and does not include these delimiters in the string + * returned. + * + * Returns the number of bytes read from the files (i.e. including delimiters — this hence usually differs from + * the number of characters in the returned string). When EOF is hit, 0 is returned. + * + * The input parameter limit is the maximum numbers of characters in the returned string, i.e. excluding + * delimiters. If the limit is hit we fail and return -ENOBUFS. + * + * If a line shall be skipped ret may be initialized as NULL. */ + + if (ret) { + if (!GREEDY_REALLOC(buffer, allocated, 1)) + return -ENOMEM; + } + + { + _unused_ _cleanup_(funlockfilep) FILE *flocked = f; + flockfile(f); + + for (;;) { + int c; + + if (n >= limit) + return -ENOBUFS; + + errno = 0; + c = fgetc_unlocked(f); + if (c == EOF) { + /* if we read an error, and have no data to return, then propagate the error */ + if (ferror_unlocked(f) && n == 0) + return errno > 0 ? -errno : -EIO; + + break; + } + + count++; + + if (IN_SET(c, '\n', 0)) /* Reached a delimiter */ + break; + + if (ret) { + if (!GREEDY_REALLOC(buffer, allocated, n + 2)) + return -ENOMEM; + + buffer[n] = (char) c; + } + + n++; + } + } + + if (ret) { + buffer[n] = 0; + + *ret = buffer; + buffer = NULL; + } + + return (int) count; +} diff -rup systemd-233/src/basic/fileio.h systemd-233-new/src/basic/fileio.h --- systemd-233/src/basic/fileio.h 2017-03-01 13:43:06.000000000 -0800 +++ systemd-233-new/src/basic/fileio.h 2019-01-04 11:03:50.863102148 -0800 @@ -28,6 +28,8 @@ #include "macro.h" #include "time-util.h" +#define LONG_LINE_MAX (1U*1024U*1024U) + typedef enum { WRITE_STRING_FILE_CREATE = 1, WRITE_STRING_FILE_ATOMIC = 2, @@ -93,3 +95,5 @@ int link_tmpfile(int fd, const char *pat int read_nul_string(FILE *f, char **ret); int mkdtemp_malloc(const char *template, char **ret); + +int read_line(FILE *f, size_t limit, char **ret); diff -rup systemd-233/src/core/job.c systemd-233-new/src/core/job.c --- systemd-233/src/core/job.c 2017-03-01 13:43:06.000000000 -0800 +++ systemd-233-new/src/core/job.c 2019-01-03 15:48:29.826150906 -0800 @@ -27,6 +27,7 @@ #include "dbus-job.h" #include "dbus.h" #include "escape.h" +#include "fileio.h" #include "job.h" #include "log.h" #include "macro.h" @@ -1036,24 +1037,26 @@ int job_serialize(Job *j, FILE *f) { } int job_deserialize(Job *j, FILE *f) { + int r; + assert(j); assert(f); for (;;) { - char line[LINE_MAX], *l, *v; + _cleanup_free_ char *line = NULL; + char *l, *v; size_t k; - if (!fgets(line, sizeof(line), f)) { - if (feof(f)) - return 0; - return -errno; - } + r = read_line(f, LONG_LINE_MAX, &line); + if (r < 0) + return log_error_errno(r, "Failed to read serialization line: %m"); + if (r == 0) + return 0; - char_array_0(line); l = strstrip(line); /* End marker */ - if (l[0] == 0) + if (isempty(l)) return 0; k = strcspn(l, "="); diff -rup systemd-233/src/core/manager.c systemd-233-new/src/core/manager.c --- systemd-233/src/core/manager.c 2017-03-01 13:43:06.000000000 -0800 +++ systemd-233-new/src/core/manager.c 2019-01-03 18:38:06.216445611 -0800 @@ -1298,8 +1298,11 @@ int manager_startup(Manager *m, FILE *se dual_timestamp_get(&m->units_load_finish_timestamp); /* Second, deserialize if there is something to deserialize */ - if (serialization) + if (serialization) { r = manager_deserialize(m, serialization, fds); + if (r < 0) + log_error_errno(r, "Deserialization failed: %m"); + } /* Any fds left? Find some unit which wants them. This is * useful to allow container managers to pass some file @@ -2585,22 +2588,19 @@ int manager_deserialize(Manager *m, FILE m->n_reloading++; for (;;) { - char line[LINE_MAX], *l; - const char *val; - - if (!fgets(line, sizeof(line), f)) { - if (feof(f)) - r = 0; - else - r = -errno; + _cleanup_free_ char *line = NULL; + const char *val, *l; + r = read_line(f, LONG_LINE_MAX, &line); + if (r < 0) { + log_error_errno(r, "Failed to read serialization line: %m"); goto finish; } + if (r == 0) + break; - char_array_0(line); l = strstrip(line); - - if (l[0] == 0) + if (isempty(l)) /* end marker */ break; if ((val = startswith(l, "current-job-id="))) { @@ -2727,34 +2727,43 @@ int manager_deserialize(Manager *m, FILE } for (;;) { + _cleanup_free_ char *line = NULL; + const char* unit_name; Unit *u; - char name[UNIT_NAME_MAX+2]; /* Start marker */ - if (!fgets(name, sizeof(name), f)) { - if (feof(f)) - r = 0; - else - r = -errno; - + r = read_line(f, LONG_LINE_MAX, &line); + if (r < 0) { + log_error_errno(r, "Failed to read serialization line: %m"); goto finish; } + if (r == 0) + break; - char_array_0(name); + unit_name = strstrip(line); - r = manager_load_unit(m, strstrip(name), NULL, NULL, &u); - if (r < 0) - goto finish; + r = manager_load_unit(m, unit_name, NULL, NULL, &u); + if (r < 0) { + log_notice_errno(r, "Failed to load unit \"%s\", skipping deserialization: %m", unit_name); + if (r == -ENOMEM) + goto finish; + + r = unit_deserialize_skip(f); + if (r < 0) + goto finish; + + continue; + } r = unit_deserialize(u, f, fds); - if (r < 0) - goto finish; + if (r < 0) { + log_notice_errno(r, "Failed to deserialize unit \"%s\": %m", unit_name); + if (r == -ENOMEM) + goto finish; + } } finish: - if (ferror(f)) - r = -EIO; - assert(m->n_reloading > 0); m->n_reloading--; @@ -2821,8 +2830,12 @@ int manager_reload(Manager *m) { /* Second, deserialize our stored data */ q = manager_deserialize(m, f, fds); - if (q < 0 && r >= 0) - r = q; + if (q < 0) { + log_error_errno(q, "Deserialization failed: %m"); + + if (r >= 0) + r = q; + } fclose(f); f = NULL; diff -rup systemd-233/src/core/unit.c systemd-233-new/src/core/unit.c --- systemd-233/src/core/unit.c 2017-03-01 13:43:06.000000000 -0800 +++ systemd-233-new/src/core/unit.c 2019-01-03 18:53:52.183309960 -0800 @@ -2856,20 +2856,20 @@ int unit_deserialize(Unit *u, FILE *f, F rt = (ExecRuntime**) ((uint8_t*) u + offset); for (;;) { - char line[LINE_MAX], *l, *v; + _cleanup_free_ char *line = NULL; + char *l, *v; size_t k; - if (!fgets(line, sizeof(line), f)) { - if (feof(f)) - return 0; - return -errno; - } + r = read_line(f, LONG_LINE_MAX, &line); + if (r < 0) + return log_error_errno(r, "Failed to read serialization line: %m"); + if (r == 0) /* eof */ + break; - char_array_0(line); l = strstrip(line); /* End marker */ - if (isempty(l)) + if (isempty(l)) /* End marker */ break; k = strcspn(l, "="); @@ -3068,6 +3068,30 @@ int unit_deserialize(Unit *u, FILE *f, F return 0; } +int unit_deserialize_skip(FILE *f) { + int r; + assert(f); + + /* Skip serialized data for this unit. We don't know what it is. */ + + for (;;) { + _cleanup_free_ char *line = NULL; + char *l; + + r = read_line(f, LONG_LINE_MAX, &line); + if (r < 0) + return log_error_errno(r, "Failed to read serialization line: %m"); + if (r == 0) + return 0; + + l = strstrip(line); + + /* End marker */ + if (isempty(l)) + return 1; + } +} + int unit_add_node_link(Unit *u, const char *what, bool wants, UnitDependency dep) { Unit *device; _cleanup_free_ char *e = NULL; diff -rup systemd-233/src/core/unit.h systemd-233-new/src/core/unit.h --- systemd-233/src/core/unit.h 2017-03-01 13:43:06.000000000 -0800 +++ systemd-233-new/src/core/unit.h 2019-01-03 18:54:09.636934022 -0800 @@ -564,6 +564,7 @@ bool unit_can_serialize(Unit *u) _pure_; int unit_serialize(Unit *u, FILE *f, FDSet *fds, bool serialize_jobs); int unit_deserialize(Unit *u, FILE *f, FDSet *fds); +int unit_deserialize_skip(FILE *f); int unit_serialize_item(Unit *u, FILE *f, const char *key, const char *value); int unit_serialize_item_escaped(Unit *u, FILE *f, const char *key, const char *value);