From: Daan De Meyer Date: Thu, 22 Dec 2022 10:05:08 +0000 (+0100) Subject: firstboot: Add --reset option X-Git-Tag: v254-rc1~841^2 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=05eb2c60bd7308550cbbfe463c953d60be5f4375;p=thirdparty%2Fsystemd.git firstboot: Add --reset option This can be used to prepare an image for firstboot by removing all files that systemd knows about that contain machine specific information. --- diff --git a/man/systemd-firstboot.xml b/man/systemd-firstboot.xml index cfce8a40ad5..42666c96f88 100644 --- a/man/systemd-firstboot.xml +++ b/man/systemd-firstboot.xml @@ -264,6 +264,16 @@ root user instead of overwriting the entire file. + + + + If specified, all existing files that are configured by + systemd-firstboot are removed. Note that the files are removed regardless of + whether they'll be configured with a new value or not. This operation ensures that the next boot of + the image will be considered a first boot, and systemd-firstboot will prompt again + to configure each of the removed files. + + diff --git a/src/firstboot/firstboot.c b/src/firstboot/firstboot.c index 7119f9970e8..3e68ed1cb02 100644 --- a/src/firstboot/firstboot.c +++ b/src/firstboot/firstboot.c @@ -72,6 +72,7 @@ static bool arg_force = false; static bool arg_delete_root_password = false; static bool arg_root_password_is_hashed = false; static bool arg_welcome = true; +static bool arg_reset = false; STATIC_DESTRUCTOR_REGISTER(arg_root, freep); STATIC_DESTRUCTOR_REGISTER(arg_image, freep); @@ -1089,6 +1090,48 @@ static int process_kernel_cmdline(int rfd) { return 0; } +static int reset_one(int rfd, const char *path) { + _cleanup_close_ int pfd = -EBADF; + _cleanup_free_ char *f = NULL; + + assert(rfd >= 0); + assert(path); + + pfd = chase_and_open_parent_at(rfd, path, CHASE_AT_RESOLVE_IN_ROOT|CHASE_WARN|CHASE_NOFOLLOW, &f); + if (pfd == -ENOENT) + return 0; + if (pfd < 0) + return log_error_errno(pfd, "Failed to resolve %s: %m", path); + + if (unlinkat(pfd, f, 0) < 0) + return errno == ENOENT ? 0 : log_error_errno(errno, "Failed to remove %s: %m", path); + + log_info("Removed %s", path); + return 0; +} + +static int process_reset(int rfd) { + int r; + + assert(rfd >= 0); + + if (!arg_reset) + return 0; + + FOREACH_STRING(p, + "/etc/locale.conf", + "/etc/vconsole.conf", + "/etc/hostname", + "/etc/machine-id", + "/etc/kernel/cmdline") { + r = reset_one(rfd, p); + if (r < 0) + return r; + } + + return 0; +} + static int help(void) { _cleanup_free_ char *link = NULL; int r; @@ -1130,6 +1173,7 @@ static int help(void) { " --force Overwrite existing files\n" " --delete-root-password Delete root password\n" " --welcome=no Disable the welcome text\n" + " --reset Remove existing files\n" "\nSee the %s for details.\n", program_invocation_short_name, link); @@ -1171,6 +1215,7 @@ static int parse_argv(int argc, char *argv[]) { ARG_FORCE, ARG_DELETE_ROOT_PASSWORD, ARG_WELCOME, + ARG_RESET, }; static const struct option options[] = { @@ -1206,6 +1251,7 @@ static int parse_argv(int argc, char *argv[]) { { "force", no_argument, NULL, ARG_FORCE }, { "delete-root-password", no_argument, NULL, ARG_DELETE_ROOT_PASSWORD }, { "welcome", required_argument, NULL, ARG_WELCOME }, + { "reset", no_argument, NULL, ARG_RESET }, {} }; @@ -1408,6 +1454,10 @@ static int parse_argv(int argc, char *argv[]) { arg_welcome = r; break; + case ARG_RESET: + arg_reset = true; + break; + case '?': return -EINVAL; @@ -1497,6 +1547,10 @@ static int run(int argc, char *argv[]) { return r; } + r = process_reset(rfd); + if (r < 0) + return r; + r = process_locale(rfd); if (r < 0) return r; diff --git a/test/units/testsuite-74.firstboot.sh b/test/units/testsuite-74.firstboot.sh index 92a607501b7..be08575c9e6 100755 --- a/test/units/testsuite-74.firstboot.sh +++ b/test/units/testsuite-74.firstboot.sh @@ -119,6 +119,15 @@ grep -q "^root:x:0:0:.*:/bin/barshell$" "$ROOT/etc/passwd" grep -q "^root:$ROOT_HASHED_PASSWORD2:" "$ROOT/etc/shadow" grep -q "hello.world=0" "$ROOT/etc/kernel/cmdline" +# Test that --reset removes all files configured by firstboot. +systemd-firstboot --root="$ROOT" --reset +[[ ! -e "$ROOT/etc/locale.conf" ]] +[[ ! -e "$ROOT/etc/vconsole.conf" ]] +[[ ! -e "$ROOT/etc/localtime" ]] +[[ ! -e "$ROOT/etc/hostname" ]] +[[ ! -e "$ROOT/etc/machine-id" ]] +[[ ! -e "$ROOT/etc/kernel/cmdline" ]] + # --copy-* options rm -fr "$ROOT" mkdir "$ROOT"