X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?a=blobdiff_plain;f=src%2Fcore%2Fmain.c;h=4d09cb71742a54fd20d6d5d53f83c13ccceb26fe;hb=97a66e94700845239cfe628da3569ac06034fa4d;hp=ea06dc80146ee4a86eeec5151826b4084bd03c59;hpb=f67cc036ba92a3c71acb664ed2d548de5827cf1f;p=elogind.git diff --git a/src/core/main.c b/src/core/main.c index ea06dc801..4d09cb717 100644 --- a/src/core/main.c +++ b/src/core/main.c @@ -746,6 +746,7 @@ static int parse_argv(int argc, char *argv[]) { ARG_SHOW_STATUS, ARG_SYSV_CONSOLE, ARG_DESERIALIZE, + ARG_SWITCHEDROOT, ARG_INTROSPECT, ARG_DEFAULT_STD_OUTPUT, ARG_DEFAULT_STD_ERROR @@ -770,6 +771,7 @@ static int parse_argv(int argc, char *argv[]) { { "sysv-console", optional_argument, NULL, ARG_SYSV_CONSOLE }, #endif { "deserialize", required_argument, NULL, ARG_DESERIALIZE }, + { "switchedroot", no_argument, NULL, ARG_SWITCHEDROOT }, { "introspect", optional_argument, NULL, ARG_INTROSPECT }, { "default-standard-output", required_argument, NULL, ARG_DEFAULT_STD_OUTPUT, }, { "default-standard-error", required_argument, NULL, ARG_DEFAULT_STD_ERROR, }, @@ -941,6 +943,10 @@ static int parse_argv(int argc, char *argv[]) { break; } + case ARG_SWITCHEDROOT: + /* Nothing special yet */ + break; + case ARG_INTROSPECT: { const char * const * i = NULL; @@ -1174,6 +1180,7 @@ static int do_switch_root(const char *switch_root) { int i; int cfd = -1; struct stat switch_root_stat, sb; + bool remove_old_root; if (path_equal(switch_root, "/")) return 0; @@ -1184,6 +1191,8 @@ static int do_switch_root(const char *switch_root) { goto fail; } + remove_old_root = in_initrd(); + for (i = 0; umounts[i] != NULL; i++) { char newmount[PATH_MAX]; @@ -1209,7 +1218,8 @@ static int do_switch_root(const char *switch_root) { goto fail; } - cfd = open("/", O_RDONLY); + if (remove_old_root) + cfd = open("/", O_RDONLY); if (mount(switch_root, "/", NULL, MS_MOVE, NULL) < 0) { r = -errno; @@ -1224,7 +1234,14 @@ static int do_switch_root(const char *switch_root) { } if (cfd >= 0) { - rm_rf_children(cfd, false, false); + struct stat rb; + + if (fstat(cfd, &rb)) { + log_error("failed to stat old root directory"); + goto fail; + } + + rm_rf_children(cfd, false, false, &rb); close(cfd); cfd=-1; } @@ -1278,6 +1295,13 @@ int main(int argc, char *argv[]) { break; } + /* If we have switched root, do all the special things */ + for (j = 1; j < argc; j++) + if (streq(argv[j], "--switchedroot")) { + is_reexec = false; + break; + } + /* If we get started via the /sbin/init symlink then we are called 'init'. After a subsequent reexecution we are then called 'systemd'. That is confusing, hence let's call us @@ -1293,6 +1317,19 @@ int main(int argc, char *argv[]) { log_set_max_level(LOG_INFO); if (getpid() == 1) { + if (in_initrd()) { + char *rd_timestamp = NULL; + + dual_timestamp_get(&initrd_timestamp); + asprintf(&rd_timestamp, "%llu %llu", + (unsigned long long) initrd_timestamp.realtime, + (unsigned long long) initrd_timestamp.monotonic); + if (rd_timestamp) { + setenv("RD_TIMESTAMP", rd_timestamp, 1); + free(rd_timestamp); + } + } + arg_running_as = MANAGER_SYSTEM; log_set_target(detect_container(NULL) > 0 ? LOG_TARGET_JOURNAL : LOG_TARGET_JOURNAL_OR_KMSG); @@ -1420,7 +1457,8 @@ int main(int argc, char *argv[]) { /* Parse the data passed to us. We leave this * variables set, but the manager later on will not * pass them on to our children. */ - parse_initrd_timestamp(&initrd_timestamp); + if(!in_initrd()) + parse_initrd_timestamp(&initrd_timestamp); /* Unset some environment variables passed in from the * kernel that don't really make sense for us. */ @@ -1693,7 +1731,7 @@ finish: if (switch_root) do_switch_root(switch_root); - args_size = MAX(5, argc+1); + args_size = MAX(6, argc+1); args = newa(const char*, args_size); if (!switch_root_init) { @@ -1712,6 +1750,8 @@ finish: i = 0; args[i++] = SYSTEMD_BINARY_PATH; + if (switch_root) + args[i++] = "--switchedroot"; args[i++] = arg_running_as == MANAGER_SYSTEM ? "--system" : "--user"; args[i++] = "--deserialize"; args[i++] = sfd;