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);