]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
core: rework serialization
authorLennart Poettering <lennart@poettering.net>
Wed, 17 Oct 2018 18:40:09 +0000 (20:40 +0200)
committerLennart Poettering <lennart@poettering.net>
Fri, 26 Oct 2018 08:52:41 +0000 (10:52 +0200)
Let's be more careful with what we serialize: let's ensure we never
serialize strings that are longer than LONG_LINE_MAX, so that we know we
can read them back with read_line(…, LONG_LINE_MAX, …) safely.

In order to implement this all serialization functions are move to
serialize.[ch], and internally will do line size checks. We'd rather
skip a serialization line (with a loud warning) than write an overly
long line out. Of course, this is just a second level protection, after
all the data we serialize shouldn't be this long in the first place.

While we are at it also clean up logging: while serializing make sure to
always log about errors immediately. Also, (void)ify all calls we don't
expect errors in (or catch errors as part of the general
fflush_and_check() at the end.

31 files changed:
src/basic/env-util.c
src/basic/env-util.h
src/basic/exec-util.c
src/basic/time-util.c
src/basic/time-util.h
src/core/automount.c
src/core/dbus.c
src/core/device.c
src/core/dynamic-user.c
src/core/job.c
src/core/main.c
src/core/manager.c
src/core/mount.c
src/core/path.c
src/core/scope.c
src/core/service.c
src/core/slice.c
src/core/socket.c
src/core/swap.c
src/core/target.c
src/core/timer.c
src/core/unit.c
src/core/unit.h
src/login/logind-session.c
src/login/logind-user.c
src/machine/machine.c
src/shared/meson.build
src/shared/serialize.c [new file with mode: 0644]
src/shared/serialize.h [new file with mode: 0644]
src/test/test-env-util.c
src/test/test-time-util.c

index fad38b08191bf5a77254bdfe7134cbc29064678d..e494f65c9879801736a77ec3d29dda214ed69f7a 100644 (file)
@@ -752,36 +752,3 @@ int getenv_bool_secure(const char *p) {
 
         return parse_boolean(e);
 }
-
-int serialize_environment(FILE *f, char **environment) {
-        char **e;
-
-        STRV_FOREACH(e, environment) {
-                _cleanup_free_ char *ce;
-
-                ce = cescape(*e);
-                if (!ce)
-                        return -ENOMEM;
-
-                fprintf(f, "env=%s\n", ce);
-        }
-
-        /* caller should call ferror() */
-
-        return 0;
-}
-
-int deserialize_environment(char ***environment, const char *line) {
-        char *uce;
-        int r;
-
-        assert(line);
-        assert(environment);
-
-        assert(startswith(line, "env="));
-        r = cunescape(line + 4, 0, &uce);
-        if (r < 0)
-                return r;
-
-        return strv_env_replace(environment, uce);
-}
index 174433ea91e6e13f2b5d305c9cd94c9f51ea7c6c..4d21ea6bef5febe9bdbbb9daacd7a0b95980495e 100644 (file)
@@ -45,6 +45,3 @@ char *strv_env_get(char **x, const char *n) _pure_;
 
 int getenv_bool(const char *p);
 int getenv_bool_secure(const char *p);
-
-int serialize_environment(FILE *f, char **environment);
-int deserialize_environment(char ***environment, const char *line);
index a6c020b0f8c3c8c3dec7bb5887de90792e1147c1..2a96ecf9bb303b5d672f7b4bc1aeeaecf3038a5c 100644 (file)
@@ -9,6 +9,7 @@
 
 #include "alloc-util.h"
 #include "conf-files.h"
+#include "def.h"
 #include "env-util.h"
 #include "exec-util.h"
 #include "fd-util.h"
@@ -16,6 +17,7 @@
 #include "hashmap.h"
 #include "macro.h"
 #include "process-util.h"
+#include "serialize.h"
 #include "set.h"
 #include "signal-util.h"
 #include "stat-util.h"
@@ -282,7 +284,7 @@ static int gather_environment_collect(int fd, void *arg) {
                 return -errno;
         }
 
-        r = serialize_environment(f, *env);
+        r = serialize_strv(f, "env", *env);
         if (r < 0)
                 return r;
 
@@ -294,29 +296,47 @@ static int gather_environment_collect(int fd, void *arg) {
 }
 
 static int gather_environment_consume(int fd, void *arg) {
-        char ***env = arg;
         _cleanup_fclose_ FILE *f = NULL;
-        char line[LINE_MAX];
-        int r = 0, k;
+        char ***env = arg;
+        int r = 0;
 
         /* Read a series of env=cescape(VAR=value) assignments from fd into env. */
 
         assert(env);
 
-        f = fdopen(fd, "r");
+        f = fdopen(fd, "re");
         if (!f) {
                 safe_close(fd);
                 return -errno;
         }
 
-        FOREACH_LINE(line, f, return -EIO) {
-                truncate_nl(line);
+        for (;;) {
+                _cleanup_free_ char *line = NULL;
+                const char *v;
+                int k;
 
-                k = deserialize_environment(env, line);
+                k = read_line(f, LONG_LINE_MAX, &line);
                 if (k < 0)
-                        log_error_errno(k, "Invalid line \"%s\": %m", line);
-                if (k < 0 && r == 0)
-                        r = k;
+                        return k;
+                if (k == 0)
+                        break;
+
+                v = startswith(line, "env=");
+                if (!v) {
+                        log_debug("Serialization line \"%s\" unexpectedly didn't start with \"env=\".", line);
+                        if (r == 0)
+                                r = -EINVAL;
+
+                        continue;
+                }
+
+                k = deserialize_environment(v, env);
+                if (k < 0) {
+                        log_debug_errno(k, "Invalid serialization line \"%s\": %m", line);
+
+                        if (r == 0)
+                                r = k;
+                }
         }
 
         return r;
index c192389584f2e63c1953c306f3a3fc30191f8dc5..e3516842193f9a9b14b9a7cef366b2ae0b50c48b 100644 (file)
@@ -24,6 +24,7 @@
 #include "parse-util.h"
 #include "path-util.h"
 #include "process-util.h"
+#include "serialize.h"
 #include "stat-util.h"
 #include "string-util.h"
 #include "strv.h"
@@ -530,64 +531,6 @@ char *format_timespan(char *buf, size_t l, usec_t t, usec_t accuracy) {
         return buf;
 }
 
-void dual_timestamp_serialize(FILE *f, const char *name, dual_timestamp *t) {
-
-        assert(f);
-        assert(name);
-        assert(t);
-
-        if (!dual_timestamp_is_set(t))
-                return;
-
-        fprintf(f, "%s="USEC_FMT" "USEC_FMT"\n",
-                name,
-                t->realtime,
-                t->monotonic);
-}
-
-int dual_timestamp_deserialize(const char *value, dual_timestamp *t) {
-        uint64_t a, b;
-        int r, pos;
-
-        assert(value);
-        assert(t);
-
-        pos = strspn(value, WHITESPACE);
-        if (value[pos] == '-')
-                return -EINVAL;
-        pos += strspn(value + pos, DIGITS);
-        pos += strspn(value + pos, WHITESPACE);
-        if (value[pos] == '-')
-                return -EINVAL;
-
-        r = sscanf(value, "%" PRIu64 "%" PRIu64 "%n", &a, &b, &pos);
-        if (r != 2) {
-                log_debug("Failed to parse dual timestamp value \"%s\".", value);
-                return -EINVAL;
-        }
-
-        if (value[pos] != '\0')
-                /* trailing garbage */
-                return -EINVAL;
-
-        t->realtime = a;
-        t->monotonic = b;
-
-        return 0;
-}
-
-int timestamp_deserialize(const char *value, usec_t *timestamp) {
-        int r;
-
-        assert(value);
-
-        r = safe_atou64(value, timestamp);
-        if (r < 0)
-                return log_debug_errno(r, "Failed to parse timestamp value \"%s\": %m", value);
-
-        return r;
-}
-
 static int parse_timestamp_impl(const char *t, usec_t *usec, bool with_tz) {
         static const struct {
                 const char *name;
index 344f2dc52e5147966aec4d04cf26fbe671124928..5316305062d10fcaaac48c2b688c6d80cb53e9df 100644 (file)
@@ -108,10 +108,6 @@ char *format_timestamp_us_utc(char *buf, size_t l, usec_t t);
 char *format_timestamp_relative(char *buf, size_t l, usec_t t);
 char *format_timespan(char *buf, size_t l, usec_t t, usec_t accuracy);
 
-void dual_timestamp_serialize(FILE *f, const char *name, dual_timestamp *t);
-int dual_timestamp_deserialize(const char *value, dual_timestamp *t);
-int timestamp_deserialize(const char *value, usec_t *timestamp);
-
 int parse_timestamp(const char *t, usec_t *usec);
 
 int parse_sec(const char *t, usec_t *usec);
index eebcc3b20b67594ebc0aca517eda1ff2fb622116..eaacf5e8b9faa42d1ae8caf649b32d67a21174d8 100644 (file)
@@ -26,6 +26,7 @@
 #include "parse-util.h"
 #include "path-util.h"
 #include "process-util.h"
+#include "serialize.h"
 #include "special.h"
 #include "stdio-util.h"
 #include "string-table.h"
@@ -841,16 +842,16 @@ static int automount_serialize(Unit *u, FILE *f, FDSet *fds) {
         assert(f);
         assert(fds);
 
-        unit_serialize_item(u, f, "state", automount_state_to_string(a->state));
-        unit_serialize_item(u, f, "result", automount_result_to_string(a->result));
-        unit_serialize_item_format(u, f, "dev-id", "%u", (unsigned) a->dev_id);
+        (void) serialize_item(f, "state", automount_state_to_string(a->state));
+        (void) serialize_item(f, "result", automount_result_to_string(a->result));
+        (void) serialize_item_format(f, "dev-id", "%lu", (unsigned long) a->dev_id);
 
         SET_FOREACH(p, a->tokens, i)
-                unit_serialize_item_format(u, f, "token", "%u", PTR_TO_UINT(p));
+                (void) serialize_item_format(f, "token", "%u", PTR_TO_UINT(p));
         SET_FOREACH(p, a->expire_tokens, i)
-                unit_serialize_item_format(u, f, "expire-token", "%u", PTR_TO_UINT(p));
+                (void) serialize_item_format(f, "expire-token", "%u", PTR_TO_UINT(p));
 
-        r = unit_serialize_item_fd(u, f, fds, "pipe-fd", a->pipe_fd);
+        r = serialize_fd(f, fds, "pipe-fd", a->pipe_fd);
         if (r < 0)
                 return r;
 
index 3ffb53cb6e6c6ebd64f728780a21b24825e420fe..c2f77b8eef525fed9bb19a2376f8489c2177ea6d 100644 (file)
@@ -36,6 +36,7 @@
 #include "mkdir.h"
 #include "process-util.h"
 #include "selinux-access.h"
+#include "serialize.h"
 #include "service.h"
 #include "special.h"
 #include "string-util.h"
@@ -1204,13 +1205,8 @@ void bus_track_serialize(sd_bus_track *t, FILE *f, const char *prefix) {
                 int c, j;
 
                 c = sd_bus_track_count_name(t, n);
-
-                for (j = 0; j < c; j++) {
-                        fputs(prefix, f);
-                        fputc('=', f);
-                        fputs(n, f);
-                        fputc('\n', f);
-                }
+                for (j = 0; j < c; j++)
+                        (void) serialize_item(f, prefix, n);
         }
 }
 
index bd69fa029a55e07c450e31911d03a914bb8ed492..63544297518e753fdc44d4b3aed0f0c9929e9dc8 100644 (file)
@@ -12,6 +12,7 @@
 #include "log.h"
 #include "parse-util.h"
 #include "path-util.h"
+#include "serialize.h"
 #include "stat-util.h"
 #include "string-util.h"
 #include "swap.h"
@@ -225,10 +226,10 @@ static int device_serialize(Unit *u, FILE *f, FDSet *fds) {
         assert(f);
         assert(fds);
 
-        unit_serialize_item(u, f, "state", device_state_to_string(d->state));
+        (void) serialize_item(f, "state", device_state_to_string(d->state));
 
         if (device_found_to_string_many(d->found, &s) >= 0)
-                unit_serialize_item(u, f, "found", s);
+                (void) serialize_item(f, "found", s);
 
         return 0;
 }
index c627027aaeae5d996a1685e7b467efb5adde24fe..c47d1740c8dcdea02d79a02402f13655514d8256 100644 (file)
@@ -12,6 +12,7 @@
 #include "io-util.h"
 #include "parse-util.h"
 #include "random-util.h"
+#include "serialize.h"
 #include "socket-util.h"
 #include "stdio-util.h"
 #include "string-util.h"
@@ -607,13 +608,13 @@ int dynamic_user_serialize(Manager *m, FILE *f, FDSet *fds) {
 
                 copy0 = fdset_put_dup(fds, d->storage_socket[0]);
                 if (copy0 < 0)
-                        return copy0;
+                        return log_error_errno(copy0, "Failed to add dynamic user storage fd to serialization: %m");
 
                 copy1 = fdset_put_dup(fds, d->storage_socket[1]);
                 if (copy1 < 0)
-                        return copy1;
+                        return log_error_errno(copy1, "Failed to add dynamic user storage fd to serialization: %m");
 
-                fprintf(f, "dynamic-user=%s %i %i\n", d->name, copy0, copy1);
+                (void) serialize_item_format(f, "dynamic-user", "%s %i %i", d->name, copy0, copy1);
         }
 
         return 0;
index 3371b49d66ab43da1adb3d61e8913d4ccfc46784..2dc520389b727ae10f9928b51d512bc7aae117c1 100644 (file)
@@ -15,6 +15,7 @@
 #include "log.h"
 #include "macro.h"
 #include "parse-util.h"
+#include "serialize.h"
 #include "set.h"
 #include "special.h"
 #include "stdio-util.h"
@@ -1075,17 +1076,17 @@ int job_serialize(Job *j, FILE *f) {
         assert(j);
         assert(f);
 
-        fprintf(f, "job-id=%u\n", j->id);
-        fprintf(f, "job-type=%s\n", job_type_to_string(j->type));
-        fprintf(f, "job-state=%s\n", job_state_to_string(j->state));
-        fprintf(f, "job-irreversible=%s\n", yes_no(j->irreversible));
-        fprintf(f, "job-sent-dbus-new-signal=%s\n", yes_no(j->sent_dbus_new_signal));
-        fprintf(f, "job-ignore-order=%s\n", yes_no(j->ignore_order));
+        (void) serialize_item_format(f, "job-id", "%u", j->id);
+        (void) serialize_item(f, "job-type", job_type_to_string(j->type));
+        (void) serialize_item(f, "job-state", job_state_to_string(j->state));
+        (void) serialize_bool(f, "job-irreversible", j->irreversible);
+        (void) serialize_bool(f, "job-sent-dbus-new-signal", j->sent_dbus_new_signal);
+        (void) serialize_bool(f, "job-ignore-order", j->ignore_order);
 
         if (j->begin_usec > 0)
-                fprintf(f, "job-begin="USEC_FMT"\n", j->begin_usec);
+                (void) serialize_usec(f, "job-begin", j->begin_usec);
         if (j->begin_running_usec > 0)
-                fprintf(f, "job-begin-running="USEC_FMT"\n", j->begin_running_usec);
+                (void) serialize_usec(f, "job-begin-running", j->begin_running_usec);
 
         bus_track_serialize(j->bus_track, f, "subscribed");
 
@@ -1177,27 +1178,17 @@ int job_deserialize(Job *j, FILE *f) {
                         else
                                 j->ignore_order = j->ignore_order || b;
 
-                } else if (streq(l, "job-begin")) {
-                        unsigned long long ull;
+                } else if (streq(l, "job-begin"))
+                        (void) deserialize_usec(v, &j->begin_usec);
 
-                        if (sscanf(v, "%llu", &ull) != 1)
-                                log_debug("Failed to parse job-begin value %s", v);
-                        else
-                                j->begin_usec = ull;
-
-                } else if (streq(l, "job-begin-running")) {
-                        unsigned long long ull;
-
-                        if (sscanf(v, "%llu", &ull) != 1)
-                                log_debug("Failed to parse job-begin-running value %s", v);
-                        else
-                                j->begin_running_usec = ull;
-
-                } else if (streq(l, "subscribed")) {
+                else if (streq(l, "job-begin-running"))
+                        (void) deserialize_usec(v, &j->begin_running_usec);
 
+                else if (streq(l, "subscribed")) {
                         if (strv_extend(&j->deserialized_clients, v) < 0)
-                                log_oom();
-                }
+                                return log_oom();
+                } else
+                        log_debug("Unknown job serialization key: %s", l);
         }
 }
 
index 851a3933bf7f348fa984199bd418cbe72add1a61..807f5457c28f662902560ca2177e17e63e488560 100644 (file)
@@ -1145,7 +1145,7 @@ static int prepare_reexecute(
 
         r = manager_serialize(m, f, fds, switching_root);
         if (r < 0)
-                return log_error_errno(r, "Failed to serialize state: %m");
+                return r;
 
         if (fseeko(f, 0, SEEK_SET) == (off_t) -1)
                 return log_error_errno(errno, "Failed to rewind serialization fd: %m");
index 0737b6af3d68036362f9d1e2fd6f86f047dd4421..a43e40a43b0f3bb59073da55a2e7c1300628aeb1 100644 (file)
@@ -22,8 +22,8 @@
 #include "sd-messages.h"
 #include "sd-path.h"
 
-#include "alloc-util.h"
 #include "all-units.h"
+#include "alloc-util.h"
 #include "audit-fd.h"
 #include "boot-timestamps.h"
 #include "bus-common-errors.h"
@@ -61,6 +61,7 @@
 #include "ratelimit.h"
 #include "rlimit-util.h"
 #include "rm-rf.h"
+#include "serialize.h"
 #include "signal-util.h"
 #include "socket-util.h"
 #include "special.h"
@@ -3113,22 +3114,22 @@ int manager_serialize(
 
         _cleanup_(manager_reloading_stopp) _unused_ Manager *reloading = manager_reloading_start(m);
 
-        fprintf(f, "current-job-id=%"PRIu32"\n", m->current_job_id);
-        fprintf(f, "n-installed-jobs=%u\n", m->n_installed_jobs);
-        fprintf(f, "n-failed-jobs=%u\n", m->n_failed_jobs);
-        fprintf(f, "taint-usr=%s\n", yes_no(m->taint_usr));
-        fprintf(f, "ready-sent=%s\n", yes_no(m->ready_sent));
-        fprintf(f, "taint-logged=%s\n", yes_no(m->taint_logged));
-        fprintf(f, "service-watchdogs=%s\n", yes_no(m->service_watchdogs));
+        (void) serialize_item_format(f, "current-job-id", "%" PRIu32, m->current_job_id);
+        (void) serialize_item_format(f, "n-installed-jobs", "%u", m->n_installed_jobs);
+        (void) serialize_item_format(f, "n-failed-jobs", "%u", m->n_failed_jobs);
+        (void) serialize_bool(f, "taint-usr", m->taint_usr);
+        (void) serialize_bool(f, "ready-sent", m->ready_sent);
+        (void) serialize_bool(f, "taint-logged", m->taint_logged);
+        (void) serialize_bool(f, "service-watchdogs", m->service_watchdogs);
 
         t = show_status_to_string(m->show_status);
         if (t)
-                fprintf(f, "show-status=%s\n", t);
+                (void) serialize_item(f, "show-status", t);
 
         if (m->log_level_overridden)
-                fprintf(f, "log-level-override=%i\n", log_get_max_level());
+                (void) serialize_item_format(f, "log-level-override", "%i", log_get_max_level());
         if (m->log_target_overridden)
-                fprintf(f, "log-target-override=%s\n", log_target_to_string(log_get_target()));
+                (void) serialize_item(f, "log-target-override", log_target_to_string(log_get_target()));
 
         for (q = 0; q < _MANAGER_TIMESTAMP_MAX; q++) {
                 _cleanup_free_ char *joined = NULL;
@@ -3140,31 +3141,24 @@ int manager_serialize(
                 if (!joined)
                         return log_oom();
 
-                dual_timestamp_serialize(f, joined, m->timestamps + q);
+                (void) serialize_dual_timestamp(f, joined, m->timestamps + q);
         }
 
         if (!switching_root)
-                (void) serialize_environment(f, m->environment);
+                (void) serialize_strv(f, "env", m->environment);
 
         if (m->notify_fd >= 0) {
-                int copy;
-
-                copy = fdset_put_dup(fds, m->notify_fd);
-                if (copy < 0)
-                        return copy;
+                r = serialize_fd(f, fds, "notify-fd", m->notify_fd);
+                if (r < 0)
+                        return r;
 
-                fprintf(f, "notify-fd=%i\n", copy);
-                fprintf(f, "notify-socket=%s\n", m->notify_socket);
+                (void) serialize_item(f, "notify-socket", m->notify_socket);
         }
 
         if (m->cgroups_agent_fd >= 0) {
-                int copy;
-
-                copy = fdset_put_dup(fds, m->cgroups_agent_fd);
-                if (copy < 0)
-                        return copy;
-
-                fprintf(f, "cgroups-agent-fd=%i\n", copy);
+                r = serialize_fd(f, fds, "cgroups-agent-fd", m->cgroups_agent_fd);
+                if (r < 0)
+                        return r;
         }
 
         if (m->user_lookup_fds[0] >= 0) {
@@ -3172,13 +3166,13 @@ int manager_serialize(
 
                 copy0 = fdset_put_dup(fds, m->user_lookup_fds[0]);
                 if (copy0 < 0)
-                        return copy0;
+                        return log_error_errno(copy0, "Failed to add user lookup fd to serialization: %m");
 
                 copy1 = fdset_put_dup(fds, m->user_lookup_fds[1]);
                 if (copy1 < 0)
-                        return copy1;
+                        return log_error_errno(copy1, "Failed to add user lookup fd to serialization: %m");
 
-                fprintf(f, "user-lookup=%i %i\n", copy0, copy1);
+                (void) serialize_item_format(f, "user-lookup", "%i %i", copy0, copy1);
         }
 
         bus_track_serialize(m->subscribed, f, "subscribed");
@@ -3211,11 +3205,11 @@ int manager_serialize(
 
         r = fflush_and_check(f);
         if (r < 0)
-                return r;
+                return log_error_errno(r, "Failed to flush serialization: %m");
 
         r = bus_fdset_add_all(m, fds);
         if (r < 0)
-                return r;
+                return log_error_errno(r, "Failed to add bus sockets to serialization: %m");
 
         return 0;
 }
@@ -3335,9 +3329,7 @@ int manager_deserialize(Manager *m, FILE *f, FDSet *fds) {
                                 manager_override_log_target(m, target);
 
                 } else if (startswith(l, "env=")) {
-                        r = deserialize_environment(&m->environment, l);
-                        if (r == -ENOMEM)
-                                return r;
+                        r = deserialize_environment(l + 4, &m->environment);
                         if (r < 0)
                                 log_notice_errno(r, "Failed to parse environment entry: \"%s\", ignoring: %m", l);
 
@@ -3407,7 +3399,7 @@ int manager_deserialize(Manager *m, FILE *f, FDSet *fds) {
                         }
 
                         if (q < _MANAGER_TIMESTAMP_MAX) /* found it */
-                                dual_timestamp_deserialize(val, m->timestamps + q);
+                                (void) deserialize_dual_timestamp(val, m->timestamps + q);
                         else if (!startswith(l, "kdbus-fd=")) /* ignore kdbus */
                                 log_notice("Unknown serialization item '%s', ignoring.", l);
                 }
@@ -3485,7 +3477,7 @@ int manager_reload(Manager *m) {
 
         r = manager_serialize(m, f, fds, false);
         if (r < 0)
-                return log_error_errno(r, "Failed to serialize manager: %m");
+                return r;
 
         if (fseeko(f, 0, SEEK_SET) < 0)
                 return log_error_errno(errno, "Failed to seek to beginning of serialization: %m");
@@ -4353,7 +4345,7 @@ static void manager_serialize_uid_refs_internal(
                 if (!(c & DESTROY_IPC_FLAG))
                         continue;
 
-                fprintf(f, "%s=" UID_FMT "\n", field_name, uid);
+                (void) serialize_item_format(f, field_name, UID_FMT, uid);
         }
 }
 
index cc6464e3562e65c9ce172383128ac485b996af6b..dafd6ea90b163d76200efe9a0459e6be26dbd843 100644 (file)
@@ -25,6 +25,7 @@
 #include "parse-util.h"
 #include "path-util.h"
 #include "process-util.h"
+#include "serialize.h"
 #include "special.h"
 #include "string-table.h"
 #include "string-util.h"
@@ -1140,15 +1141,15 @@ static int mount_serialize(Unit *u, FILE *f, FDSet *fds) {
         assert(f);
         assert(fds);
 
-        unit_serialize_item(u, f, "state", mount_state_to_string(m->state));
-        unit_serialize_item(u, f, "result", mount_result_to_string(m->result));
-        unit_serialize_item(u, f, "reload-result", mount_result_to_string(m->reload_result));
+        (void) serialize_item(f, "state", mount_state_to_string(m->state));
+        (void) serialize_item(f, "result", mount_result_to_string(m->result));
+        (void) serialize_item(f, "reload-result", mount_result_to_string(m->reload_result));
 
         if (m->control_pid > 0)
-                unit_serialize_item_format(u, f, "control-pid", PID_FMT, m->control_pid);
+                (void) serialize_item_format(f, "control-pid", PID_FMT, m->control_pid);
 
         if (m->control_command_id >= 0)
-                unit_serialize_item(u, f, "control-command", mount_exec_command_to_string(m->control_command_id));
+                (void) serialize_item(f, "control-command", mount_exec_command_to_string(m->control_command_id));
 
         return 0;
 }
index 1c6b6a880d159169f4750af86254c3362caf9c89..258e3a00cb2a6a837943f975a1b88bc04f700f19 100644 (file)
@@ -14,6 +14,7 @@
 #include "macro.h"
 #include "mkdir.h"
 #include "path.h"
+#include "serialize.h"
 #include "special.h"
 #include "stat-util.h"
 #include "string-table.h"
@@ -600,8 +601,8 @@ static int path_serialize(Unit *u, FILE *f, FDSet *fds) {
         assert(f);
         assert(fds);
 
-        unit_serialize_item(u, f, "state", path_state_to_string(p->state));
-        unit_serialize_item(u, f, "result", path_result_to_string(p->result));
+        (void) serialize_item(f, "state", path_state_to_string(p->state));
+        (void) serialize_item(f, "result", path_result_to_string(p->result));
 
         return 0;
 }
index 40503a59611c1b4e127dbf27b1f9b7a785330792..7883d19325bfce5401282342a59bd968f91bdf29 100644 (file)
@@ -8,6 +8,7 @@
 #include "load-dropin.h"
 #include "log.h"
 #include "scope.h"
+#include "serialize.h"
 #include "special.h"
 #include "string-table.h"
 #include "string-util.h"
@@ -402,11 +403,11 @@ static int scope_serialize(Unit *u, FILE *f, FDSet *fds) {
         assert(f);
         assert(fds);
 
-        unit_serialize_item(u, f, "state", scope_state_to_string(s->state));
-        unit_serialize_item(u, f, "was-abandoned", yes_no(s->was_abandoned));
+        (void) serialize_item(f, "state", scope_state_to_string(s->state));
+        (void) serialize_bool(f, "was-abandoned", s->was_abandoned);
 
         if (s->controller)
-                unit_serialize_item(u, f, "controller", s->controller);
+                (void) serialize_item(f, "controller", s->controller);
 
         return 0;
 }
@@ -441,7 +442,7 @@ static int scope_deserialize_item(Unit *u, const char *key, const char *value, F
 
                 r = free_and_strdup(&s->controller, value);
                 if (r < 0)
-                        log_oom();
+                        return log_oom();
 
         } else
                 log_unit_debug(u, "Unknown serialization key: %s", key);
index 2084b1c92873abe9a4b3e961e7440b68f20277e2..510d8d6a3adf23a44cc0cc336522cabe0e2446ef 100644 (file)
@@ -27,6 +27,7 @@
 #include "parse-util.h"
 #include "path-util.h"
 #include "process-util.h"
+#include "serialize.h"
 #include "service.h"
 #include "signal-util.h"
 #include "special.h"
@@ -2431,13 +2432,13 @@ static unsigned service_exec_command_index(Unit *u, ServiceExecCommand id, ExecC
 }
 
 static int service_serialize_exec_command(Unit *u, FILE *f, ExecCommand *command) {
+        _cleanup_free_ char *args = NULL, *p = NULL;
+        size_t allocated = 0, length = 0;
         Service *s = SERVICE(u);
+        const char *type, *key;
         ServiceExecCommand id;
         unsigned idx;
-        const char *type;
         char **arg;
-        _cleanup_free_ char *args = NULL, *p = NULL;
-        size_t allocated = 0, length = 0;
 
         assert(s);
         assert(f);
@@ -2456,16 +2457,16 @@ static int service_serialize_exec_command(Unit *u, FILE *f, ExecCommand *command
         idx = service_exec_command_index(u, id, command);
 
         STRV_FOREACH(arg, command->argv) {
-                size_t n;
                 _cleanup_free_ char *e = NULL;
+                size_t n;
 
-                e = xescape(*arg, WHITESPACE);
+                e = cescape(*arg);
                 if (!e)
-                        return -ENOMEM;
+                        return log_oom();
 
                 n = strlen(e);
                 if (!GREEDY_REALLOC(args, allocated, length + 1 + n + 1))
-                        return -ENOMEM;
+                        return log_oom();
 
                 if (length > 0)
                         args[length++] = ' ';
@@ -2475,16 +2476,16 @@ static int service_serialize_exec_command(Unit *u, FILE *f, ExecCommand *command
         }
 
         if (!GREEDY_REALLOC(args, allocated, length + 1))
-                return -ENOMEM;
+                return log_oom();
+
         args[length++] = 0;
 
-        p = xescape(command->path, WHITESPACE);
+        p = cescape(command->path);
         if (!p)
                 return -ENOMEM;
 
-        fprintf(f, "%s-command=%s %u %s %s\n", type, service_exec_command_to_string(id), idx, p, args);
-
-        return 0;
+        key = strjoina(type, "-command");
+        return serialize_item_format(f, key, "%s %u %s %s", service_exec_command_to_string(id), idx, p, args);
 }
 
 static int service_serialize(Unit *u, FILE *f, FDSet *fds) {
@@ -2496,54 +2497,55 @@ static int service_serialize(Unit *u, FILE *f, FDSet *fds) {
         assert(f);
         assert(fds);
 
-        unit_serialize_item(u, f, "state", service_state_to_string(s->state));
-        unit_serialize_item(u, f, "result", service_result_to_string(s->result));
-        unit_serialize_item(u, f, "reload-result", service_result_to_string(s->reload_result));
+        (void) serialize_item(f, "state", service_state_to_string(s->state));
+        (void) serialize_item(f, "result", service_result_to_string(s->result));
+        (void) serialize_item(f, "reload-result", service_result_to_string(s->reload_result));
 
         if (s->control_pid > 0)
-                unit_serialize_item_format(u, f, "control-pid", PID_FMT, s->control_pid);
+                (void) serialize_item_format(f, "control-pid", PID_FMT, s->control_pid);
 
         if (s->main_pid_known && s->main_pid > 0)
-                unit_serialize_item_format(u, f, "main-pid", PID_FMT, s->main_pid);
+                (void) serialize_item_format(f, "main-pid", PID_FMT, s->main_pid);
 
-        unit_serialize_item(u, f, "main-pid-known", yes_no(s->main_pid_known));
-        unit_serialize_item(u, f, "bus-name-good", yes_no(s->bus_name_good));
-        unit_serialize_item(u, f, "bus-name-owner", s->bus_name_owner);
+        (void) serialize_bool(f, "main-pid-known", s->main_pid_known);
+        (void) serialize_bool(f, "bus-name-good", s->bus_name_good);
+        (void) serialize_bool(f, "bus-name-owner", s->bus_name_owner);
 
-        unit_serialize_item_format(u, f, "n-restarts", "%u", s->n_restarts);
-        unit_serialize_item(u, f, "flush-n-restarts", yes_no(s->flush_n_restarts));
+        (void) serialize_item_format(f, "n-restarts", "%u", s->n_restarts);
+        (void) serialize_bool(f, "flush-n-restarts", s->flush_n_restarts);
 
-        r = unit_serialize_item_escaped(u, f, "status-text", s->status_text);
+        r = serialize_item_escaped(f, "status-text", s->status_text);
         if (r < 0)
                 return r;
 
         service_serialize_exec_command(u, f, s->control_command);
         service_serialize_exec_command(u, f, s->main_command);
 
-        r = unit_serialize_item_fd(u, f, fds, "stdin-fd", s->stdin_fd);
+        r = serialize_fd(f, fds, "stdin-fd", s->stdin_fd);
         if (r < 0)
                 return r;
-        r = unit_serialize_item_fd(u, f, fds, "stdout-fd", s->stdout_fd);
+        r = serialize_fd(f, fds, "stdout-fd", s->stdout_fd);
         if (r < 0)
                 return r;
-        r = unit_serialize_item_fd(u, f, fds, "stderr-fd", s->stderr_fd);
+        r = serialize_fd(f, fds, "stderr-fd", s->stderr_fd);
         if (r < 0)
                 return r;
 
         if (s->exec_fd_event_source) {
-                r = unit_serialize_item_fd(u, f, fds, "exec-fd", sd_event_source_get_io_fd(s->exec_fd_event_source));
+                r = serialize_fd(f, fds, "exec-fd", sd_event_source_get_io_fd(s->exec_fd_event_source));
                 if (r < 0)
                         return r;
-                unit_serialize_item(u, f, "exec-fd-hot", yes_no(s->exec_fd_hot));
+
+                (void) serialize_bool(f, "exec-fd-hot", s->exec_fd_hot);
         }
 
         if (UNIT_ISSET(s->accept_socket)) {
-                r = unit_serialize_item(u, f, "accept-socket", UNIT_DEREF(s->accept_socket)->id);
+                r = serialize_item(f, "accept-socket", UNIT_DEREF(s->accept_socket)->id);
                 if (r < 0)
                         return r;
         }
 
-        r = unit_serialize_item_fd(u, f, fds, "socket-fd", s->socket_fd);
+        r = serialize_fd(f, fds, "socket-fd", s->socket_fd);
         if (r < 0)
                 return r;
 
@@ -2553,30 +2555,31 @@ static int service_serialize(Unit *u, FILE *f, FDSet *fds) {
 
                 copy = fdset_put_dup(fds, fs->fd);
                 if (copy < 0)
-                        return copy;
+                        return log_error_errno(copy, "Failed to copy file descriptor for serialization: %m");
 
                 c = cescape(fs->fdname);
+                if (!c)
+                        return log_oom();
 
-                unit_serialize_item_format(u, f, "fd-store-fd", "%i %s", copy, strempty(c));
+                (void) serialize_item_format(f, "fd-store-fd", "%i %s", copy, c);
         }
 
         if (s->main_exec_status.pid > 0) {
-                unit_serialize_item_format(u, f, "main-exec-status-pid", PID_FMT, s->main_exec_status.pid);
-                dual_timestamp_serialize(f, "main-exec-status-start", &s->main_exec_status.start_timestamp);
-                dual_timestamp_serialize(f, "main-exec-status-exit", &s->main_exec_status.exit_timestamp);
+                (void) serialize_item_format(f, "main-exec-status-pid", PID_FMT, s->main_exec_status.pid);
+                (void) serialize_dual_timestamp(f, "main-exec-status-start", &s->main_exec_status.start_timestamp);
+                (void) serialize_dual_timestamp(f, "main-exec-status-exit", &s->main_exec_status.exit_timestamp);
 
                 if (dual_timestamp_is_set(&s->main_exec_status.exit_timestamp)) {
-                        unit_serialize_item_format(u, f, "main-exec-status-code", "%i", s->main_exec_status.code);
-                        unit_serialize_item_format(u, f, "main-exec-status-status", "%i", s->main_exec_status.status);
+                        (void) serialize_item_format(f, "main-exec-status-code", "%i", s->main_exec_status.code);
+                        (void) serialize_item_format(f, "main-exec-status-status", "%i", s->main_exec_status.status);
                 }
         }
 
-        dual_timestamp_serialize(f, "watchdog-timestamp", &s->watchdog_timestamp);
-
-        unit_serialize_item(u, f, "forbid-restart", yes_no(s->forbid_restart));
+        (void) serialize_dual_timestamp(f, "watchdog-timestamp", &s->watchdog_timestamp);
+        (void) serialize_bool(f, "forbid-restart", s->forbid_restart);
 
         if (s->watchdog_override_enable)
-               unit_serialize_item_format(u, f, "watchdog-override-usec", USEC_FMT, s->watchdog_override_usec);
+                (void) serialize_item_format(f, "watchdog-override-usec", USEC_FMT, s->watchdog_override_usec);
 
         return 0;
 }
@@ -2825,11 +2828,11 @@ static int service_deserialize_item(Unit *u, const char *key, const char *value,
                 else
                         s->main_exec_status.status = i;
         } else if (streq(key, "main-exec-status-start"))
-                dual_timestamp_deserialize(value, &s->main_exec_status.start_timestamp);
+                deserialize_dual_timestamp(value, &s->main_exec_status.start_timestamp);
         else if (streq(key, "main-exec-status-exit"))
-                dual_timestamp_deserialize(value, &s->main_exec_status.exit_timestamp);
+                deserialize_dual_timestamp(value, &s->main_exec_status.exit_timestamp);
         else if (streq(key, "watchdog-timestamp"))
-                dual_timestamp_deserialize(value, &s->watchdog_timestamp);
+                deserialize_dual_timestamp(value, &s->watchdog_timestamp);
         else if (streq(key, "forbid-restart")) {
                 int b;
 
@@ -2881,13 +2884,11 @@ static int service_deserialize_item(Unit *u, const char *key, const char *value,
                                 safe_close(fd);
                 }
         } else if (streq(key, "watchdog-override-usec")) {
-                usec_t watchdog_override_usec;
-                if (timestamp_deserialize(value, &watchdog_override_usec) < 0)
+                if (deserialize_usec(value, &s->watchdog_override_usec) < 0)
                         log_unit_debug(u, "Failed to parse watchdog_override_usec value: %s", value);
-                else {
+                else
                         s->watchdog_override_enable = true;
-                        s->watchdog_override_usec = watchdog_override_usec;
-                }
+
         } else if (STR_IN_SET(key, "main-command", "control-command")) {
                 r = service_deserialize_exec_command(u, key, value);
                 if (r < 0)
index 1760f725c41903f415578a1efb984dfa33a33e8c..a8bdbebe4b69351f072e7d59cc08759d7826ed53 100644 (file)
@@ -5,6 +5,7 @@
 #include "alloc-util.h"
 #include "dbus-slice.h"
 #include "log.h"
+#include "serialize.h"
 #include "slice.h"
 #include "special.h"
 #include "string-util.h"
@@ -256,7 +257,8 @@ static int slice_serialize(Unit *u, FILE *f, FDSet *fds) {
         assert(f);
         assert(fds);
 
-        unit_serialize_item(u, f, "state", slice_state_to_string(s->state));
+        (void) serialize_item(f, "state", slice_state_to_string(s->state));
+
         return 0;
 }
 
index f980ed8a48a58ee5210a8215f7e307ef19503090..d54dadbacff5c268355f84dd40f7c72a9fabc7ce 100644 (file)
 #include "path-util.h"
 #include "process-util.h"
 #include "selinux-util.h"
+#include "serialize.h"
 #include "signal-util.h"
 #include "smack-util.h"
-#include "socket.h"
 #include "socket-protocol-list.h"
+#include "socket.h"
 #include "special.h"
 #include "string-table.h"
 #include "string-util.h"
@@ -2499,16 +2500,16 @@ static int socket_serialize(Unit *u, FILE *f, FDSet *fds) {
         assert(f);
         assert(fds);
 
-        unit_serialize_item(u, f, "state", socket_state_to_string(s->state));
-        unit_serialize_item(u, f, "result", socket_result_to_string(s->result));
-        unit_serialize_item_format(u, f, "n-accepted", "%u", s->n_accepted);
-        unit_serialize_item_format(u, f, "n-refused", "%u", s->n_refused);
+        (void) serialize_item(f, "state", socket_state_to_string(s->state));
+        (void) serialize_item(f, "result", socket_result_to_string(s->result));
+        (void) serialize_item_format(f, "n-accepted", "%u", s->n_accepted);
+        (void) serialize_item_format(f, "n-refused", "%u", s->n_refused);
 
         if (s->control_pid > 0)
-                unit_serialize_item_format(u, f, "control-pid", PID_FMT, s->control_pid);
+                (void) serialize_item_format(f, "control-pid", PID_FMT, s->control_pid);
 
         if (s->control_command_id >= 0)
-                unit_serialize_item(u, f, "control-command", socket_exec_command_to_string(s->control_command_id));
+                (void) serialize_item(f, "control-command", socket_exec_command_to_string(s->control_command_id));
 
         LIST_FOREACH(port, p, s->ports) {
                 int copy;
@@ -2518,29 +2519,28 @@ static int socket_serialize(Unit *u, FILE *f, FDSet *fds) {
 
                 copy = fdset_put_dup(fds, p->fd);
                 if (copy < 0)
-                        return copy;
+                        return log_warning_errno(copy, "Failed to serialize socket fd: %m");
 
                 if (p->type == SOCKET_SOCKET) {
                         _cleanup_free_ char *t = NULL;
 
                         r = socket_address_print(&p->address, &t);
                         if (r < 0)
-                                return r;
+                                return log_error_errno(r, "Failed to format socket address: %m");
 
                         if (socket_address_family(&p->address) == AF_NETLINK)
-                                unit_serialize_item_format(u, f, "netlink", "%i %s", copy, t);
+                                (void) serialize_item_format(f, "netlink", "%i %s", copy, t);
                         else
-                                unit_serialize_item_format(u, f, "socket", "%i %i %s", copy, p->address.type, t);
-
+                                (void) serialize_item_format(f, "socket", "%i %i %s", copy, p->address.type, t);
                 } else if (p->type == SOCKET_SPECIAL)
-                        unit_serialize_item_format(u, f, "special", "%i %s", copy, p->path);
+                        (void) serialize_item_format(f, "special", "%i %s", copy, p->path);
                 else if (p->type == SOCKET_MQUEUE)
-                        unit_serialize_item_format(u, f, "mqueue", "%i %s", copy, p->path);
+                        (void) serialize_item_format(f, "mqueue", "%i %s", copy, p->path);
                 else if (p->type == SOCKET_USB_FUNCTION)
-                        unit_serialize_item_format(u, f, "ffs", "%i %s", copy, p->path);
+                        (void) serialize_item_format(f, "ffs", "%i %s", copy, p->path);
                 else {
                         assert(p->type == SOCKET_FIFO);
-                        unit_serialize_item_format(u, f, "fifo", "%i %s", copy, p->path);
+                        (void) serialize_item_format(f, "fifo", "%i %s", copy, p->path);
                 }
         }
 
@@ -2548,6 +2548,8 @@ static int socket_serialize(Unit *u, FILE *f, FDSet *fds) {
 }
 
 static void socket_port_take_fd(SocketPort *p, FDSet *fds, int fd) {
+        assert(p);
+
         safe_close(p->fd);
         p->fd = fdset_remove(fds, fd);
 }
index 6b0b794749892b19f135a17dcd2df1eaabd08342..dd1ef8e88e9a6ea3269bba8b142720a16cab23df 100644 (file)
@@ -20,6 +20,7 @@
 #include "parse-util.h"
 #include "path-util.h"
 #include "process-util.h"
+#include "serialize.h"
 #include "special.h"
 #include "string-table.h"
 #include "string-util.h"
@@ -894,14 +895,14 @@ static int swap_serialize(Unit *u, FILE *f, FDSet *fds) {
         assert(f);
         assert(fds);
 
-        unit_serialize_item(u, f, "state", swap_state_to_string(s->state));
-        unit_serialize_item(u, f, "result", swap_result_to_string(s->result));
+        (void) serialize_item(f, "state", swap_state_to_string(s->state));
+        (void) serialize_item(f, "result", swap_result_to_string(s->result));
 
         if (s->control_pid > 0)
-                unit_serialize_item_format(u, f, "control-pid", PID_FMT, s->control_pid);
+                (void) serialize_item_format(f, "control-pid", PID_FMT, s->control_pid);
 
         if (s->control_command_id >= 0)
-                unit_serialize_item(u, f, "control-command", swap_exec_command_to_string(s->control_command_id));
+                (void) serialize_item(f, "control-command", swap_exec_command_to_string(s->control_command_id));
 
         return 0;
 }
index a91c85ed2eea090934b0f9fecc68a6e71affa65e..b8b8e32805eb0988b4a90150457c93dc2063abe6 100644 (file)
@@ -2,11 +2,12 @@
 
 #include "dbus-target.h"
 #include "log.h"
+#include "serialize.h"
 #include "special.h"
 #include "string-util.h"
+#include "target.h"
 #include "unit-name.h"
 #include "unit.h"
-#include "target.h"
 
 static const UnitActiveState state_translation_table[_TARGET_STATE_MAX] = {
         [TARGET_DEAD] = UNIT_INACTIVE,
@@ -144,7 +145,7 @@ static int target_serialize(Unit *u, FILE *f, FDSet *fds) {
         assert(f);
         assert(fds);
 
-        unit_serialize_item(u, f, "state", target_state_to_string(s->state));
+        (void) serialize_item(f, "state", target_state_to_string(s->state));
         return 0;
 }
 
index 111aa428774855f20a71ffecc470ba6a4ed93faf..01a3b238cccd645c9007bd7d52311fea2f9d2fff 100644 (file)
@@ -9,6 +9,7 @@
 #include "fs-util.h"
 #include "parse-util.h"
 #include "random-util.h"
+#include "serialize.h"
 #include "special.h"
 #include "string-table.h"
 #include "string-util.h"
@@ -661,21 +662,20 @@ static int timer_serialize(Unit *u, FILE *f, FDSet *fds) {
         assert(f);
         assert(fds);
 
-        unit_serialize_item(u, f, "state", timer_state_to_string(t->state));
-        unit_serialize_item(u, f, "result", timer_result_to_string(t->result));
+        (void) serialize_item(f, "state", timer_state_to_string(t->state));
+        (void) serialize_item(f, "result", timer_result_to_string(t->result));
 
         if (t->last_trigger.realtime > 0)
-                unit_serialize_item_format(u, f, "last-trigger-realtime", "%" PRIu64, t->last_trigger.realtime);
+                (void) serialize_usec(f, "last-trigger-realtime", t->last_trigger.realtime);
 
         if (t->last_trigger.monotonic > 0)
-                unit_serialize_item_format(u, f, "last-trigger-monotonic", "%" PRIu64, t->last_trigger.monotonic);
+                (void) serialize_usec(f, "last-trigger-monotonic", t->last_trigger.monotonic);
 
         return 0;
 }
 
 static int timer_deserialize_item(Unit *u, const char *key, const char *value, FDSet *fds) {
         Timer *t = TIMER(u);
-        int r;
 
         assert(u);
         assert(key);
@@ -690,6 +690,7 @@ static int timer_deserialize_item(Unit *u, const char *key, const char *value, F
                         log_unit_debug(u, "Failed to parse state value: %s", value);
                 else
                         t->deserialized_state = state;
+
         } else if (streq(key, "result")) {
                 TimerResult f;
 
@@ -698,19 +699,12 @@ static int timer_deserialize_item(Unit *u, const char *key, const char *value, F
                         log_unit_debug(u, "Failed to parse result value: %s", value);
                 else if (f != TIMER_SUCCESS)
                         t->result = f;
-        } else if (streq(key, "last-trigger-realtime")) {
-
-                r = safe_atou64(value, &t->last_trigger.realtime);
-                if (r < 0)
-                        log_unit_debug(u, "Failed to parse last-trigger-realtime value: %s", value);
 
-        } else if (streq(key, "last-trigger-monotonic")) {
-
-                r = safe_atou64(value, &t->last_trigger.monotonic);
-                if (r < 0)
-                        log_unit_debug(u, "Failed to parse last-trigger-monotonic value: %s", value);
-
-        } else
+        } else if (streq(key, "last-trigger-realtime"))
+                (void) deserialize_usec(value, &t->last_trigger.realtime);
+        else if (streq(key, "last-trigger-monotonic"))
+                (void) deserialize_usec(value, &t->last_trigger.monotonic);
+        else
                 log_unit_debug(u, "Unknown serialization key: %s", key);
 
         return 0;
index 5bbc92dd3580f05c9d09178312f89f795c3723af..e35f7f26d128712a67661e41ba7775747edf7f1e 100644 (file)
@@ -10,8 +10,8 @@
 #include "sd-id128.h"
 #include "sd-messages.h"
 
-#include "alloc-util.h"
 #include "all-units.h"
+#include "alloc-util.h"
 #include "bus-common-errors.h"
 #include "bus-util.h"
 #include "cgroup-util.h"
@@ -35,6 +35,7 @@
 #include "parse-util.h"
 #include "path-util.h"
 #include "process-util.h"
+#include "serialize.h"
 #include "set.h"
 #include "signal-util.h"
 #include "sparse-endian.h"
@@ -3206,23 +3207,21 @@ bool unit_can_serialize(Unit *u) {
         return UNIT_VTABLE(u)->serialize && UNIT_VTABLE(u)->deserialize_item;
 }
 
-static int unit_serialize_cgroup_mask(FILE *f, const char *key, CGroupMask mask) {
+static int serialize_cgroup_mask(FILE *f, const char *key, CGroupMask mask) {
         _cleanup_free_ char *s = NULL;
-        int r = 0;
+        int r;
 
         assert(f);
         assert(key);
 
-        if (mask != 0) {
-                r = cg_mask_to_string(mask, &s);
-                if (r >= 0) {
-                        fputs(key, f);
-                        fputc('=', f);
-                        fputs(s, f);
-                        fputc('\n', f);
-                }
-        }
-        return r;
+        if (mask == 0)
+                return 0;
+
+        r = cg_mask_to_string(mask, &s);
+        if (r < 0)
+                return log_error_errno(r, "Failed to format cgroup mask: %m");
+
+        return serialize_item(f, key, s);
 }
 
 static const char *ip_accounting_metric_field[_CGROUP_IP_ACCOUNTING_METRIC_MAX] = {
@@ -3246,50 +3245,50 @@ int unit_serialize(Unit *u, FILE *f, FDSet *fds, bool serialize_jobs) {
                         return r;
         }
 
-        dual_timestamp_serialize(f, "state-change-timestamp", &u->state_change_timestamp);
+        (void) serialize_dual_timestamp(f, "state-change-timestamp", &u->state_change_timestamp);
 
-        dual_timestamp_serialize(f, "inactive-exit-timestamp", &u->inactive_exit_timestamp);
-        dual_timestamp_serialize(f, "active-enter-timestamp", &u->active_enter_timestamp);
-        dual_timestamp_serialize(f, "active-exit-timestamp", &u->active_exit_timestamp);
-        dual_timestamp_serialize(f, "inactive-enter-timestamp", &u->inactive_enter_timestamp);
+        (void) serialize_dual_timestamp(f, "inactive-exit-timestamp", &u->inactive_exit_timestamp);
+        (void) serialize_dual_timestamp(f, "active-enter-timestamp", &u->active_enter_timestamp);
+        (void) serialize_dual_timestamp(f, "active-exit-timestamp", &u->active_exit_timestamp);
+        (void) serialize_dual_timestamp(f, "inactive-enter-timestamp", &u->inactive_enter_timestamp);
 
-        dual_timestamp_serialize(f, "condition-timestamp", &u->condition_timestamp);
-        dual_timestamp_serialize(f, "assert-timestamp", &u->assert_timestamp);
+        (void) serialize_dual_timestamp(f, "condition-timestamp", &u->condition_timestamp);
+        (void) serialize_dual_timestamp(f, "assert-timestamp", &u->assert_timestamp);
 
         if (dual_timestamp_is_set(&u->condition_timestamp))
-                unit_serialize_item(u, f, "condition-result", yes_no(u->condition_result));
+                (void) serialize_bool(f, "condition-result", u->condition_result);
 
         if (dual_timestamp_is_set(&u->assert_timestamp))
-                unit_serialize_item(u, f, "assert-result", yes_no(u->assert_result));
-
-        unit_serialize_item(u, f, "transient", yes_no(u->transient));
+                (void) serialize_bool(f, "assert-result", u->assert_result);
 
-        unit_serialize_item(u, f, "in-audit", yes_no(u->in_audit));
+        (void) serialize_bool(f, "transient", u->transient);
+        (void) serialize_bool(f, "in-audit", u->in_audit);
 
-        unit_serialize_item(u, f, "exported-invocation-id", yes_no(u->exported_invocation_id));
-        unit_serialize_item(u, f, "exported-log-level-max", yes_no(u->exported_log_level_max));
-        unit_serialize_item(u, f, "exported-log-extra-fields", yes_no(u->exported_log_extra_fields));
-        unit_serialize_item(u, f, "exported-log-rate-limit-interval", yes_no(u->exported_log_rate_limit_interval));
-        unit_serialize_item(u, f, "exported-log-rate-limit-burst", yes_no(u->exported_log_rate_limit_burst));
+        (void) serialize_bool(f, "exported-invocation-id", u->exported_invocation_id);
+        (void) serialize_bool(f, "exported-log-level-max", u->exported_log_level_max);
+        (void) serialize_bool(f, "exported-log-extra-fields", u->exported_log_extra_fields);
+        (void) serialize_bool(f, "exported-log-rate-limit-interval", u->exported_log_rate_limit_interval);
+        (void) serialize_bool(f, "exported-log-rate-limit-burst", u->exported_log_rate_limit_burst);
 
-        unit_serialize_item_format(u, f, "cpu-usage-base", "%" PRIu64, u->cpu_usage_base);
+        (void) serialize_item_format(f, "cpu-usage-base", "%" PRIu64, u->cpu_usage_base);
         if (u->cpu_usage_last != NSEC_INFINITY)
-                unit_serialize_item_format(u, f, "cpu-usage-last", "%" PRIu64, u->cpu_usage_last);
+                (void) serialize_item_format(f, "cpu-usage-last", "%" PRIu64, u->cpu_usage_last);
 
         if (u->cgroup_path)
-                unit_serialize_item(u, f, "cgroup", u->cgroup_path);
-        unit_serialize_item(u, f, "cgroup-realized", yes_no(u->cgroup_realized));
-        (void) unit_serialize_cgroup_mask(f, "cgroup-realized-mask", u->cgroup_realized_mask);
-        (void) unit_serialize_cgroup_mask(f, "cgroup-enabled-mask", u->cgroup_enabled_mask);
-        (void) unit_serialize_cgroup_mask(f, "cgroup-invalidated-mask", u->cgroup_invalidated_mask);
+                (void) serialize_item(f, "cgroup", u->cgroup_path);
+
+        (void) serialize_bool(f, "cgroup-realized", u->cgroup_realized);
+        (void) serialize_cgroup_mask(f, "cgroup-realized-mask", u->cgroup_realized_mask);
+        (void) serialize_cgroup_mask(f, "cgroup-enabled-mask", u->cgroup_enabled_mask);
+        (void) serialize_cgroup_mask(f, "cgroup-invalidated-mask", u->cgroup_invalidated_mask);
 
         if (uid_is_valid(u->ref_uid))
-                unit_serialize_item_format(u, f, "ref-uid", UID_FMT, u->ref_uid);
+                (void) serialize_item_format(f, "ref-uid", UID_FMT, u->ref_uid);
         if (gid_is_valid(u->ref_gid))
-                unit_serialize_item_format(u, f, "ref-gid", GID_FMT, u->ref_gid);
+                (void) serialize_item_format(f, "ref-gid", GID_FMT, u->ref_gid);
 
         if (!sd_id128_is_null(u->invocation_id))
-                unit_serialize_item_format(u, f, "invocation-id", SD_ID128_FORMAT_STR, SD_ID128_FORMAT_VAL(u->invocation_id));
+                (void) serialize_item_format(f, "invocation-id", SD_ID128_FORMAT_STR, SD_ID128_FORMAT_VAL(u->invocation_id));
 
         bus_track_serialize(u->bus_track, f, "ref");
 
@@ -3298,17 +3297,17 @@ int unit_serialize(Unit *u, FILE *f, FDSet *fds, bool serialize_jobs) {
 
                 r = unit_get_ip_accounting(u, m, &v);
                 if (r >= 0)
-                        unit_serialize_item_format(u, f, ip_accounting_metric_field[m], "%" PRIu64, v);
+                        (void) serialize_item_format(f, ip_accounting_metric_field[m], "%" PRIu64, v);
         }
 
         if (serialize_jobs) {
                 if (u->job) {
-                        fprintf(f, "job\n");
+                        fputs("job\n", f);
                         job_serialize(u->job, f);
                 }
 
                 if (u->nop_job) {
-                        fprintf(f, "job\n");
+                        fputs("job\n", f);
                         job_serialize(u->nop_job, f);
                 }
         }
@@ -3318,80 +3317,6 @@ int unit_serialize(Unit *u, FILE *f, FDSet *fds, bool serialize_jobs) {
         return 0;
 }
 
-int unit_serialize_item(Unit *u, FILE *f, const char *key, const char *value) {
-        assert(u);
-        assert(f);
-        assert(key);
-
-        if (!value)
-                return 0;
-
-        fputs(key, f);
-        fputc('=', f);
-        fputs(value, f);
-        fputc('\n', f);
-
-        return 1;
-}
-
-int unit_serialize_item_escaped(Unit *u, FILE *f, const char *key, const char *value) {
-        _cleanup_free_ char *c = NULL;
-
-        assert(u);
-        assert(f);
-        assert(key);
-
-        if (!value)
-                return 0;
-
-        c = cescape(value);
-        if (!c)
-                return -ENOMEM;
-
-        fputs(key, f);
-        fputc('=', f);
-        fputs(c, f);
-        fputc('\n', f);
-
-        return 1;
-}
-
-int unit_serialize_item_fd(Unit *u, FILE *f, FDSet *fds, const char *key, int fd) {
-        int copy;
-
-        assert(u);
-        assert(f);
-        assert(key);
-
-        if (fd < 0)
-                return 0;
-
-        copy = fdset_put_dup(fds, fd);
-        if (copy < 0)
-                return copy;
-
-        fprintf(f, "%s=%i\n", key, copy);
-        return 1;
-}
-
-void unit_serialize_item_format(Unit *u, FILE *f, const char *key, const char *format, ...) {
-        va_list ap;
-
-        assert(u);
-        assert(f);
-        assert(key);
-        assert(format);
-
-        fputs(key, f);
-        fputc('=', f);
-
-        va_start(ap, format);
-        vfprintf(f, format, ap);
-        va_end(ap);
-
-        fputc('\n', f);
-}
-
 int unit_deserialize(Unit *u, FILE *f, FDSet *fds) {
         int r;
 
@@ -3454,25 +3379,25 @@ int unit_deserialize(Unit *u, FILE *f, FDSet *fds) {
                                 log_unit_warning(u, "Update from too old systemd versions are unsupported, cannot deserialize job: %s", v);
                         continue;
                 } else if (streq(l, "state-change-timestamp")) {
-                        dual_timestamp_deserialize(v, &u->state_change_timestamp);
+                        (void) deserialize_dual_timestamp(v, &u->state_change_timestamp);
                         continue;
                 } else if (streq(l, "inactive-exit-timestamp")) {
-                        dual_timestamp_deserialize(v, &u->inactive_exit_timestamp);
+                        (void) deserialize_dual_timestamp(v, &u->inactive_exit_timestamp);
                         continue;
                 } else if (streq(l, "active-enter-timestamp")) {
-                        dual_timestamp_deserialize(v, &u->active_enter_timestamp);
+                        (void) deserialize_dual_timestamp(v, &u->active_enter_timestamp);
                         continue;
                 } else if (streq(l, "active-exit-timestamp")) {
-                        dual_timestamp_deserialize(v, &u->active_exit_timestamp);
+                        (void) deserialize_dual_timestamp(v, &u->active_exit_timestamp);
                         continue;
                 } else if (streq(l, "inactive-enter-timestamp")) {
-                        dual_timestamp_deserialize(v, &u->inactive_enter_timestamp);
+                        (void) deserialize_dual_timestamp(v, &u->inactive_enter_timestamp);
                         continue;
                 } else if (streq(l, "condition-timestamp")) {
-                        dual_timestamp_deserialize(v, &u->condition_timestamp);
+                        (void) deserialize_dual_timestamp(v, &u->condition_timestamp);
                         continue;
                 } else if (streq(l, "assert-timestamp")) {
-                        dual_timestamp_deserialize(v, &u->assert_timestamp);
+                        (void) deserialize_dual_timestamp(v, &u->assert_timestamp);
                         continue;
                 } else if (streq(l, "condition-result")) {
 
@@ -3647,7 +3572,7 @@ int unit_deserialize(Unit *u, FILE *f, FDSet *fds) {
 
                         r = strv_extend(&u->deserialized_refs, v);
                         if (r < 0)
-                                log_oom();
+                                return log_oom();
 
                         continue;
                 } else if (streq(l, "invocation-id")) {
index 4a51a9de7d90465196dd58ade3080f019f66abcb..1aea658e972284d953229589c37dcf54d35e4caf 100644 (file)
@@ -684,11 +684,6 @@ 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);
-int unit_serialize_item_fd(Unit *u, FILE *f, FDSet *fds, const char *key, int fd);
-void unit_serialize_item_format(Unit *u, FILE *f, const char *key, const char *value, ...) _printf_(4,5);
-
 int unit_add_node_dependency(Unit *u, const char *what, bool wants, UnitDependency d, UnitDependencyMask mask);
 
 int unit_coldplug(Unit *u);
index cadf5b787911f2ef67b6fc002c3a71e713d6b5f7..197154a897b76fcf4c61213b20f67f93deecd3ab 100644 (file)
@@ -26,6 +26,7 @@
 #include "parse-util.h"
 #include "path-util.h"
 #include "process-util.h"
+#include "serialize.h"
 #include "string-table.h"
 #include "strv.h"
 #include "terminal-util.h"
@@ -546,9 +547,9 @@ int session_load(Session *s) {
         }
 
         if (realtime)
-                timestamp_deserialize(realtime, &s->timestamp.realtime);
+                (void) deserialize_usec(realtime, &s->timestamp.realtime);
         if (monotonic)
-                timestamp_deserialize(monotonic, &s->timestamp.monotonic);
+                (void) deserialize_usec(monotonic, &s->timestamp.monotonic);
 
         if (active) {
                 k = parse_boolean(active);
index 16a83ae5d5432746c5f19b1a8cfa21c948d08c3b..0f4c5ccadbda6f09b0f84385470660f6a562d60f 100644 (file)
@@ -23,6 +23,7 @@
 #include "parse-util.h"
 #include "path-util.h"
 #include "rm-rf.h"
+#include "serialize.h"
 #include "special.h"
 #include "stdio-util.h"
 #include "string-table.h"
@@ -332,11 +333,11 @@ int user_load(User *u) {
         }
 
         if (realtime)
-                (void) timestamp_deserialize(realtime, &u->timestamp.realtime);
+                (void) deserialize_usec(realtime, &u->timestamp.realtime);
         if (monotonic)
-                (void) timestamp_deserialize(monotonic, &u->timestamp.monotonic);
+                (void) deserialize_usec(monotonic, &u->timestamp.monotonic);
         if (last_session_timestamp)
-                (void) timestamp_deserialize(last_session_timestamp, &u->last_session_timestamp);
+                (void) deserialize_usec(last_session_timestamp, &u->last_session_timestamp);
 
         return 0;
 }
index 215ce12ae94a410a0c1a64fd5ec9a957b04ea5ef..239228b2d28d839a6505eb91284d42434cf89f43 100644 (file)
@@ -21,6 +21,7 @@
 #include "mkdir.h"
 #include "parse-util.h"
 #include "process-util.h"
+#include "serialize.h"
 #include "special.h"
 #include "stdio-util.h"
 #include "string-table.h"
@@ -284,9 +285,9 @@ int machine_load(Machine *m) {
         }
 
         if (realtime)
-                timestamp_deserialize(realtime, &m->timestamp.realtime);
+                (void) deserialize_usec(realtime, &m->timestamp.realtime);
         if (monotonic)
-                timestamp_deserialize(monotonic, &m->timestamp.monotonic);
+                (void) deserialize_usec(monotonic, &m->timestamp.monotonic);
 
         if (netif) {
                 size_t allocated = 0, nr = 0;
index 83a2592c0a5f750b7eef4edf8a05e3b64479467c..c692f012b17c965ec362ccbdc15fb0ae72917378 100644 (file)
@@ -52,10 +52,10 @@ shared_sources = files('''
         import-util.c
         import-util.h
         initreq.h
-        install.c
-        install.h
         install-printf.c
         install-printf.h
+        install.c
+        install.h
         journal-util.c
         journal-util.h
         logs-show.c
@@ -78,6 +78,8 @@ shared_sources = files('''
         resolve-util.c
         resolve-util.h
         seccomp-util.h
+        serialize.c
+        serialize.h
         sleep-config.c
         sleep-config.h
         spawn-ask-password-agent.c
@@ -92,8 +94,8 @@ shared_sources = files('''
         sysctl-util.h
         tomoyo-util.c
         tomoyo-util.h
-        udev-util.h
         udev-util.c
+        udev-util.h
         uid-range.c
         uid-range.h
         utmp-wtmp.h
diff --git a/src/shared/serialize.c b/src/shared/serialize.c
new file mode 100644 (file)
index 0000000..c76a0d0
--- /dev/null
@@ -0,0 +1,190 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
+
+#include "alloc-util.h"
+#include "def.h"
+#include "env-util.h"
+#include "escape.h"
+#include "parse-util.h"
+#include "serialize.h"
+#include "strv.h"
+
+int serialize_item(FILE *f, const char *key, const char *value) {
+        assert(f);
+        assert(key);
+
+        if (!value)
+                return 0;
+
+        /* Make sure that anything we serialize we can also read back again with read_line() with a maximum line size
+         * of LONG_LINE_MAX. This is a safety net only. All code calling us should filter this out earlier anyway. */
+        if (strlen(key) + 1 + strlen(value) + 1 > LONG_LINE_MAX) {
+                log_warning("Attempted to serialize overly long item '%s', refusing.", key);
+                return -EINVAL;
+        }
+
+        fputs(key, f);
+        fputc('=', f);
+        fputs(value, f);
+        fputc('\n', f);
+
+        return 1;
+}
+
+int serialize_item_escaped(FILE *f, const char *key, const char *value) {
+        _cleanup_free_ char *c = NULL;
+
+        assert(f);
+        assert(key);
+
+        if (!value)
+                return 0;
+
+        c = cescape(value);
+        if (!c)
+                return log_oom();
+
+        return serialize_item(f, key, c);
+}
+
+int serialize_item_format(FILE *f, const char *key, const char *format, ...) {
+        char buf[LONG_LINE_MAX];
+        va_list ap;
+        int k;
+
+        assert(f);
+        assert(key);
+        assert(format);
+
+        va_start(ap, format);
+        k = vsnprintf(buf, sizeof(buf), format, ap);
+        va_end(ap);
+
+        if (k < 0 || (size_t) k >= sizeof(buf) || strlen(key) + 1 + k + 1 > LONG_LINE_MAX) {
+                log_warning("Attempted to serialize overly long item '%s', refusing.", key);
+                return -EINVAL;
+        }
+
+        fputs(key, f);
+        fputc('=', f);
+        fputs(buf, f);
+        fputc('\n', f);
+
+        return 1;
+}
+
+int serialize_fd(FILE *f, FDSet *fds, const char *key, int fd) {
+        int copy;
+
+        assert(f);
+        assert(key);
+
+        if (fd < 0)
+                return 0;
+
+        copy = fdset_put_dup(fds, fd);
+        if (copy < 0)
+                return log_error_errno(copy, "Failed to add file descriptor to serialization set: %m");
+
+        return serialize_item_format(f, key, "%i", copy);
+}
+
+int serialize_usec(FILE *f, const char *key, usec_t usec) {
+        assert(f);
+        assert(key);
+
+        if (usec == USEC_INFINITY)
+                return 0;
+
+        return serialize_item_format(f, key, USEC_FMT, usec);
+}
+
+int serialize_dual_timestamp(FILE *f, const char *name, const dual_timestamp *t) {
+        assert(f);
+        assert(name);
+        assert(t);
+
+        if (!dual_timestamp_is_set(t))
+                return 0;
+
+        return serialize_item_format(f, name, USEC_FMT " " USEC_FMT, t->realtime, t->monotonic);
+}
+
+int serialize_strv(FILE *f, const char *key, char **l) {
+        int ret = 0, r;
+        char **i;
+
+        /* Returns the first error */
+
+        STRV_FOREACH(i, l) {
+                r = serialize_item_escaped(f, key, *i);
+                if ((ret >= 0 && r < 0) ||
+                    (ret == 0 && r > 0))
+                        ret = r;
+        }
+
+        return ret;
+}
+
+int deserialize_usec(const char *value, usec_t *ret) {
+        int r;
+
+        assert(value);
+
+        r = safe_atou64(value, ret);
+        if (r < 0)
+                return log_debug_errno(r, "Failed to parse usec value \"%s\": %m", value);
+
+        return 0;
+}
+
+int deserialize_dual_timestamp(const char *value, dual_timestamp *t) {
+        uint64_t a, b;
+        int r, pos;
+
+        assert(value);
+        assert(t);
+
+        pos = strspn(value, WHITESPACE);
+        if (value[pos] == '-')
+                return -EINVAL;
+        pos += strspn(value + pos, DIGITS);
+        pos += strspn(value + pos, WHITESPACE);
+        if (value[pos] == '-')
+                return -EINVAL;
+
+        r = sscanf(value, "%" PRIu64 "%" PRIu64 "%n", &a, &b, &pos);
+        if (r != 2) {
+                log_debug("Failed to parse dual timestamp value \"%s\".", value);
+                return -EINVAL;
+        }
+
+        if (value[pos] != '\0')
+                /* trailing garbage */
+                return -EINVAL;
+
+        t->realtime = a;
+        t->monotonic = b;
+
+        return 0;
+}
+
+int deserialize_environment(const char *value, char ***list) {
+        _cleanup_free_ char *unescaped = NULL;
+        int r;
+
+        assert(value);
+        assert(list);
+
+        /* Changes the *environment strv inline. */
+
+        r = cunescape(value, 0, &unescaped);
+        if (r < 0)
+                return log_error_errno(r, "Failed to unescape: %m");
+
+        r = strv_env_replace(list, unescaped);
+        if (r < 0)
+                return log_error_errno(r, "Failed to append environment variable: %m");
+
+        unescaped = NULL; /* now part of 'list' */
+        return 0;
+}
diff --git a/src/shared/serialize.h b/src/shared/serialize.h
new file mode 100644 (file)
index 0000000..a671524
--- /dev/null
@@ -0,0 +1,23 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
+#pragma once
+
+#include <stdio.h>
+
+#include "fdset.h"
+#include "macro.h"
+
+int serialize_item(FILE *f, const char *key, const char *value);
+int serialize_item_escaped(FILE *f, const char *key, const char *value);
+int serialize_item_format(FILE *f, const char *key, const char *value, ...) _printf_(3,4);
+int serialize_fd(FILE *f, FDSet *fds, const char *key, int fd);
+int serialize_usec(FILE *f, const char *key, usec_t usec);
+int serialize_dual_timestamp(FILE *f, const char *key, const dual_timestamp *t);
+int serialize_strv(FILE *f, const char *key, char **l);
+
+static inline int serialize_bool(FILE *f, const char *key, bool b) {
+        return serialize_item(f, key, yes_no(b));
+}
+
+int deserialize_usec(const char *value, usec_t *timestamp);
+int deserialize_dual_timestamp(const char *value, dual_timestamp *t);
+int deserialize_environment(const char *value, char ***environment);
index e645d4968eeee91acf6bf68abbb6509d7ecdd902..c988fc6eeea86305c399c6d4625e959e569cd2cf 100644 (file)
@@ -2,9 +2,11 @@
 
 #include <string.h>
 
+#include "def.h"
 #include "env-util.h"
 #include "fd-util.h"
 #include "fileio.h"
+#include "serialize.h"
 #include "string-util.h"
 #include "strv.h"
 #include "util.h"
@@ -304,52 +306,59 @@ static void test_env_assignment_is_valid(void) {
 }
 
 static void test_deserialize_environment(void) {
-        _cleanup_strv_free_ char **env = strv_new("A=1", NULL);
+        _cleanup_strv_free_ char **env;
 
-        assert_se(deserialize_environment(&env, "env=B=2") >= 0);
-        assert_se(deserialize_environment(&env, "env=FOO%%=a\\177b\\nc\\td e") >= 0);
+        assert_se(env = strv_new("A=1", NULL));
+
+        assert_se(deserialize_environment("B=2", &env) >= 0);
+        assert_se(deserialize_environment("FOO%%=a\\177b\\nc\\td e", &env) >= 0);
 
         assert_se(strv_equal(env, STRV_MAKE("A=1", "B=2", "FOO%%=a\177b\nc\td e")));
 
-        assert_se(deserialize_environment(&env, "env=foo\\") < 0);
-        assert_se(deserialize_environment(&env, "env=bar\\_baz") < 0);
+        assert_se(deserialize_environment("foo\\", &env) < 0);
+        assert_se(deserialize_environment("bar\\_baz", &env) < 0);
 }
 
 static void test_serialize_environment(void) {
+        _cleanup_strv_free_ char **env = NULL, **env2 = NULL;
         char fn[] = "/tmp/test-env-util.XXXXXXX";
-        int fd, r;
         _cleanup_fclose_ FILE *f = NULL;
+        int fd, r;
 
-        _cleanup_strv_free_ char **env = strv_new("A=1",
-                                                  "B=2",
-                                                  "C=ąęółń",
-                                                  "D=D=a\\x0Ab",
-                                                  "FOO%%=a\177b\nc\td e",
-                                                  NULL);
-        _cleanup_strv_free_ char **env2 = NULL;
+
+        assert_se(env = strv_new("A=1",
+                                 "B=2",
+                                 "C=ąęółń",
+                                 "D=D=a\\x0Ab",
+                                 "FOO%%=a\177b\nc\td e",
+                                 NULL));
 
         fd = mkostemp_safe(fn);
         assert_se(fd >= 0);
 
         assert_se(f = fdopen(fd, "r+"));
 
-        assert_se(serialize_environment(f, env) == 0);
+        assert_se(serialize_strv(f, "env", env) > 0);
         assert_se(fflush_and_check(f) == 0);
 
         rewind(f);
 
         for (;;) {
-                char line[LINE_MAX];
+                _cleanup_free_ char *line = NULL;
                 const char *l;
 
-                if (!fgets(line, sizeof line, f))
+                r = read_line(f, LONG_LINE_MAX, &line);
+                assert_se(r >= 0);
+
+                if (r == 0)
                         break;
 
-                char_array_0(line);
                 l = strstrip(line);
 
-                r = deserialize_environment(&env2, l);
-                assert_se(r == 1);
+                assert_se(startswith(l, "env="));
+
+                r = deserialize_environment(l+4, &env2);
+                assert_se(r >= 0);
         }
         assert_se(feof(f));
 
index abb174b7a6ae5beec58a598f4f065d63368ce206..00051eb434e5820aa3761e8a3ddbed7af878d80e 100644 (file)
@@ -1,6 +1,7 @@
 /* SPDX-License-Identifier: LGPL-2.1+ */
 
 #include "random-util.h"
+#include "serialize.h"
 #include "string-util.h"
 #include "strv.h"
 #include "time-util.h"
@@ -340,40 +341,40 @@ static void test_format_timestamp_utc(void) {
         test_format_timestamp_utc_one(USEC_INFINITY, NULL);
 }
 
-static void test_dual_timestamp_deserialize(void) {
+static void test_deserialize_dual_timestamp(void) {
         int r;
         dual_timestamp t;
 
         log_info("/* %s */", __func__);
 
-        r = dual_timestamp_deserialize("1234 5678", &t);
+        r = deserialize_dual_timestamp("1234 5678", &t);
         assert_se(r == 0);
         assert_se(t.realtime == 1234);
         assert_se(t.monotonic == 5678);
 
-        r = dual_timestamp_deserialize("1234x 5678", &t);
+        r = deserialize_dual_timestamp("1234x 5678", &t);
         assert_se(r == -EINVAL);
 
-        r = dual_timestamp_deserialize("1234 5678y", &t);
+        r = deserialize_dual_timestamp("1234 5678y", &t);
         assert_se(r == -EINVAL);
 
-        r = dual_timestamp_deserialize("-1234 5678", &t);
+        r = deserialize_dual_timestamp("-1234 5678", &t);
         assert_se(r == -EINVAL);
 
-        r = dual_timestamp_deserialize("1234 -5678", &t);
+        r = deserialize_dual_timestamp("1234 -5678", &t);
         assert_se(r == -EINVAL);
 
         /* Check that output wasn't modified. */
         assert_se(t.realtime == 1234);
         assert_se(t.monotonic == 5678);
 
-        r = dual_timestamp_deserialize("+123 567", &t);
+        r = deserialize_dual_timestamp("+123 567", &t);
         assert_se(r == 0);
         assert_se(t.realtime == 123);
         assert_se(t.monotonic == 567);
 
         /* Check that we get "infinity" on overflow. */
-        r = dual_timestamp_deserialize("18446744073709551617 0", &t);
+        r = deserialize_dual_timestamp("18446744073709551617 0", &t);
         assert_se(r == 0);
         assert_se(t.realtime == USEC_INFINITY);
         assert_se(t.monotonic == 0);
@@ -461,7 +462,7 @@ int main(int argc, char *argv[]) {
         test_usec_sub_unsigned();
         test_format_timestamp();
         test_format_timestamp_utc();
-        test_dual_timestamp_deserialize();
+        test_deserialize_dual_timestamp();
         test_usec_shift_clock();
         test_in_utc_timezone();