X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?p=elogind.git;a=blobdiff_plain;f=src%2Fcore%2Fdbus-manager.c;h=e96929a55c502c422553814e5c63c285986eeff4;hp=6655f2940ca8b82ebae0871a35f9c38256455c04;hb=7c0987d8129e4761d24c21bbc2e5d39731a6b7f0;hpb=e677bf7ef610acdc5068b9d5d4c79556a236e52f diff --git a/src/core/dbus-manager.c b/src/core/dbus-manager.c index 6655f2940..e96929a55 100644 --- a/src/core/dbus-manager.c +++ b/src/core/dbus-manager.c @@ -31,6 +31,8 @@ #include "dbus-common.h" #include "install.h" #include "watchdog.h" +#include "hwclock.h" +#include "path-util.h" #define BUS_MANAGER_INTERFACE_BEGIN \ " \n" @@ -125,6 +127,10 @@ " \n" \ " \n" \ " \n" \ + " \n" \ + " \n" \ + " \n" \ + " \n" \ " \n" \ " \n" \ " \n" \ @@ -198,10 +204,12 @@ " \n" \ " \n" \ " \n" \ + " \n" \ " \n" \ " \n" \ " \n" \ " \n" \ + " \n" \ " \n" \ " " \ " \n" \ @@ -217,7 +225,6 @@ " \n" \ " \n" \ " \n" \ - " \n" \ " \n" \ " \n" \ " \n" \ @@ -235,7 +242,6 @@ " \n" \ " \n" \ " \n" \ - " \n" \ " \n" \ " \n" \ " \n" \ @@ -281,7 +287,6 @@ const char bus_manager_interface[] _introspect_("Manager") = BUS_MANAGER_INTERFACE; -static DEFINE_BUS_PROPERTY_APPEND_ENUM(bus_manager_append_running_as, manager_running_as, ManagerRunningAs); static DEFINE_BUS_PROPERTY_APPEND_ENUM(bus_manager_append_exec_output, exec_output, ExecOutput); static int bus_manager_append_tainted(DBusMessageIter *i, const char *property, void *data) { @@ -302,13 +307,14 @@ static int bus_manager_append_tainted(DBusMessageIter *i, const char *property, free(p); if (access("/proc/cgroups", F_OK) < 0) - stpcpy(e, "cgroups-missing:"); + e = stpcpy(e, "cgroups-missing:"); if (hwclock_is_localtime() > 0) - stpcpy(e, "local-hwclock:"); + e = stpcpy(e, "local-hwclock:"); - if (endswith(buf, ":")) - buf[strlen(buf)-1] = 0; + /* remove the last ':' */ + if (e != buf) + e[-1] = 0; t = buf; @@ -537,7 +543,6 @@ static const BusProperty bus_systemd_properties[] = { }; static const BusProperty bus_manager_properties[] = { - { "RunningAs", bus_manager_append_running_as, "s", offsetof(Manager, running_as) }, { "Tainted", bus_manager_append_tainted, "s", 0 }, { "InitRDTimestamp", bus_property_append_uint64, "t", offsetof(Manager, initrd_timestamp.realtime) }, { "InitRDTimestampMonotonic", bus_property_append_uint64, "t", offsetof(Manager, initrd_timestamp.monotonic) }, @@ -556,7 +561,6 @@ static const BusProperty bus_manager_properties[] = { { "ConfirmSpawn", bus_property_append_bool, "b", offsetof(Manager, confirm_spawn) }, { "ShowStatus", bus_property_append_bool, "b", offsetof(Manager, show_status) }, { "UnitPath", bus_property_append_strv, "as", offsetof(Manager, lookup_paths.unit_path), true }, - { "NotifySocket", bus_property_append_string, "s", offsetof(Manager, notify_socket), true }, { "ControlGroupHierarchy", bus_property_append_string, "s", offsetof(Manager, cgroup_hierarchy), true }, { "DefaultControllers", bus_property_append_strv, "as", offsetof(Manager, default_controllers), true }, { "DefaultStandardOutput", bus_manager_append_exec_output, "s", offsetof(Manager, default_std_output) }, @@ -1174,6 +1178,70 @@ static DBusHandlerResult bus_manager_message_handler(DBusConnection *connection, m->exit_code = MANAGER_KEXEC; + } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "SwitchRoot")) { + const char *switch_root, *switch_root_init; + char *u, *v; + int k; + + if (!dbus_message_get_args( + message, + &error, + DBUS_TYPE_STRING, &switch_root, + DBUS_TYPE_STRING, &switch_root_init, + DBUS_TYPE_INVALID)) + return bus_send_error_reply(connection, message, &error, -EINVAL); + + if (path_equal(switch_root, "/") || !path_is_absolute(switch_root)) + return bus_send_error_reply(connection, message, NULL, -EINVAL); + + if (!isempty(switch_root_init) && !path_is_absolute(switch_root_init)) + return bus_send_error_reply(connection, message, NULL, -EINVAL); + + if (m->running_as != MANAGER_SYSTEM) { + dbus_set_error(&error, BUS_ERROR_NOT_SUPPORTED, "Switching root is only supported for system managers."); + return bus_send_error_reply(connection, message, &error, -ENOTSUP); + } + + /* Safety check */ + if (isempty(switch_root_init)) + k = access(switch_root, F_OK); + else { + char *p; + + p = join(switch_root, "/", switch_root_init, NULL); + if (!p) + goto oom; + + k = access(p, X_OK); + free(p); + } + if (k < 0) + return bus_send_error_reply(connection, message, NULL, -errno); + + u = strdup(switch_root); + if (!u) + goto oom; + + if (!isempty(switch_root_init)) { + v = strdup(switch_root_init); + if (!v) { + free(u); + goto oom; + } + } else + v = NULL; + + free(m->switch_root); + free(m->switch_root_init); + m->switch_root = u; + m->switch_root_init = v; + + reply = dbus_message_new_method_return(message); + if (!reply) + goto oom; + + m->exit_code = MANAGER_SWITCH_ROOT; + } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "SetEnvironment")) { char **l = NULL, **e = NULL;