systemctl: add switch-root verb
This commit is contained in:
parent
50913bc0c8
commit
957eb8cab2
|
@ -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>
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in New Issue