From e26807239bd65bc17535a53cd540f38600e7ef24 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Mon, 7 Jul 2014 19:25:31 +0200 Subject: [PATCH] firstboot: get rid of firstboot generator again, introduce ConditionFirstBoot= instead As Zbigniew pointed out a new ConditionFirstBoot= appears like the nicer way to hook in systemd-firstboot.service on first boots (those with /etc unpopulated), so let's do this, and get rid of the generator again. --- .gitignore | 1 - Makefile-man.am | 6 +-- Makefile.am | 11 +---- man/systemd.unit.xml | 13 +++++ src/core/condition.c | 17 +++++++ src/core/load-fragment-gperf.gperf.m4 | 1 + src/core/main.c | 2 +- src/core/manager.c | 25 ++++++---- src/core/manager.h | 4 +- src/core/shutdown.c | 2 +- src/firstboot/firstboot-generator.c | 71 --------------------------- src/shared/condition-util.c | 1 + src/shared/condition-util.h | 1 + src/shared/util.c | 10 +--- src/shared/util.h | 2 +- src/sleep/sleep.c | 4 +- units/systemd-firstboot.service.in | 1 + 17 files changed, 64 insertions(+), 108 deletions(-) delete mode 100644 src/firstboot/firstboot-generator.c diff --git a/.gitignore b/.gitignore index 1ba3d06cf..e3ddbf8d3 100644 --- a/.gitignore +++ b/.gitignore @@ -65,7 +65,6 @@ /systemd-detect-virt /systemd-efi-boot-generator /systemd-firstboot -/systemd-firstboot-generator /systemd-fsck /systemd-fstab-generator /systemd-getty-generator diff --git a/Makefile-man.am b/Makefile-man.am index e6043f1ff..66c40b466 100644 --- a/Makefile-man.am +++ b/Makefile-man.am @@ -63,7 +63,7 @@ MANPAGES += \ man/systemd-delta.1 \ man/systemd-detect-virt.1 \ man/systemd-efi-boot-generator.8 \ - man/systemd-firstboot.8 \ + man/systemd-firstboot.1 \ man/systemd-fsck@.service.8 \ man/systemd-fstab-generator.8 \ man/systemd-getty-generator.8 \ @@ -194,7 +194,7 @@ MANPAGES_ALIAS += \ man/systemd-ask-password-console.path.8 \ man/systemd-ask-password-wall.path.8 \ man/systemd-ask-password-wall.service.8 \ - man/systemd-firstboot.service.8 \ + man/systemd-firstboot.service.1 \ man/systemd-fsck-root.service.8 \ man/systemd-fsck.8 \ man/systemd-hibernate.service.8 \ @@ -300,7 +300,7 @@ man/sd_notifyf.3: man/sd_notify.3 man/systemd-ask-password-console.path.8: man/systemd-ask-password-console.service.8 man/systemd-ask-password-wall.path.8: man/systemd-ask-password-console.service.8 man/systemd-ask-password-wall.service.8: man/systemd-ask-password-console.service.8 -man/systemd-firstboot.service.8: man/systemd-firstboot.8 +man/systemd-firstboot.service.1: man/systemd-firstboot.1 man/systemd-fsck-root.service.8: man/systemd-fsck@.service.8 man/systemd-fsck.8: man/systemd-fsck@.service.8 man/systemd-hibernate.service.8: man/systemd-suspend.service.8 diff --git a/Makefile.am b/Makefile.am index 321379ca5..3ddbdf77d 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1894,15 +1894,8 @@ nodist_systemunit_DATA += \ EXTRA_DIST += \ units/systemd-firstboot.service.in -systemgenerator_PROGRAMS += \ - systemd-firstboot-generator - -systemd_firstboot_generator_SOURCES = \ - src/firstboot/firstboot-generator.c - -systemd_firstboot_generator_LDADD = \ - libsystemd-label.la \ - libsystemd-shared.la +SYSINIT_TARGET_WANTS += \ + systemd-firstboot.service endif diff --git a/man/systemd.unit.xml b/man/systemd.unit.xml index cd3279c19..b1f810898 100644 --- a/man/systemd.unit.xml +++ b/man/systemd.unit.xml @@ -901,6 +901,7 @@ ConditionCapability= ConditionACPower= ConditionNeedsUpdate= + ConditionFirstBoot= ConditionPathExists= ConditionPathExistsGlob= ConditionPathIsDirectory= @@ -1101,6 +1102,18 @@ files's modification time gets reset indicating a completed update. + ConditionFirstBoot= + takes a boolean argument. This + condition may be used to + conditionalize units on whether the + system is booting up with an + unpopulated /etc + directory. This may be used to + populate /etc on + the first boot after factory reset, or + when a new system instances boots up + for the first time. + With ConditionPathExists= a file existence condition is diff --git a/src/core/condition.c b/src/core/condition.c index 410fb3679..353e0c97f 100644 --- a/src/core/condition.c +++ b/src/core/condition.c @@ -120,6 +120,20 @@ static bool condition_test_needs_update(Condition *c) { (usr.st_mtim.tv_sec == other.st_mtim.tv_sec && usr.st_mtim.tv_nsec > other.st_mtim.tv_nsec)) == !c->negate; } +static bool condition_test_first_boot(Condition *c) { + int r; + + assert(c); + assert(c->parameter); + assert(c->type == CONDITION_FIRST_BOOT); + + r = parse_boolean(c->parameter); + if (r < 0) + return c->negate; + + return ((access("/run/systemd/first-boot", F_OK) >= 0) == !!r) == !c->negate; +} + static bool condition_test(Condition *c) { assert(c); @@ -202,6 +216,9 @@ static bool condition_test(Condition *c) { case CONDITION_NEEDS_UPDATE: return condition_test_needs_update(c); + case CONDITION_FIRST_BOOT: + return condition_test_first_boot(c); + case CONDITION_NULL: return !c->negate; diff --git a/src/core/load-fragment-gperf.gperf.m4 b/src/core/load-fragment-gperf.gperf.m4 index a7c4469a4..4c092d77a 100644 --- a/src/core/load-fragment-gperf.gperf.m4 +++ b/src/core/load-fragment-gperf.gperf.m4 @@ -162,6 +162,7 @@ Unit.ConditionDirectoryNotEmpty, config_parse_unit_condition_path, CONDITION_D Unit.ConditionFileNotEmpty, config_parse_unit_condition_path, CONDITION_FILE_NOT_EMPTY, 0 Unit.ConditionFileIsExecutable, config_parse_unit_condition_path, CONDITION_FILE_IS_EXECUTABLE, 0 Unit.ConditionNeedsUpdate, config_parse_unit_condition_path, CONDITION_NEEDS_UPDATE, 0 +Unit.ConditionFirstBoot, config_parse_unit_condition_path, CONDITION_FIRST_BOOT, 0 Unit.ConditionKernelCommandLine, config_parse_unit_condition_string, CONDITION_KERNEL_COMMAND_LINE, 0 Unit.ConditionArchitecture, config_parse_unit_condition_string, CONDITION_ARCHITECTURE, 0 Unit.ConditionVirtualization, config_parse_unit_condition_string, CONDITION_VIRTUALIZATION, 0 diff --git a/src/core/main.c b/src/core/main.c index e1fc3f371..a21a959be 100644 --- a/src/core/main.c +++ b/src/core/main.c @@ -1648,11 +1648,11 @@ int main(int argc, char *argv[]) { m->initrd_timestamp = initrd_timestamp; m->security_start_timestamp = security_start_timestamp; m->security_finish_timestamp = security_finish_timestamp; - m->is_first_boot = empty_etc; manager_set_default_rlimits(m, arg_default_rlimit); manager_environment_add(m, NULL, arg_default_environment); manager_set_show_status(m, arg_show_status); + manager_set_first_boot(m, empty_etc); /* Remember whether we should queue the default job */ queue_default_job = !arg_serialization || arg_switched_root; diff --git a/src/core/manager.c b/src/core/manager.c index 9d078c0af..3dffbe259 100644 --- a/src/core/manager.c +++ b/src/core/manager.c @@ -2477,7 +2477,7 @@ void manager_check_finished(Manager *m) { m->confirm_spawn = false; /* This is no longer the first boot */ - m->is_first_boot = false; + manager_set_first_boot(m, false); if (dual_timestamp_is_set(&m->finish_timestamp)) return; @@ -2631,7 +2631,6 @@ void manager_run_generators(Manager *m) { _cleanup_closedir_ DIR *d = NULL; const char *generator_path; const char *argv[5]; - const char *env[2]; int r; assert(m); @@ -2665,14 +2664,8 @@ void manager_run_generators(Manager *m) { argv[3] = m->generator_unit_path_late; argv[4] = NULL; - if (m->is_first_boot) { - env[0] = (char*) "SYSTEMD_FIRST_BOOT=1"; - env[1] = NULL; - } else - env[0] = NULL; - RUN_WITH_UMASK(0022) - execute_directory(generator_path, d, DEFAULT_TIMEOUT_USEC, (char**) argv, (char**) env); + execute_directory(generator_path, d, DEFAULT_TIMEOUT_USEC, (char**) argv); finish: trim_generator_dir(m, &m->generator_unit_path); @@ -2816,6 +2809,20 @@ static bool manager_get_show_status(Manager *m) { return plymouth_running(); } +void manager_set_first_boot(Manager *m, bool b) { + assert(m); + + if (m->running_as != SYSTEMD_SYSTEM) + return; + + m->first_boot = b; + + if (m->first_boot) + touch("/run/systemd/first-boot"); + else + unlink("/run/systemd/first-boot"); +} + void manager_status_printf(Manager *m, bool ephemeral, const char *status, const char *format, ...) { va_list ap; diff --git a/src/core/manager.h b/src/core/manager.h index eff639d1b..718c29fa0 100644 --- a/src/core/manager.h +++ b/src/core/manager.h @@ -228,6 +228,7 @@ struct Manager { bool dispatching_dbus_queue:1; bool taint_usr:1; + bool first_boot:1; ShowStatus show_status; bool confirm_spawn; @@ -243,7 +244,6 @@ struct Manager { bool default_cpu_accounting; bool default_memory_accounting; bool default_blockio_accounting; - bool is_first_boot; usec_t default_timer_accuracy_usec; @@ -334,6 +334,8 @@ void manager_undo_generators(Manager *m); void manager_recheck_journal(Manager *m); void manager_set_show_status(Manager *m, ShowStatus mode); +void manager_set_first_boot(Manager *m, bool b); + void manager_status_printf(Manager *m, bool ephemeral, const char *status, const char *format, ...) _printf_(4,5); void manager_flip_auto_status(Manager *m, bool enable); diff --git a/src/core/shutdown.c b/src/core/shutdown.c index e7771c968..fde3ce9c2 100644 --- a/src/core/shutdown.c +++ b/src/core/shutdown.c @@ -375,7 +375,7 @@ int main(int argc, char *argv[]) { arguments[0] = NULL; arguments[1] = arg_verb; arguments[2] = NULL; - execute_directory(SYSTEM_SHUTDOWN_PATH, NULL, DEFAULT_TIMEOUT_USEC, arguments, NULL); + execute_directory(SYSTEM_SHUTDOWN_PATH, NULL, DEFAULT_TIMEOUT_USEC, arguments); if (!in_container && !in_initrd() && access("/run/initramfs/shutdown", X_OK) == 0) { diff --git a/src/firstboot/firstboot-generator.c b/src/firstboot/firstboot-generator.c deleted file mode 100644 index 6d23f40fa..000000000 --- a/src/firstboot/firstboot-generator.c +++ /dev/null @@ -1,71 +0,0 @@ -/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/ - -/*** - This file is part of systemd. - - Copyright 2014 Lennart Poettering - - systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation; either version 2.1 of the License, or - (at your option) any later version. - - systemd is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with systemd; If not, see . -***/ - -#include "util.h" -#include "mkdir.h" - -static const char *arg_dest = "/tmp"; - -static bool is_first_boot(void) { - const char *e; - - e = getenv("SYSTEMD_FIRST_BOOT"); - if (!e) - return false; - - return parse_boolean(e) > 0; -} - -int main(int argc, char *argv[]) { - int r; - - if (argc > 1 && argc != 4) { - log_error("This program takes three or no arguments."); - return EXIT_FAILURE; - } - - if (argc > 1) - arg_dest = argv[2]; - - log_set_target(LOG_TARGET_SAFE); - log_parse_environment(); - log_open(); - - umask(0022); - - if (is_first_boot()) { - const char *t; - - t = strappenda(arg_dest, "/default.target.wants/systemd-firstboot.service"); - - mkdir_parents(t, 0755); - if (symlink(SYSTEM_DATA_UNIT_PATH "/systemd-firstboot.service", t) < 0 && errno != EEXIST) { - log_error("Failed to create firstboot service symlinks %s: %m", t); - r = -errno; - goto finish; - } - } - - r = 0; - -finish: - return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS; -} diff --git a/src/shared/condition-util.c b/src/shared/condition-util.c index 7b89b0fba..928edeeb9 100644 --- a/src/shared/condition-util.c +++ b/src/shared/condition-util.c @@ -257,6 +257,7 @@ static const char* const condition_type_table[_CONDITION_TYPE_MAX] = { [CONDITION_AC_POWER] = "ConditionACPower", [CONDITION_ARCHITECTURE] = "ConditionArchitecture", [CONDITION_NEEDS_UPDATE] = "ConditionNeedsUpdate", + [CONDITION_FIRST_BOOT] = "ConditionFirstBoot", [CONDITION_NULL] = "ConditionNull" }; diff --git a/src/shared/condition-util.h b/src/shared/condition-util.h index 0b09f83f9..047fdbfd8 100644 --- a/src/shared/condition-util.h +++ b/src/shared/condition-util.h @@ -45,6 +45,7 @@ typedef enum ConditionType { CONDITION_AC_POWER, CONDITION_ARCHITECTURE, CONDITION_NEEDS_UPDATE, + CONDITION_FIRST_BOOT, CONDITION_NULL, _CONDITION_TYPE_MAX, _CONDITION_TYPE_INVALID = -1 diff --git a/src/shared/util.c b/src/shared/util.c index 88511b69c..33427981e 100644 --- a/src/shared/util.c +++ b/src/shared/util.c @@ -3795,7 +3795,7 @@ bool dirent_is_file_with_suffix(const struct dirent *de, const char *suffix) { return endswith(de->d_name, suffix); } -void execute_directory(const char *directory, DIR *d, usec_t timeout, char *argv[], char *env[]) { +void execute_directory(const char *directory, DIR *d, usec_t timeout, char *argv[]) { pid_t executor_pid; int r; @@ -3826,14 +3826,6 @@ void execute_directory(const char *directory, DIR *d, usec_t timeout, char *argv assert_se(prctl(PR_SET_PDEATHSIG, SIGTERM) == 0); - if (!strv_isempty(env)) { - char **i; - - STRV_FOREACH(i, env) - putenv(*i); - } - - if (!d) { d = _d = opendir(directory); if (!d) { diff --git a/src/shared/util.h b/src/shared/util.h index fb852d697..c5eadc97c 100644 --- a/src/shared/util.h +++ b/src/shared/util.h @@ -505,7 +505,7 @@ bool tty_is_console(const char *tty) _pure_; int vtnr_from_tty(const char *tty); const char *default_term_for_tty(const char *tty); -void execute_directory(const char *directory, DIR *_d, usec_t timeout, char *argv[], char *env[]); +void execute_directory(const char *directory, DIR *_d, usec_t timeout, char *argv[]); int kill_and_sigcont(pid_t pid, int sig); diff --git a/src/sleep/sleep.c b/src/sleep/sleep.c index 3b0e927c4..5adbea595 100644 --- a/src/sleep/sleep.c +++ b/src/sleep/sleep.c @@ -110,7 +110,7 @@ static int execute(char **modes, char **states) { arguments[1] = (char*) "pre"; arguments[2] = arg_verb; arguments[3] = NULL; - execute_directory(SYSTEM_SLEEP_PATH, NULL, DEFAULT_TIMEOUT_USEC, arguments, NULL); + execute_directory(SYSTEM_SLEEP_PATH, NULL, DEFAULT_TIMEOUT_USEC, arguments); log_struct(LOG_INFO, MESSAGE_ID(SD_MESSAGE_SLEEP_START), @@ -129,7 +129,7 @@ static int execute(char **modes, char **states) { NULL); arguments[1] = (char*) "post"; - execute_directory(SYSTEM_SLEEP_PATH, NULL, DEFAULT_TIMEOUT_USEC, arguments, NULL); + execute_directory(SYSTEM_SLEEP_PATH, NULL, DEFAULT_TIMEOUT_USEC, arguments); return r; } diff --git a/units/systemd-firstboot.service.in b/units/systemd-firstboot.service.in index e7ae74556..a8719a8c7 100644 --- a/units/systemd-firstboot.service.in +++ b/units/systemd-firstboot.service.in @@ -13,6 +13,7 @@ Conflicts=shutdown.target After=systemd-readahead-collect.service systemd-readahead-replay.service systemd-remount-fs.service systemd-sysusers.service Before=sysinit.target shutdown.target ConditionPathIsReadWrite=/etc +ConditionFirstBoot=yes [Service] Type=oneshot -- 2.30.2