]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
core: add proper escaping to writing of drop-ins/transient unit files
authorLennart Poettering <lennart@poettering.net>
Wed, 22 Nov 2017 14:03:51 +0000 (15:03 +0100)
committerLennart Poettering <lennart@poettering.net>
Wed, 29 Nov 2017 11:34:12 +0000 (12:34 +0100)
This majorly refactors the transient unit file and drop-in writing
logic, so that we properly C-escape and specifier-escape (% → %%)
everything we write out, so that when we read it back again, specifiers
are parsed that aren't supposed to be parsed.

This renames unit_write_drop_in() and friends by unit_write_setting().
The name change is supposed to clarify that the functions are not only
used to write drop-in files, but also transient unit files.

The previous "mode" parameter to this function is replaced by a more
generic "flags", which knows additional flags for implicit C-style and
specifier escaping before writing things out. This can cover most
properties where either form of escaping is defined. For the cases where
this isn't sufficient, we add helpers unit_escape_setting() and
unit_concat_strv() for escaping individual strings or strvs properly.

While we are at it, we also prettify generation of transient unit files:
we try to reduce the number of section headers written out: previously
we'd write the right section header our for each setting. With this
change we do so only if the setting lives in a different section than
the one before.

(This should also be considered preparation for when we add proper APIs
to systemd to write normal, persistant unit files through the bus API)

26 files changed:
src/core/dbus-automount.c
src/core/dbus-automount.h
src/core/dbus-cgroup.c
src/core/dbus-cgroup.h
src/core/dbus-execute.c
src/core/dbus-execute.h
src/core/dbus-kill.c
src/core/dbus-kill.h
src/core/dbus-mount.c
src/core/dbus-mount.h
src/core/dbus-scope.c
src/core/dbus-scope.h
src/core/dbus-service.c
src/core/dbus-service.h
src/core/dbus-slice.c
src/core/dbus-slice.h
src/core/dbus-socket.c
src/core/dbus-socket.h
src/core/dbus-swap.c
src/core/dbus-swap.h
src/core/dbus-timer.c
src/core/dbus-timer.h
src/core/dbus-unit.c
src/core/dbus-unit.h
src/core/unit.c
src/core/unit.h

index 3c165c41a5249d2f51392c1b5fd8076731587b2d..4b1b86f7b9e59960833ec568feaf5ff7c8b5305a 100644 (file)
@@ -38,7 +38,7 @@ static int bus_automount_set_transient_property(
                 Automount *a,
                 const char *name,
                 sd_bus_message *message,
-                UnitSetPropertiesMode mode,
+                UnitWriteFlags flags,
                 sd_bus_error *error) {
 
         int r;
@@ -47,18 +47,21 @@ static int bus_automount_set_transient_property(
         assert(name);
         assert(message);
 
+        flags |= UNIT_PRIVATE;
+
         if (streq(name, "TimeoutIdleUSec")) {
                 usec_t timeout_idle_usec;
+
                 r = sd_bus_message_read(message, "t", &timeout_idle_usec);
                 if (r < 0)
                         return r;
 
-                if (mode != UNIT_CHECK) {
+                if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
                         char time[FORMAT_TIMESPAN_MAX];
 
                         a->timeout_idle_usec = timeout_idle_usec;
-                        unit_write_drop_in_format(UNIT(a), mode, name, "[Automount]\nTimeoutIdleSec=%s\n",
-                                format_timespan(time, sizeof(time), timeout_idle_usec, USEC_PER_MSEC));
+                        unit_write_settingf(UNIT(a), flags, name, "TimeoutIdleSec=%s\n",
+                                            format_timespan(time, sizeof(time), timeout_idle_usec, USEC_PER_MSEC));
                 }
         } else
                 return 0;
@@ -70,20 +73,17 @@ int bus_automount_set_property(
                 Unit *u,
                 const char *name,
                 sd_bus_message *message,
-                UnitSetPropertiesMode mode,
+                UnitWriteFlags flags,
                 sd_bus_error *error) {
 
         Automount *a = AUTOMOUNT(u);
-        int r = 0;
 
         assert(a);
         assert(name);
         assert(message);
 
-        if (u->transient && u->load_state == UNIT_STUB)
-                /* This is a transient unit, let's load a little more */
-
-                r = bus_automount_set_transient_property(a, name, message, mode, error);
+        if (u->transient && u->load_state == UNIT_STUB) /* This is a transient unit? let's load a little more */
+                return bus_automount_set_transient_property(a, name, message, flags, error);
 
-        return r;
+        return 0;
 }
index dc56de954abc8a0ec16f39d69bf3490692433fcc..378119410cac0da5201e47ed3e545c200164367b 100644 (file)
@@ -23,4 +23,4 @@
 
 extern const sd_bus_vtable bus_automount_vtable[];
 
-int bus_automount_set_property(Unit *u, const char *name, sd_bus_message *message, UnitSetPropertiesMode mode, sd_bus_error *error);
+int bus_automount_set_property(Unit *u, const char *name, sd_bus_message *message, UnitWriteFlags flags, sd_bus_error *error);
index f09d9fecab87cef84ccdb449c36f1faf8678d83d..0343aaed628f422473b2c568ade03547afc65ab4 100644 (file)
@@ -334,7 +334,7 @@ static int bus_cgroup_set_transient_property(
                 CGroupContext *c,
                 const char *name,
                 sd_bus_message *message,
-                UnitSetPropertiesMode mode,
+                UnitWriteFlags flags,
                 sd_bus_error *error) {
 
         int r;
@@ -344,6 +344,8 @@ static int bus_cgroup_set_transient_property(
         assert(name);
         assert(message);
 
+        flags |= UNIT_PRIVATE;
+
         if (streq(name, "Delegate")) {
                 int b;
 
@@ -351,11 +353,11 @@ static int bus_cgroup_set_transient_property(
                 if (r < 0)
                         return r;
 
-                if (mode != UNIT_CHECK) {
+                if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
                         c->delegate = b;
                         c->delegate_controllers = b ? _CGROUP_MASK_ALL : 0;
 
-                        unit_write_drop_in_private(u, mode, name, b ? "Delegate=yes" : "Delegate=no");
+                        unit_write_settingf(u, flags, name, "Delegate=%s", yes_no(b));
                 }
 
                 return 1;
@@ -388,7 +390,7 @@ static int bus_cgroup_set_transient_property(
                 if (r < 0)
                         return r;
 
-                if (mode != UNIT_CHECK) {
+                if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
                         _cleanup_free_ char *t = NULL;
 
                         r = cg_mask_to_string(mask, &t);
@@ -401,7 +403,7 @@ static int bus_cgroup_set_transient_property(
                         else
                                 c->delegate_controllers |= mask;
 
-                        unit_write_drop_in_private_format(u, mode, name, "Delegate=%s", strempty(t));
+                        unit_write_settingf(u, flags, name, "Delegate=%s", strempty(t));
                 }
 
                 return 1;
@@ -415,7 +417,7 @@ int bus_cgroup_set_property(
                 CGroupContext *c,
                 const char *name,
                 sd_bus_message *message,
-                UnitSetPropertiesMode mode,
+                UnitWriteFlags flags,
                 sd_bus_error *error) {
 
         CGroupIOLimitType iol_type;
@@ -426,6 +428,8 @@ int bus_cgroup_set_property(
         assert(name);
         assert(message);
 
+        flags |= UNIT_PRIVATE;
+
         if (streq(name, "CPUAccounting")) {
                 int b;
 
@@ -433,10 +437,10 @@ int bus_cgroup_set_property(
                 if (r < 0)
                         return r;
 
-                if (mode != UNIT_CHECK) {
+                if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
                         c->cpu_accounting = b;
                         unit_invalidate_cgroup(u, CGROUP_MASK_CPUACCT|CGROUP_MASK_CPU);
-                        unit_write_drop_in_private(u, mode, name, b ? "CPUAccounting=yes" : "CPUAccounting=no");
+                        unit_write_settingf(u, flags, name, "CPUAccounting=%s", yes_no(b));
                 }
 
                 return 1;
@@ -449,16 +453,16 @@ int bus_cgroup_set_property(
                         return r;
 
                 if (!CGROUP_WEIGHT_IS_OK(weight))
-                        return sd_bus_error_set_errnof(error, EINVAL, "CPUWeight value out of range");
+                        return sd_bus_error_set_errnof(error, EINVAL, "CPUWeight= value out of range");
 
-                if (mode != UNIT_CHECK) {
+                if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
                         c->cpu_weight = weight;
                         unit_invalidate_cgroup(u, CGROUP_MASK_CPU);
 
                         if (weight == CGROUP_WEIGHT_INVALID)
-                                unit_write_drop_in_private(u, mode, name, "CPUWeight=");
+                                unit_write_setting(u, flags, name, "CPUWeight=");
                         else
-                                unit_write_drop_in_private_format(u, mode, name, "CPUWeight=%" PRIu64, weight);
+                                unit_write_settingf(u, flags, name, "CPUWeight=%" PRIu64, weight);
                 }
 
                 return 1;
@@ -471,16 +475,16 @@ int bus_cgroup_set_property(
                         return r;
 
                 if (!CGROUP_WEIGHT_IS_OK(weight))
-                        return sd_bus_error_set_errnof(error, EINVAL, "StartupCPUWeight value out of range");
+                        return sd_bus_error_set_errnof(error, EINVAL, "StartupCPUWeight= value out of range");
 
-                if (mode != UNIT_CHECK) {
+                if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
                         c->startup_cpu_weight = weight;
                         unit_invalidate_cgroup(u, CGROUP_MASK_CPU);
 
                         if (weight == CGROUP_CPU_SHARES_INVALID)
-                                unit_write_drop_in_private(u, mode, name, "StartupCPUWeight=");
+                                unit_write_setting(u, flags, name, "StartupCPUWeight=");
                         else
-                                unit_write_drop_in_private_format(u, mode, name, "StartupCPUWeight=%" PRIu64, weight);
+                                unit_write_settingf(u, flags, name, "StartupCPUWeight=%" PRIu64, weight);
                 }
 
                 return 1;
@@ -493,16 +497,16 @@ int bus_cgroup_set_property(
                         return r;
 
                 if (!CGROUP_CPU_SHARES_IS_OK(shares))
-                        return sd_bus_error_set_errnof(error, EINVAL, "CPUShares value out of range");
+                        return sd_bus_error_set_errnof(error, EINVAL, "CPUShares= value out of range");
 
-                if (mode != UNIT_CHECK) {
+                if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
                         c->cpu_shares = shares;
                         unit_invalidate_cgroup(u, CGROUP_MASK_CPU);
 
                         if (shares == CGROUP_CPU_SHARES_INVALID)
-                                unit_write_drop_in_private(u, mode, name, "CPUShares=");
+                                unit_write_setting(u, flags, name, "CPUShares=");
                         else
-                                unit_write_drop_in_private_format(u, mode, name, "CPUShares=%" PRIu64, shares);
+                                unit_write_settingf(u, flags, name, "CPUShares=%" PRIu64, shares);
                 }
 
                 return 1;
@@ -515,16 +519,16 @@ int bus_cgroup_set_property(
                         return r;
 
                 if (!CGROUP_CPU_SHARES_IS_OK(shares))
-                        return sd_bus_error_set_errnof(error, EINVAL, "StartupCPUShares value out of range");
+                        return sd_bus_error_set_errnof(error, EINVAL, "StartupCPUShares= value out of range");
 
-                if (mode != UNIT_CHECK) {
+                if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
                         c->startup_cpu_shares = shares;
                         unit_invalidate_cgroup(u, CGROUP_MASK_CPU);
 
                         if (shares == CGROUP_CPU_SHARES_INVALID)
-                                unit_write_drop_in_private(u, mode, name, "StartupCPUShares=");
+                                unit_write_setting(u, flags, name, "StartupCPUShares=");
                         else
-                                unit_write_drop_in_private_format(u, mode, name, "StartupCPUShares=%" PRIu64, shares);
+                                unit_write_settingf(u, flags, name, "StartupCPUShares=%" PRIu64, shares);
                 }
 
                 return 1;
@@ -537,20 +541,20 @@ int bus_cgroup_set_property(
                         return r;
 
                 if (u64 <= 0)
-                        return sd_bus_error_set_errnof(error, EINVAL, "CPUQuotaPerSecUSec value out of range");
+                        return sd_bus_error_set_errnof(error, EINVAL, "CPUQuotaPerSecUSec= value out of range");
 
-                if (mode != UNIT_CHECK) {
+                if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
                         c->cpu_quota_per_sec_usec = u64;
                         unit_invalidate_cgroup(u, CGROUP_MASK_CPU);
+
                         if (c->cpu_quota_per_sec_usec == USEC_INFINITY)
-                                unit_write_drop_in_private_format(u, mode, "CPUQuota",
-                                                                  "CPUQuota=");
+                                unit_write_setting(u, flags, "CPUQuota", "CPUQuota=");
                         else
-                                /* config_parse_cpu_quota() requires an integer, so
-                                 * truncating division is used on purpose here. */
-                                unit_write_drop_in_private_format(u, mode, "CPUQuota",
-                                                                  "CPUQuota=%0.f%%",
-                                                                  (double) (c->cpu_quota_per_sec_usec / 10000));
+                                /* config_parse_cpu_quota() requires an integer, so truncating division is used on
+                                 * purpose here. */
+                                unit_write_settingf(u, flags, "CPUQuota",
+                                                    "CPUQuota=%0.f%%",
+                                                    (double) (c->cpu_quota_per_sec_usec / 10000));
                 }
 
                 return 1;
@@ -562,10 +566,10 @@ int bus_cgroup_set_property(
                 if (r < 0)
                         return r;
 
-                if (mode != UNIT_CHECK) {
+                if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
                         c->io_accounting = b;
                         unit_invalidate_cgroup(u, CGROUP_MASK_IO);
-                        unit_write_drop_in_private(u, mode, name, b ? "IOAccounting=yes" : "IOAccounting=no");
+                        unit_write_settingf(u, flags, name, "IOAccounting=%s", yes_no(b));
                 }
 
                 return 1;
@@ -578,16 +582,16 @@ int bus_cgroup_set_property(
                         return r;
 
                 if (!CGROUP_WEIGHT_IS_OK(weight))
-                        return sd_bus_error_set_errnof(error, EINVAL, "IOWeight value out of range");
+                        return sd_bus_error_set_errnof(error, EINVAL, "IOWeight= value out of range");
 
-                if (mode != UNIT_CHECK) {
+                if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
                         c->io_weight = weight;
                         unit_invalidate_cgroup(u, CGROUP_MASK_IO);
 
                         if (weight == CGROUP_WEIGHT_INVALID)
-                                unit_write_drop_in_private(u, mode, name, "IOWeight=");
+                                unit_write_setting(u, flags, name, "IOWeight=");
                         else
-                                unit_write_drop_in_private_format(u, mode, name, "IOWeight=%" PRIu64, weight);
+                                unit_write_settingf(u, flags, name, "IOWeight=%" PRIu64, weight);
                 }
 
                 return 1;
@@ -600,16 +604,16 @@ int bus_cgroup_set_property(
                         return r;
 
                 if (CGROUP_WEIGHT_IS_OK(weight))
-                        return sd_bus_error_set_errnof(error, EINVAL, "StartupIOWeight value out of range");
+                        return sd_bus_error_set_errnof(error, EINVAL, "StartupIOWeight= value out of range");
 
-                if (mode != UNIT_CHECK) {
+                if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
                         c->startup_io_weight = weight;
                         unit_invalidate_cgroup(u, CGROUP_MASK_IO);
 
                         if (weight == CGROUP_WEIGHT_INVALID)
-                                unit_write_drop_in_private(u, mode, name, "StartupIOWeight=");
+                                unit_write_setting(u, flags, name, "StartupIOWeight=");
                         else
-                                unit_write_drop_in_private_format(u, mode, name, "StartupIOWeight=%" PRIu64, weight);
+                                unit_write_settingf(u, flags, name, "StartupIOWeight=%" PRIu64, weight);
                 }
 
                 return 1;
@@ -625,7 +629,7 @@ int bus_cgroup_set_property(
 
                 while ((r = sd_bus_message_read(message, "(st)", &path, &u64)) > 0) {
 
-                        if (mode != UNIT_CHECK) {
+                        if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
                                 CGroupIODeviceLimit *a = NULL, *b;
 
                                 LIST_FOREACH(device_limits, b, c->io_device_limits) {
@@ -666,7 +670,7 @@ int bus_cgroup_set_property(
                 if (r < 0)
                         return r;
 
-                if (mode != UNIT_CHECK) {
+                if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
                         CGroupIODeviceLimit *a;
                         _cleanup_free_ char *buf = NULL;
                         _cleanup_fclose_ FILE *f = NULL;
@@ -691,7 +695,7 @@ int bus_cgroup_set_property(
                         r = fflush_and_check(f);
                         if (r < 0)
                                 return r;
-                        unit_write_drop_in_private(u, mode, name, buf);
+                        unit_write_setting(u, flags, name, buf);
                 }
 
                 return 1;
@@ -708,9 +712,9 @@ int bus_cgroup_set_property(
                 while ((r = sd_bus_message_read(message, "(st)", &path, &weight)) > 0) {
 
                         if (!CGROUP_WEIGHT_IS_OK(weight) || weight == CGROUP_WEIGHT_INVALID)
-                                return sd_bus_error_set_errnof(error, EINVAL, "IODeviceWeight out of range");
+                                return sd_bus_error_set_errnof(error, EINVAL, "IODeviceWeight= value out of range");
 
-                        if (mode != UNIT_CHECK) {
+                        if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
                                 CGroupIODeviceWeight *a = NULL, *b;
 
                                 LIST_FOREACH(device_weights, b, c->io_device_weights) {
@@ -743,7 +747,7 @@ int bus_cgroup_set_property(
                 if (r < 0)
                         return r;
 
-                if (mode != UNIT_CHECK) {
+                if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
                         _cleanup_free_ char *buf = NULL;
                         _cleanup_fclose_ FILE *f = NULL;
                         CGroupIODeviceWeight *a;
@@ -767,7 +771,7 @@ int bus_cgroup_set_property(
                         r = fflush_and_check(f);
                         if (r < 0)
                                 return r;
-                        unit_write_drop_in_private(u, mode, name, buf);
+                        unit_write_setting(u, flags, name, buf);
                 }
 
                 return 1;
@@ -779,10 +783,10 @@ int bus_cgroup_set_property(
                 if (r < 0)
                         return r;
 
-                if (mode != UNIT_CHECK) {
+                if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
                         c->blockio_accounting = b;
                         unit_invalidate_cgroup(u, CGROUP_MASK_BLKIO);
-                        unit_write_drop_in_private(u, mode, name, b ? "BlockIOAccounting=yes" : "BlockIOAccounting=no");
+                        unit_write_settingf(u, flags, name, "BlockIOAccounting=%s", yes_no(b));
                 }
 
                 return 1;
@@ -795,16 +799,16 @@ int bus_cgroup_set_property(
                         return r;
 
                 if (!CGROUP_BLKIO_WEIGHT_IS_OK(weight))
-                        return sd_bus_error_set_errnof(error, EINVAL, "BlockIOWeight value out of range");
+                        return sd_bus_error_set_errnof(error, EINVAL, "BlockIOWeight= value out of range");
 
-                if (mode != UNIT_CHECK) {
+                if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
                         c->blockio_weight = weight;
                         unit_invalidate_cgroup(u, CGROUP_MASK_BLKIO);
 
                         if (weight == CGROUP_BLKIO_WEIGHT_INVALID)
-                                unit_write_drop_in_private(u, mode, name, "BlockIOWeight=");
+                                unit_write_setting(u, flags, name, "BlockIOWeight=");
                         else
-                                unit_write_drop_in_private_format(u, mode, name, "BlockIOWeight=%" PRIu64, weight);
+                                unit_write_settingf(u, flags, name, "BlockIOWeight=%" PRIu64, weight);
                 }
 
                 return 1;
@@ -817,16 +821,16 @@ int bus_cgroup_set_property(
                         return r;
 
                 if (!CGROUP_BLKIO_WEIGHT_IS_OK(weight))
-                        return sd_bus_error_set_errnof(error, EINVAL, "StartupBlockIOWeight value out of range");
+                        return sd_bus_error_set_errnof(error, EINVAL, "StartupBlockIOWeight= value out of range");
 
-                if (mode != UNIT_CHECK) {
+                if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
                         c->startup_blockio_weight = weight;
                         unit_invalidate_cgroup(u, CGROUP_MASK_BLKIO);
 
                         if (weight == CGROUP_BLKIO_WEIGHT_INVALID)
-                                unit_write_drop_in_private(u, mode, name, "StartupBlockIOWeight=");
+                                unit_write_setting(u, flags, name, "StartupBlockIOWeight=");
                         else
-                                unit_write_drop_in_private_format(u, mode, name, "StartupBlockIOWeight=%" PRIu64, weight);
+                                unit_write_settingf(u, flags, name, "StartupBlockIOWeight=%" PRIu64, weight);
                 }
 
                 return 1;
@@ -846,7 +850,7 @@ int bus_cgroup_set_property(
 
                 while ((r = sd_bus_message_read(message, "(st)", &path, &u64)) > 0) {
 
-                        if (mode != UNIT_CHECK) {
+                        if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
                                 CGroupBlockIODeviceBandwidth *a = NULL, *b;
 
                                 LIST_FOREACH(device_bandwidths, b, c->blockio_device_bandwidths) {
@@ -887,7 +891,7 @@ int bus_cgroup_set_property(
                 if (r < 0)
                         return r;
 
-                if (mode != UNIT_CHECK) {
+                if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
                         CGroupBlockIODeviceBandwidth *a;
                         _cleanup_free_ char *buf = NULL;
                         _cleanup_fclose_ FILE *f = NULL;
@@ -923,7 +927,8 @@ int bus_cgroup_set_property(
                         r = fflush_and_check(f);
                         if (r < 0)
                                 return r;
-                        unit_write_drop_in_private(u, mode, name, buf);
+
+                        unit_write_setting(u, flags, name, buf);
                 }
 
                 return 1;
@@ -940,9 +945,9 @@ int bus_cgroup_set_property(
                 while ((r = sd_bus_message_read(message, "(st)", &path, &weight)) > 0) {
 
                         if (!CGROUP_BLKIO_WEIGHT_IS_OK(weight) || weight == CGROUP_BLKIO_WEIGHT_INVALID)
-                                return sd_bus_error_set_errnof(error, EINVAL, "BlockIODeviceWeight out of range");
+                                return sd_bus_error_set_errnof(error, EINVAL, "BlockIODeviceWeight= out of range");
 
-                        if (mode != UNIT_CHECK) {
+                        if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
                                 CGroupBlockIODeviceWeight *a = NULL, *b;
 
                                 LIST_FOREACH(device_weights, b, c->blockio_device_weights) {
@@ -975,7 +980,7 @@ int bus_cgroup_set_property(
                 if (r < 0)
                         return r;
 
-                if (mode != UNIT_CHECK) {
+                if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
                         _cleanup_free_ char *buf = NULL;
                         _cleanup_fclose_ FILE *f = NULL;
                         CGroupBlockIODeviceWeight *a;
@@ -999,7 +1004,8 @@ int bus_cgroup_set_property(
                         r = fflush_and_check(f);
                         if (r < 0)
                                 return r;
-                        unit_write_drop_in_private(u, mode, name, buf);
+
+                        unit_write_setting(u, flags, name, buf);
                 }
 
                 return 1;
@@ -1011,10 +1017,10 @@ int bus_cgroup_set_property(
                 if (r < 0)
                         return r;
 
-                if (mode != UNIT_CHECK) {
+                if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
                         c->memory_accounting = b;
                         unit_invalidate_cgroup(u, CGROUP_MASK_MEMORY);
-                        unit_write_drop_in_private(u, mode, name, b ? "MemoryAccounting=yes" : "MemoryAccounting=no");
+                        unit_write_settingf(u, flags, name, "MemoryAccounting=%s", yes_no(b));
                 }
 
                 return 1;
@@ -1028,7 +1034,7 @@ int bus_cgroup_set_property(
                 if (v <= 0)
                         return sd_bus_error_set_errnof(error, EINVAL, "%s= is too small", name);
 
-                if (mode != UNIT_CHECK) {
+                if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
                         if (streq(name, "MemoryLow"))
                                 c->memory_low = v;
                         else if (streq(name, "MemoryHigh"))
@@ -1041,9 +1047,9 @@ int bus_cgroup_set_property(
                         unit_invalidate_cgroup(u, CGROUP_MASK_MEMORY);
 
                         if (v == CGROUP_LIMIT_MAX)
-                                unit_write_drop_in_private_format(u, mode, name, "%s=infinity", name);
+                                unit_write_settingf(u, flags, name, "%s=infinity", name);
                         else
-                                unit_write_drop_in_private_format(u, mode, name, "%s=%" PRIu64, name, v);
+                                unit_write_settingf(u, flags, name, "%s=%" PRIu64, name, v);
                 }
 
                 return 1;
@@ -1060,7 +1066,7 @@ int bus_cgroup_set_property(
                 if (v <= 0 || v == UINT64_MAX)
                         return sd_bus_error_set_errnof(error, EINVAL, "%s= is out of range", name);
 
-                if (mode != UNIT_CHECK) {
+                if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
                         const char *e;
 
                         /* Chop off suffix */
@@ -1075,8 +1081,8 @@ int bus_cgroup_set_property(
                                 c->memory_max = v;
 
                         unit_invalidate_cgroup(u, CGROUP_MASK_MEMORY);
-                        unit_write_drop_in_private_format(u, mode, name, "%s=%" PRIu32 "%%", name,
-                                                          (uint32_t) (DIV_ROUND_UP((uint64_t) raw * 100U, (uint64_t) UINT32_MAX)));
+                        unit_write_settingf(u, flags, name, "%s=%" PRIu32 "%%", name,
+                                            (uint32_t) (DIV_ROUND_UP((uint64_t) raw * 100U, (uint64_t) UINT32_MAX)));
                 }
 
                 return 1;
@@ -1090,14 +1096,14 @@ int bus_cgroup_set_property(
                 if (limit <= 0)
                         return sd_bus_error_set_errnof(error, EINVAL, "%s= is too small", name);
 
-                if (mode != UNIT_CHECK) {
+                if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
                         c->memory_limit = limit;
                         unit_invalidate_cgroup(u, CGROUP_MASK_MEMORY);
 
                         if (limit == (uint64_t) -1)
-                                unit_write_drop_in_private(u, mode, name, "MemoryLimit=infinity");
+                                unit_write_setting(u, flags, name, "MemoryLimit=infinity");
                         else
-                                unit_write_drop_in_private_format(u, mode, name, "MemoryLimit=%" PRIu64, limit);
+                                unit_write_settingf(u, flags, name, "MemoryLimit=%" PRIu64, limit);
                 }
 
                 return 1;
@@ -1114,10 +1120,10 @@ int bus_cgroup_set_property(
                 if (limit <= 0 || limit == UINT64_MAX)
                         return sd_bus_error_set_errnof(error, EINVAL, "%s= is out of range", name);
 
-                if (mode != UNIT_CHECK) {
+                if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
                         c->memory_limit = limit;
                         unit_invalidate_cgroup(u, CGROUP_MASK_MEMORY);
-                        unit_write_drop_in_private_format(u, mode, "MemoryLimit", "MemoryLimit=%" PRIu32 "%%",
+                        unit_write_settingf(u, flags, "MemoryLimit", "MemoryLimit=%" PRIu32 "%%",
                                                           (uint32_t) (DIV_ROUND_UP((uint64_t) raw * 100U, (uint64_t) UINT32_MAX)));
                 }
 
@@ -1135,10 +1141,10 @@ int bus_cgroup_set_property(
                 if (p < 0)
                         return -EINVAL;
 
-                if (mode != UNIT_CHECK) {
+                if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
                         c->device_policy = p;
                         unit_invalidate_cgroup(u, CGROUP_MASK_DEVICES);
-                        unit_write_drop_in_private_format(u, mode, name, "DevicePolicy=%s", policy);
+                        unit_write_settingf(u, flags, name, "DevicePolicy=%s", policy);
                 }
 
                 return 1;
@@ -1166,7 +1172,7 @@ int bus_cgroup_set_property(
                         if (!in_charset(rwm, "rwm"))
                                 return sd_bus_error_set_errnof(error, EINVAL, "DeviceAllow= requires combination of rwm flags");
 
-                        if (mode != UNIT_CHECK) {
+                        if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
                                 CGroupDeviceAllow *a = NULL, *b;
 
                                 LIST_FOREACH(device_allow, b, c->device_allow) {
@@ -1204,7 +1210,7 @@ int bus_cgroup_set_property(
                 if (r < 0)
                         return r;
 
-                if (mode != UNIT_CHECK) {
+                if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
                         _cleanup_free_ char *buf = NULL;
                         _cleanup_fclose_ FILE *f = NULL;
                         CGroupDeviceAllow *a;
@@ -1228,7 +1234,7 @@ int bus_cgroup_set_property(
                         r = fflush_and_check(f);
                         if (r < 0)
                                 return r;
-                        unit_write_drop_in_private(u, mode, name, buf);
+                        unit_write_setting(u, flags, name, buf);
                 }
 
                 return 1;
@@ -1240,10 +1246,10 @@ int bus_cgroup_set_property(
                 if (r < 0)
                         return r;
 
-                if (mode != UNIT_CHECK) {
+                if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
                         c->tasks_accounting = b;
                         unit_invalidate_cgroup(u, CGROUP_MASK_PIDS);
-                        unit_write_drop_in_private(u, mode, name, b ? "TasksAccounting=yes" : "TasksAccounting=no");
+                        unit_write_settingf(u, flags, name, "TasksAccounting=%s", yes_no(b));
                 }
 
                 return 1;
@@ -1257,14 +1263,14 @@ int bus_cgroup_set_property(
                 if (limit <= 0)
                         return sd_bus_error_set_errnof(error, EINVAL, "%s= is too small", name);
 
-                if (mode != UNIT_CHECK) {
+                if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
                         c->tasks_max = limit;
                         unit_invalidate_cgroup(u, CGROUP_MASK_PIDS);
 
                         if (limit == (uint64_t) -1)
-                                unit_write_drop_in_private(u, mode, name, "TasksMax=infinity");
+                                unit_write_setting(u, flags, name, "TasksMax=infinity");
                         else
-                                unit_write_drop_in_private_format(u, mode, name, "TasksMax=%" PRIu64, limit);
+                                unit_write_settingf(u, flags, name, "TasksMax=%" PRIu64, limit);
                 }
 
                 return 1;
@@ -1281,11 +1287,11 @@ int bus_cgroup_set_property(
                 if (limit <= 0 || limit >= UINT64_MAX)
                         return sd_bus_error_set_errnof(error, EINVAL, "%s= is out of range", name);
 
-                if (mode != UNIT_CHECK) {
+                if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
                         c->tasks_max = limit;
                         unit_invalidate_cgroup(u, CGROUP_MASK_PIDS);
-                        unit_write_drop_in_private_format(u, mode, name, "TasksMax=%" PRIu32 "%%",
-                                                          (uint32_t) (DIV_ROUND_UP((uint64_t) raw * 100U, (uint64_t) UINT32_MAX)));
+                        unit_write_settingf(u, flags, name, "TasksMax=%" PRIu32 "%%",
+                                            (uint32_t) (DIV_ROUND_UP((uint64_t) raw * 100U, (uint64_t) UINT32_MAX)));
                 }
 
                 return 1;
@@ -1297,11 +1303,11 @@ int bus_cgroup_set_property(
                 if (r < 0)
                         return r;
 
-                if (mode != UNIT_CHECK) {
+                if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
                         c->ip_accounting = b;
 
                         unit_invalidate_cgroup_bpf(u);
-                        unit_write_drop_in_private(u, mode, name, b ? "IPAccounting=yes" : "IPAccounting=no");
+                        unit_write_settingf(u, flags, name, "IPAccounting=%s", yes_no(b));
                 }
 
                 return 1;
@@ -1350,7 +1356,7 @@ int bus_cgroup_set_property(
                         if (prefixlen > FAMILY_ADDRESS_SIZE(family)*8)
                                 return sd_bus_error_set_errnof(error, EINVAL, "Prefix length %" PRIu32 " too large for address family %s.", prefixlen, af_to_name(family));
 
-                        if (mode != UNIT_CHECK) {
+                        if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
                                 IPAddressAccessItem *item;
 
                                 item = new0(IPAddressAccessItem, 1);
@@ -1377,7 +1383,7 @@ int bus_cgroup_set_property(
 
                 *list = ip_address_access_reduce(*list);
 
-                if (mode != UNIT_CHECK) {
+                if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
                         _cleanup_free_ char *buf = NULL;
                         _cleanup_fclose_ FILE *f = NULL;
                         IPAddressAccessItem *item;
@@ -1407,7 +1413,8 @@ int bus_cgroup_set_property(
                         r = fflush_and_check(f);
                         if (r < 0)
                                 return r;
-                        unit_write_drop_in_private(u, mode, name, buf);
+
+                        unit_write_setting(u, flags, name, buf);
 
                         if (*list) {
                                 r = bpf_firewall_supported();
@@ -1429,7 +1436,7 @@ int bus_cgroup_set_property(
         }
 
         if (u->transient && u->load_state == UNIT_STUB) {
-                r = bus_cgroup_set_transient_property(u, c, name, message, mode, error);
+                r = bus_cgroup_set_transient_property(u, c, name, message, flags, error);
                 if (r != 0)
                         return r;
 
index 0e3b903f6fac7b4ad60def90aa49606271ca865a..0588370aa5192c8ad3927ea8373cca95ecf12b8d 100644 (file)
@@ -26,4 +26,4 @@
 
 extern const sd_bus_vtable bus_cgroup_vtable[];
 
-int bus_cgroup_set_property(Unit *u, CGroupContext *c, const char *name, sd_bus_message *message, UnitSetPropertiesMode mode, sd_bus_error *error);
+int bus_cgroup_set_property(Unit *u, CGroupContext *c, const char *name, sd_bus_message *message, UnitWriteFlags flags, sd_bus_error *error);
index 57ccdcbe330cc6688682f47a3cafc094f19cbe50..412be2a6c4e25fe10e43e87060884eb371ecc841 100644 (file)
@@ -32,6 +32,7 @@
 #include "dbus-execute.h"
 #include "env-util.h"
 #include "errno-list.h"
+#include "escape.h"
 #include "execute.h"
 #include "fd-util.h"
 #include "fileio.h"
@@ -50,6 +51,7 @@
 #include "seccomp-util.h"
 #endif
 #include "securebits-util.h"
+#include "specifier.h"
 #include "strv.h"
 #include "syslog-util.h"
 #include "unit-printf.h"
@@ -1037,7 +1039,7 @@ int bus_exec_context_set_transient_property(
                 ExecContext *c,
                 const char *name,
                 sd_bus_message *message,
-                UnitSetPropertiesMode mode,
+                UnitWriteFlags flags,
                 sd_bus_error *error) {
 
         const char *soft = NULL;
@@ -1048,6 +1050,8 @@ int bus_exec_context_set_transient_property(
         assert(name);
         assert(message);
 
+        flags |= UNIT_PRIVATE;
+
         if (streq(name, "User")) {
                 const char *uu;
 
@@ -1058,14 +1062,13 @@ int bus_exec_context_set_transient_property(
                 if (!isempty(uu) && !valid_user_group_name_or_id(uu))
                         return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid user name: %s", uu);
 
-                if (mode != UNIT_CHECK) {
+                if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
 
-                        if (isempty(uu))
-                                c->user = mfree(c->user);
-                        else if (free_and_strdup(&c->user, uu) < 0)
-                                return -ENOMEM;
+                        r = free_and_strdup(&c->user, empty_to_null(uu));
+                        if (r < 0)
+                                return r;
 
-                        unit_write_drop_in_private_format(u, mode, name, "User=%s", uu);
+                        unit_write_settingf(u, flags|UNIT_ESCAPE_SPECIFIERS, name, "User=%s", uu);
                 }
 
                 return 1;
@@ -1080,14 +1083,13 @@ int bus_exec_context_set_transient_property(
                 if (!isempty(gg) && !valid_user_group_name_or_id(gg))
                         return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid group name: %s", gg);
 
-                if (mode != UNIT_CHECK) {
+                if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
 
-                        if (isempty(gg))
-                                c->group = mfree(c->group);
-                        else if (free_and_strdup(&c->group, gg) < 0)
-                                return -ENOMEM;
+                        r = free_and_strdup(&c->group, empty_to_null(gg));
+                        if (r < 0)
+                                return r;
 
-                        unit_write_drop_in_private_format(u, mode, name, "Group=%s", gg);
+                        unit_write_settingf(u, flags|UNIT_ESCAPE_SPECIFIERS, name, "Group=%s", gg);
                 }
 
                 return 1;
@@ -1105,10 +1107,10 @@ int bus_exec_context_set_transient_property(
                                 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid supplementary group names");
                 }
 
-                if (mode != UNIT_CHECK) {
+                if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
                         if (strv_length(l) == 0) {
                                 c->supplementary_groups = strv_free(c->supplementary_groups);
-                                unit_write_drop_in_private_format(u, mode, name, "%s=", name);
+                                unit_write_settingf(u, flags, name, "%s=", name);
                         } else {
                                 _cleanup_free_ char *joined = NULL;
 
@@ -1120,7 +1122,7 @@ int bus_exec_context_set_transient_property(
                                 if (!joined)
                                         return -ENOMEM;
 
-                                unit_write_drop_in_private_format(u, mode, name, "%s=%s", name, joined);
+                                unit_write_settingf(u, flags|UNIT_ESCAPE_SPECIFIERS, name, "%s=%s", name, joined);
                         }
                 }
 
@@ -1133,14 +1135,14 @@ int bus_exec_context_set_transient_property(
                 if (r < 0)
                         return r;
 
-                if (mode != UNIT_CHECK) {
+                if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
 
                         if (isempty(id))
                                 c->syslog_identifier = mfree(c->syslog_identifier);
                         else if (free_and_strdup(&c->syslog_identifier, id) < 0)
                                 return -ENOMEM;
 
-                        unit_write_drop_in_private_format(u, mode, name, "SyslogIdentifier=%s", id);
+                        unit_write_settingf(u, flags|UNIT_ESCAPE_SPECIFIERS, name, "SyslogIdentifier=%s", id);
                 }
 
                 return 1;
@@ -1154,9 +1156,9 @@ int bus_exec_context_set_transient_property(
                 if (!log_level_is_valid(level))
                         return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Log level value out of range");
 
-                if (mode != UNIT_CHECK) {
+                if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
                         c->syslog_priority = (c->syslog_priority & LOG_FACMASK) | level;
-                        unit_write_drop_in_private_format(u, mode, name, "SyslogLevel=%i", level);
+                        unit_write_settingf(u, flags, name, "SyslogLevel=%i", level);
                 }
 
                 return 1;
@@ -1170,9 +1172,9 @@ int bus_exec_context_set_transient_property(
                 if (!log_facility_unshifted_is_valid(facility))
                         return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Log facility value out of range");
 
-                if (mode != UNIT_CHECK) {
+                if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
                         c->syslog_priority = (facility << 3) | LOG_PRI(c->syslog_priority);
-                        unit_write_drop_in_private_format(u, mode, name, "SyslogFacility=%i", facility);
+                        unit_write_settingf(u, flags, name, "SyslogFacility=%i", facility);
                 }
 
                 return 1;
@@ -1187,9 +1189,9 @@ int bus_exec_context_set_transient_property(
                 if (!log_level_is_valid(level))
                         return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Maximum log level value out of range");
 
-                if (mode != UNIT_CHECK) {
+                if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
                         c->log_level_max = level;
-                        unit_write_drop_in_private_format(u, mode, name, "LogLevelMax=%i", level);
+                        unit_write_settingf(u, flags, name, "LogLevelMax=%i", level);
                 }
 
                 return 1;
@@ -1230,7 +1232,7 @@ int bus_exec_context_set_transient_property(
                         if (!journal_field_valid(p, eq - (const char*) p, false))
                                 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Journal field invalid");
 
-                        if (mode != UNIT_CHECK) {
+                        if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
                                 t = realloc_multiply(c->log_extra_fields, sizeof(struct iovec), c->n_log_extra_fields+1);
                                 if (!t)
                                         return -ENOMEM;
@@ -1247,9 +1249,9 @@ int bus_exec_context_set_transient_property(
                         if (!utf8_is_valid(copy))
                                 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Journal field is not valid UTF-8");
 
-                        if (mode != UNIT_CHECK) {
+                        if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
                                 c->log_extra_fields[c->n_log_extra_fields++] = IOVEC_MAKE(copy, sz);
-                                unit_write_drop_in_private_format(u, mode, name, "LogExtraFields=%s", (char*) copy);
+                                unit_write_settingf(u, flags|UNIT_ESCAPE_SPECIFIERS|UNIT_ESCAPE_C, name, "LogExtraFields=%s", (char*) copy);
 
                                 copy = NULL;
                         }
@@ -1261,9 +1263,9 @@ int bus_exec_context_set_transient_property(
                 if (r < 0)
                         return r;
 
-                if (mode != UNIT_CHECK && n == 0) {
+                if (!UNIT_WRITE_FLAGS_NOOP(flags) && n == 0) {
                         exec_context_free_log_extra_fields(c);
-                        unit_write_drop_in_private(u, mode, name, "LogExtraFields=");
+                        unit_write_setting(u, flags, name, "LogExtraFields=");
                 }
 
                 return 1;
@@ -1278,7 +1280,7 @@ int bus_exec_context_set_transient_property(
                 if (!secure_bits_is_valid(n))
                         return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid secure bits");
 
-                if (mode != UNIT_CHECK) {
+                if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
                         _cleanup_free_ char *str = NULL;
 
                         c->secure_bits = n;
@@ -1286,7 +1288,7 @@ int bus_exec_context_set_transient_property(
                         if (r < 0)
                                 return r;
 
-                        unit_write_drop_in_private_format(u, mode, name, "SecureBits=%s", str);
+                        unit_write_settingf(u, flags, name, "SecureBits=%s", str);
                 }
 
                 return 1;
@@ -1297,7 +1299,7 @@ int bus_exec_context_set_transient_property(
                 if (r < 0)
                         return r;
 
-                if (mode != UNIT_CHECK) {
+                if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
                         _cleanup_free_ char *str = NULL;
 
                         if (streq(name, "CapabilityBoundingSet"))
@@ -1309,7 +1311,7 @@ int bus_exec_context_set_transient_property(
                         if (r < 0)
                                 return r;
 
-                        unit_write_drop_in_private_format(u, mode, name, "%s=%s", name, str);
+                        unit_write_settingf(u, flags, name, "%s=%s", name, str);
                 }
 
                 return 1;
@@ -1326,9 +1328,9 @@ int bus_exec_context_set_transient_property(
                 if (p == PERSONALITY_INVALID)
                         return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid personality");
 
-                if (mode != UNIT_CHECK) {
+                if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
                         c->personality = p;
-                        unit_write_drop_in_private_format(u, mode, name, "%s=%s", name, s);
+                        unit_write_settingf(u, flags, name, "%s=%s", name, s);
                 }
 
                 return 1;
@@ -1355,7 +1357,7 @@ int bus_exec_context_set_transient_property(
                 if (r < 0)
                         return r;
 
-                if (mode != UNIT_CHECK) {
+                if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
                         _cleanup_free_ char *joined = NULL;
 
                         if (strv_length(l) == 0) {
@@ -1416,7 +1418,7 @@ int bus_exec_context_set_transient_property(
                         if (!joined)
                                 return -ENOMEM;
 
-                        unit_write_drop_in_private_format(u, mode, name, "SystemCallFilter=%s%s", whitelist ? "" : "~", joined);
+                        unit_write_settingf(u, flags, name, "SystemCallFilter=%s%s", whitelist ? "" : "~", joined);
                 }
 
                 return 1;
@@ -1428,7 +1430,7 @@ int bus_exec_context_set_transient_property(
                 if (r < 0)
                         return r;
 
-                if (mode != UNIT_CHECK) {
+                if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
                         _cleanup_free_ char *joined = NULL;
 
                         if (strv_length(l) == 0)
@@ -1458,7 +1460,7 @@ int bus_exec_context_set_transient_property(
                         if (!joined)
                                 return -ENOMEM;
 
-                        unit_write_drop_in_private_format(u, mode, name, "%s=%s", name, joined);
+                        unit_write_settingf(u, flags, name, "%s=%s", name, joined);
                 }
 
                 return 1;
@@ -1473,10 +1475,10 @@ int bus_exec_context_set_transient_property(
                 if (n <= 0 || n > ERRNO_MAX)
                         return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid SystemCallErrorNumber");
 
-                if (mode != UNIT_CHECK) {
+                if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
                         c->syscall_errno = n;
 
-                        unit_write_drop_in_private_format(u, mode, name, "SystemCallErrorNumber=%d", n);
+                        unit_write_settingf(u, flags, name, "SystemCallErrorNumber=%d", n);
                 }
 
                 return 1;
@@ -1501,7 +1503,7 @@ int bus_exec_context_set_transient_property(
                 if (r < 0)
                         return r;
 
-                if (mode != UNIT_CHECK) {
+                if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
                         _cleanup_free_ char *joined = NULL;
 
                         if (strv_length(l) == 0) {
@@ -1533,7 +1535,7 @@ int bus_exec_context_set_transient_property(
                         if (!joined)
                                 return -ENOMEM;
 
-                        unit_write_drop_in_private_format(u, mode, name, "RestrictAddressFamilies=%s%s", whitelist ? "" : "~", joined);
+                        unit_write_settingf(u, flags, name, "RestrictAddressFamilies=%s%s", whitelist ? "" : "~", joined);
                 }
 
                 return 1;
@@ -1549,7 +1551,7 @@ int bus_exec_context_set_transient_property(
                 if (!sched_policy_is_valid(n))
                         return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid CPU scheduling policy");
 
-                if (mode != UNIT_CHECK) {
+                if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
                         _cleanup_free_ char *str = NULL;
 
                         c->cpu_sched_policy = n;
@@ -1557,7 +1559,7 @@ int bus_exec_context_set_transient_property(
                         if (r < 0)
                                 return r;
 
-                        unit_write_drop_in_private_format(u, mode, name, "CPUSchedulingPolicy=%s", str);
+                        unit_write_settingf(u, flags, name, "CPUSchedulingPolicy=%s", str);
                 }
 
                 return 1;
@@ -1572,9 +1574,9 @@ int bus_exec_context_set_transient_property(
                 if (!ioprio_priority_is_valid(n))
                         return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid CPU scheduling priority");
 
-                if (mode != UNIT_CHECK) {
+                if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
                         c->cpu_sched_priority = n;
-                        unit_write_drop_in_private_format(u, mode, name, "CPUSchedulingPriority=%i", n);
+                        unit_write_settingf(u, flags, name, "CPUSchedulingPriority=%i", n);
                 }
 
                 return 1;
@@ -1587,10 +1589,10 @@ int bus_exec_context_set_transient_property(
                 if (r < 0)
                         return r;
 
-                if (mode != UNIT_CHECK) {
+                if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
                         if (n == 0) {
                                 c->cpuset = mfree(c->cpuset);
-                                unit_write_drop_in_private_format(u, mode, name, "%s=", name);
+                                unit_write_settingf(u, flags, name, "%s=", name);
                         } else {
                                 _cleanup_free_ char *str = NULL;
                                 uint8_t *l;
@@ -1621,7 +1623,7 @@ int bus_exec_context_set_transient_property(
                                 if (len != 0)
                                         str[len - 1] = '\0';
 
-                                unit_write_drop_in_private_format(u, mode, name, "%s=%s", name, str);
+                                unit_write_settingf(u, flags, name, "%s=%s", name, str);
                         }
                 }
 
@@ -1636,9 +1638,9 @@ int bus_exec_context_set_transient_property(
                 if (!nice_is_valid(n))
                         return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Nice value out of range");
 
-                if (mode != UNIT_CHECK) {
+                if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
                         c->nice = n;
-                        unit_write_drop_in_private_format(u, mode, name, "Nice=%i", n);
+                        unit_write_settingf(u, flags, name, "Nice=%i", n);
                 }
 
                 return 1;
@@ -1653,7 +1655,7 @@ int bus_exec_context_set_transient_property(
                 if (!ioprio_class_is_valid(q))
                         return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid IO scheduling class: %i", q);
 
-                if (mode != UNIT_CHECK) {
+                if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
                         _cleanup_free_ char *s = NULL;
 
                         r = ioprio_class_to_string_alloc(q, &s);
@@ -1663,7 +1665,7 @@ int bus_exec_context_set_transient_property(
                         c->ioprio = IOPRIO_PRIO_VALUE(q, IOPRIO_PRIO_DATA(c->ioprio));
                         c->ioprio_set = true;
 
-                        unit_write_drop_in_private_format(u, mode, name, "IOSchedulingClass=%s", s);
+                        unit_write_settingf(u, flags, name, "IOSchedulingClass=%s", s);
                 }
 
                 return 1;
@@ -1678,11 +1680,11 @@ int bus_exec_context_set_transient_property(
                 if (!ioprio_priority_is_valid(p))
                         return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid IO scheduling priority: %i", p);
 
-                if (mode != UNIT_CHECK) {
+                if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
                         c->ioprio = IOPRIO_PRIO_VALUE(IOPRIO_PRIO_CLASS(c->ioprio), p);
                         c->ioprio_set = true;
 
-                        unit_write_drop_in_private_format(u, mode, name, "IOSchedulingPriority=%i", p);
+                        unit_write_settingf(u, flags, name, "IOSchedulingPriority=%i", p);
                 }
 
                 return 1;
@@ -1697,7 +1699,7 @@ int bus_exec_context_set_transient_property(
                 if (!path_is_absolute(s))
                         return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "%s takes an absolute path", name);
 
-                if (mode != UNIT_CHECK) {
+                if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
                         if (streq(name, "TTYPath"))
                                 r = free_and_strdup(&c->tty_path, s);
                         else if (streq(name, "RootImage"))
@@ -1709,7 +1711,7 @@ int bus_exec_context_set_transient_property(
                         if (r < 0)
                                 return r;
 
-                        unit_write_drop_in_private_format(u, mode, name, "%s=%s", name, s);
+                        unit_write_settingf(u, flags|UNIT_ESCAPE_SPECIFIERS, name, "%s=%s", name, s);
                 }
 
                 return 1;
@@ -1731,7 +1733,7 @@ int bus_exec_context_set_transient_property(
                 if (!streq(s, "~") && !path_is_absolute(s))
                         return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "WorkingDirectory= expects an absolute path or '~'");
 
-                if (mode != UNIT_CHECK) {
+                if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
                         if (streq(s, "~")) {
                                 c->working_directory = mfree(c->working_directory);
                                 c->working_directory_home = true;
@@ -1744,7 +1746,7 @@ int bus_exec_context_set_transient_property(
                         }
 
                         c->working_directory_missing_ok = missing_ok;
-                        unit_write_drop_in_private_format(u, mode, name, "WorkingDirectory=%s%s", missing_ok ? "-" : "", s);
+                        unit_write_settingf(u, flags|UNIT_ESCAPE_SPECIFIERS, name, "WorkingDirectory=%s%s", missing_ok ? "-" : "", s);
                 }
 
                 return 1;
@@ -1761,10 +1763,10 @@ int bus_exec_context_set_transient_property(
                 if (p < 0)
                         return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid standard input name");
 
-                if (mode != UNIT_CHECK) {
+                if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
                         c->std_input = p;
 
-                        unit_write_drop_in_private_format(u, mode, name, "StandardInput=%s", exec_input_to_string(p));
+                        unit_write_settingf(u, flags, name, "StandardInput=%s", exec_input_to_string(p));
                 }
 
                 return 1;
@@ -1781,10 +1783,10 @@ int bus_exec_context_set_transient_property(
                 if (p < 0)
                         return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid standard output name");
 
-                if (mode != UNIT_CHECK) {
+                if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
                         c->std_output = p;
 
-                        unit_write_drop_in_private_format(u, mode, name, "StandardOutput=%s", exec_output_to_string(p));
+                        unit_write_settingf(u, flags, name, "StandardOutput=%s", exec_output_to_string(p));
                 }
 
                 return 1;
@@ -1801,10 +1803,10 @@ int bus_exec_context_set_transient_property(
                 if (p < 0)
                         return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid standard error name");
 
-                if (mode != UNIT_CHECK) {
+                if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
                         c->std_error = p;
 
-                        unit_write_drop_in_private_format(u, mode, name, "StandardError=%s", exec_output_to_string(p));
+                        unit_write_settingf(u, flags, name, "StandardError=%s", exec_output_to_string(p));
                 }
 
                 return 1;
@@ -1822,7 +1824,7 @@ int bus_exec_context_set_transient_property(
                 else if (!fdname_is_valid(s))
                         return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid file descriptor name");
 
-                if (mode != UNIT_CHECK) {
+                if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
 
                         if (streq(name, "StandardInputFileDescriptorName")) {
                                 r = free_and_strdup(c->stdio_fdname + STDIN_FILENO, s);
@@ -1830,7 +1832,7 @@ int bus_exec_context_set_transient_property(
                                         return r;
 
                                 c->std_input = EXEC_INPUT_NAMED_FD;
-                                unit_write_drop_in_private_format(u, mode, name, "StandardInput=fd:%s", exec_context_fdname(c, STDIN_FILENO));
+                                unit_write_settingf(u, flags|UNIT_ESCAPE_SPECIFIERS, name, "StandardInput=fd:%s", exec_context_fdname(c, STDIN_FILENO));
 
                         } else if (streq(name, "StandardOutputFileDescriptorName")) {
                                 r = free_and_strdup(c->stdio_fdname + STDOUT_FILENO, s);
@@ -1838,7 +1840,7 @@ int bus_exec_context_set_transient_property(
                                         return r;
 
                                 c->std_output = EXEC_OUTPUT_NAMED_FD;
-                                unit_write_drop_in_private_format(u, mode, name, "StandardOutput=fd:%s", exec_context_fdname(c, STDOUT_FILENO));
+                                unit_write_settingf(u, flags|UNIT_ESCAPE_SPECIFIERS, name, "StandardOutput=fd:%s", exec_context_fdname(c, STDOUT_FILENO));
 
                         } else {
                                 assert(streq(name, "StandardErrorFileDescriptorName"));
@@ -1848,7 +1850,7 @@ int bus_exec_context_set_transient_property(
                                         return r;
 
                                 c->std_error = EXEC_OUTPUT_NAMED_FD;
-                                unit_write_drop_in_private_format(u, mode, name, "StandardError=fd:%s", exec_context_fdname(c, STDERR_FILENO));
+                                unit_write_settingf(u, flags|UNIT_ESCAPE_SPECIFIERS, name, "StandardError=fd:%s", exec_context_fdname(c, STDERR_FILENO));
                         }
                 }
 
@@ -1866,7 +1868,7 @@ int bus_exec_context_set_transient_property(
                 if (!path_is_normalized(s))
                         return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Path %s is not normalized", s);
 
-                if (mode != UNIT_CHECK) {
+                if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
 
                         if (streq(name, "StandardInputFile")) {
                                 r = free_and_strdup(&c->stdio_file[STDIN_FILENO], s);
@@ -1874,7 +1876,7 @@ int bus_exec_context_set_transient_property(
                                         return r;
 
                                 c->std_input = EXEC_INPUT_FILE;
-                                unit_write_drop_in_private_format(u, mode, name, "StandardInput=file:%s", s);
+                                unit_write_settingf(u, flags|UNIT_ESCAPE_SPECIFIERS, name, "StandardInput=file:%s", s);
 
                         } else if (streq(name, "StandardOutputFile")) {
                                 r = free_and_strdup(&c->stdio_file[STDOUT_FILENO], s);
@@ -1882,7 +1884,7 @@ int bus_exec_context_set_transient_property(
                                         return r;
 
                                 c->std_output = EXEC_OUTPUT_FILE;
-                                unit_write_drop_in_private_format(u, mode, name, "StandardOutput=file:%s", s);
+                                unit_write_settingf(u, flags|UNIT_ESCAPE_SPECIFIERS, name, "StandardOutput=file:%s", s);
 
                         } else {
                                 assert(streq(name, "StandardErrorFile"));
@@ -1892,7 +1894,7 @@ int bus_exec_context_set_transient_property(
                                         return r;
 
                                 c->std_error = EXEC_OUTPUT_FILE;
-                                unit_write_drop_in_private_format(u, mode, name, "StandardError=file:%s", s);
+                                unit_write_settingf(u, flags|UNIT_ESCAPE_SPECIFIERS, name, "StandardError=file:%s", s);
                         }
                 }
 
@@ -1906,14 +1908,14 @@ int bus_exec_context_set_transient_property(
                 if (r < 0)
                         return r;
 
-                if (mode != UNIT_CHECK) {
+                if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
                         _cleanup_free_ char *encoded = NULL;
 
                         if (sz == 0) {
                                 c->stdin_data = mfree(c->stdin_data);
                                 c->stdin_data_size = 0;
 
-                                unit_write_drop_in_private(u, mode, name, "StandardInputData=");
+                                unit_write_settingf(u, flags, name, "StandardInputData=");
                         } else {
                                 void *q;
                                 ssize_t n;
@@ -1935,7 +1937,7 @@ int bus_exec_context_set_transient_property(
                                 c->stdin_data = q;
                                 c->stdin_data_size += sz;
 
-                                unit_write_drop_in_private_format(u, mode, name, "StandardInputData=%s", encoded);
+                                unit_write_settingf(u, flags, name, "StandardInputData=%s", encoded);
                         }
                 }
 
@@ -1954,7 +1956,7 @@ int bus_exec_context_set_transient_property(
                 if (r < 0)
                         return r;
 
-                if (mode != UNIT_CHECK) {
+                if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
                         if (streq(name, "IgnoreSIGPIPE"))
                                 c->ignore_sigpipe = b;
                         else if (streq(name, "TTYVHangup"))
@@ -1998,7 +2000,7 @@ int bus_exec_context_set_transient_property(
                         else if (streq(name, "LockPersonality"))
                                 c->lock_personality = b;
 
-                        unit_write_drop_in_private_format(u, mode, name, "%s=%s", name, yes_no(b));
+                        unit_write_settingf(u, flags, name, "%s=%s", name, yes_no(b));
                 }
 
                 return 1;
@@ -2010,13 +2012,13 @@ int bus_exec_context_set_transient_property(
                 if (r < 0)
                         return r;
 
-                if (mode != UNIT_CHECK) {
-                        if (isempty(id))
-                                c->utmp_id = mfree(c->utmp_id);
-                        else if (free_and_strdup(&c->utmp_id, id) < 0)
-                                return -ENOMEM;
+                if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
+
+                        r = free_and_strdup(&c->utmp_id, empty_to_null(id));
+                        if (r < 0)
+                                return r;
 
-                        unit_write_drop_in_private_format(u, mode, name, "UtmpIdentifier=%s", strempty(id));
+                        unit_write_settingf(u, flags|UNIT_ESCAPE_SPECIFIERS, name, "UtmpIdentifier=%s", strempty(id));
                 }
 
                 return 1;
@@ -2033,10 +2035,10 @@ int bus_exec_context_set_transient_property(
                 if (m < 0)
                         return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid utmp mode");
 
-                if (mode != UNIT_CHECK) {
+                if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
                         c->utmp_mode = m;
 
-                        unit_write_drop_in_private_format(u, mode, name, "UtmpMode=%s", exec_utmp_mode_to_string(m));
+                        unit_write_settingf(u, flags, name, "UtmpMode=%s", exec_utmp_mode_to_string(m));
                 }
 
                 return 1;
@@ -2048,13 +2050,13 @@ int bus_exec_context_set_transient_property(
                 if (r < 0)
                         return r;
 
-                if (mode != UNIT_CHECK) {
-                        if (isempty(n))
-                                c->pam_name = mfree(c->pam_name);
-                        else if (free_and_strdup(&c->pam_name, n) < 0)
-                                return -ENOMEM;
+                if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
 
-                        unit_write_drop_in_private_format(u, mode, name, "PAMName=%s", strempty(n));
+                        r = free_and_strdup(&c->pam_name, empty_to_null(n));
+                        if (r < 0)
+                                return r;
+
+                        unit_write_settingf(u, flags|UNIT_ESCAPE_SPECIFIERS, name, "PAMName=%s", strempty(n));
                 }
 
                 return 1;
@@ -2070,14 +2072,18 @@ int bus_exec_context_set_transient_property(
                 if (!strv_env_is_valid(l))
                         return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid environment block.");
 
-                if (mode != UNIT_CHECK) {
+                if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
                         if (strv_length(l) == 0) {
                                 c->environment = strv_free(c->environment);
-                                unit_write_drop_in_private_format(u, mode, name, "Environment=");
+                                unit_write_setting(u, flags, name, "Environment=");
                         } else {
                                 _cleanup_free_ char *joined = NULL;
                                 char **e;
 
+                                joined = unit_concat_strv(l, UNIT_ESCAPE_SPECIFIERS|UNIT_ESCAPE_C);
+                                if (!joined)
+                                        return -ENOMEM;
+
                                 e = strv_env_merge(2, c->environment, l);
                                 if (!e)
                                         return -ENOMEM;
@@ -2085,11 +2091,7 @@ int bus_exec_context_set_transient_property(
                                 strv_free(c->environment);
                                 c->environment = e;
 
-                                joined = strv_join_quoted(l);
-                                if (!joined)
-                                        return -ENOMEM;
-
-                                unit_write_drop_in_private_format(u, mode, name, "Environment=%s", joined);
+                                unit_write_settingf(u, flags, name, "Environment=%s", joined);
                         }
                 }
 
@@ -2106,14 +2108,18 @@ int bus_exec_context_set_transient_property(
                 if (!strv_env_name_or_assignment_is_valid(l))
                         return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid UnsetEnvironment= list.");
 
-                if (mode != UNIT_CHECK) {
+                if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
                         if (strv_length(l) == 0) {
                                 c->unset_environment = strv_free(c->unset_environment);
-                                unit_write_drop_in_private_format(u, mode, name, "UnsetEnvironment=");
+                                unit_write_setting(u, flags, name, "UnsetEnvironment=");
                         } else {
                                 _cleanup_free_ char *joined = NULL;
                                 char **e;
 
+                                joined = unit_concat_strv(l, UNIT_ESCAPE_SPECIFIERS|UNIT_ESCAPE_C);
+                                if (!joined)
+                                        return -ENOMEM;
+
                                 e = strv_env_merge(2, c->unset_environment, l);
                                 if (!e)
                                         return -ENOMEM;
@@ -2121,12 +2127,7 @@ int bus_exec_context_set_transient_property(
                                 strv_free(c->unset_environment);
                                 c->unset_environment = e;
 
-                                /* We write just the new settings out to file, with unresolved specifiers */
-                                joined = strv_join_quoted(l);
-                                if (!joined)
-                                        return -ENOMEM;
-
-                                unit_write_drop_in_private_format(u, mode, name, "UnsetEnvironment=%s", joined);
+                                unit_write_settingf(u, flags, name, "UnsetEnvironment=%s", joined);
                         }
                 }
 
@@ -2140,9 +2141,9 @@ int bus_exec_context_set_transient_property(
                 if (r < 0)
                         return r;
 
-                if (mode != UNIT_CHECK) {
+                if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
                         c->timer_slack_nsec = n;
-                        unit_write_drop_in_private_format(u, mode, name, "TimerSlackNSec=" NSEC_FMT, n);
+                        unit_write_settingf(u, flags, name, "TimerSlackNSec=" NSEC_FMT, n);
                 }
 
                 return 1;
@@ -2157,10 +2158,10 @@ int bus_exec_context_set_transient_property(
                 if (!oom_score_adjust_is_valid(oa))
                         return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "OOM score adjust value out of range");
 
-                if (mode != UNIT_CHECK) {
+                if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
                         c->oom_score_adjust = oa;
                         c->oom_score_adjust_set = true;
-                        unit_write_drop_in_private_format(u, mode, name, "OOMScoreAdjust=%i", oa);
+                        unit_write_settingf(u, flags, name, "OOMScoreAdjust=%i", oa);
                 }
 
                 return 1;
@@ -2181,8 +2182,17 @@ int bus_exec_context_set_transient_property(
                 if (!f)
                         return -ENOMEM;
 
-                STRV_FOREACH(i, c->environment_files)
-                        fprintf(f, "EnvironmentFile=%s", *i);
+                fputs("EnvironmentFile=\n", f);
+
+                STRV_FOREACH(i, c->environment_files) {
+                        _cleanup_free_ char *q = NULL;
+
+                        q = specifier_escape(*i);
+                        if (!q)
+                                return -ENOMEM;
+
+                        fprintf(f, "EnvironmentFile=%s\n", q);
+                }
 
                 while ((r = sd_bus_message_enter_container(message, 'r', "sb")) > 0) {
                         const char *path;
@@ -2199,14 +2209,21 @@ int bus_exec_context_set_transient_property(
                         if (!path_is_absolute(path))
                                 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Path %s is not absolute.", path);
 
-                        if (mode != UNIT_CHECK) {
+                        if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
+                                _cleanup_free_ char *q = NULL;
                                 char *buf;
 
                                 buf = strjoin(b ? "-" : "", path);
                                 if (!buf)
                                         return -ENOMEM;
 
-                                fprintf(f, "EnvironmentFile=%s", buf);
+                                q = specifier_escape(buf);
+                                if (!q) {
+                                        free(buf);
+                                        return -ENOMEM;
+                                }
+
+                                fprintf(f, "EnvironmentFile=%s\n", q);
 
                                 r = strv_consume(&l, buf);
                                 if (r < 0)
@@ -2224,16 +2241,16 @@ int bus_exec_context_set_transient_property(
                 if (r < 0)
                         return r;
 
-                if (mode != UNIT_CHECK) {
+                if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
                         if (strv_isempty(l)) {
                                 c->environment_files = strv_free(c->environment_files);
-                                unit_write_drop_in_private(u, mode, name, "EnvironmentFile=");
+                                unit_write_setting(u, flags, name, "EnvironmentFile=");
                         } else {
                                 r = strv_extend_strv(&c->environment_files, l, true);
                                 if (r < 0)
                                         return r;
 
-                                unit_write_drop_in_private(u, mode, name, joined);
+                                unit_write_setting(u, flags, name, joined);
                         }
                 }
 
@@ -2250,19 +2267,19 @@ int bus_exec_context_set_transient_property(
                 if (!strv_env_name_is_valid(l))
                         return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid PassEnvironment= block.");
 
-                if (mode != UNIT_CHECK) {
+                if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
                         if (strv_isempty(l)) {
                                 c->pass_environment = strv_free(c->pass_environment);
-                                unit_write_drop_in_private_format(u, mode, name, "PassEnvironment=");
+                                unit_write_setting(u, flags, name, "PassEnvironment=");
                         } else {
                                 _cleanup_free_ char *joined = NULL;
 
                                 /* We write just the new settings out to file, with unresolved specifiers. */
-                                joined = strv_join_quoted(l);
+                                joined = unit_concat_strv(l, UNIT_ESCAPE_SPECIFIERS);
                                 if (!joined)
                                         return -ENOMEM;
 
-                                unit_write_drop_in_private_format(u, mode, name, "PassEnvironment=%s", joined);
+                                unit_write_settingf(u, flags, name, "PassEnvironment=%s", joined);
                         }
                 }
 
@@ -2291,9 +2308,7 @@ int bus_exec_context_set_transient_property(
                                 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid %s", name);
                 }
 
-                if (mode != UNIT_CHECK) {
-                        _cleanup_free_ char *joined = NULL;
-
+                if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
                         if (STR_IN_SET(name, "ReadWriteDirectories", "ReadWritePaths"))
                                 dirs = &c->read_write_paths;
                         else if (STR_IN_SET(name, "ReadOnlyDirectories", "ReadOnlyPaths"))
@@ -2303,19 +2318,20 @@ int bus_exec_context_set_transient_property(
 
                         if (strv_length(l) == 0) {
                                 *dirs = strv_free(*dirs);
-                                unit_write_drop_in_private_format(u, mode, name, "%s=", name);
+                                unit_write_settingf(u, flags, name, "%s=", name);
                         } else {
-                                r = strv_extend_strv(dirs, l, true);
-                                if (r < 0)
-                                        return -ENOMEM;
+                                _cleanup_free_ char *joined = NULL;
 
-                                joined = strv_join_quoted(*dirs);
+                                joined = unit_concat_strv(l, UNIT_ESCAPE_SPECIFIERS);
                                 if (!joined)
                                         return -ENOMEM;
 
-                                unit_write_drop_in_private_format(u, mode, name, "%s=%s", name, joined);
-                        }
+                                r = strv_extend_strv(dirs, l, true);
+                                if (r < 0)
+                                        return -ENOMEM;
 
+                                unit_write_settingf(u, flags, name, "%s=%s", name, joined);
+                        }
                 }
 
                 return 1;
@@ -2339,9 +2355,9 @@ int bus_exec_context_set_transient_property(
                                 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Failed to parse protect system value");
                 }
 
-                if (mode != UNIT_CHECK) {
+                if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
                         c->protect_system = ps;
-                        unit_write_drop_in_private_format(u, mode, name, "%s=%s", name, s);
+                        unit_write_settingf(u, flags, name, "%s=%s", name, s);
                 }
 
                 return 1;
@@ -2365,9 +2381,9 @@ int bus_exec_context_set_transient_property(
                                 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Failed to parse protect home value");
                 }
 
-                if (mode != UNIT_CHECK) {
+                if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
                         c->protect_home = ph;
-                        unit_write_drop_in_private_format(u, mode, name, "%s=%s", name, s);
+                        unit_write_settingf(u, flags, name, "%s=%s", name, s);
                 }
 
                 return 1;
@@ -2385,10 +2401,10 @@ int bus_exec_context_set_transient_property(
                 if (m < 0)
                         return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid keyring mode");
 
-                if (mode != UNIT_CHECK) {
+                if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
                         c->keyring_mode = m;
 
-                        unit_write_drop_in_private_format(u, mode, name, "KeyringMode=%s", exec_keyring_mode_to_string(m));
+                        unit_write_settingf(u, flags, name, "KeyringMode=%s", exec_keyring_mode_to_string(m));
                 }
 
                 return 1;
@@ -2405,10 +2421,10 @@ int bus_exec_context_set_transient_property(
                 if (m < 0)
                         return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid preserve mode");
 
-                if (mode != UNIT_CHECK) {
+                if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
                         c->runtime_directory_preserve_mode = m;
 
-                        unit_write_drop_in_private_format(u, mode, name, "RuntimeDirectoryPreserve=%s", exec_preserve_mode_to_string(m));
+                        unit_write_settingf(u, flags, name, "RuntimeDirectoryPreserve=%s", exec_preserve_mode_to_string(m));
                 }
 
                 return 1;
@@ -2420,7 +2436,7 @@ int bus_exec_context_set_transient_property(
                 if (r < 0)
                         return r;
 
-                if (mode != UNIT_CHECK) {
+                if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
                         ExecDirectoryType i;
 
                         if (streq(name, "UMask"))
@@ -2432,7 +2448,7 @@ int bus_exec_context_set_transient_property(
                                                 break;
                                         }
 
-                        unit_write_drop_in_private_format(u, mode, name, "%s=%040o", name, m);
+                        unit_write_settingf(u, flags, name, "%s=%040o", name, m);
                 }
 
                 return 1;
@@ -2450,8 +2466,7 @@ int bus_exec_context_set_transient_property(
                                 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "%s= path is not valid: %s", name, *p);
                 }
 
-                if (mode != UNIT_CHECK) {
-                        _cleanup_free_ char *joined = NULL;
+                if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
                         char ***dirs = NULL;
                         ExecDirectoryType i;
 
@@ -2465,17 +2480,19 @@ int bus_exec_context_set_transient_property(
 
                         if (strv_isempty(l)) {
                                 *dirs = strv_free(*dirs);
-                                unit_write_drop_in_private_format(u, mode, name, "%s=", name);
+                                unit_write_settingf(u, flags, name, "%s=", name);
                         } else {
+                                _cleanup_free_ char *joined = NULL;
+
                                 r = strv_extend_strv(dirs, l, true);
                                 if (r < 0)
                                         return -ENOMEM;
 
-                                joined = strv_join_quoted(*dirs);
+                                joined = unit_concat_strv(l, UNIT_ESCAPE_SPECIFIERS);
                                 if (!joined)
                                         return -ENOMEM;
 
-                                unit_write_drop_in_private_format(u, mode, name, "%s=%s", name, joined);
+                                unit_write_settingf(u, flags, name, "%s=%s", name, joined);
                         }
                 }
 
@@ -2487,13 +2504,13 @@ int bus_exec_context_set_transient_property(
                 if (r < 0)
                         return r;
 
-                if (mode != UNIT_CHECK) {
+                if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
                         if (isempty(s))
                                 c->selinux_context = mfree(c->selinux_context);
                         else if (free_and_strdup(&c->selinux_context, s) < 0)
                                 return -ENOMEM;
 
-                        unit_write_drop_in_private_format(u, mode, name, "%s=%s", name, strempty(s));
+                        unit_write_settingf(u, flags|UNIT_ESCAPE_SPECIFIERS, name, "%s=%s", name, strempty(s));
                 }
 
                 return 1;
@@ -2510,7 +2527,7 @@ int bus_exec_context_set_transient_property(
                 if (r < 0)
                         return r;
 
-                if (mode != UNIT_CHECK) {
+                if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
                         char **p;
                         bool *b;
 
@@ -2531,45 +2548,45 @@ int bus_exec_context_set_transient_property(
                                 *b = ignore;
                         }
 
-                        unit_write_drop_in_private_format(u, mode, name, "%s=%s%s", name, ignore ? "-" : "", strempty(s));
+                        unit_write_settingf(u, flags|UNIT_ESCAPE_SPECIFIERS, name, "%s=%s%s", name, ignore ? "-" : "", strempty(s));
                 }
 
                 return 1;
 
         } else if (streq(name, "RestrictNamespaces")) {
-                uint64_t flags;
+                uint64_t rf;
 
-                r = sd_bus_message_read(message, "t", &flags);
+                r = sd_bus_message_read(message, "t", &rf);
                 if (r < 0)
                         return r;
-                if ((flags & NAMESPACE_FLAGS_ALL) != flags)
+                if ((rf & NAMESPACE_FLAGS_ALL) != rf)
                         return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Unknown namespace types");
 
-                if (mode != UNIT_CHECK) {
+                if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
                         _cleanup_free_ char *s = NULL;
 
-                        r = namespace_flag_to_string_many(flags, &s);
+                        r = namespace_flag_to_string_many(rf, &s);
                         if (r < 0)
                                 return r;
 
-                        c->restrict_namespaces = flags;
-                        unit_write_drop_in_private_format(u, mode, name, "%s=%s", name, s);
+                        c->restrict_namespaces = rf;
+                        unit_write_settingf(u, flags, name, "%s=%s", name, s);
                 }
 
                 return 1;
         } else if (streq(name, "MountFlags")) {
-                uint64_t flags;
+                uint64_t fl;
 
-                r = sd_bus_message_read(message, "t", &flags);
+                r = sd_bus_message_read(message, "t", &fl);
                 if (r < 0)
                         return r;
-                if (!IN_SET(flags, 0, MS_SHARED, MS_PRIVATE, MS_SLAVE))
+                if (!IN_SET(fl, 0, MS_SHARED, MS_PRIVATE, MS_SLAVE))
                         return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Unknown mount propagation flags");
 
-                if (mode != UNIT_CHECK) {
-                        c->mount_flags = flags;
+                if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
+                        c->mount_flags = fl;
 
-                        unit_write_drop_in_private_format(u, mode, name, "%s=%s", name, mount_propagation_flags_to_string(flags));
+                        unit_write_settingf(u, flags, name, "%s=%s", name, mount_propagation_flags_to_string(fl));
                 }
 
                 return 1;
@@ -2600,7 +2617,7 @@ int bus_exec_context_set_transient_property(
                         if (!IN_SET(mount_flags, 0, MS_REC))
                                 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Unknown mount flags.");
 
-                        if (mode != UNIT_CHECK) {
+                        if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
                                 r = bind_mount_add(&c->bind_mounts, &c->n_bind_mounts,
                                                    &(BindMount) {
                                                            .source = strdup(source),
@@ -2612,8 +2629,8 @@ int bus_exec_context_set_transient_property(
                                 if (r < 0)
                                         return r;
 
-                                unit_write_drop_in_private_format(
-                                                u, mode, name,
+                                unit_write_settingf(
+                                                u, flags|UNIT_ESCAPE_SPECIFIERS, name,
                                                 "%s=%s%s:%s:%s",
                                                 name,
                                                 ignore_enoent ? "-" : "",
@@ -2635,6 +2652,8 @@ int bus_exec_context_set_transient_property(
                         bind_mount_free_many(c->bind_mounts, c->n_bind_mounts);
                         c->bind_mounts = NULL;
                         c->n_bind_mounts = 0;
+
+                        unit_write_settingf(u, flags, name, "%s=", name);
                 }
 
                 return 1;
@@ -2671,7 +2690,7 @@ int bus_exec_context_set_transient_property(
                                 return -ERANGE;
                 }
 
-                if (mode != UNIT_CHECK) {
+                if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
                         _cleanup_free_ char *f = NULL;
                         struct rlimit nl;
 
@@ -2701,7 +2720,7 @@ int bus_exec_context_set_transient_property(
                                         return -ENOMEM;
                         }
 
-                        unit_write_drop_in_private_format(u, mode, name, "%s=%s", name, f);
+                        unit_write_settingf(u, flags, name, "%s=%s", name, f);
                 }
 
                 return 1;
index 631edcc8c850ed099732d450b4cb4568e19f7d7d..f30f0774cd2b9e8235659e1f6f42463a71ff3387 100644 (file)
@@ -43,4 +43,4 @@ int bus_property_get_exec_output(sd_bus *bus, const char *path, const char *inte
 int bus_property_get_exec_command(sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *reply, void *userdata, sd_bus_error *ret_error);
 int bus_property_get_exec_command_list(sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *reply, void *userdata, sd_bus_error *ret_error);
 
-int bus_exec_context_set_transient_property(Unit *u, ExecContext *c, const char *name, sd_bus_message *message, UnitSetPropertiesMode mode, sd_bus_error *error);
+int bus_exec_context_set_transient_property(Unit *u, ExecContext *c, const char *name, sd_bus_message *message, UnitWriteFlags flags, sd_bus_error *error);
index 4ac9f363cc867be2c468e8bd16a8ec12db13b491..bf3bbb2047567f936d2f285d1fa03314761dc449 100644 (file)
@@ -39,7 +39,7 @@ int bus_kill_context_set_transient_property(
                 KillContext *c,
                 const char *name,
                 sd_bus_message *message,
-                UnitSetPropertiesMode mode,
+                UnitWriteFlags flags,
                 sd_bus_error *error) {
 
         int r;
@@ -49,6 +49,8 @@ int bus_kill_context_set_transient_property(
         assert(name);
         assert(message);
 
+        flags |= UNIT_PRIVATE;
+
         if (streq(name, "KillMode")) {
                 const char *m;
                 KillMode k;
@@ -61,10 +63,10 @@ int bus_kill_context_set_transient_property(
                 if (k < 0)
                         return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Kill mode '%s' not known.", m);
 
-                if (mode != UNIT_CHECK) {
+                if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
                         c->kill_mode = k;
 
-                        unit_write_drop_in_private_format(u, mode, name, "KillMode=%s", kill_mode_to_string(k));
+                        unit_write_settingf(u, flags, name, "KillMode=%s", kill_mode_to_string(k));
                 }
 
                 return 1;
@@ -79,10 +81,10 @@ int bus_kill_context_set_transient_property(
                 if (!SIGNAL_VALID(sig))
                         return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Signal %i out of range", sig);
 
-                if (mode != UNIT_CHECK) {
+                if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
                         c->kill_signal = sig;
 
-                        unit_write_drop_in_private_format(u, mode, name, "KillSignal=%s", signal_to_string(sig));
+                        unit_write_settingf(u, flags, name, "KillSignal=%s", signal_to_string(sig));
                 }
 
                 return 1;
@@ -94,10 +96,10 @@ int bus_kill_context_set_transient_property(
                 if (r < 0)
                         return r;
 
-                if (mode != UNIT_CHECK) {
+                if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
                         c->send_sighup = b;
 
-                        unit_write_drop_in_private_format(u, mode, name, "SendSIGHUP=%s", yes_no(b));
+                        unit_write_settingf(u, flags, name, "SendSIGHUP=%s", yes_no(b));
                 }
 
                 return 1;
@@ -109,10 +111,10 @@ int bus_kill_context_set_transient_property(
                 if (r < 0)
                         return r;
 
-                if (mode != UNIT_CHECK) {
+                if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
                         c->send_sigkill = b;
 
-                        unit_write_drop_in_private_format(u, mode, name, "SendSIGKILL=%s", yes_no(b));
+                        unit_write_settingf(u, flags, name, "SendSIGKILL=%s", yes_no(b));
                 }
 
                 return 1;
index 44fb9f9a9303476169458b2621e8ae469e534a24..1df3b37c651ee7898922e97c2a036e0ef7f834a2 100644 (file)
@@ -27,4 +27,4 @@
 
 extern const sd_bus_vtable bus_kill_vtable[];
 
-int bus_kill_context_set_transient_property(Unit *u, KillContext *c, const char *name, sd_bus_message *message, UnitSetPropertiesMode mode, sd_bus_error *error);
+int bus_kill_context_set_transient_property(Unit *u, KillContext *c, const char *name, sd_bus_message *message, UnitWriteFlags flags, sd_bus_error *error);
index 794b292ad380dc9ba8d507d1d790fb5e3eb7d448..628bce0b6aee90cd3477906d84a238b4a3a8b82d 100644 (file)
@@ -126,18 +126,19 @@ static int bus_mount_set_transient_property(
                 Mount *m,
                 const char *name,
                 sd_bus_message *message,
-                UnitSetPropertiesMode mode,
+                UnitWriteFlags flags,
                 sd_bus_error *error) {
 
         const char *new_property;
         char **property;
-        char *p;
         int r;
 
         assert(m);
         assert(name);
         assert(message);
 
+        flags |= UNIT_PRIVATE;
+
         if (streq(name, "What"))
                 property = &m->parameters_fragment.what;
         else if (streq(name, "Options"))
@@ -151,16 +152,13 @@ static int bus_mount_set_transient_property(
         if (r < 0)
                 return r;
 
-        if (mode != UNIT_CHECK) {
-                p = strdup(new_property);
-                if (!p)
-                        return -ENOMEM;
+        if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
 
-                unit_write_drop_in_format(UNIT(m), mode, name, "[Mount]\n%s=%s\n",
-                        name, new_property);
+                r = free_and_strdup(property, new_property);
+                if (r < 0)
+                        return r;
 
-                free(*property);
-                *property = p;
+                unit_write_settingf(UNIT(m), flags|UNIT_ESCAPE_SPECIFIERS, name, "%s=%s", name, new_property);
         }
 
         return 1;
@@ -170,7 +168,7 @@ int bus_mount_set_property(
                 Unit *u,
                 const char *name,
                 sd_bus_message *message,
-                UnitSetPropertiesMode mode,
+                UnitWriteFlags flags,
                 sd_bus_error *error) {
 
         Mount *m = MOUNT(u);
@@ -180,22 +178,22 @@ int bus_mount_set_property(
         assert(name);
         assert(message);
 
-        r = bus_cgroup_set_property(u, &m->cgroup_context, name, message, mode, error);
+        r = bus_cgroup_set_property(u, &m->cgroup_context, name, message, flags, error);
         if (r != 0)
                 return r;
 
         if (u->transient && u->load_state == UNIT_STUB) {
                 /* This is a transient unit, let's load a little more */
 
-                r = bus_mount_set_transient_property(m, name, message, mode, error);
+                r = bus_mount_set_transient_property(m, name, message, flags, error);
                 if (r != 0)
                         return r;
 
-                r = bus_exec_context_set_transient_property(u, &m->exec_context, name, message, mode, error);
+                r = bus_exec_context_set_transient_property(u, &m->exec_context, name, message, flags, error);
                 if (r != 0)
                         return r;
 
-                r = bus_kill_context_set_transient_property(u, &m->kill_context, name, message, mode, error);
+                r = bus_kill_context_set_transient_property(u, &m->kill_context, name, message, flags, error);
                 if (r != 0)
                         return r;
         }
index f0a763788fa094a22e80b7161b439a5f4d1fe0cb..5d5e1f679f7efd0b8b6630fbe36980cb7227da89 100644 (file)
@@ -26,5 +26,5 @@
 
 extern const sd_bus_vtable bus_mount_vtable[];
 
-int bus_mount_set_property(Unit *u, const char *name, sd_bus_message *message, UnitSetPropertiesMode mode, sd_bus_error *error);
+int bus_mount_set_property(Unit *u, const char *name, sd_bus_message *message, UnitWriteFlags flags, sd_bus_error *error);
 int bus_mount_commit_properties(Unit *u);
index 4737c6d4063e07c41c9788e0df7c674f8c33748b..9195ad36d081a7a472cf5de8ab66aca59fb99074 100644 (file)
@@ -73,7 +73,7 @@ static int bus_scope_set_transient_property(
                 Scope *s,
                 const char *name,
                 sd_bus_message *message,
-                UnitSetPropertiesMode mode,
+                UnitWriteFlags flags,
                 sd_bus_error *error) {
 
         int r;
@@ -82,6 +82,8 @@ static int bus_scope_set_transient_property(
         assert(name);
         assert(message);
 
+        flags |= UNIT_PRIVATE;
+
         if (streq(name, "PIDs")) {
                 unsigned n = 0;
                 uint32_t pid;
@@ -95,7 +97,7 @@ static int bus_scope_set_transient_property(
                         if (pid <= 1)
                                 return -EINVAL;
 
-                        if (mode != UNIT_CHECK) {
+                        if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
                                 r = unit_watch_pid(UNIT(s), pid);
                                 if (r < 0 && r != -EEXIST)
                                         return r;
@@ -117,7 +119,6 @@ static int bus_scope_set_transient_property(
 
         } else if (streq(name, "Controller")) {
                 const char *controller;
-                char *c;
 
                 /* We can't support direct connections with this, as direct connections know no service or unique name
                  * concept, but the Controller field stores exactly that. */
@@ -131,33 +132,25 @@ static int bus_scope_set_transient_property(
                 if (!isempty(controller) && !service_name_is_valid(controller))
                         return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Controller '%s' is not a valid bus name.", controller);
 
-                if (mode != UNIT_CHECK) {
-                        if (isempty(controller))
-                                c = NULL;
-                        else {
-                                c = strdup(controller);
-                                if (!c)
-                                        return -ENOMEM;
-                        }
-
-                        free(s->controller);
-                        s->controller = c;
+                if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
+                        r = free_and_strdup(&s->controller, empty_to_null(controller));
+                        if (r < 0)
+                                return r;
                 }
 
                 return 1;
 
         } else if (streq(name, "TimeoutStopUSec")) {
+                uint64_t t;
 
-                if (mode != UNIT_CHECK) {
-                        r = sd_bus_message_read(message, "t", &s->timeout_stop_usec);
-                        if (r < 0)
-                                return r;
+                r = sd_bus_message_read(message, "t", &t);
+                if (r < 0)
+                        return r;
 
-                        unit_write_drop_in_private_format(UNIT(s), mode, name, "TimeoutStopSec="USEC_FMT"us", s->timeout_stop_usec);
-                } else {
-                        r = sd_bus_message_skip(message, "t");
-                        if (r < 0)
-                                return r;
+                if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
+                        s->timeout_stop_usec = t;
+
+                        unit_write_settingf(UNIT(s), flags, name, "TimeoutStopSec=" USEC_FMT "us", t);
                 }
 
                 return 1;
@@ -170,7 +163,7 @@ int bus_scope_set_property(
                 Unit *u,
                 const char *name,
                 sd_bus_message *message,
-                UnitSetPropertiesMode mode,
+                UnitWriteFlags flags,
                 sd_bus_error *error) {
 
         Scope *s = SCOPE(u);
@@ -180,18 +173,18 @@ int bus_scope_set_property(
         assert(name);
         assert(message);
 
-        r = bus_cgroup_set_property(u, &s->cgroup_context, name, message, mode, error);
+        r = bus_cgroup_set_property(u, &s->cgroup_context, name, message, flags, error);
         if (r != 0)
                 return r;
 
         if (u->load_state == UNIT_STUB) {
                 /* While we are created we still accept PIDs */
 
-                r = bus_scope_set_transient_property(s, name, message, mode, error);
+                r = bus_scope_set_transient_property(s, name, message, flags, error);
                 if (r != 0)
                         return r;
 
-                r = bus_kill_context_set_transient_property(u, &s->kill_context, name, message, mode, error);
+                r = bus_kill_context_set_transient_property(u, &s->kill_context, name, message, flags, error);
                 if (r != 0)
                         return r;
         }
index c80317c4b21bd725dd20ba7de09846d242899d11..aa604897ebcda9e311cd7ccbb65333615a378c7f 100644 (file)
@@ -26,7 +26,7 @@
 
 extern const sd_bus_vtable bus_scope_vtable[];
 
-int bus_scope_set_property(Unit *u, const char *name, sd_bus_message *i, UnitSetPropertiesMode mode, sd_bus_error *error);
+int bus_scope_set_property(Unit *u, const char *name, sd_bus_message *i, UnitWriteFlags flags, sd_bus_error *error);
 int bus_scope_commit_properties(Unit *u);
 
 int bus_scope_send_request_stop(Scope *s);
index 7b6cb395d8eccd22cfd321d5a421cd05b8205d25..593094ee338792ad97e91172dfcbdb57661adbbf 100644 (file)
@@ -90,7 +90,7 @@ static int bus_service_set_transient_property(
                 Service *s,
                 const char *name,
                 sd_bus_message *message,
-                UnitSetPropertiesMode mode,
+                UnitWriteFlags flags,
                 sd_bus_error *error) {
 
         int r;
@@ -99,6 +99,8 @@ static int bus_service_set_transient_property(
         assert(name);
         assert(message);
 
+        flags |= UNIT_PRIVATE;
+
         if (streq(name, "RemainAfterExit")) {
                 int b;
 
@@ -106,9 +108,9 @@ static int bus_service_set_transient_property(
                 if (r < 0)
                         return r;
 
-                if (mode != UNIT_CHECK) {
+                if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
                         s->remain_after_exit = b;
-                        unit_write_drop_in_private_format(UNIT(s), mode, name, "RemainAfterExit=%s", yes_no(b));
+                        unit_write_settingf(UNIT(s), flags, name, "RemainAfterExit=%s", yes_no(b));
                 }
 
                 return 1;
@@ -125,9 +127,9 @@ static int bus_service_set_transient_property(
                 if (k < 0)
                         return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid service type %s", t);
 
-                if (mode != UNIT_CHECK) {
+                if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
                         s->type = k;
-                        unit_write_drop_in_private_format(UNIT(s), mode, name, "Type=%s", service_type_to_string(s->type));
+                        unit_write_settingf(UNIT(s), flags, name, "Type=%s", service_type_to_string(s->type));
                 }
 
                 return 1;
@@ -138,9 +140,9 @@ static int bus_service_set_transient_property(
                 if (r < 0)
                         return r;
 
-                if (mode != UNIT_CHECK) {
+                if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
                         s->runtime_max_usec = u;
-                        unit_write_drop_in_private_format(UNIT(s), mode, name, "RuntimeMaxSec=" USEC_FMT "us", u);
+                        unit_write_settingf(UNIT(s), flags, name, "RuntimeMaxSec=" USEC_FMT "us", u);
                 }
 
                 return 1;
@@ -161,9 +163,9 @@ static int bus_service_set_transient_property(
                                 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid restart setting: %s", v);
                 }
 
-                if (mode != UNIT_CHECK) {
+                if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
                         s->restart = sr;
-                        unit_write_drop_in_private_format(UNIT(s), mode, name, "Restart=%s", service_restart_to_string(sr));
+                        unit_write_settingf(UNIT(s), flags, name, "Restart=%s", service_restart_to_string(sr));
                 }
 
                 return 1;
@@ -178,7 +180,7 @@ static int bus_service_set_transient_property(
                 if (r < 0)
                         return r;
 
-                if (mode != UNIT_CHECK) {
+                if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
                         int copy;
 
                         copy = fcntl(fd, F_DUPFD_CLOEXEC, 3);
@@ -208,9 +210,9 @@ static int bus_service_set_transient_property(
                 if (r < 0)
                         return r;
 
-                if (mode != UNIT_CHECK) {
+                if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
                         s->n_fd_store_max = (unsigned) u;
-                        unit_write_drop_in_private_format(UNIT(s), mode, name, "FileDescriptorStoreMax=%" PRIu32, u);
+                        unit_write_settingf(UNIT(s), flags, name, "FileDescriptorStoreMax=%" PRIu32, u);
                 }
 
                 return 1;
@@ -227,9 +229,9 @@ static int bus_service_set_transient_property(
                 if (k < 0)
                         return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid notify access setting %s", t);
 
-                if (mode != UNIT_CHECK) {
+                if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
                         s->notify_access = k;
-                        unit_write_drop_in_private_format(UNIT(s), mode, name, "NotifyAccess=%s", notify_access_to_string(s->notify_access));
+                        unit_write_settingf(UNIT(s), flags, name, "NotifyAccess=%s", notify_access_to_string(s->notify_access));
                 }
 
                 return 1;
@@ -265,7 +267,7 @@ static int bus_service_set_transient_property(
                         if (r < 0)
                                 return r;
 
-                        if (mode != UNIT_CHECK) {
+                        if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
                                 ExecCommand *c;
 
                                 c = new0(ExecCommand, 1);
@@ -297,7 +299,7 @@ static int bus_service_set_transient_property(
                 if (r < 0)
                         return r;
 
-                if (mode != UNIT_CHECK) {
+                if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
                         _cleanup_free_ char *buf = NULL;
                         _cleanup_fclose_ FILE *f = NULL;
                         ExecCommand *c;
@@ -313,22 +315,28 @@ static int bus_service_set_transient_property(
                         fputs_unlocked("ExecStart=\n", f);
 
                         LIST_FOREACH(command, c, s->exec_command[SERVICE_EXEC_START]) {
-                                _cleanup_free_ char *a;
+                                _cleanup_free_ char *a = NULL, *t = NULL;
+                                const char *p;
+
+                                p = unit_escape_setting(c->path, UNIT_ESCAPE_C|UNIT_ESCAPE_SPECIFIERS, &t);
+                                if (!p)
+                                        return -ENOMEM;
 
-                                a = strv_join_quoted(c->argv);
+                                a = unit_concat_strv(c->argv, UNIT_ESCAPE_C|UNIT_ESCAPE_SPECIFIERS);
                                 if (!a)
                                         return -ENOMEM;
 
                                 fprintf(f, "ExecStart=%s@%s %s\n",
                                         c->flags & EXEC_COMMAND_IGNORE_FAILURE ? "-" : "",
-                                        c->path,
+                                        p,
                                         a);
                         }
 
                         r = fflush_and_check(f);
                         if (r < 0)
                                 return r;
-                        unit_write_drop_in_private(UNIT(s), mode, name, buf);
+
+                        unit_write_setting(UNIT(s), flags, name, buf);
                 }
 
                 return 1;
@@ -341,7 +349,7 @@ int bus_service_set_property(
                 Unit *u,
                 const char *name,
                 sd_bus_message *message,
-                UnitSetPropertiesMode mode,
+                UnitWriteFlags flags,
                 sd_bus_error *error) {
 
         Service *s = SERVICE(u);
@@ -351,22 +359,22 @@ int bus_service_set_property(
         assert(name);
         assert(message);
 
-        r = bus_cgroup_set_property(u, &s->cgroup_context, name, message, mode, error);
+        r = bus_cgroup_set_property(u, &s->cgroup_context, name, message, flags, error);
         if (r != 0)
                 return r;
 
         if (u->transient && u->load_state == UNIT_STUB) {
                 /* This is a transient unit, let's load a little more */
 
-                r = bus_service_set_transient_property(s, name, message, mode, error);
+                r = bus_service_set_transient_property(s, name, message, flags, error);
                 if (r != 0)
                         return r;
 
-                r = bus_exec_context_set_transient_property(u, &s->exec_context, name, message, mode, error);
+                r = bus_exec_context_set_transient_property(u, &s->exec_context, name, message, flags, error);
                 if (r != 0)
                         return r;
 
-                r = bus_kill_context_set_transient_property(u, &s->kill_context, name, message, mode, error);
+                r = bus_kill_context_set_transient_property(u, &s->kill_context, name, message, flags, error);
                 if (r != 0)
                         return r;
         }
index a0f89fa23c12de73e95033c622e8eda86b632b71..2da29ec601921f45d5a4524c283b24322eca64a7 100644 (file)
@@ -26,5 +26,5 @@
 
 extern const sd_bus_vtable bus_service_vtable[];
 
-int bus_service_set_property(Unit *u, const char *name, sd_bus_message *i, UnitSetPropertiesMode mode, sd_bus_error *error);
+int bus_service_set_property(Unit *u, const char *name, sd_bus_message *i, UnitWriteFlags flags, sd_bus_error *error);
 int bus_service_commit_properties(Unit *u);
index d269cb2b1e11bfdd06eae9aa0b75658517113e1b..fa2ff72151d0384aa329eb416ccd3c9232b4a19e 100644 (file)
@@ -32,7 +32,7 @@ int bus_slice_set_property(
                 Unit *u,
                 const char *name,
                 sd_bus_message *message,
-                UnitSetPropertiesMode mode,
+                UnitWriteFlags flags,
                 sd_bus_error *error) {
 
         Slice *s = SLICE(u);
@@ -40,7 +40,7 @@ int bus_slice_set_property(
         assert(name);
         assert(u);
 
-        return bus_cgroup_set_property(u, &s->cgroup_context, name, message, mode, error);
+        return bus_cgroup_set_property(u, &s->cgroup_context, name, message, flags, error);
 }
 
 int bus_slice_commit_properties(Unit *u) {
index 58553321262fe532805c9f603bcb680bb90b64b2..0c21919ad144fd3f070cc012299783dd43087271 100644 (file)
@@ -26,5 +26,5 @@
 
 extern const sd_bus_vtable bus_slice_vtable[];
 
-int bus_slice_set_property(Unit *u, const char *name, sd_bus_message *message, UnitSetPropertiesMode mode, sd_bus_error *error);
+int bus_slice_set_property(Unit *u, const char *name, sd_bus_message *message, UnitWriteFlags flags, sd_bus_error *error);
 int bus_slice_commit_properties(Unit *u);
index 3c7d99c356a6bc56745fffee72b998cc7489cf36..930b7fa87dd3b53d4f0b7d5ff55ffbb64dbd4756 100644 (file)
@@ -166,7 +166,7 @@ int bus_socket_set_property(
                 Unit *u,
                 const char *name,
                 sd_bus_message *message,
-                UnitSetPropertiesMode mode,
+                UnitWriteFlags flags,
                 sd_bus_error *error) {
 
         Socket *s = SOCKET(u);
@@ -175,7 +175,7 @@ int bus_socket_set_property(
         assert(name);
         assert(message);
 
-        return bus_cgroup_set_property(u, &s->cgroup_context, name, message, mode, error);
+        return bus_cgroup_set_property(u, &s->cgroup_context, name, message, flags, error);
 }
 
 int bus_socket_commit_properties(Unit *u) {
index ee9663f904dc4b236f95e4e5dfd0d7fbda74f315..e6db2d07727d45d72235f1cad6dbadd4c20f020f 100644 (file)
@@ -26,5 +26,5 @@
 
 extern const sd_bus_vtable bus_socket_vtable[];
 
-int bus_socket_set_property(Unit *u, const char *name, sd_bus_message *message, UnitSetPropertiesMode mode, sd_bus_error *error);
+int bus_socket_set_property(Unit *u, const char *name, sd_bus_message *message, UnitWriteFlags flags, sd_bus_error *error);
 int bus_socket_commit_properties(Unit *u);
index ae67f3e6d52e53e7750a5104f7337512b7e4dc4c..795aaa94feffb6462ce848d546dc0ff553f08b21 100644 (file)
@@ -96,7 +96,7 @@ int bus_swap_set_property(
                 Unit *u,
                 const char *name,
                 sd_bus_message *message,
-                UnitSetPropertiesMode mode,
+                UnitWriteFlags flags,
                 sd_bus_error *error) {
 
         Swap *s = SWAP(u);
@@ -105,7 +105,7 @@ int bus_swap_set_property(
         assert(name);
         assert(message);
 
-        return bus_cgroup_set_property(u, &s->cgroup_context, name, message, mode, error);
+        return bus_cgroup_set_property(u, &s->cgroup_context, name, message, flags, error);
 }
 
 int bus_swap_commit_properties(Unit *u) {
index 7df5cc7e54c8aa3d4f3c8d7f49286e6aceb4608d..6cca7483d8836fd8ac5d9d4c5d1a869c78913fff 100644 (file)
@@ -27,5 +27,5 @@
 
 extern const sd_bus_vtable bus_swap_vtable[];
 
-int bus_swap_set_property(Unit *u, const char *name, sd_bus_message *message, UnitSetPropertiesMode mode, sd_bus_error *error);
+int bus_swap_set_property(Unit *u, const char *name, sd_bus_message *message, UnitWriteFlags flags, sd_bus_error *error);
 int bus_swap_commit_properties(Unit *u);
index 282d7f6fab73f339e02a834562bd9ae6f1bbc65c..e4403203ed5b4e07e1019fa090045970e73574e6 100644 (file)
@@ -176,7 +176,7 @@ static int bus_timer_set_transient_property(
                 Timer *t,
                 const char *name,
                 sd_bus_message *message,
-                UnitSetPropertiesMode mode,
+                UnitWriteFlags flags,
                 sd_bus_error *error) {
 
         int r;
@@ -185,6 +185,8 @@ static int bus_timer_set_transient_property(
         assert(name);
         assert(message);
 
+        flags |= UNIT_PRIVATE;
+
         if (STR_IN_SET(name,
                        "OnActiveSec",
                        "OnBootSec",
@@ -204,10 +206,10 @@ static int bus_timer_set_transient_property(
                 if (r < 0)
                         return r;
 
-                if (mode != UNIT_CHECK) {
+                if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
                         char time[FORMAT_TIMESPAN_MAX];
 
-                        unit_write_drop_in_private_format(UNIT(t), mode, name, "%s=%s", name, format_timespan(time, sizeof(time), u, USEC_PER_MSEC));
+                        unit_write_settingf(UNIT(t), flags|UNIT_ESCAPE_SPECIFIERS, name, "%s=%s", name, format_timespan(time, sizeof(time), u, USEC_PER_MSEC));
 
                         v = new0(TimerValue, 1);
                         if (!v)
@@ -231,12 +233,12 @@ static int bus_timer_set_transient_property(
                 if (r < 0)
                         return r;
 
-                if (mode != UNIT_CHECK) {
+                if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
                         r = calendar_spec_from_string(str, &c);
                         if (r < 0)
                                 return r;
 
-                        unit_write_drop_in_private_format(UNIT(t), mode, name, "%s=%s", name, str);
+                        unit_write_settingf(UNIT(t), flags|UNIT_ESCAPE_SPECIFIERS, name, "%s=%s", name, str);
 
                         v = new0(TimerValue, 1);
                         if (!v) {
@@ -262,9 +264,9 @@ static int bus_timer_set_transient_property(
                 if (r < 0)
                         return r;
 
-                if (mode != UNIT_CHECK) {
+                if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
                         t->accuracy_usec = u;
-                        unit_write_drop_in_private_format(UNIT(t), mode, name, "AccuracySec=" USEC_FMT "us", u);
+                        unit_write_settingf(UNIT(t), flags, name, "AccuracySec=" USEC_FMT "us", u);
                 }
 
                 return 1;
@@ -276,9 +278,9 @@ static int bus_timer_set_transient_property(
                 if (r < 0)
                         return r;
 
-                if (mode != UNIT_CHECK) {
+                if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
                         t->random_usec = u;
-                        unit_write_drop_in_private_format(UNIT(t), mode, name, "RandomizedDelaySec=" USEC_FMT "us", u);
+                        unit_write_settingf(UNIT(t), flags, name, "RandomizedDelaySec=" USEC_FMT "us", u);
                 }
 
                 return 1;
@@ -290,9 +292,9 @@ static int bus_timer_set_transient_property(
                 if (r < 0)
                         return r;
 
-                if (mode != UNIT_CHECK) {
+                if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
                         t->wake_system = b;
-                        unit_write_drop_in_private_format(UNIT(t), mode, name, "%s=%s", name, yes_no(b));
+                        unit_write_settingf(UNIT(t), flags, name, "%s=%s", name, yes_no(b));
                 }
 
                 return 1;
@@ -304,9 +306,9 @@ static int bus_timer_set_transient_property(
                 if (r < 0)
                         return r;
 
-                if (mode != UNIT_CHECK) {
+                if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
                         t->remain_after_elapse = b;
-                        unit_write_drop_in_private_format(UNIT(t), mode, name, "%s=%s", name, yes_no(b));
+                        unit_write_settingf(UNIT(t), flags, name, "%s=%s", name, yes_no(b));
                 }
 
                 return 1;
@@ -319,21 +321,17 @@ int bus_timer_set_property(
                 Unit *u,
                 const char *name,
                 sd_bus_message *message,
-                UnitSetPropertiesMode mode,
+                UnitWriteFlags mode,
                 sd_bus_error *error) {
 
         Timer *t = TIMER(u);
-        int r;
 
         assert(t);
         assert(name);
         assert(message);
 
-        if (u->transient && u->load_state == UNIT_STUB) {
-                r = bus_timer_set_transient_property(t, name, message, mode, error);
-                if (r != 0)
-                        return r;
-        }
+        if (u->transient && u->load_state == UNIT_STUB)
+                return bus_timer_set_transient_property(t, name, message, mode, error);
 
         return 0;
 }
index e71f6cfefb0aa16c2a4401b0ea565faa808ea3e3..d810b048eec56c0adee7062046c2ce33322d9dc1 100644 (file)
@@ -26,4 +26,4 @@
 
 extern const sd_bus_vtable bus_timer_vtable[];
 
-int bus_timer_set_property(Unit *u, const char *name, sd_bus_message *i, UnitSetPropertiesMode mode, sd_bus_error *error);
+int bus_timer_set_property(Unit *u, const char *name, sd_bus_message *i, UnitWriteFlags flags, sd_bus_error *error);
index d4bdf1760abfc5e462784976eb112995991f845b..5d4bc28cde6b22a9de0eaa55456d19cfe13c9178 100644 (file)
@@ -1319,7 +1319,7 @@ static int bus_unit_set_transient_property(
                 Unit *u,
                 const char *name,
                 sd_bus_message *message,
-                UnitSetPropertiesMode mode,
+                UnitWriteFlags flags,
                 sd_bus_error *error) {
 
         int r;
@@ -1335,12 +1335,12 @@ static int bus_unit_set_transient_property(
                 if (r < 0)
                         return r;
 
-                if (mode != UNIT_CHECK) {
+                if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
                         r = unit_set_description(u, d);
                         if (r < 0)
                                 return r;
 
-                        unit_write_drop_in_format(u, mode, name, "[Unit]\nDescription=%s", d);
+                        unit_write_settingf(u, flags|UNIT_ESCAPE_SPECIFIERS, name, "Description=%s", d);
                 }
 
                 return 1;
@@ -1352,9 +1352,9 @@ static int bus_unit_set_transient_property(
                 if (r < 0)
                         return r;
 
-                if (mode != UNIT_CHECK) {
+                if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
                         u->default_dependencies = b;
-                        unit_write_drop_in_format(u, mode, name, "[Unit]\nDefaultDependencies=%s", yes_no(b));
+                        unit_write_settingf(u, flags, name, "DefaultDependencies=%s", yes_no(b));
                 }
 
                 return 1;
@@ -1371,9 +1371,9 @@ static int bus_unit_set_transient_property(
                 if (m < 0)
                         return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Unknown garbage collection mode: %s", s);
 
-                if (mode != UNIT_CHECK) {
+                if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
                         u->collect_mode = m;
-                        unit_write_drop_in_format(u, mode, name, "[Unit]\nCollectMode=%s", collect_mode_to_string(m));
+                        unit_write_settingf(u, flags, name, "CollectMode=%s", collect_mode_to_string(m));
                 }
 
                 return 1;
@@ -1406,12 +1406,12 @@ static int bus_unit_set_transient_property(
                 if (slice->type != UNIT_SLICE)
                         return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Unit name '%s' is not a slice", s);
 
-                if (mode != UNIT_CHECK) {
+                if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
                         r = unit_set_slice(u, slice);
                         if (r < 0)
                                 return r;
 
-                        unit_write_drop_in_private_format(u, mode, name, "Slice=%s", s);
+                        unit_write_settingf(u, flags|UNIT_PRIVATE, name, "Slice=%s", s);
                 }
 
                 return 1;
@@ -1448,7 +1448,7 @@ static int bus_unit_set_transient_property(
                         if (!unit_name_is_valid(other, UNIT_NAME_PLAIN|UNIT_NAME_INSTANCE))
                                 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid unit name %s", other);
 
-                        if (mode != UNIT_CHECK) {
+                        if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
                                 _cleanup_free_ char *label = NULL;
 
                                 r = unit_add_dependency_by_name(u, d, other, NULL, true, UNIT_DEPENDENCY_FILE);
@@ -1459,7 +1459,7 @@ static int bus_unit_set_transient_property(
                                 if (!label)
                                         return -ENOMEM;
 
-                                unit_write_drop_in_format(u, mode, label, "[Unit]\n%s=%s", name, other);
+                                unit_write_settingf(u, flags, label, "%s=%s", name, other);
                         }
 
                 }
@@ -1484,14 +1484,14 @@ static int bus_unit_set_transient_property(
                 if (action < 0)
                         return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid emergency action: %s", s);
 
-                if (mode != UNIT_CHECK) {
+                if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
 
                         if (streq(name, "FailureAction"))
                                 u->failure_action = action;
                         else
                                 u->success_action = action;
 
-                        unit_write_drop_in_format(u, mode, name, "%s=%s", name, emergency_action_to_string(action));
+                        unit_write_settingf(u, flags, name, "%s=%s", name, emergency_action_to_string(action));
                 }
 
                 return 1;
@@ -1514,7 +1514,7 @@ static int bus_unit_set_transient_property(
                 if (r < 0)
                         return r;
 
-                if (mode != UNIT_CHECK)
+                if (!UNIT_WRITE_FLAGS_NOOP(flags))
                         u->bus_track_add = b;
 
                 return 1;
@@ -1526,7 +1526,7 @@ static int bus_unit_set_transient_property(
 int bus_unit_set_properties(
                 Unit *u,
                 sd_bus_message *message,
-                UnitSetPropertiesMode mode,
+                UnitWriteFlags flags,
                 bool commit,
                 sd_bus_error *error) {
 
@@ -1548,12 +1548,13 @@ int bus_unit_set_properties(
 
         for (;;) {
                 const char *name;
+                UnitWriteFlags f;
 
                 r = sd_bus_message_enter_container(message, 'r', "sv");
                 if (r < 0)
                         return r;
                 if (r == 0) {
-                        if (for_real || mode == UNIT_CHECK)
+                        if (for_real || UNIT_WRITE_FLAGS_NOOP(flags))
                                 break;
 
                         /* Reached EOF. Let's try again, and this time for realz... */
@@ -1576,9 +1577,12 @@ int bus_unit_set_properties(
                 if (r < 0)
                         return r;
 
-                r = UNIT_VTABLE(u)->bus_set_property(u, name, message, for_real ? mode : UNIT_CHECK, error);
+                /* If not for real, then mask out the two target flags */
+                f = for_real ? flags : (flags & ~(UNIT_RUNTIME|UNIT_PERSISTENT));
+
+                r = UNIT_VTABLE(u)->bus_set_property(u, name, message, f, error);
                 if (r == 0 && u->transient && u->load_state == UNIT_STUB)
-                        r = bus_unit_set_transient_property(u, name, message, for_real ? mode : UNIT_CHECK, error);
+                        r = bus_unit_set_transient_property(u, name, message, f, error);
                 if (r < 0)
                         return r;
                 if (r == 0)
index b723453f379e3ea84835cdf43d3d48a38efa8531..d7066eefc808b37028ebe0c931826aa1ffa91d31 100644 (file)
@@ -34,7 +34,7 @@ int bus_unit_method_start_generic(sd_bus_message *message, Unit *u, JobType job_
 int bus_unit_method_kill(sd_bus_message *message, void *userdata, sd_bus_error *error);
 int bus_unit_method_reset_failed(sd_bus_message *message, void *userdata, sd_bus_error *error);
 
-int bus_unit_set_properties(Unit *u, sd_bus_message *message, UnitSetPropertiesMode mode, bool commit, sd_bus_error *error);
+int bus_unit_set_properties(Unit *u, sd_bus_message *message, UnitWriteFlags flags, bool commit, sd_bus_error *error);
 int bus_unit_method_set_properties(sd_bus_message *message, void *userdata, sd_bus_error *error);
 int bus_unit_method_get_processes(sd_bus_message *message, void *userdata, sd_bus_error *error);
 int bus_unit_method_ref(sd_bus_message *message, void *userdata, sd_bus_error *error);
index 856939853a87f326e236035a9dd10209f673d15c..90a09ce659ce1fd4a8395d9fea21a19bc527228c 100644 (file)
@@ -55,6 +55,7 @@
 #include "signal-util.h"
 #include "sparse-endian.h"
 #include "special.h"
+#include "specifier.h"
 #include "stat-util.h"
 #include "stdio-util.h"
 #include "string-table.h"
@@ -117,6 +118,8 @@ Unit *unit_new(Manager *m, size_t size) {
         u->ipv4_deny_map_fd = -1;
         u->ipv6_deny_map_fd = -1;
 
+        u->last_section_private = -1;
+
         RATELIMIT_INIT(u->start_limit, m->default_start_limit_interval, m->default_start_limit_burst);
         RATELIMIT_INIT(u->auto_stop_ratelimit, 10 * USEC_PER_SEC, 16);
 
@@ -4120,43 +4123,156 @@ ExecRuntime *unit_get_exec_runtime(Unit *u) {
         return *(ExecRuntime**) ((uint8_t*) u + offset);
 }
 
-static const char* unit_drop_in_dir(Unit *u, UnitSetPropertiesMode mode) {
+static const char* unit_drop_in_dir(Unit *u, UnitWriteFlags flags) {
         assert(u);
 
-        if (!IN_SET(mode, UNIT_RUNTIME, UNIT_PERSISTENT))
+        if (UNIT_WRITE_FLAGS_NOOP(flags))
                 return NULL;
 
         if (u->transient) /* Redirect drop-ins for transient units always into the transient directory. */
                 return u->manager->lookup_paths.transient;
 
-        if (mode == UNIT_RUNTIME)
-                return u->manager->lookup_paths.runtime_control;
-
-        if (mode == UNIT_PERSISTENT)
+        if (flags & UNIT_PERSISTENT)
                 return u->manager->lookup_paths.persistent_control;
 
+        if (flags & UNIT_RUNTIME)
+                return u->manager->lookup_paths.runtime_control;
+
         return NULL;
 }
 
-int unit_write_drop_in(Unit *u, UnitSetPropertiesMode mode, const char *name, const char *data) {
-        _cleanup_free_ char *p = NULL, *q = NULL;
+char* unit_escape_setting(const char *s, UnitWriteFlags flags, char **buf) {
+        char *ret = NULL;
+
+        if (!s)
+                return NULL;
+
+        /* Escapes the input string as requested. Returns the escaped string. If 'buf' is specified then the allocated
+         * return buffer pointer is also written to *buf, except if no escaping was necessary, in which case *buf is
+         * set to NULL, and the input pointer is returned as-is. This means the return value always contains a properly
+         * escaped version, but *buf when passed only contains a pointer if an allocation was necessary. If *buf is
+         * not specified, then the return value always needs to be freed. Callers can use this to optimize memory
+         * allocations. */
+
+        if (flags & UNIT_ESCAPE_SPECIFIERS) {
+                ret = specifier_escape(s);
+                if (!ret)
+                        return NULL;
+
+                s = ret;
+        }
+
+        if (flags & UNIT_ESCAPE_C) {
+                char *a;
+
+                a = cescape(s);
+                free(ret);
+                if (!a)
+                        return NULL;
+
+                ret = a;
+        }
+
+        if (buf) {
+                *buf = ret;
+                return ret ?: (char*) s;
+        }
+
+        return ret ?: strdup(s);
+}
+
+char* unit_concat_strv(char **l, UnitWriteFlags flags) {
+        _cleanup_free_ char *result = NULL;
+        size_t n = 0, allocated = 0;
+        char **i, *ret;
+
+        /* Takes a list of strings, escapes them, and concatenates them. This may be used to format command lines in a
+         * way suitable for ExecStart= stanzas */
+
+        STRV_FOREACH(i, l) {
+                _cleanup_free_ char *buf = NULL;
+                const char *p;
+                size_t a;
+                char *q;
+
+                p = unit_escape_setting(*i, flags, &buf);
+                if (!p)
+                        return NULL;
+
+                a = (n > 0) + 1 + strlen(p) + 1; /* separating space + " + entry + " */
+                if (!GREEDY_REALLOC(result, allocated, n + a + 1))
+                        return NULL;
+
+                q = result + n;
+                if (n > 0)
+                        *(q++) = ' ';
+
+                *(q++) = '"';
+                q = stpcpy(q, p);
+                *(q++) = '"';
+
+                n += a;
+        }
+
+        if (!GREEDY_REALLOC(result, allocated, n + 1))
+                return NULL;
+
+        result[n] = 0;
+
+        ret = result;
+        result = NULL;
+
+        return ret;
+}
+
+int unit_write_setting(Unit *u, UnitWriteFlags flags, const char *name, const char *data) {
+        _cleanup_free_ char *p = NULL, *q = NULL, *escaped = NULL;
         const char *dir, *wrapped;
         int r;
 
         assert(u);
+        assert(name);
+        assert(data);
+
+        if (UNIT_WRITE_FLAGS_NOOP(flags))
+                return 0;
+
+        data = unit_escape_setting(data, flags, &escaped);
+        if (!data)
+                return -ENOMEM;
+
+        /* Prefix the section header. If we are writing this out as transient file, then let's suppress this if the
+         * previous section header is the same */
+
+        if (flags & UNIT_PRIVATE) {
+                if (!UNIT_VTABLE(u)->private_section)
+                        return -EINVAL;
+
+                if (!u->transient_file || u->last_section_private < 0)
+                        data = strjoina("[", UNIT_VTABLE(u)->private_section, "]\n", data);
+                else if (u->last_section_private == 0)
+                        data = strjoina("\n[", UNIT_VTABLE(u)->private_section, "]\n", data);
+        } else {
+                if (!u->transient_file || u->last_section_private < 0)
+                        data = strjoina("[Unit]\n", data);
+                else if (u->last_section_private > 0)
+                        data = strjoina("\n[Unit]\n", data);
+        }
 
         if (u->transient_file) {
                 /* When this is a transient unit file in creation, then let's not create a new drop-in but instead
                  * write to the transient unit file. */
                 fputs(data, u->transient_file);
-                fputc('\n', u->transient_file);
-                return 0;
-        }
 
-        if (!IN_SET(mode, UNIT_PERSISTENT, UNIT_RUNTIME))
+                if (!endswith(data, "\n"))
+                        fputc('\n', u->transient_file);
+
+                /* Remember which section we wrote this entry to */
+                u->last_section_private = !!(flags & UNIT_PRIVATE);
                 return 0;
+        }
 
-        dir = unit_drop_in_dir(u, mode);
+        dir = unit_drop_in_dir(u, flags);
         if (!dir)
                 return -EINVAL;
 
@@ -4186,47 +4302,7 @@ int unit_write_drop_in(Unit *u, UnitSetPropertiesMode mode, const char *name, co
         return 0;
 }
 
-int unit_write_drop_in_format(Unit *u, UnitSetPropertiesMode mode, const char *name, const char *format, ...) {
-        _cleanup_free_ char *p = NULL;
-        va_list ap;
-        int r;
-
-        assert(u);
-        assert(name);
-        assert(format);
-
-        if (!IN_SET(mode, UNIT_PERSISTENT, UNIT_RUNTIME))
-                return 0;
-
-        va_start(ap, format);
-        r = vasprintf(&p, format, ap);
-        va_end(ap);
-
-        if (r < 0)
-                return -ENOMEM;
-
-        return unit_write_drop_in(u, mode, name, p);
-}
-
-int unit_write_drop_in_private(Unit *u, UnitSetPropertiesMode mode, const char *name, const char *data) {
-        const char *ndata;
-
-        assert(u);
-        assert(name);
-        assert(data);
-
-        if (!UNIT_VTABLE(u)->private_section)
-                return -EINVAL;
-
-        if (!IN_SET(mode, UNIT_PERSISTENT, UNIT_RUNTIME))
-                return 0;
-
-        ndata = strjoina("[", UNIT_VTABLE(u)->private_section, "]\n", data);
-
-        return unit_write_drop_in(u, mode, name, ndata);
-}
-
-int unit_write_drop_in_private_format(Unit *u, UnitSetPropertiesMode mode, const char *name, const char *format, ...) {
+int unit_write_settingf(Unit *u, UnitWriteFlags flags, const char *name, const char *format, ...) {
         _cleanup_free_ char *p = NULL;
         va_list ap;
         int r;
@@ -4235,7 +4311,7 @@ int unit_write_drop_in_private_format(Unit *u, UnitSetPropertiesMode mode, const
         assert(name);
         assert(format);
 
-        if (!IN_SET(mode, UNIT_PERSISTENT, UNIT_RUNTIME))
+        if (UNIT_WRITE_FLAGS_NOOP(flags))
                 return 0;
 
         va_start(ap, format);
@@ -4245,7 +4321,7 @@ int unit_write_drop_in_private_format(Unit *u, UnitSetPropertiesMode mode, const
         if (r < 0)
                 return -ENOMEM;
 
-        return unit_write_drop_in_private(u, mode, name, p);
+        return unit_write_setting(u, flags, name, p);
 }
 
 int unit_make_transient(Unit *u) {
index cd7c08a20d83beb3ee17d71276b8edc22bf1b384..92bb4779a9735a5c24ed7a9720bb182d78036900 100644 (file)
@@ -360,6 +360,10 @@ struct Unit {
         bool exported_invocation_id:1;
         bool exported_log_level_max:1;
         bool exported_log_extra_fields:1;
+
+        /* When writing transient unit files, stores which section we stored last. If < 0, we didn't write any yet. If
+         * == 0 we are in the [Unit] section, if > 0 we are in the unit type-specific section. */
+        int last_section_private:2;
 };
 
 struct UnitStatusMessageFormats {
@@ -368,11 +372,26 @@ struct UnitStatusMessageFormats {
         const char *finished_stop_job[_JOB_RESULT_MAX];
 };
 
-typedef enum UnitSetPropertiesMode {
-        UNIT_CHECK = 0,
-        UNIT_RUNTIME = 1,
-        UNIT_PERSISTENT = 2,
-} UnitSetPropertiesMode;
+/* Flags used when writing drop-in files or transient unit files */
+typedef enum UnitWriteFlags {
+        /* Write a runtime unit file or drop-in (i.e. one below /run) */
+        UNIT_RUNTIME           = 1 << 0,
+
+        /* Write a persistent drop-in (i.e. one below /etc) */
+        UNIT_PERSISTENT        = 1 << 1,
+
+        /* Place this item in the per-unit-type private section, instead of [Unit] */
+        UNIT_PRIVATE           = 1 << 2,
+
+        /* Apply specifier escaping before writing */
+        UNIT_ESCAPE_SPECIFIERS = 1 << 3,
+
+        /* Apply C escaping before writing */
+        UNIT_ESCAPE_C          = 1 << 4,
+} UnitWriteFlags;
+
+/* Returns true if neither persistent, nor runtime storage is requested, i.e. this is a check invocation only */
+#define UNIT_WRITE_FLAGS_NOOP(flags) (((flags) & (UNIT_RUNTIME|UNIT_PERSISTENT)) == 0)
 
 #include "automount.h"
 #include "device.h"
@@ -490,7 +509,7 @@ struct UnitVTable {
         void (*bus_name_owner_change)(Unit *u, const char *name, const char *old_owner, const char *new_owner);
 
         /* Called for each property that is being set */
-        int (*bus_set_property)(Unit *u, const char *name, sd_bus_message *message, UnitSetPropertiesMode mode, sd_bus_error *error);
+        int (*bus_set_property)(Unit *u, const char *name, sd_bus_message *message, UnitWriteFlags flags, sd_bus_error *error);
 
         /* Called after at least one property got changed to apply the necessary change */
         int (*bus_commit_properties)(Unit *u);
@@ -713,11 +732,11 @@ ExecRuntime *unit_get_exec_runtime(Unit *u) _pure_;
 int unit_setup_exec_runtime(Unit *u);
 int unit_setup_dynamic_creds(Unit *u);
 
-int unit_write_drop_in(Unit *u, UnitSetPropertiesMode mode, const char *name, const char *data);
-int unit_write_drop_in_format(Unit *u, UnitSetPropertiesMode mode, const char *name, const char *format, ...) _printf_(4,5);
+char* unit_escape_setting(const char *s, UnitWriteFlags flags, char **buf);
+char* unit_concat_strv(char **l, UnitWriteFlags flags);
 
-int unit_write_drop_in_private(Unit *u, UnitSetPropertiesMode mode, const char *name, const char *data);
-int unit_write_drop_in_private_format(Unit *u, UnitSetPropertiesMode mode, const char *name, const char *format, ...) _printf_(4,5);
+int unit_write_setting(Unit *u, UnitWriteFlags flags, const char *name, const char *data);
+int unit_write_settingf(Unit *u, UnitWriteFlags mode, const char *name, const char *format, ...) _printf_(4,5);
 
 int unit_kill_context(Unit *u, KillContext *c, KillOperation k, pid_t main_pid, pid_t control_pid, bool main_pid_alien);