Sophie

Sophie

distrib > Fedora > 17 > i386 > media > updates-src > by-pkgid > ab4b662b9827b6375ffd451bf4abd615 > files > 280

systemd-44-24.fc17.src.rpm

From cc6621a4d474098af88d5147b7b98a614a0cd040 Mon Sep 17 00:00:00 2001
From: Lennart Poettering <lennart@poettering.net>
Date: Fri, 11 May 2012 17:35:46 +0200
Subject: [PATCH] systemctl: add switch-root verb (cherry picked from commit
 957eb8cab28dc83aa4b800d033031e53cd0a9e00)

---
 man/systemctl.xml         |   27 +++++++++++++++++++
 src/systemctl/systemctl.c |   63 ++++++++++++++++++++++++++++++++++++++++++++-
 2 files changed, 89 insertions(+), 1 deletion(-)

diff --git a/man/systemctl.xml b/man/systemctl.xml
index 15cc91d..72ce8a4 100644
--- a/man/systemctl.xml
+++ b/man/systemctl.xml
@@ -1160,6 +1160,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>
diff --git a/src/systemctl/systemctl.c b/src/systemctl/systemctl.c
index ccd10f8..6dad623 100644
--- a/src/systemctl/systemctl.c
+++ b/src/systemctl/systemctl.c
@@ -3560,6 +3560,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;
@@ -4200,6 +4259,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);
@@ -5149,7 +5209,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;