+ if (dbus_message_iter_get_arg_type(i) != DBUS_TYPE_STRING)
+ return -EINVAL;
+
+ dbus_message_iter_get_basic(i, &s);
+
+ if (isempty(s)) {
+ if (mode != UNIT_CHECK)
+ unit_ref_unset(&u->slice);
+ } else {
+ _cleanup_free_ char *contents = NULL;
+
+ r = manager_load_unit(u->manager, s, NULL, error, &slice);
+ if (r < 0)
+ return r;
+
+ if (slice->type != UNIT_SLICE)
+ return -EINVAL;
+
+ if (mode != UNIT_CHECK)
+ unit_ref_set(&u->slice, slice);
+
+ contents = strjoin("[", UNIT_VTABLE(u)->private_section, "]\nSlice=", s, NULL);
+ if (!contents)
+ return -ENOMEM;
+
+ unit_write_drop_in(u, mode, "Slice", contents);
+ }
+ return 1;
+
+ } else if (streq(name, "Requires") ||
+ streq(name, "RequiresOverridable") ||
+ streq(name, "Requisite") ||
+ streq(name, "RequisiteOverridable") ||
+ streq(name, "Wants") ||
+ streq(name, "BindsTo") ||
+ streq(name, "Conflicts") ||
+ streq(name, "Before") ||
+ streq(name, "After") ||
+ streq(name, "OnFailure") ||
+ streq(name, "PropagatesReloadTo") ||
+ streq(name, "ReloadPropagatedFrom") ||
+ streq(name, "PartOf")) {
+
+ UnitDependency d;
+ DBusMessageIter sub;
+
+ d = unit_dependency_from_string(name);
+ if (d < 0)
+ return -EINVAL;
+
+ if (dbus_message_iter_get_arg_type(i) != DBUS_TYPE_ARRAY ||
+ dbus_message_iter_get_element_type(i) != DBUS_TYPE_STRING)
+ return -EINVAL;
+
+ dbus_message_iter_recurse(i, &sub);
+ while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRING) {
+ const char *other;
+
+ dbus_message_iter_get_basic(&sub, &other);
+
+ if (!unit_name_is_valid(other, false))
+ return -EINVAL;
+
+ if (mode != UNIT_CHECK) {
+ _cleanup_free_ char *label = NULL, *contents = NULL;
+
+ r = unit_add_dependency_by_name(u, d, other, NULL, true);
+ if (r < 0)
+ return r;
+
+ label = strjoin(name, "-", other, NULL);
+ if (!label)
+ return -ENOMEM;
+
+ contents = strjoin("[Unit]\n", name, "=", other, "\n", NULL);
+ if (!contents)
+ return -ENOMEM;
+
+ unit_write_drop_in(u, mode, label, contents);
+ }
+
+ dbus_message_iter_next(&sub);
+ }
+
+ return 1;
+ }
+
+ return 0;
+}
+
+int bus_unit_set_properties(
+ Unit *u,
+ DBusMessageIter *iter,
+ UnitSetPropertiesMode mode,
+ bool commit,
+ DBusError *error) {
+
+ bool for_real = false;
+ DBusMessageIter sub;
+ unsigned n = 0;
+ int r;
+
+ assert(u);
+ assert(iter);
+
+ if (u->transient)
+ mode &= UNIT_RUNTIME;
+
+ /* We iterate through the array twice. First run we just check
+ * if all passed data is valid, second run actually applies
+ * it. This is to implement transaction-like behaviour without
+ * actually providing full transactions. */
+
+ if (dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_ARRAY ||
+ dbus_message_iter_get_element_type(iter) != DBUS_TYPE_STRUCT)
+ return -EINVAL;
+
+ dbus_message_iter_recurse(iter, &sub);
+ for (;;) {
+ DBusMessageIter sub2, sub3;
+ const char *name;
+
+ if (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_INVALID) {
+
+ if (for_real)
+ break;
+
+ /* Reached EOF. Let's try again, and this time for realz... */
+ dbus_message_iter_recurse(iter, &sub);
+ for_real = true;
+ continue;
+ }
+
+ if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRUCT)
+ return -EINVAL;
+
+ dbus_message_iter_recurse(&sub, &sub2);
+
+ if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &name, true) < 0 ||
+ dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_VARIANT)
+ return -EINVAL;
+
+ if (!UNIT_VTABLE(u)->bus_set_property) {
+ dbus_set_error(error, DBUS_ERROR_PROPERTY_READ_ONLY, "Objects of this type do not support setting properties.");
+ return -ENOENT;
+ }
+
+ dbus_message_iter_recurse(&sub2, &sub3);
+ r = UNIT_VTABLE(u)->bus_set_property(u, name, &sub3, for_real ? mode : UNIT_CHECK, error);
+ if (r == 0 && u->transient && u->load_state == UNIT_STUB)
+ r = bus_unit_set_transient_property(u, name, &sub3, for_real ? mode : UNIT_CHECK, error);
+ if (r < 0)
+ return r;
+ if (r == 0) {
+ dbus_set_error(error, DBUS_ERROR_PROPERTY_READ_ONLY, "Cannot set property %s, or unknown property.", name);
+ return -ENOENT;
+ }
+
+ dbus_message_iter_next(&sub);
+
+ n += for_real;
+ }
+
+ if (commit && n > 0 && UNIT_VTABLE(u)->bus_commit_properties)
+ UNIT_VTABLE(u)->bus_commit_properties(u);
+
+ return n;