return 0;
}
+static int bus_property_append_condition(DBusMessageIter *i, const char *property, void *data) {
+ Condition **cp = data;
+ Condition *c;
+ const char *name, *param;
+ dbus_bool_t trigger, negate;
+ dbus_int32_t state;
+ DBusMessageIter sub;
+
+ assert(i);
+ assert(property);
+ assert(cp);
+
+ c = *cp;
+ assert(c);
+
+ name = condition_type_to_string(c->type);
+ param = c->parameter;
+ trigger = c->trigger;
+ negate = c->negate;
+ state = c->state;
+
+ if (!dbus_message_iter_open_container(i, DBUS_TYPE_STRUCT, NULL, &sub) ||
+ !dbus_message_iter_append_basic(&sub, DBUS_TYPE_STRING, &name) ||
+ !dbus_message_iter_append_basic(&sub, DBUS_TYPE_BOOLEAN, &trigger) ||
+ !dbus_message_iter_append_basic(&sub, DBUS_TYPE_BOOLEAN, &negate) ||
+ !dbus_message_iter_append_basic(&sub, DBUS_TYPE_STRING, ¶m) ||
+ !dbus_message_iter_append_basic(&sub, DBUS_TYPE_INT32, &state) ||
+ !dbus_message_iter_close_container(i, &sub))
+ return -ENOMEM;
+
+ return 0;
+}
+
+static int bus_property_append_condition_list(DBusMessageIter *i, const char *property, void *data) {
+ Condition **first = data, *c;
+ DBusMessageIter sub;
+
+ assert(i);
+ assert(data);
+
+ if (!dbus_message_iter_open_container(i, DBUS_TYPE_ARRAY, "(sbbsi)", &sub))
+ return -ENOMEM;
+
+ LIST_FOREACH(conditions, c, *first)
+ bus_property_append_condition(&sub, property, &c);
+
+ if (!dbus_message_iter_close_container(i, &sub))
+ return -ENOMEM;
+
+ return 0;
+}
+
static int bus_unit_append_load_error(DBusMessageIter *i, const char *property, void *data) {
Unit *u = data;
const char *name, *message;
};
void bus_unit_send_change_signal(Unit *u) {
- _cleanup_free_ char *p = NULL;
_cleanup_dbus_message_unref_ DBusMessage *m = NULL;
+ _cleanup_free_ char *p = NULL;
+ int r;
assert(u);
}
p = unit_dbus_path(u);
- if (!p)
- goto oom;
+ if (!p) {
+ log_oom();
+ return;
+ }
if (u->sent_dbus_new_signal) {
/* Send a properties changed signal. First for the
m = bus_properties_changed_new(p,
UNIT_VTABLE(u)->bus_interface,
UNIT_VTABLE(u)->bus_invalidating_properties);
- if (!m)
- goto oom;
+ if (!m) {
+ log_oom();
+ return;
+ }
- if (bus_broadcast(u->manager, m) < 0)
- goto oom;
+ r = bus_broadcast(u->manager, m);
+ if (r < 0) {
+ log_error("Failed to broadcast change message: %s", strerror(-r));
+ return;
+ }
dbus_message_unref(m);
}
m = bus_properties_changed_new(p, "org.freedesktop.systemd1.Unit",
INVALIDATING_PROPERTIES);
- if (!m)
- goto oom;
+ if (!m) {
+ log_oom();
+ return;
+ }
} else {
/* Send a new signal */
m = dbus_message_new_signal("/org/freedesktop/systemd1",
"org.freedesktop.systemd1.Manager",
"UnitNew");
- if (!m)
- goto oom;
+ if (!m) {
+ log_oom();
+ return;
+ }
if (!dbus_message_append_args(m,
DBUS_TYPE_STRING, &u->id,
DBUS_TYPE_OBJECT_PATH, &p,
- DBUS_TYPE_INVALID))
- goto oom;
+ DBUS_TYPE_INVALID)) {
+ log_oom();
+ return;
+ }
}
- if (bus_broadcast(u->manager, m) < 0)
- goto oom;
+ r = bus_broadcast(u->manager, m);
+ if (r < 0) {
+ log_error("Failed to broadcast UnitNew/PropertiesChanged message.");
+ return;
+ }
u->sent_dbus_new_signal = true;
-
- return;
-
-oom:
- log_oom();
}
void bus_unit_send_removed_signal(Unit *u) {
assert(i);
if (streq(name, "Description")) {
- const char *description;
-
if (dbus_message_iter_get_arg_type(i) != DBUS_TYPE_STRING)
return -EINVAL;
- dbus_message_iter_get_basic(i, &description);
+ if (mode != UNIT_CHECK) {
+ const char *description;
- r = unit_set_description(u, description);
- if (r < 0)
- return r;
+ dbus_message_iter_get_basic(i, &description);
+
+ r = unit_set_description(u, description);
+ if (r < 0)
+ return r;
+
+ unit_write_drop_in_format(u, mode, name, "[Unit]\nDescription=%s\n", description);
+ }
return 1;
} else if (streq(name, "Slice") && unit_get_cgroup_context(u)) {
const char *s;
- Unit *slice;
if (dbus_message_iter_get_arg_type(i) != DBUS_TYPE_STRING)
return -EINVAL;
dbus_message_iter_get_basic(i, &s);
- r = manager_load_unit(u->manager, s, NULL, error, &slice);
- if (r < 0)
- return r;
+ if (isempty(s)) {
+ if (mode != UNIT_CHECK) {
+ unit_ref_unset(&u->slice);
+ unit_remove_drop_in(u, mode, name);
+ }
+ } else {
+ Unit *slice;
+
+ 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);
+ unit_write_drop_in_private_format(u, mode, name, "Slice=%s\n", s);
+ }
+ }
+
+ 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 (slice->type != UNIT_SLICE)
+ if (dbus_message_iter_get_arg_type(i) != DBUS_TYPE_ARRAY ||
+ dbus_message_iter_get_element_type(i) != DBUS_TYPE_STRING)
return -EINVAL;
- unit_ref_set(&u->slice, slice);
+ 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;
+
+ 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;
+
+ unit_write_drop_in_format(u, mode, label, "[Unit]\n%s=%s\n", name, other);
+ }
+
+ dbus_message_iter_next(&sub);
+ }
+
return 1;
}
if (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_INVALID) {
- if (for_real)
+ if (for_real || mode == UNIT_CHECK)
break;
/* Reached EOF. Let's try again, and this time for realz... */
}
const BusProperty bus_unit_properties[] = {
- { "Id", bus_property_append_string, "s", offsetof(Unit, id), true },
- { "Names", bus_unit_append_names, "as", 0 },
- { "Following", bus_unit_append_following, "s", 0 },
- { "Requires", bus_unit_append_dependencies, "as", offsetof(Unit, dependencies[UNIT_REQUIRES]), true },
- { "RequiresOverridable", bus_unit_append_dependencies, "as", offsetof(Unit, dependencies[UNIT_REQUIRES_OVERRIDABLE]), true },
- { "Requisite", bus_unit_append_dependencies, "as", offsetof(Unit, dependencies[UNIT_REQUISITE]), true },
- { "RequisiteOverridable", bus_unit_append_dependencies, "as", offsetof(Unit, dependencies[UNIT_REQUISITE_OVERRIDABLE]), true },
- { "Wants", bus_unit_append_dependencies, "as", offsetof(Unit, dependencies[UNIT_WANTS]), true },
- { "BindsTo", bus_unit_append_dependencies, "as", offsetof(Unit, dependencies[UNIT_BINDS_TO]), true },
- { "PartOf", bus_unit_append_dependencies, "as", offsetof(Unit, dependencies[UNIT_PART_OF]), true },
- { "RequiredBy", bus_unit_append_dependencies, "as", offsetof(Unit, dependencies[UNIT_REQUIRED_BY]), true },
- { "RequiredByOverridable",bus_unit_append_dependencies, "as", offsetof(Unit, dependencies[UNIT_REQUIRED_BY_OVERRIDABLE]), true },
- { "WantedBy", bus_unit_append_dependencies, "as", offsetof(Unit, dependencies[UNIT_WANTED_BY]), true },
- { "BoundBy", bus_unit_append_dependencies, "as", offsetof(Unit, dependencies[UNIT_BOUND_BY]), true },
- { "ConsistsOf", bus_unit_append_dependencies, "as", offsetof(Unit, dependencies[UNIT_CONSISTS_OF]), true },
- { "Conflicts", bus_unit_append_dependencies, "as", offsetof(Unit, dependencies[UNIT_CONFLICTS]), true },
- { "ConflictedBy", bus_unit_append_dependencies, "as", offsetof(Unit, dependencies[UNIT_CONFLICTED_BY]), true },
- { "Before", bus_unit_append_dependencies, "as", offsetof(Unit, dependencies[UNIT_BEFORE]), true },
- { "After", bus_unit_append_dependencies, "as", offsetof(Unit, dependencies[UNIT_AFTER]), true },
- { "OnFailure", bus_unit_append_dependencies, "as", offsetof(Unit, dependencies[UNIT_ON_FAILURE]), true },
- { "Triggers", bus_unit_append_dependencies, "as", offsetof(Unit, dependencies[UNIT_TRIGGERS]), true },
- { "TriggeredBy", bus_unit_append_dependencies, "as", offsetof(Unit, dependencies[UNIT_TRIGGERED_BY]), true },
- { "PropagatesReloadTo", bus_unit_append_dependencies, "as", offsetof(Unit, dependencies[UNIT_PROPAGATES_RELOAD_TO]), true },
- { "ReloadPropagatedFrom", bus_unit_append_dependencies, "as", offsetof(Unit, dependencies[UNIT_RELOAD_PROPAGATED_FROM]), true },
- { "RequiresMountsFor", bus_property_append_strv, "as", offsetof(Unit, requires_mounts_for), true },
- { "Documentation", bus_property_append_strv, "as", offsetof(Unit, documentation), true },
- { "Description", bus_unit_append_description, "s", 0 },
- { "LoadState", bus_unit_append_load_state, "s", offsetof(Unit, load_state) },
- { "ActiveState", bus_unit_append_active_state, "s", 0 },
- { "SubState", bus_unit_append_sub_state, "s", 0 },
- { "FragmentPath", bus_property_append_string, "s", offsetof(Unit, fragment_path), true },
- { "SourcePath", bus_property_append_string, "s", offsetof(Unit, source_path), true },
- { "DropInPaths", bus_property_append_strv, "as", offsetof(Unit, dropin_paths), true },
- { "UnitFileState", bus_unit_append_file_state, "s", 0 },
- { "InactiveExitTimestamp",bus_property_append_usec, "t", offsetof(Unit, inactive_exit_timestamp.realtime) },
- { "InactiveExitTimestampMonotonic", bus_property_append_usec, "t", offsetof(Unit, inactive_exit_timestamp.monotonic) },
- { "ActiveEnterTimestamp", bus_property_append_usec, "t", offsetof(Unit, active_enter_timestamp.realtime) },
- { "ActiveEnterTimestampMonotonic", bus_property_append_usec, "t", offsetof(Unit, active_enter_timestamp.monotonic) },
- { "ActiveExitTimestamp", bus_property_append_usec, "t", offsetof(Unit, active_exit_timestamp.realtime) },
- { "ActiveExitTimestampMonotonic", bus_property_append_usec, "t", offsetof(Unit, active_exit_timestamp.monotonic) },
- { "InactiveEnterTimestamp", bus_property_append_usec, "t", offsetof(Unit, inactive_enter_timestamp.realtime) },
- { "InactiveEnterTimestampMonotonic",bus_property_append_usec, "t", offsetof(Unit, inactive_enter_timestamp.monotonic) },
- { "CanStart", bus_unit_append_can_start, "b", 0 },
- { "CanStop", bus_unit_append_can_stop, "b", 0 },
- { "CanReload", bus_unit_append_can_reload, "b", 0 },
- { "CanIsolate", bus_unit_append_can_isolate, "b", 0 },
- { "Job", bus_unit_append_job, "(uo)", 0 },
- { "StopWhenUnneeded", bus_property_append_bool, "b", offsetof(Unit, stop_when_unneeded) },
- { "RefuseManualStart", bus_property_append_bool, "b", offsetof(Unit, refuse_manual_start) },
- { "RefuseManualStop", bus_property_append_bool, "b", offsetof(Unit, refuse_manual_stop) },
- { "AllowIsolate", bus_property_append_bool, "b", offsetof(Unit, allow_isolate) },
- { "DefaultDependencies", bus_property_append_bool, "b", offsetof(Unit, default_dependencies) },
- { "OnFailureIsolate", bus_property_append_bool, "b", offsetof(Unit, on_failure_isolate) },
- { "IgnoreOnIsolate", bus_property_append_bool, "b", offsetof(Unit, ignore_on_isolate) },
- { "IgnoreOnSnapshot", bus_property_append_bool, "b", offsetof(Unit, ignore_on_snapshot) },
- { "NeedDaemonReload", bus_unit_append_need_daemon_reload, "b", 0 },
- { "JobTimeoutUSec", bus_property_append_usec, "t", offsetof(Unit, job_timeout) },
- { "ConditionTimestamp", bus_property_append_usec, "t", offsetof(Unit, condition_timestamp.realtime) },
- { "ConditionTimestampMonotonic", bus_property_append_usec, "t", offsetof(Unit, condition_timestamp.monotonic) },
- { "ConditionResult", bus_property_append_bool, "b", offsetof(Unit, condition_result) },
- { "LoadError", bus_unit_append_load_error, "(ss)", 0 },
- { "Transient", bus_property_append_bool, "b", offsetof(Unit, transient) },
- { NULL, }
+ { "Id", bus_property_append_string, "s", offsetof(Unit, id), true },
+ { "Names", bus_unit_append_names, "as", 0 },
+ { "Following", bus_unit_append_following, "s", 0 },
+ { "Requires", bus_unit_append_dependencies, "as", offsetof(Unit, dependencies[UNIT_REQUIRES]), true },
+ { "RequiresOverridable", bus_unit_append_dependencies, "as", offsetof(Unit, dependencies[UNIT_REQUIRES_OVERRIDABLE]), true },
+ { "Requisite", bus_unit_append_dependencies, "as", offsetof(Unit, dependencies[UNIT_REQUISITE]), true },
+ { "RequisiteOverridable", bus_unit_append_dependencies, "as", offsetof(Unit, dependencies[UNIT_REQUISITE_OVERRIDABLE]), true },
+ { "Wants", bus_unit_append_dependencies, "as", offsetof(Unit, dependencies[UNIT_WANTS]), true },
+ { "BindsTo", bus_unit_append_dependencies, "as", offsetof(Unit, dependencies[UNIT_BINDS_TO]), true },
+ { "PartOf", bus_unit_append_dependencies, "as", offsetof(Unit, dependencies[UNIT_PART_OF]), true },
+ { "RequiredBy", bus_unit_append_dependencies, "as", offsetof(Unit, dependencies[UNIT_REQUIRED_BY]), true },
+ { "RequiredByOverridable", bus_unit_append_dependencies, "as", offsetof(Unit, dependencies[UNIT_REQUIRED_BY_OVERRIDABLE]), true },
+ { "WantedBy", bus_unit_append_dependencies, "as", offsetof(Unit, dependencies[UNIT_WANTED_BY]), true },
+ { "BoundBy", bus_unit_append_dependencies, "as", offsetof(Unit, dependencies[UNIT_BOUND_BY]), true },
+ { "ConsistsOf", bus_unit_append_dependencies, "as", offsetof(Unit, dependencies[UNIT_CONSISTS_OF]), true },
+ { "Conflicts", bus_unit_append_dependencies, "as", offsetof(Unit, dependencies[UNIT_CONFLICTS]), true },
+ { "ConflictedBy", bus_unit_append_dependencies, "as", offsetof(Unit, dependencies[UNIT_CONFLICTED_BY]), true },
+ { "Before", bus_unit_append_dependencies, "as", offsetof(Unit, dependencies[UNIT_BEFORE]), true },
+ { "After", bus_unit_append_dependencies, "as", offsetof(Unit, dependencies[UNIT_AFTER]), true },
+ { "OnFailure", bus_unit_append_dependencies, "as", offsetof(Unit, dependencies[UNIT_ON_FAILURE]), true },
+ { "Triggers", bus_unit_append_dependencies, "as", offsetof(Unit, dependencies[UNIT_TRIGGERS]), true },
+ { "TriggeredBy", bus_unit_append_dependencies, "as", offsetof(Unit, dependencies[UNIT_TRIGGERED_BY]), true },
+ { "PropagatesReloadTo", bus_unit_append_dependencies, "as", offsetof(Unit, dependencies[UNIT_PROPAGATES_RELOAD_TO]), true },
+ { "ReloadPropagatedFrom", bus_unit_append_dependencies, "as", offsetof(Unit, dependencies[UNIT_RELOAD_PROPAGATED_FROM]), true },
+ { "RequiresMountsFor", bus_property_append_strv, "as", offsetof(Unit, requires_mounts_for), true },
+ { "Documentation", bus_property_append_strv, "as", offsetof(Unit, documentation), true },
+ { "Description", bus_unit_append_description, "s", 0 },
+ { "LoadState", bus_unit_append_load_state, "s", offsetof(Unit, load_state) },
+ { "ActiveState", bus_unit_append_active_state, "s", 0 },
+ { "SubState", bus_unit_append_sub_state, "s", 0 },
+ { "FragmentPath", bus_property_append_string, "s", offsetof(Unit, fragment_path), true },
+ { "SourcePath", bus_property_append_string, "s", offsetof(Unit, source_path), true },
+ { "DropInPaths", bus_property_append_strv, "as", offsetof(Unit, dropin_paths), true },
+ { "UnitFileState", bus_unit_append_file_state, "s", 0 },
+ { "InactiveExitTimestamp", bus_property_append_usec, "t", offsetof(Unit, inactive_exit_timestamp.realtime) },
+ { "InactiveExitTimestampMonotonic", bus_property_append_usec, "t", offsetof(Unit, inactive_exit_timestamp.monotonic) },
+ { "ActiveEnterTimestamp", bus_property_append_usec, "t", offsetof(Unit, active_enter_timestamp.realtime) },
+ { "ActiveEnterTimestampMonotonic", bus_property_append_usec, "t", offsetof(Unit, active_enter_timestamp.monotonic) },
+ { "ActiveExitTimestamp", bus_property_append_usec, "t", offsetof(Unit, active_exit_timestamp.realtime) },
+ { "ActiveExitTimestampMonotonic", bus_property_append_usec, "t", offsetof(Unit, active_exit_timestamp.monotonic) },
+ { "InactiveEnterTimestamp", bus_property_append_usec, "t", offsetof(Unit, inactive_enter_timestamp.realtime) },
+ { "InactiveEnterTimestampMonotonic", bus_property_append_usec, "t", offsetof(Unit, inactive_enter_timestamp.monotonic) },
+ { "CanStart", bus_unit_append_can_start, "b", 0 },
+ { "CanStop", bus_unit_append_can_stop, "b", 0 },
+ { "CanReload", bus_unit_append_can_reload, "b", 0 },
+ { "CanIsolate", bus_unit_append_can_isolate, "b", 0 },
+ { "Job", bus_unit_append_job, "(uo)", 0 },
+ { "StopWhenUnneeded", bus_property_append_bool, "b", offsetof(Unit, stop_when_unneeded) },
+ { "RefuseManualStart", bus_property_append_bool, "b", offsetof(Unit, refuse_manual_start) },
+ { "RefuseManualStop", bus_property_append_bool, "b", offsetof(Unit, refuse_manual_stop) },
+ { "AllowIsolate", bus_property_append_bool, "b", offsetof(Unit, allow_isolate) },
+ { "DefaultDependencies", bus_property_append_bool, "b", offsetof(Unit, default_dependencies) },
+ { "OnFailureIsolate", bus_property_append_bool, "b", offsetof(Unit, on_failure_isolate) },
+ { "IgnoreOnIsolate", bus_property_append_bool, "b", offsetof(Unit, ignore_on_isolate) },
+ { "IgnoreOnSnapshot", bus_property_append_bool, "b", offsetof(Unit, ignore_on_snapshot) },
+ { "NeedDaemonReload", bus_unit_append_need_daemon_reload, "b", 0 },
+ { "JobTimeoutUSec", bus_property_append_usec, "t", offsetof(Unit, job_timeout) },
+ { "ConditionTimestamp", bus_property_append_usec, "t", offsetof(Unit, condition_timestamp.realtime) },
+ { "ConditionTimestampMonotonic", bus_property_append_usec, "t", offsetof(Unit, condition_timestamp.monotonic) },
+ { "ConditionResult", bus_property_append_bool, "b", offsetof(Unit, condition_result) },
+ { "Conditions", bus_property_append_condition_list, "a(sbbsi)", offsetof(Unit, conditions) },
+ { "LoadError", bus_unit_append_load_error, "(ss)", 0 },
+ { "Transient", bus_property_append_bool, "b", offsetof(Unit, transient) },
+ {}
};
const BusProperty bus_unit_cgroup_properties[] = {
{ "Slice", bus_unit_append_slice, "s", 0 },
{ "ControlGroup", bus_property_append_string, "s", offsetof(Unit, cgroup_path), true },
+ {}
};