</varlistentry>
<varlistentry>
- <term><command>switch-root</command> <replaceable>ROOT</replaceable> <optional><replaceable>INIT</replaceable></optional></term>
+ <term><command>switch-root</command> <optional><replaceable>ROOT</replaceable> <optional><replaceable>INIT</replaceable></optional></optional></term>
<listitem>
<para>Switches to a different root directory and executes a new system manager process below it.
This is intended for use in the initrd, and will transition from the initrd's system manager
- process (a.k.a. "init" process) to the main system manager process which is loaded from the
- actual host root files system. This call takes two arguments: the directory that is to become the
- new root directory, and the path to the new system manager binary below it to execute as PID 1.
- If the latter is omitted or the empty string, a systemd binary will automatically be searched for
- and used as init. If the system manager path is omitted, equal to the empty string or identical
- to the path to the systemd binary, 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 phase.</para>
+ process (a.k.a. "init" process, PID 1) to the main system manager process which is loaded from
+ the actual host root files system. This call takes two arguments: the directory that is to become
+ the new root directory, and the path to the new system manager binary below it to execute as PID
+ 1. If both are omitted or the former is an empty string it defaults to
+ <filename>/sysroot/</filename>. If the latter is omitted or is an empty string, a systemd binary
+ will automatically be searched for and used as service manager. If the system manager path is
+ omitted, equal to the empty string or identical to the path to the systemd binary, 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 phase.</para>
</listitem>
</varlistentry>
if (r < 0)
return r;
- if (!path_is_valid(root))
- return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS,
- "New root directory must be a valid path.");
- if (!path_is_absolute(root))
- return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS,
- "New root path '%s' is not absolute.", root);
- if (path_equal(root, "/"))
- return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS,
- "New root directory cannot be the old root directory.");
+ if (isempty(root))
+ /* If path is not specified, default to "/sysroot" which is what we generally expect initrds
+ * to use */
+ root = "/sysroot";
+ else {
+ if (!path_is_valid(root))
+ return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS,
+ "New root directory must be a valid path.");
+ if (!path_is_absolute(root))
+ return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS,
+ "New root path '%s' is not absolute.", root);
+ if (path_equal(root, "/"))
+ return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS,
+ "New root directory cannot be the old root directory.");
+ }
/* Safety check */
if (isempty(init)) {
if (arg_transport != BUS_TRANSPORT_LOCAL)
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Cannot switch root remotely.");
- if (argc < 2 || argc > 3)
- return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Wrong number of arguments.");
-
- root = argv[1];
- if (!path_is_valid(root))
- return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Invalid root path: %s", root);
- if (!path_is_absolute(root))
- return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Root path is not absolute: %s", root);
+ if (argc > 3)
+ return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Too many arguments.");
+
+ if (argc >= 2) {
+ root = argv[1];
+ if (!path_is_valid(root))
+ return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Invalid root path: %s", root);
+ if (!path_is_absolute(root))
+ return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Root path is not absolute: %s", root);
+ if (path_equal(root, "/"))
+ return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Cannot switch to current root directory: %s", root);
+ } else
+ root = "/sysroot";
if (argc >= 3)
init = argv[2];
" reboot Shut down and reboot the system\n"
" kexec Shut down and reboot the system with kexec\n"
" exit [EXIT_CODE] Request user instance or container exit\n"
- " switch-root ROOT [INIT] Change to a different root file system\n"
+ " switch-root [ROOT [INIT]] Change to a different root file system\n"
" suspend Suspend the system\n"
" hibernate Hibernate the system\n"
" hybrid-sleep Hibernate and suspend the system\n"
{ "unmask", 2, VERB_ANY, 0, verb_enable },
{ "link", 2, VERB_ANY, 0, verb_enable },
{ "revert", 2, VERB_ANY, 0, verb_enable },
- { "switch-root", 2, VERB_ANY, VERB_ONLINE_ONLY, verb_switch_root },
+ { "switch-root", VERB_ANY, VERB_ANY, VERB_ONLINE_ONLY, verb_switch_root },
{ "list-dependencies", VERB_ANY, VERB_ANY, VERB_ONLINE_ONLY, verb_list_dependencies },
{ "set-default", 2, 2, 0, verb_set_default },
{ "get-default", VERB_ANY, 1, 0, verb_get_default },
[Service]
Type=oneshot
-ExecStart=systemctl --no-block switch-root /sysroot
+ExecStart=systemctl --no-block switch-root