X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?p=elogind.git;a=blobdiff_plain;f=src%2Fdbus-unit.c;h=c7532c72552b4deae843c28229e6b35a05e8c625;hp=66b7ae829757edc24800d9e04d7ddbd9f077f8d6;hb=e2110e5d1bf36b995efa62a9a05db5636ed05d46;hpb=45fb0699c45d2e042e04a53e3ea00501e3f65f59 diff --git a/src/dbus-unit.c b/src/dbus-unit.c index 66b7ae829..c7532c725 100644 --- a/src/dbus-unit.c +++ b/src/dbus-unit.c @@ -1,4 +1,4 @@ -/*-*- Mode: C; c-basic-offset: 8 -*-*/ +/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/ /*** This file is part of systemd. @@ -25,10 +25,22 @@ #include "log.h" #include "dbus-unit.h" #include "bus-errors.h" - -const char bus_unit_interface[] = BUS_UNIT_INTERFACE; - -int bus_unit_append_names(Manager *m, DBusMessageIter *i, const char *property, void *data) { +#include "dbus-common.h" + +const char bus_unit_interface[] _introspect_("Unit") = BUS_UNIT_INTERFACE; + +#define INVALIDATING_PROPERTIES \ + "LoadState\0" \ + "ActiveState\0" \ + "SubState\0" \ + "InactiveExitTimestamp\0" \ + "ActiveEnterTimestamp\0" \ + "ActiveExitTimestamp\0" \ + "InactiveEnterTimestamp\0" \ + "Job\0" \ + "NeedDaemonReload\0" + +static int bus_unit_append_names(DBusMessageIter *i, const char *property, void *data) { char *t; Iterator j; DBusMessageIter sub; @@ -37,7 +49,7 @@ int bus_unit_append_names(Manager *m, DBusMessageIter *i, const char *property, if (!dbus_message_iter_open_container(i, DBUS_TYPE_ARRAY, "s", &sub)) return -ENOMEM; - SET_FOREACH(t, u->meta.names, j) + SET_FOREACH(t, u->names, j) if (!dbus_message_iter_append_basic(&sub, DBUS_TYPE_STRING, &t)) return -ENOMEM; @@ -47,7 +59,24 @@ int bus_unit_append_names(Manager *m, DBusMessageIter *i, const char *property, return 0; } -int bus_unit_append_dependencies(Manager *m, DBusMessageIter *i, const char *property, void *data) { +static int bus_unit_append_following(DBusMessageIter *i, const char *property, void *data) { + Unit *u = data, *f; + const char *d; + + assert(i); + assert(property); + assert(u); + + f = unit_following(u); + d = f ? f->id : ""; + + if (!dbus_message_iter_append_basic(i, DBUS_TYPE_STRING, &d)) + return -ENOMEM; + + return 0; +} + +static int bus_unit_append_dependencies(DBusMessageIter *i, const char *property, void *data) { Unit *u; Iterator j; DBusMessageIter sub; @@ -57,7 +86,7 @@ int bus_unit_append_dependencies(Manager *m, DBusMessageIter *i, const char *pro return -ENOMEM; SET_FOREACH(u, s, j) - if (!dbus_message_iter_append_basic(&sub, DBUS_TYPE_STRING, &u->meta.id)) + if (!dbus_message_iter_append_basic(&sub, DBUS_TYPE_STRING, &u->id)) return -ENOMEM; if (!dbus_message_iter_close_container(i, &sub)) @@ -66,11 +95,10 @@ int bus_unit_append_dependencies(Manager *m, DBusMessageIter *i, const char *pro return 0; } -int bus_unit_append_description(Manager *m, DBusMessageIter *i, const char *property, void *data) { +static int bus_unit_append_description(DBusMessageIter *i, const char *property, void *data) { Unit *u = data; const char *d; - assert(m); assert(i); assert(property); assert(u); @@ -83,13 +111,12 @@ int bus_unit_append_description(Manager *m, DBusMessageIter *i, const char *prop return 0; } -DEFINE_BUS_PROPERTY_APPEND_ENUM(bus_unit_append_load_state, unit_load_state, UnitLoadState); +static DEFINE_BUS_PROPERTY_APPEND_ENUM(bus_unit_append_load_state, unit_load_state, UnitLoadState); -int bus_unit_append_active_state(Manager *m, DBusMessageIter *i, const char *property, void *data) { +static int bus_unit_append_active_state(DBusMessageIter *i, const char *property, void *data) { Unit *u = data; const char *state; - assert(m); assert(i); assert(property); assert(u); @@ -102,11 +129,10 @@ int bus_unit_append_active_state(Manager *m, DBusMessageIter *i, const char *pro return 0; } -int bus_unit_append_sub_state(Manager *m, DBusMessageIter *i, const char *property, void *data) { +static int bus_unit_append_sub_state(DBusMessageIter *i, const char *property, void *data) { Unit *u = data; const char *state; - assert(m); assert(i); assert(property); assert(u); @@ -119,16 +145,32 @@ int bus_unit_append_sub_state(Manager *m, DBusMessageIter *i, const char *proper return 0; } -int bus_unit_append_can_start(Manager *m, DBusMessageIter *i, const char *property, void *data) { +static int bus_unit_append_file_state(DBusMessageIter *i, const char *property, void *data) { + Unit *u = data; + const char *state; + + assert(i); + assert(property); + assert(u); + + state = strempty(unit_file_state_to_string(unit_get_unit_file_state(u))); + + if (!dbus_message_iter_append_basic(i, DBUS_TYPE_STRING, &state)) + return -ENOMEM; + + return 0; +} + +static int bus_unit_append_can_start(DBusMessageIter *i, const char *property, void *data) { Unit *u = data; dbus_bool_t b; - assert(m); assert(i); assert(property); assert(u); - b = unit_can_start(u); + b = unit_can_start(u) && + !u->refuse_manual_start; if (!dbus_message_iter_append_basic(i, DBUS_TYPE_BOOLEAN, &b)) return -ENOMEM; @@ -136,11 +178,30 @@ int bus_unit_append_can_start(Manager *m, DBusMessageIter *i, const char *proper return 0; } -int bus_unit_append_can_reload(Manager *m, DBusMessageIter *i, const char *property, void *data) { +static int bus_unit_append_can_stop(DBusMessageIter *i, const char *property, void *data) { + Unit *u = data; + dbus_bool_t b; + + assert(i); + assert(property); + assert(u); + + /* On the lower levels we assume that every unit we can start + * we can also stop */ + + b = unit_can_start(u) && + !u->refuse_manual_stop; + + if (!dbus_message_iter_append_basic(i, DBUS_TYPE_BOOLEAN, &b)) + return -ENOMEM; + + return 0; +} + +static int bus_unit_append_can_reload(DBusMessageIter *i, const char *property, void *data) { Unit *u = data; dbus_bool_t b; - assert(m); assert(i); assert(property); assert(u); @@ -153,12 +214,28 @@ int bus_unit_append_can_reload(Manager *m, DBusMessageIter *i, const char *prope return 0; } -int bus_unit_append_job(Manager *m, DBusMessageIter *i, const char *property, void *data) { +static int bus_unit_append_can_isolate(DBusMessageIter *i, const char *property, void *data) { + Unit *u = data; + dbus_bool_t b; + + assert(i); + assert(property); + assert(u); + + b = unit_can_isolate(u) && + !u->refuse_manual_start; + + if (!dbus_message_iter_append_basic(i, DBUS_TYPE_BOOLEAN, &b)) + return -ENOMEM; + + return 0; +} + +static int bus_unit_append_job(DBusMessageIter *i, const char *property, void *data) { Unit *u = data; DBusMessageIter sub; char *p; - assert(m); assert(i); assert(property); assert(u); @@ -166,12 +243,12 @@ int bus_unit_append_job(Manager *m, DBusMessageIter *i, const char *property, vo if (!dbus_message_iter_open_container(i, DBUS_TYPE_STRUCT, NULL, &sub)) return -ENOMEM; - if (u->meta.job) { + if (u->job) { - if (!(p = job_dbus_path(u->meta.job))) + if (!(p = job_dbus_path(u->job))) return -ENOMEM; - if (!dbus_message_iter_append_basic(&sub, DBUS_TYPE_UINT32, &u->meta.job->id) || + if (!dbus_message_iter_append_basic(&sub, DBUS_TYPE_UINT32, &u->job->id) || !dbus_message_iter_append_basic(&sub, DBUS_TYPE_OBJECT_PATH, &p)) { free(p); return -ENOMEM; @@ -201,13 +278,12 @@ int bus_unit_append_job(Manager *m, DBusMessageIter *i, const char *property, vo return 0; } -int bus_unit_append_default_cgroup(Manager *m, DBusMessageIter *i, const char *property, void *data) { +static int bus_unit_append_default_cgroup(DBusMessageIter *i, const char *property, void *data) { Unit *u = data; char *t; CGroupBonding *cgb; bool success; - assert(m); assert(i); assert(property); assert(u); @@ -226,7 +302,7 @@ int bus_unit_append_default_cgroup(Manager *m, DBusMessageIter *i, const char *p return success ? 0 : -ENOMEM; } -int bus_unit_append_cgroups(Manager *m, DBusMessageIter *i, const char *property, void *data) { +static int bus_unit_append_cgroups(DBusMessageIter *i, const char *property, void *data) { Unit *u = data; CGroupBonding *cgb; DBusMessageIter sub; @@ -234,7 +310,7 @@ int bus_unit_append_cgroups(Manager *m, DBusMessageIter *i, const char *property if (!dbus_message_iter_open_container(i, DBUS_TYPE_ARRAY, "s", &sub)) return -ENOMEM; - LIST_FOREACH(by_unit, cgb, u->meta.cgroup_bondings) { + LIST_FOREACH(by_unit, cgb, u->cgroup_bondings) { char *t; bool success; @@ -254,11 +330,44 @@ int bus_unit_append_cgroups(Manager *m, DBusMessageIter *i, const char *property return 0; } -int bus_unit_append_need_daemon_reload(Manager *m, DBusMessageIter *i, const char *property, void *data) { +static int bus_unit_append_cgroup_attrs(DBusMessageIter *i, const char *property, void *data) { + Unit *u = data; + CGroupAttribute *a; + DBusMessageIter sub, sub2; + + if (!dbus_message_iter_open_container(i, DBUS_TYPE_ARRAY, "(sss)", &sub)) + return -ENOMEM; + + LIST_FOREACH(by_unit, a, u->cgroup_attributes) { + char *v = NULL; + bool success; + + if (a->map_callback) + a->map_callback(a->controller, a->name, a->value, &v); + + success = + dbus_message_iter_open_container(&sub, DBUS_TYPE_STRUCT, NULL, &sub2) && + dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &a->controller) && + dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &a->name) && + dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, v ? &v : &a->value) && + dbus_message_iter_close_container(&sub, &sub2); + + free(v); + + if (!success) + return -ENOMEM; + } + + if (!dbus_message_iter_close_container(i, &sub)) + return -ENOMEM; + + return 0; +} + +static int bus_unit_append_need_daemon_reload(DBusMessageIter *i, const char *property, void *data) { Unit *u = data; dbus_bool_t b; - assert(m); assert(i); assert(property); assert(u); @@ -271,9 +380,33 @@ int bus_unit_append_need_daemon_reload(Manager *m, DBusMessageIter *i, const cha return 0; } +static int bus_unit_append_load_error(DBusMessageIter *i, const char *property, void *data) { + Unit *u = data; + const char *name, *message; + DBusMessageIter sub; + + assert(i); + assert(property); + assert(u); + + if (u->load_error != 0) { + name = bus_errno_to_dbus(u->load_error); + message = strempty(strerror(-u->load_error)); + } else + name = message = ""; + + 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_STRING, &message) || + !dbus_message_iter_close_container(i, &sub)) + return -ENOMEM; + + return 0; +} + static DBusHandlerResult bus_unit_message_dispatch(Unit *u, DBusConnection *connection, DBusMessage *message) { DBusMessage *reply = NULL; - Manager *m = u->meta.manager; + Manager *m = u->manager; DBusError error; JobType job_type = _JOB_TYPE_INVALID; char *path = NULL; @@ -297,6 +430,54 @@ static DBusHandlerResult bus_unit_message_dispatch(Unit *u, DBusConnection *conn } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Unit", "ReloadOrTryRestart")) { reload_if_possible = true; job_type = JOB_TRY_RESTART; + } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Unit", "Kill")) { + const char *swho, *smode; + int32_t signo; + KillMode mode; + KillWho who; + int r; + + if (!dbus_message_get_args( + message, + &error, + DBUS_TYPE_STRING, &swho, + DBUS_TYPE_STRING, &smode, + DBUS_TYPE_INT32, &signo, + DBUS_TYPE_INVALID)) + return bus_send_error_reply(connection, message, &error, -EINVAL); + + if (isempty(swho)) + who = KILL_ALL; + else { + who = kill_who_from_string(swho); + if (who < 0) + return bus_send_error_reply(connection, message, &error, -EINVAL); + } + + if (isempty(smode)) + mode = KILL_CONTROL_GROUP; + else { + mode = kill_mode_from_string(smode); + if (mode < 0) + return bus_send_error_reply(connection, message, &error, -EINVAL); + } + + if (signo <= 0 || signo >= _NSIG) + return bus_send_error_reply(connection, message, &error, -EINVAL); + + if ((r = unit_kill(u, who, mode, signo, &error)) < 0) + return bus_send_error_reply(connection, message, &error, r); + + if (!(reply = dbus_message_new_method_return(message))) + goto oom; + + } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Unit", "ResetFailed")) { + + unit_reset_failed(u); + + if (!(reply = dbus_message_new_method_return(message))) + goto oom; + } else if (UNIT_VTABLE(u)->bus_message_handler) return UNIT_VTABLE(u)->bus_message_handler(u, connection, message); else @@ -308,9 +489,12 @@ static DBusHandlerResult bus_unit_message_dispatch(Unit *u, DBusConnection *conn Job *j; int r; - if (job_type == JOB_START && u->meta.only_by_dependency) { - dbus_set_error(&error, BUS_ERROR_ONLY_BY_DEPENDENCY, "Unit may be activated by dependency only."); - return bus_send_error_reply(m, connection, message, &error, -EPERM); + if ((job_type == JOB_START && u->refuse_manual_start) || + (job_type == JOB_STOP && u->refuse_manual_stop) || + ((job_type == JOB_RESTART || job_type == JOB_TRY_RESTART) && + (u->refuse_manual_start || u->refuse_manual_stop))) { + dbus_set_error(&error, BUS_ERROR_ONLY_BY_DEPENDENCY, "Operation refused, may be requested by dependency only."); + return bus_send_error_reply(connection, message, &error, -EPERM); } if (!dbus_message_get_args( @@ -318,7 +502,7 @@ static DBusHandlerResult bus_unit_message_dispatch(Unit *u, DBusConnection *conn &error, DBUS_TYPE_STRING, &smode, DBUS_TYPE_INVALID)) - return bus_send_error_reply(m, connection, message, &error, -EINVAL); + return bus_send_error_reply(connection, message, &error, -EINVAL); if (reload_if_possible && unit_can_reload(u)) { if (job_type == JOB_RESTART) @@ -329,11 +513,11 @@ static DBusHandlerResult bus_unit_message_dispatch(Unit *u, DBusConnection *conn if ((mode = job_mode_from_string(smode)) == _JOB_MODE_INVALID) { dbus_set_error(&error, BUS_ERROR_INVALID_JOB_MODE, "Job mode %s is invalid.", smode); - return bus_send_error_reply(m, connection, message, &error, -EINVAL); + return bus_send_error_reply(connection, message, &error, -EINVAL); } if ((r = manager_add_job(m, job_type, u, mode, true, &error, &j)) < 0) - return bus_send_error_reply(m, connection, message, &error, r); + return bus_send_error_reply(connection, message, &error, r); if (!(reply = dbus_message_new_method_return(message))) goto oom; @@ -348,8 +532,6 @@ static DBusHandlerResult bus_unit_message_dispatch(Unit *u, DBusConnection *conn goto oom; } - free(path); - if (reply) { if (!dbus_connection_send(connection, reply, NULL)) goto oom; @@ -357,6 +539,8 @@ static DBusHandlerResult bus_unit_message_dispatch(Unit *u, DBusConnection *conn dbus_message_unref(reply); } + free(path); + return DBUS_HANDLER_RESULT_HANDLED; oom: @@ -374,23 +558,109 @@ static DBusHandlerResult bus_unit_message_handler(DBusConnection *connection, DB Manager *m = data; Unit *u; int r; + DBusMessage *reply; assert(connection); assert(message); assert(m); + if (streq(dbus_message_get_path(message), "/org/freedesktop/systemd1/unit")) { + /* Be nice to gdbus and return introspection data for our mid-level paths */ + + if (dbus_message_is_method_call(message, "org.freedesktop.DBus.Introspectable", "Introspect")) { + char *introspection = NULL; + FILE *f; + Iterator i; + const char *k; + size_t size; + + if (!(reply = dbus_message_new_method_return(message))) + goto oom; + + /* We roll our own introspection code here, instead of + * relying on bus_default_message_handler() because we + * need to generate our introspection string + * dynamically. */ + + if (!(f = open_memstream(&introspection, &size))) + goto oom; + + fputs(DBUS_INTROSPECT_1_0_XML_DOCTYPE_DECL_NODE + "\n", f); + + fputs(BUS_INTROSPECTABLE_INTERFACE, f); + fputs(BUS_PEER_INTERFACE, f); + + HASHMAP_FOREACH_KEY(u, k, m->units, i) { + char *p; + + if (k != u->id) + continue; + + if (!(p = bus_path_escape(k))) { + fclose(f); + free(introspection); + goto oom; + } + + fprintf(f, "", p); + free(p); + } + + fputs("\n", f); + + if (ferror(f)) { + fclose(f); + free(introspection); + goto oom; + } + + fclose(f); + + if (!introspection) + goto oom; + + if (!dbus_message_append_args(reply, DBUS_TYPE_STRING, &introspection, DBUS_TYPE_INVALID)) { + free(introspection); + goto oom; + } + + free(introspection); + + if (!dbus_connection_send(connection, reply, NULL)) + goto oom; + + dbus_message_unref(reply); + + return DBUS_HANDLER_RESULT_HANDLED; + } + + return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; + } + if ((r = manager_get_unit_from_dbus_path(m, dbus_message_get_path(message), &u)) < 0) { if (r == -ENOMEM) return DBUS_HANDLER_RESULT_NEED_MEMORY; - if (r == -ENOENT) - return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; + if (r == -ENOENT) { + DBusError e; + + dbus_error_init(&e); + dbus_set_error_const(&e, DBUS_ERROR_UNKNOWN_OBJECT, "Unknown unit"); + return bus_send_error_reply(connection, message, &e, r); + } - return bus_send_error_reply(m, connection, message, NULL, r); + return bus_send_error_reply(connection, message, NULL, r); } return bus_unit_message_dispatch(u, connection, message); + +oom: + if (reply) + dbus_message_unref(reply); + + return DBUS_HANDLER_RESULT_NEED_MEMORY; } const DBusObjectPathVTable bus_unit_vtable = { @@ -403,24 +673,44 @@ void bus_unit_send_change_signal(Unit *u) { assert(u); - if (u->meta.in_dbus_queue) { - LIST_REMOVE(Meta, dbus_queue, u->meta.manager->dbus_unit_queue, &u->meta); - u->meta.in_dbus_queue = false; + if (u->in_dbus_queue) { + LIST_REMOVE(Unit, dbus_queue, u->manager->dbus_unit_queue, u); + u->in_dbus_queue = false; } - if (!bus_has_subscriber(u->meta.manager)) { - u->meta.sent_dbus_new_signal = true; + if (!u->id) + return; + + if (!bus_has_subscriber(u->manager)) { + u->sent_dbus_new_signal = true; return; } if (!(p = unit_dbus_path(u))) goto oom; - if (u->meta.sent_dbus_new_signal) { - /* Send a change signal */ + if (u->sent_dbus_new_signal) { + /* Send a properties changed signal. First for the + * specific type, then for the generic unit. The + * clients may rely on this order to get atomic + * behaviour if needed. */ - if (!(m = dbus_message_new_signal(p, "org.freedesktop.systemd1.Unit", "Changed"))) + if (UNIT_VTABLE(u)->bus_invalidating_properties) { + + if (!(m = bus_properties_changed_new(p, + UNIT_VTABLE(u)->bus_interface, + UNIT_VTABLE(u)->bus_invalidating_properties))) + goto oom; + + if (bus_broadcast(u->manager, m) < 0) + goto oom; + + dbus_message_unref(m); + } + + if (!(m = bus_properties_changed_new(p, "org.freedesktop.systemd1.Unit", INVALIDATING_PROPERTIES))) goto oom; + } else { /* Send a new signal */ @@ -428,19 +718,19 @@ void bus_unit_send_change_signal(Unit *u) { goto oom; if (!dbus_message_append_args(m, - DBUS_TYPE_STRING, &u->meta.id, + DBUS_TYPE_STRING, &u->id, DBUS_TYPE_OBJECT_PATH, &p, DBUS_TYPE_INVALID)) goto oom; } - if (bus_broadcast(u->meta.manager, m) < 0) + if (bus_broadcast(u->manager, m) < 0) goto oom; free(p); dbus_message_unref(m); - u->meta.sent_dbus_new_signal = true; + u->sent_dbus_new_signal = true; return; @@ -459,12 +749,15 @@ void bus_unit_send_removed_signal(Unit *u) { assert(u); - if (!bus_has_subscriber(u->meta.manager)) + if (!bus_has_subscriber(u->manager)) return; - if (!u->meta.sent_dbus_new_signal) + if (!u->sent_dbus_new_signal) bus_unit_send_change_signal(u); + if (!u->id) + return; + if (!(p = unit_dbus_path(u))) goto oom; @@ -472,12 +765,12 @@ void bus_unit_send_removed_signal(Unit *u) { goto oom; if (!dbus_message_append_args(m, - DBUS_TYPE_STRING, &u->meta.id, + DBUS_TYPE_STRING, &u->id, DBUS_TYPE_OBJECT_PATH, &p, DBUS_TYPE_INVALID)) goto oom; - if (bus_broadcast(u->meta.manager, m) < 0) + if (bus_broadcast(u->manager, m) < 0) goto oom; free(p); @@ -493,3 +786,65 @@ oom: log_error("Failed to allocate unit remove signal."); } + +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 }, + { "BindTo", bus_unit_append_dependencies, "as", offsetof(Unit, dependencies[UNIT_BIND_TO]), 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 }, + { "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 }, + { "PropagateReloadTo", bus_unit_append_dependencies, "as", offsetof(Unit, dependencies[UNIT_PROPAGATE_RELOAD_TO]), true }, + { "PropagateReloadFrom", bus_unit_append_dependencies, "as", offsetof(Unit, dependencies[UNIT_PROPAGATE_RELOAD_FROM]), 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 }, + { "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) }, + { "DefaultControlGroup", bus_unit_append_default_cgroup, "s", 0 }, + { "ControlGroup", bus_unit_append_cgroups, "as", 0 }, + { "ControlGroupAttributes", bus_unit_append_cgroup_attrs,"a(sss)", 0 }, + { "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 }, + { NULL, } +};