X-Git-Url: https://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?a=blobdiff_plain;f=src%2Fmachine%2Fmachined-dbus.c;h=1e8bc609a3598340221e7a64a832e73b066fd72c;hb=554604b3073467af75dc94fac9e2343148603289;hp=83a45b63baa0b54eaa379de909bf7d50848a0573;hpb=6a4e0b13473baed129522310c39f3bb70f46ed42;p=elogind.git diff --git a/src/machine/machined-dbus.c b/src/machine/machined-dbus.c index 83a45b63b..1e8bc609a 100644 --- a/src/machine/machined-dbus.c +++ b/src/machine/machined-dbus.c @@ -116,7 +116,7 @@ static bool valid_machine_name(const char *p) { static int bus_manager_create_machine(Manager *manager, DBusMessage *message) { - const char *name, *service, *class, *slice, *root_directory; + const char *name, *service, *class, *root_directory; _cleanup_free_ char *p = NULL; DBusMessageIter iter, sub; MachineClass c; @@ -185,6 +185,13 @@ static int bus_manager_create_machine(Manager *manager, DBusMessage *message) { if (!(isempty(root_directory) || path_is_absolute(root_directory))) return -EINVAL; + if (!dbus_message_iter_next(&iter) || + 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); + if (hashmap_get(manager->machines, name)) return -EEXIST; @@ -218,7 +225,7 @@ static int bus_manager_create_machine(Manager *manager, DBusMessage *message) { } } - r = machine_start(m); + r = machine_start(m, &sub); if (r < 0) goto fail; @@ -531,12 +538,12 @@ DBusHandlerResult bus_message_filter( goto finish; } - mm = hashmap_get(m->machine_units, unit); if (mm) { if (streq_ptr(path, mm->scope_job)) { free(mm->scope_job); mm->scope_job = NULL; + machine_save(mm); if (mm->started) { if (streq(result, "done")) @@ -569,6 +576,43 @@ DBusHandlerResult bus_message_filter( if (mm) machine_add_to_gc_queue(mm); } + + } else if (dbus_message_is_signal(message, "org.freedesktop.systemd1.Manager", "UnitRemoved")) { + const char *path, *unit; + Machine *mm; + + if (!dbus_message_get_args(message, &error, + DBUS_TYPE_STRING, &unit, + DBUS_TYPE_OBJECT_PATH, &path, + DBUS_TYPE_INVALID)) { + log_error("Failed to parse UnitRemoved message: %s", bus_error_message(&error)); + goto finish; + } + + mm = hashmap_get(m->machine_units, unit); + if (mm) + machine_add_to_gc_queue(mm); + + } else if (dbus_message_is_signal(message, "org.freedesktop.systemd1.Manager", "Reloading")) { + dbus_bool_t b; + + if (!dbus_message_get_args(message, &error, + DBUS_TYPE_BOOLEAN, &b, + DBUS_TYPE_INVALID)) { + log_error("Failed to parse Reloading message: %s", bus_error_message(&error)); + goto finish; + } + + /* systemd finished reloading, let's recheck all our machines */ + if (!b) { + Machine *mm; + Iterator i; + + log_debug("System manager has been reloaded, rechecking machines..."); + + HASHMAP_FOREACH(mm, m->machines, i) + machine_add_to_gc_queue(mm); + } } finish: @@ -577,12 +621,118 @@ finish: return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; } +static int copy_many_fields(DBusMessageIter *dest, DBusMessageIter *src); + +static int copy_one_field(DBusMessageIter *dest, DBusMessageIter *src) { + int type, r; + + type = dbus_message_iter_get_arg_type(src); + + switch (type) { + + case DBUS_TYPE_STRUCT: { + DBusMessageIter dest_sub, src_sub; + + dbus_message_iter_recurse(src, &src_sub); + + if (!dbus_message_iter_open_container(dest, DBUS_TYPE_STRUCT, NULL, &dest_sub)) + return log_oom(); + + r = copy_many_fields(&dest_sub, &src_sub); + if (r < 0) + return r; + + if (!dbus_message_iter_close_container(dest, &dest_sub)) + return log_oom(); + + return 0; + } + + case DBUS_TYPE_ARRAY: { + DBusMessageIter dest_sub, src_sub; + + dbus_message_iter_recurse(src, &src_sub); + + if (!dbus_message_iter_open_container(dest, DBUS_TYPE_ARRAY, dbus_message_iter_get_signature(&src_sub), &dest_sub)) + return log_oom(); + + r = copy_many_fields(&dest_sub, &src_sub); + if (r < 0) + return r; + + if (!dbus_message_iter_close_container(dest, &dest_sub)) + return log_oom(); + + return 0; + } + + case DBUS_TYPE_VARIANT: { + DBusMessageIter dest_sub, src_sub; + + dbus_message_iter_recurse(src, &src_sub); + + if (!dbus_message_iter_open_container(dest, DBUS_TYPE_VARIANT, dbus_message_iter_get_signature(&src_sub), &dest_sub)) + return log_oom(); + + r = copy_one_field(&dest_sub, &src_sub); + if (r < 0) + return r; + + if (!dbus_message_iter_close_container(dest, &dest_sub)) + return log_oom(); + + return 0; + } + + case DBUS_TYPE_STRING: + case DBUS_TYPE_OBJECT_PATH: + case DBUS_TYPE_BYTE: + case DBUS_TYPE_BOOLEAN: + case DBUS_TYPE_UINT16: + case DBUS_TYPE_INT16: + case DBUS_TYPE_UINT32: + case DBUS_TYPE_INT32: + case DBUS_TYPE_UINT64: + case DBUS_TYPE_INT64: + case DBUS_TYPE_DOUBLE: + case DBUS_TYPE_SIGNATURE: { + const void *p; + + dbus_message_iter_get_basic(src, &p); + dbus_message_iter_append_basic(dest, type, &p); + return 0; + } + + default: + return -EINVAL; + } +} + +static int copy_many_fields(DBusMessageIter *dest, DBusMessageIter *src) { + int r; + + assert(dest); + assert(src); + + while (dbus_message_iter_get_arg_type(src) != DBUS_TYPE_INVALID) { + + r = copy_one_field(dest, src); + if (r < 0) + return r; + + dbus_message_iter_next(src); + } + + return 0; +} + int manager_start_scope( Manager *manager, const char *scope, pid_t pid, const char *slice, const char *description, + DBusMessageIter *more_properties, DBusError *error, char **job) { @@ -593,6 +743,7 @@ int manager_start_scope( uint64_t timeout = 500 * USEC_PER_MSEC; const char *fail = "fail"; uint32_t u; + int r; assert(manager); assert(scope); @@ -661,8 +812,16 @@ int manager_start_scope( !dbus_message_iter_append_basic(&sub4, DBUS_TYPE_UINT32, &u) || !dbus_message_iter_close_container(&sub3, &sub4) || !dbus_message_iter_close_container(&sub2, &sub3) || - !dbus_message_iter_close_container(&sub, &sub2) || - !dbus_message_iter_close_container(&iter, &sub)) + !dbus_message_iter_close_container(&sub, &sub2)) + return log_oom(); + + if (more_properties) { + r = copy_many_fields(&sub, more_properties); + if (r < 0) + return r; + } + + if (!dbus_message_iter_close_container(&iter, &sub)) return log_oom(); reply = dbus_connection_send_with_reply_and_block(manager->bus, m, -1, error); @@ -706,6 +865,16 @@ int manager_stop_unit(Manager *manager, const char *unit, DBusError *error, char DBUS_TYPE_STRING, &fail, DBUS_TYPE_INVALID); if (r < 0) { + if (dbus_error_has_name(error, BUS_ERROR_NO_SUCH_UNIT) || + dbus_error_has_name(error, BUS_ERROR_LOAD_FAILED)) { + + if (job) + *job = NULL; + + dbus_error_free(error); + return 0; + } + log_error("Failed to stop unit %s: %s", unit, bus_error(error, r)); return r; } @@ -728,7 +897,7 @@ int manager_stop_unit(Manager *manager, const char *unit, DBusError *error, char *job = copy; } - return 0; + return 1; } int manager_kill_unit(Manager *manager, const char *unit, KillWho who, int signo, DBusError *error) { @@ -793,8 +962,19 @@ int manager_unit_is_active(Manager *manager, const char *unit) { DBUS_TYPE_STRING, &interface, DBUS_TYPE_STRING, &property, DBUS_TYPE_INVALID); - if (r < 0) { + if (dbus_error_has_name(&error, DBUS_ERROR_NO_REPLY) || + dbus_error_has_name(&error, DBUS_ERROR_DISCONNECTED)) { + dbus_error_free(&error); + return true; + } + + if (dbus_error_has_name(&error, BUS_ERROR_NO_SUCH_UNIT) || + dbus_error_has_name(&error, BUS_ERROR_LOAD_FAILED)) { + dbus_error_free(&error); + return false; + } + log_error("Failed to query ActiveState: %s", bus_error(&error, r)); dbus_error_free(&error); return r;