systemctl: add switch-root verb

This commit is contained in:
Lennart Poettering 2012-05-11 17:35:46 +02:00
parent 50913bc0c8
commit 957eb8cab2
2 changed files with 89 additions and 1 deletions

View File

@ -1159,6 +1159,33 @@
<listitem><para>Hibernate the system.</para></listitem>
</varlistentry>
<varlistentry>
<term><command>switch-root [ROOT] [INIT]</command></term>
<listitem><para>Switches to a
different root directory and executes
a new system manager process below
it. This is intended for usage in
initial RAM disks ("initrd"), and will
transition from the initrd's system
manager process (a.k.a "init" process)
to the main system manager
process. Takes two arguments: the
directory to make the new root
directory, and the path to the new
system manager binary below it to
execute as PID 1. If the latter is
ommitted or the empty string, a
systemd binary will automatically be
searched for and used as init. If the
system manager path is ommitted or
equal the empty string the state of
the initrd's system manager process is
passed to the main system manager,
which allows later introspection of the
state of the services involved in the
initrd boot.</para></listitem>
</varlistentry>
</variablelist>
</refsect1>

View File

@ -3580,6 +3580,65 @@ finish:
return r;
}
static int switch_root(DBusConnection *bus, char **args) {
DBusMessage *m = NULL, *reply = NULL;
unsigned l;
const char *root, *init;
DBusError error;
int r;
dbus_error_init(&error);
l = strv_length(args);
if (l < 2 || l > 3) {
log_error("Wrong number of arguments.");
return -EINVAL;
}
root = args[1];
init = l >= 3 ? args[2] : "";
m = dbus_message_new_method_call(
"org.freedesktop.systemd1",
"/org/freedesktop/systemd1",
"org.freedesktop.systemd1.Manager",
"SwitchRoot");
if (!m) {
log_error("Could not allocate message.");
return -ENOMEM;
}
if (!dbus_message_append_args(
m,
DBUS_TYPE_STRING, &root,
DBUS_TYPE_STRING, &init,
DBUS_TYPE_INVALID)) {
log_error("Could not append arguments to message.");
r = -ENOMEM;
goto finish;
}
reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error);
if (!reply) {
log_error("Failed to issue method call: %s", bus_error_message(&error));
r = -EIO;
goto finish;
}
r = 0;
finish:
if (m)
dbus_message_unref(m);
if (reply)
dbus_message_unref(reply);
dbus_error_free(&error);
return r;
}
static int set_environment(DBusConnection *bus, char **args) {
DBusMessage *m = NULL, *reply = NULL;
DBusError error;
@ -4220,6 +4279,7 @@ static int systemctl_help(void) {
" reboot Shut down and reboot the system\n"
" kexec Shut down and reboot the system with kexec\n"
" exit Request user instance exit\n"
" switch-root [ROOT] [INIT] Change to a different root file system\n"
" suspend Suspend the system\n"
" hibernate Hibernate the system\n",
program_invocation_short_name);
@ -5169,7 +5229,8 @@ static int systemctl_main(DBusConnection *bus, int argc, char *argv[], DBusError
{ "preset", MORE, 2, enable_unit },
{ "mask", MORE, 2, enable_unit },
{ "unmask", MORE, 2, enable_unit },
{ "link", MORE, 2, enable_unit }
{ "link", MORE, 2, enable_unit },
{ "switch-root", MORE, 2, switch_root },
};
int left;