• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

systemd / systemd / 13380515387

17 Feb 2025 09:20PM UTC coverage: 71.822% (+0.1%) from 71.714%
13380515387

push

github

DaanDeMeyer
ukify: print all remaining log-like output to stderr

We want to be able to capture stdout for json and such, so convert
all remaining logging to stderr.

293883 of 409184 relevant lines covered (71.82%)

716959.33 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

75.57
/src/firstboot/firstboot.c
1
/* SPDX-License-Identifier: LGPL-2.1-or-later */
2

3
#include <fcntl.h>
4
#include <getopt.h>
5
#include <linux/loop.h>
6
#include <unistd.h>
7

8
#include "sd-id128.h"
9

10
#include "alloc-util.h"
11
#include "ask-password-api.h"
12
#include "build.h"
13
#include "bus-error.h"
14
#include "bus-locator.h"
15
#include "bus-unit-util.h"
16
#include "bus-util.h"
17
#include "bus-wait-for-jobs.h"
18
#include "chase.h"
19
#include "copy.h"
20
#include "creds-util.h"
21
#include "dissect-image.h"
22
#include "env-file.h"
23
#include "errno-util.h"
24
#include "fd-util.h"
25
#include "fileio.h"
26
#include "fs-util.h"
27
#include "glyph-util.h"
28
#include "hostname-util.h"
29
#include "kbd-util.h"
30
#include "libcrypt-util.h"
31
#include "locale-util.h"
32
#include "lock-util.h"
33
#include "main-func.h"
34
#include "memory-util.h"
35
#include "mkdir.h"
36
#include "mount-util.h"
37
#include "os-util.h"
38
#include "parse-argument.h"
39
#include "parse-util.h"
40
#include "password-quality-util.h"
41
#include "path-util.h"
42
#include "pretty-print.h"
43
#include "proc-cmdline.h"
44
#include "random-util.h"
45
#include "smack-util.h"
46
#include "string-util.h"
47
#include "strv.h"
48
#include "terminal-util.h"
49
#include "time-util.h"
50
#include "tmpfile-util-label.h"
51
#include "tmpfile-util.h"
52
#include "umask-util.h"
53
#include "user-util.h"
54
#include "vconsole-util.h"
55

56
static char *arg_root = NULL;
57
static char *arg_image = NULL;
58
static char *arg_locale = NULL;  /* $LANG */
59
static char *arg_locale_messages = NULL; /* $LC_MESSAGES */
60
static char *arg_keymap = NULL;
61
static char *arg_timezone = NULL;
62
static char *arg_hostname = NULL;
63
static sd_id128_t arg_machine_id = {};
64
static char *arg_root_password = NULL;
65
static char *arg_root_shell = NULL;
66
static char *arg_kernel_cmdline = NULL;
67
static bool arg_prompt_locale = false;
68
static bool arg_prompt_keymap = false;
69
static bool arg_prompt_timezone = false;
70
static bool arg_prompt_hostname = false;
71
static bool arg_prompt_root_password = false;
72
static bool arg_prompt_root_shell = false;
73
static bool arg_copy_locale = false;
74
static bool arg_copy_keymap = false;
75
static bool arg_copy_timezone = false;
76
static bool arg_copy_root_password = false;
77
static bool arg_copy_root_shell = false;
78
static bool arg_force = false;
79
static bool arg_delete_root_password = false;
80
static bool arg_root_password_is_hashed = false;
81
static bool arg_welcome = true;
82
static bool arg_reset = false;
83
static ImagePolicy *arg_image_policy = NULL;
84

85
STATIC_DESTRUCTOR_REGISTER(arg_root, freep);
136✔
86
STATIC_DESTRUCTOR_REGISTER(arg_image, freep);
136✔
87
STATIC_DESTRUCTOR_REGISTER(arg_locale, freep);
136✔
88
STATIC_DESTRUCTOR_REGISTER(arg_locale_messages, freep);
136✔
89
STATIC_DESTRUCTOR_REGISTER(arg_keymap, freep);
136✔
90
STATIC_DESTRUCTOR_REGISTER(arg_timezone, freep);
136✔
91
STATIC_DESTRUCTOR_REGISTER(arg_hostname, freep);
136✔
92
STATIC_DESTRUCTOR_REGISTER(arg_root_password, erase_and_freep);
136✔
93
STATIC_DESTRUCTOR_REGISTER(arg_root_shell, freep);
136✔
94
STATIC_DESTRUCTOR_REGISTER(arg_kernel_cmdline, freep);
136✔
95
STATIC_DESTRUCTOR_REGISTER(arg_image_policy, image_policy_freep);
136✔
96

97
static void print_welcome(int rfd) {
7✔
98
        _cleanup_free_ char *pretty_name = NULL, *os_name = NULL, *ansi_color = NULL;
7✔
99
        static bool done = false;
7✔
100
        const char *pn, *ac;
7✔
101
        int r;
7✔
102

103
        assert(rfd >= 0);
7✔
104

105
        if (!arg_welcome)
7✔
106
                return;
107

108
        if (done) {
6✔
109
                putchar('\n'); /* Add some breathing room between multiple prompts */
1✔
110
                return;
111
        }
112

113
        r = parse_os_release_at(rfd,
6✔
114
                                "PRETTY_NAME", &pretty_name,
115
                                "NAME", &os_name,
116
                                "ANSI_COLOR", &ansi_color);
117
        if (r < 0)
6✔
118
                log_full_errno(r == -ENOENT ? LOG_DEBUG : LOG_WARNING, r,
6✔
119
                               "Failed to read os-release file, ignoring: %m");
120

121
        pn = os_release_pretty_name(pretty_name, os_name);
6✔
122
        ac = isempty(ansi_color) ? "0" : ansi_color;
6✔
123

124
        (void) terminal_reset_defensive_locked(STDOUT_FILENO, /* switch_to_text= */ false);
6✔
125

126
        if (colors_enabled())
6✔
127
                printf("\nWelcome to your new installation of \x1B[%sm%s\x1B[0m!\n", ac, pn);
×
128
        else
129
                printf("\nWelcome to your new installation of %s!\n", pn);
6✔
130

131
        printf("\nPlease configure your system!\n");
6✔
132

133
        any_key_to_proceed();
6✔
134

135
        done = true;
6✔
136
}
137

138
static int get_completions(
×
139
                const char *key,
140
                char ***ret_list,
141
                void *userdata) {
142

143
        int r;
×
144

145
        if (!userdata) {
×
146
                *ret_list = NULL;
×
147
                return 0;
×
148
        }
149

150
        _cleanup_strv_free_ char **copy = strv_copy(userdata);
×
151
        if (!copy)
×
152
                return -ENOMEM;
153

154
        r = strv_extend(&copy, "list");
×
155
        if (r < 0)
×
156
                return r;
157

158
        *ret_list = TAKE_PTR(copy);
×
159
        return 0;
×
160
}
161

162
static int prompt_loop(
7✔
163
                int rfd,
164
                const char *text,
165
                char **l,
166
                unsigned ellipsize_percentage,
167
                bool (*is_valid)(int rfd, const char *name),
168
                char **ret) {
169

170
        int r;
7✔
171

172
        assert(text);
7✔
173
        assert(is_valid);
7✔
174
        assert(ret);
7✔
175

176
        for (;;) {
7✔
177
                _cleanup_free_ char *p = NULL;
7✔
178

179
                r = ask_string_full(
7✔
180
                                &p,
181
                                get_completions,
182
                                l,
183
                                strv_isempty(l) ? "%s %s (empty to skip): "
7✔
184
                                                : "%s %s (empty to skip, \"list\" to list options): ",
185
                                special_glyph(SPECIAL_GLYPH_TRIANGULAR_BULLET), text);
186
                if (r < 0)
7✔
187
                        return log_error_errno(r, "Failed to query user: %m");
×
188

189
                if (isempty(p)) {
7✔
190
                        log_info("No data entered, skipping.");
×
191
                        return 0;
×
192
                }
193

194
                if (!strv_isempty(l)) {
7✔
195
                        if (streq(p, "list")) {
4✔
196
                                r = show_menu(l,
×
197
                                              /* n_columns= */ 3,
198
                                              /* column_width= */ 20,
199
                                              ellipsize_percentage,
200
                                              /* grey_prefix= */ NULL,
201
                                              /* with_numbers= */ true);
202
                                if (r < 0)
×
203
                                        return log_error_errno(r, "Failed to show menu: %m");
×
204

205
                                putchar('\n');
×
206
                                continue;
×
207
                        }
208

209
                        unsigned u;
4✔
210
                        r = safe_atou(p, &u);
4✔
211
                        if (r >= 0) {
4✔
212
                                if (u <= 0 || u > strv_length(l)) {
×
213
                                        log_error("Specified entry number out of range.");
×
214
                                        continue;
×
215
                                }
216

217
                                log_info("Selected '%s'.", l[u-1]);
×
218
                                return free_and_strdup_warn(ret, l[u-1]);
×
219
                        }
220
                }
221

222
                if (is_valid(rfd, p))
7✔
223
                        return free_and_replace(*ret, p);
7✔
224

225
                /* Be more helpful to the user, and give a hint what the user might have wanted to type. */
226
                const char *best_match = strv_find_closest(l, p);
×
227
                if (best_match)
×
228
                        log_error("Invalid data '%s', did you mean '%s'?", p, best_match);
×
229
                else
230
                        log_error("Invalid data '%s'.", p);
×
231
        }
232
}
233

234
static int should_configure(int dir_fd, const char *filename) {
1,064✔
235
        _cleanup_fclose_ FILE *passwd = NULL, *shadow = NULL;
1,064✔
236
        int r;
1,064✔
237

238
        assert(dir_fd >= 0);
1,064✔
239
        assert(filename);
1,064✔
240

241
        if (streq(filename, "passwd") && !arg_force)
1,064✔
242
                /* We may need to do additional checks, so open the file. */
243
                r = xfopenat(dir_fd, filename, "re", O_NOFOLLOW, &passwd);
131✔
244
        else
245
                r = RET_NERRNO(faccessat(dir_fd, filename, F_OK, AT_SYMLINK_NOFOLLOW));
933✔
246

247
        if (r == -ENOENT)
517✔
248
                return true; /* missing */
249
        if (r < 0)
655✔
250
                return log_error_errno(r, "Failed to access %s: %m", filename);
×
251
        if (arg_force)
655✔
252
                return true; /* exists, but if --force was given we should still configure the file. */
253

254
        if (!passwd)
641✔
255
                return false;
256

257
        /* In case of /etc/passwd, do an additional check for the root password field.
258
         * We first check that passwd redirects to shadow, and then we check shadow.
259
         */
260
        struct passwd *i;
261
        while ((r = fgetpwent_sane(passwd, &i)) > 0) {
108✔
262
                if (!streq(i->pw_name, "root"))
107✔
263
                        continue;
×
264

265
                if (streq_ptr(i->pw_passwd, PASSWORD_SEE_SHADOW))
107✔
266
                        break;
267
                log_debug("passwd: root account with non-shadow password found, treating root as configured");
×
268
                return false;
269
        }
270
        if (r < 0)
108✔
271
                return log_error_errno(r, "Failed to read %s: %m", filename);
×
272
        if (r == 0) {
108✔
273
                log_debug("No root account found in %s, assuming root is not configured.", filename);
1✔
274
                return true;
1✔
275
        }
276

277
        r = xfopenat(dir_fd, "shadow", "re", O_NOFOLLOW, &shadow);
107✔
278
        if (r == -ENOENT) {
107✔
279
                log_debug("No shadow file found, assuming root is not configured.");
×
280
                return true; /* missing */
×
281
        }
282
        if (r < 0)
107✔
283
                return log_error_errno(r, "Failed to access shadow: %m");
×
284

285
        struct spwd *j;
286
        while ((r = fgetspent_sane(shadow, &j)) > 0) {
107✔
287
                if (!streq(j->sp_namp, "root"))
107✔
288
                        continue;
×
289

290
                bool unprovisioned = streq_ptr(j->sp_pwdp, PASSWORD_UNPROVISIONED);
107✔
291
                log_debug("Root account found, %s.",
208✔
292
                          unprovisioned ? "with unprovisioned password, treating root as not configured" :
293
                                          "treating root as configured");
294
                return unprovisioned;
107✔
295
        }
296
        if (r < 0)
×
297
                return log_error_errno(r, "Failed to read shadow: %m");
×
298
        assert(r == 0);
×
299
        log_debug("No root account found in shadow, assuming root is not configured.");
1,064✔
300
        return true;
301
}
302

303
static bool locale_is_installed_bool(const char *name) {
×
304
        return locale_is_installed(name) > 0;
×
305
}
306

307
static bool locale_is_ok(int rfd, const char *name) {
10✔
308
        int r;
10✔
309

310
        assert(rfd >= 0);
10✔
311

312
        r = dir_fd_is_root(rfd);
10✔
313
        if (r < 0)
10✔
314
                log_debug_errno(r, "Unable to determine if operating on host root directory, assuming we are: %m");
×
315

316
        return r != 0 ? locale_is_installed_bool(name) : locale_is_valid(name);
10✔
317
}
318

319
static int prompt_locale(int rfd) {
10✔
320
        _cleanup_strv_free_ char **locales = NULL;
×
321
        bool acquired_from_creds = false;
10✔
322
        int r;
10✔
323

324
        assert(rfd >= 0);
10✔
325

326
        if (arg_locale || arg_locale_messages)
10✔
327
                return 0;
328

329
        r = read_credential("firstboot.locale", (void**) &arg_locale, NULL);
6✔
330
        if (r < 0)
6✔
331
                log_debug_errno(r, "Failed to read credential firstboot.locale, ignoring: %m");
5✔
332
        else
333
                acquired_from_creds = true;
334

335
        r = read_credential("firstboot.locale-messages", (void**) &arg_locale_messages, NULL);
6✔
336
        if (r < 0)
6✔
337
                log_debug_errno(r, "Failed to read credential firstboot.locale-messages, ignoring: %m");
5✔
338
        else
339
                acquired_from_creds = true;
340

341
        if (acquired_from_creds) {
5✔
342
                log_debug("Acquired locale from credentials.");
1✔
343
                return 0;
1✔
344
        }
345

346
        if (!arg_prompt_locale) {
5✔
347
                log_debug("Prompting for locale was not requested.");
4✔
348
                return 0;
4✔
349
        }
350

351
        r = get_locales(&locales);
1✔
352
        if (r < 0)
1✔
353
                return log_error_errno(r, "Cannot query locales list: %m");
×
354

355
        if (strv_isempty(locales))
1✔
356
                log_debug("No locales found, skipping locale selection.");
×
357
        else if (strv_length(locales) == 1) {
1✔
358

359
                if (streq(locales[0], SYSTEMD_DEFAULT_LOCALE))
×
360
                        log_debug("Only installed locale is default locale anyway, not setting locale explicitly.");
×
361
                else {
362
                        log_debug("Only a single locale available (%s), selecting it as default.", locales[0]);
×
363

364
                        arg_locale = strdup(locales[0]);
×
365
                        if (!arg_locale)
×
366
                                return log_oom();
×
367

368
                        /* Not setting arg_locale_message here, since it defaults to LANG anyway */
369
                }
370
        } else {
371
                print_welcome(rfd);
1✔
372

373
                r = prompt_loop(rfd, "Please enter the new system locale name or number",
1✔
374
                                locales, 60, locale_is_ok, &arg_locale);
375
                if (r < 0)
1✔
376
                        return r;
377

378
                if (isempty(arg_locale))
11✔
379
                        return 0;
380

381
                r = prompt_loop(rfd, "Please enter the new system message locale name or number",
1✔
382
                                locales, 60, locale_is_ok, &arg_locale_messages);
383
                if (r < 0)
1✔
384
                        return r;
385

386
                /* Suppress the messages setting if it's the same as the main locale anyway */
387
                if (streq_ptr(arg_locale, arg_locale_messages))
1✔
388
                        arg_locale_messages = mfree(arg_locale_messages);
×
389
        }
390

391
        return 0;
392
}
393

394
static int process_locale(int rfd) {
133✔
395
        _cleanup_close_ int pfd = -EBADF;
133✔
396
        _cleanup_free_ char *f = NULL;
133✔
397
        char* locales[3];
133✔
398
        unsigned i = 0;
133✔
399
        int r;
133✔
400

401
        assert(rfd >= 0);
133✔
402

403
        pfd = chase_and_open_parent_at(rfd, "/etc/locale.conf",
133✔
404
                                       CHASE_AT_RESOLVE_IN_ROOT|CHASE_MKDIR_0755|CHASE_WARN|CHASE_NOFOLLOW,
405
                                       &f);
406
        if (pfd < 0)
133✔
407
                return log_error_errno(pfd, "Failed to chase /etc/locale.conf: %m");
×
408

409
        r = should_configure(pfd, f);
133✔
410
        if (r == 0)
133✔
411
                log_debug("Found /etc/locale.conf, assuming locale information has been configured.");
121✔
412
        if (r <= 0)
133✔
413
                return r;
414

415
        r = dir_fd_is_root(rfd);
12✔
416
        if (r < 0)
12✔
417
                return log_error_errno(r, "Failed to check if directory file descriptor is root: %m");
×
418

419
        if (arg_copy_locale && r == 0) {
12✔
420
                r = copy_file_atomic_at(AT_FDCWD, "/etc/locale.conf", pfd, f, 0644, COPY_REFLINK);
2✔
421
                if (r != -ENOENT) {
2✔
422
                        if (r < 0)
2✔
423
                                return log_error_errno(r, "Failed to copy host's /etc/locale.conf: %m");
×
424

425
                        log_info("Copied host's /etc/locale.conf.");
2✔
426
                        return 0;
2✔
427
                }
428
        }
429

430
        r = prompt_locale(rfd);
10✔
431
        if (r < 0)
10✔
432
                return r;
433

434
        if (!isempty(arg_locale))
10✔
435
                locales[i++] = strjoina("LANG=", arg_locale);
25✔
436
        if (!isempty(arg_locale_messages) && !streq_ptr(arg_locale_messages, arg_locale))
15✔
437
                locales[i++] = strjoina("LC_MESSAGES=", arg_locale_messages);
25✔
438

439
        if (i == 0)
10✔
440
                return 0;
441

442
        locales[i] = NULL;
6✔
443

444
        r = write_env_file(pfd, f, NULL, locales);
6✔
445
        if (r < 0)
6✔
446
                return log_error_errno(r, "Failed to write /etc/locale.conf: %m");
×
447

448
        log_info("/etc/locale.conf written.");
133✔
449
        return 1;
450
}
451

452
static bool keymap_exists_bool(const char *name) {
×
453
        return keymap_exists(name) > 0;
×
454
}
455

456
static bool keymap_is_ok(int rfd, const char* name) {
4✔
457
        int r;
4✔
458

459
        assert(rfd >= 0);
4✔
460

461
        r = dir_fd_is_root(rfd);
4✔
462
        if (r < 0)
4✔
463
                log_debug_errno(r, "Unable to determine if operating on host root directory, assuming we are: %m");
×
464

465
        return r != 0 ? keymap_exists_bool(name) : keymap_is_valid(name);
4✔
466
}
467

468
static int prompt_keymap(int rfd) {
12✔
469
        _cleanup_strv_free_ char **kmaps = NULL;
12✔
470
        int r;
12✔
471

472
        assert(rfd >= 0);
12✔
473

474
        if (arg_keymap)
12✔
475
                return 0;
476

477
        r = read_credential("firstboot.keymap", (void**) &arg_keymap, NULL);
10✔
478
        if (r < 0)
10✔
479
                log_debug_errno(r, "Failed to read credential firstboot.keymap, ignoring: %m");
9✔
480
        else {
481
                log_debug("Acquired keymap from credential.");
1✔
482
                return 0;
1✔
483
        }
484

485
        if (!arg_prompt_keymap) {
9✔
486
                log_debug("Prompting for keymap was not requested.");
8✔
487
                return 0;
8✔
488
        }
489

490
        r = get_keymaps(&kmaps);
1✔
491
        if (r == -ENOENT) /* no keymaps installed */
1✔
492
                return log_debug_errno(r, "No keymaps are installed.");
×
493
        if (r < 0)
1✔
494
                return log_error_errno(r, "Failed to read keymaps: %m");
×
495

496
        print_welcome(rfd);
1✔
497

498
        return prompt_loop(rfd, "Please enter the new keymap name or number",
1✔
499
                           kmaps, 60, keymap_is_ok, &arg_keymap);
500
}
501

502
static int process_keymap(int rfd) {
133✔
503
        _cleanup_close_ int pfd = -EBADF;
133✔
504
        _cleanup_free_ char *f = NULL;
133✔
505
        _cleanup_strv_free_ char **keymap = NULL;
×
506
        int r;
133✔
507

508
        assert(rfd >= 0);
133✔
509

510
        pfd = chase_and_open_parent_at(rfd, "/etc/vconsole.conf",
133✔
511
                                       CHASE_AT_RESOLVE_IN_ROOT|CHASE_MKDIR_0755|CHASE_WARN|CHASE_NOFOLLOW,
512
                                       &f);
513
        if (pfd < 0)
133✔
514
                return log_error_errno(pfd, "Failed to chase /etc/vconsole.conf: %m");
×
515

516
        r = should_configure(pfd, f);
133✔
517
        if (r == 0)
133✔
518
                log_debug("Found /etc/vconsole.conf, assuming console has been configured.");
119✔
519
        if (r <= 0)
133✔
520
                return r;
521

522
        r = dir_fd_is_root(rfd);
14✔
523
        if (r < 0)
14✔
524
                return log_error_errno(r, "Failed to check if directory file descriptor is root: %m");
×
525

526
        if (arg_copy_keymap && r == 0) {
14✔
527
                r = copy_file_atomic_at(AT_FDCWD, "/etc/vconsole.conf", pfd, f, 0644, COPY_REFLINK);
2✔
528
                if (r != -ENOENT) {
2✔
529
                        if (r < 0)
2✔
530
                                return log_error_errno(r, "Failed to copy host's /etc/vconsole.conf: %m");
×
531

532
                        log_info("Copied host's /etc/vconsole.conf.");
2✔
533
                        return 0;
2✔
534
                }
535
        }
536

537
        r = prompt_keymap(rfd);
12✔
538
        if (r == -ENOENT)
12✔
539
                return 0; /* don't fail if no keymaps are installed */
540
        if (r < 0)
12✔
541
                return r;
542

543
        if (isempty(arg_keymap))
137✔
544
                return 0;
545

546
        VCContext vc = {
4✔
547
                .keymap = arg_keymap,
548
        };
549
        _cleanup_(x11_context_clear) X11Context xc = {};
×
550

551
        r = vconsole_convert_to_x11(&vc, /* verify= */ NULL, &xc);
4✔
552
        if (r < 0)
4✔
553
                return log_error_errno(r, "Failed to convert keymap data: %m");
×
554

555
        r = vconsole_serialize(&vc, &xc, &keymap);
4✔
556
        if (r < 0)
4✔
557
                return log_error_errno(r, "Failed to serialize keymap data: %m");
×
558

559
        r = write_vconsole_conf(pfd, f, keymap);
4✔
560
        if (r < 0)
4✔
561
                return log_error_errno(r, "Failed to write /etc/vconsole.conf: %m");
×
562

563
        log_info("/etc/vconsole.conf written.");
4✔
564
        return 1;
565
}
566

567
static bool timezone_is_ok(int rfd, const char *name) {
1✔
568
        assert(rfd >= 0);
1✔
569

570
        return timezone_is_valid(name, LOG_DEBUG);
1✔
571
}
572

573
static int prompt_timezone(int rfd) {
72✔
574
        _cleanup_strv_free_ char **zones = NULL;
72✔
575
        int r;
72✔
576

577
        assert(rfd >= 0);
72✔
578

579
        if (arg_timezone)
72✔
580
                return 0;
581

582
        r = read_credential("firstboot.timezone", (void**) &arg_timezone, NULL);
70✔
583
        if (r < 0)
70✔
584
                log_debug_errno(r, "Failed to read credential firstboot.timezone, ignoring: %m");
11✔
585
        else {
586
                log_debug("Acquired timezone from credential.");
59✔
587
                return 0;
59✔
588
        }
589

590
        if (!arg_prompt_timezone) {
11✔
591
                log_debug("Prompting for timezone was not requested.");
10✔
592
                return 0;
10✔
593
        }
594

595
        r = get_timezones(&zones);
1✔
596
        if (r < 0)
1✔
597
                return log_error_errno(r, "Cannot query timezone list: %m");
×
598

599
        print_welcome(rfd);
1✔
600

601
        return prompt_loop(rfd, "Please enter the new timezone name or number",
1✔
602
                           zones, 30, timezone_is_ok, &arg_timezone);
603
}
604

605
static int process_timezone(int rfd) {
133✔
606
        _cleanup_close_ int pfd = -EBADF;
133✔
607
        _cleanup_free_ char *f = NULL;
133✔
608
        const char *e;
133✔
609
        int r;
133✔
610

611
        assert(rfd >= 0);
133✔
612

613
        pfd = chase_and_open_parent_at(rfd, "/etc/localtime",
133✔
614
                                       CHASE_AT_RESOLVE_IN_ROOT|CHASE_MKDIR_0755|CHASE_WARN|CHASE_NOFOLLOW,
615
                                       &f);
616
        if (pfd < 0)
133✔
617
                return log_error_errno(pfd, "Failed to chase /etc/localtime: %m");
×
618

619
        r = should_configure(pfd, f);
133✔
620
        if (r == 0)
133✔
621
                log_debug("Found /etc/localtime, assuming timezone has been configured.");
59✔
622
        if (r <= 0)
133✔
623
                return r;
624

625
        r = dir_fd_is_root(rfd);
74✔
626
        if (r < 0)
74✔
627
                return log_error_errno(r, "Failed to check if directory file descriptor is root: %m");
×
628

629
        if (arg_copy_timezone && r == 0) {
74✔
630
                _cleanup_free_ char *s = NULL;
2✔
631

632
                r = readlink_malloc("/etc/localtime", &s);
2✔
633
                if (r != -ENOENT) {
2✔
634
                        if (r < 0)
2✔
635
                                return log_error_errno(r, "Failed to read host's /etc/localtime: %m");
×
636

637
                        r = symlinkat_atomic_full(s, pfd, f, /* make_relative= */ false);
2✔
638
                        if (r < 0)
2✔
639
                                return log_error_errno(r, "Failed to create /etc/localtime symlink: %m");
×
640

641
                        log_info("Copied host's /etc/localtime.");
2✔
642
                        return 0;
2✔
643
                }
644
        }
645

646
        r = prompt_timezone(rfd);
72✔
647
        if (r < 0)
72✔
648
                return r;
649

650
        if (isempty(arg_timezone))
72✔
651
                return 0;
652

653
        e = strjoina("../usr/share/zoneinfo/", arg_timezone);
310✔
654

655
        r = symlinkat_atomic_full(e, pfd, f, /* make_relative= */ false);
62✔
656
        if (r < 0)
62✔
657
                return log_error_errno(r, "Failed to create /etc/localtime symlink: %m");
×
658

659
        log_info("/etc/localtime written");
133✔
660
        return 0;
661
}
662

663
static bool hostname_is_ok(int rfd, const char *name) {
1✔
664
        assert(rfd >= 0);
1✔
665

666
        return hostname_is_valid(name, VALID_HOSTNAME_TRAILING_DOT);
1✔
667
}
668

669
static int prompt_hostname(int rfd) {
119✔
670
        int r;
119✔
671

672
        assert(rfd >= 0);
119✔
673

674
        if (arg_hostname)
119✔
675
                return 0;
676

677
        if (!arg_prompt_hostname) {
117✔
678
                log_debug("Prompting for hostname was not requested.");
116✔
679
                return 0;
116✔
680
        }
681

682
        print_welcome(rfd);
1✔
683

684
        r = prompt_loop(rfd, "Please enter the new hostname",
1✔
685
                        NULL, 0, hostname_is_ok, &arg_hostname);
686
        if (r < 0)
1✔
687
                return r;
688

689
        if (arg_hostname)
1✔
690
                hostname_cleanup(arg_hostname);
1✔
691

692
        return 0;
693
}
694

695
static int process_hostname(int rfd) {
133✔
696
        _cleanup_close_ int pfd = -EBADF;
133✔
697
        _cleanup_free_ char *f = NULL;
133✔
698
        int r;
133✔
699

700
        assert(rfd >= 0);
133✔
701

702
        pfd = chase_and_open_parent_at(rfd, "/etc/hostname",
133✔
703
                                       CHASE_AT_RESOLVE_IN_ROOT|CHASE_MKDIR_0755|CHASE_WARN,
704
                                       &f);
705
        if (pfd < 0)
133✔
706
                return log_error_errno(pfd, "Failed to chase /etc/hostname: %m");
×
707

708
        r = should_configure(pfd, f);
133✔
709
        if (r == 0)
133✔
710
                log_debug("Found /etc/hostname, assuming hostname has been configured.");
14✔
711
        if (r <= 0)
133✔
712
                return r;
713

714
        r = prompt_hostname(rfd);
119✔
715
        if (r < 0)
119✔
716
                return r;
717

718
        if (isempty(arg_hostname))
119✔
719
                return 0;
720

721
        r = write_string_file_at(pfd, f, arg_hostname,
3✔
722
                                 WRITE_STRING_FILE_CREATE|WRITE_STRING_FILE_SYNC|WRITE_STRING_FILE_ATOMIC);
723
        if (r < 0)
3✔
724
                return log_error_errno(r, "Failed to write /etc/hostname: %m");
×
725

726
        log_info("/etc/hostname written.");
133✔
727
        return 0;
728
}
729

730
static int process_machine_id(int rfd) {
133✔
731
        _cleanup_close_ int pfd = -EBADF;
133✔
732
        _cleanup_free_ char *f = NULL;
133✔
733
        int r;
133✔
734

735
        assert(rfd >= 0);
133✔
736

737
        pfd = chase_and_open_parent_at(rfd, "/etc/machine-id",
133✔
738
                                       CHASE_AT_RESOLVE_IN_ROOT|CHASE_MKDIR_0755|CHASE_WARN|CHASE_NOFOLLOW,
739
                                       &f);
740
        if (pfd < 0)
133✔
741
                return log_error_errno(pfd, "Failed to chase /etc/machine-id: %m");
×
742

743
        r = should_configure(pfd, f);
133✔
744
        if (r == 0)
133✔
745
                log_debug("Found /etc/machine-id, assuming machine-id has been configured.");
111✔
746
        if (r <= 0)
133✔
747
                return r;
748

749
        if (sd_id128_is_null(arg_machine_id)) {
22✔
750
                log_debug("Initialization of machine-id was not requested, skipping.");
19✔
751
                return 0;
19✔
752
        }
753

754
        r = write_string_file_at(pfd, "machine-id", SD_ID128_TO_STRING(arg_machine_id),
3✔
755
                                 WRITE_STRING_FILE_CREATE|WRITE_STRING_FILE_SYNC|WRITE_STRING_FILE_ATOMIC);
756
        if (r < 0)
3✔
757
                return log_error_errno(r, "Failed to write /etc/machine-id: %m");
×
758

759
        log_info("/etc/machine-id written.");
133✔
760
        return 0;
761
}
762

763
static int prompt_root_password(int rfd) {
27✔
764
        const char *msg1, *msg2;
27✔
765
        int r;
27✔
766

767
        assert(rfd >= 0);
27✔
768

769
        if (arg_root_password)
27✔
770
                return 0;
771

772
        if (get_credential_user_password("root", &arg_root_password, &arg_root_password_is_hashed) >= 0)
18✔
773
                return 0;
774

775
        if (!arg_prompt_root_password) {
17✔
776
                log_debug("Prompting for root password was not requested.");
16✔
777
                return 0;
16✔
778
        }
779

780
        print_welcome(rfd);
1✔
781

782
        msg1 = strjoina(special_glyph(SPECIAL_GLYPH_TRIANGULAR_BULLET), " Please enter the new root password (empty to skip):");
5✔
783
        msg2 = strjoina(special_glyph(SPECIAL_GLYPH_TRIANGULAR_BULLET), " Please enter the new root password again:");
5✔
784

785
        suggest_passwords();
1✔
786

787
        for (;;) {
×
788
                _cleanup_strv_free_erase_ char **a = NULL, **b = NULL;
1✔
789
                _cleanup_free_ char *error = NULL;
1✔
790

791
                AskPasswordRequest req = {
1✔
792
                        .tty_fd = -EBADF,
793
                        .message = msg1,
794
                        .until = USEC_INFINITY,
795
                        .hup_fd = -EBADF,
796
                };
797

798
                r = ask_password_tty(&req, /* flags= */ 0, &a);
1✔
799
                if (r < 0)
1✔
800
                        return log_error_errno(r, "Failed to query root password: %m");
×
801
                if (strv_length(a) != 1)
1✔
802
                        return log_error_errno(SYNTHETIC_ERRNO(EIO),
×
803
                                               "Received multiple passwords, where we expected one.");
804

805
                if (isempty(*a)) {
1✔
806
                        log_info("No password entered, skipping.");
1✔
807
                        break;
808
                }
809

810
                r = check_password_quality(*a, /* old */ NULL, "root", &error);
×
811
                if (ERRNO_IS_NEG_NOT_SUPPORTED(r))
×
812
                        log_warning("Password quality check is not supported, proceeding anyway.");
×
813
                else if (r < 0)
×
814
                        return log_error_errno(r, "Failed to check password quality: %m");
×
815
                else if (r == 0)
×
816
                        log_warning("Password is weak, accepting anyway: %s", error);
×
817

818
                req.message = msg2;
×
819

820
                r = ask_password_tty(&req, /* flags= */ 0, &b);
×
821
                if (r < 0)
×
822
                        return log_error_errno(r, "Failed to query root password: %m");
×
823
                if (strv_length(b) != 1)
×
824
                        return log_error_errno(SYNTHETIC_ERRNO(EIO),
×
825
                                               "Received multiple passwords, where we expected one.");
826

827
                if (!streq(*a, *b)) {
×
828
                        log_error("Entered passwords did not match, please try again.");
×
829
                        continue;
×
830
                }
831

832
                arg_root_password = TAKE_PTR(*a);
×
833
                break;
×
834
        }
835

836
        return 0;
1✔
837
}
838

839
static int find_shell(int rfd, const char *path) {
7✔
840
        int r;
7✔
841

842
        assert(path);
7✔
843

844
        if (!valid_shell(path))
7✔
845
                return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "%s is not a valid shell", path);
×
846

847
        r = chaseat(rfd, path, CHASE_AT_RESOLVE_IN_ROOT, NULL, NULL);
7✔
848
        if (r < 0)
7✔
849
                return log_error_errno(r, "Failed to resolve shell %s: %m", path);
1✔
850

851
        return 0;
852
}
853

854
static bool shell_is_ok(int rfd, const char *path) {
2✔
855
        assert(rfd >= 0);
2✔
856

857
        return find_shell(rfd, path) >= 0;
2✔
858
}
859

860
static int prompt_root_shell(int rfd) {
27✔
861
        int r;
27✔
862

863
        assert(rfd >= 0);
27✔
864

865
        if (arg_root_shell)
27✔
866
                return 0;
867

868
        r = read_credential("passwd.shell.root", (void**) &arg_root_shell, NULL);
22✔
869
        if (r < 0)
22✔
870
                log_debug_errno(r, "Failed to read credential passwd.shell.root, ignoring: %m");
21✔
871
        else {
872
                log_debug("Acquired root shell from credential.");
1✔
873
                return 0;
1✔
874
        }
875

876
        if (!arg_prompt_root_shell) {
21✔
877
                log_debug("Prompting for root shell was not requested.");
19✔
878
                return 0;
19✔
879
        }
880

881
        print_welcome(rfd);
2✔
882

883
        return prompt_loop(rfd, "Please enter the new root shell",
2✔
884
                           NULL, 0, shell_is_ok, &arg_root_shell);
885
}
886

887
static int write_root_passwd(int rfd, int etc_fd, const char *password, const char *shell) {
15✔
888
        _cleanup_fclose_ FILE *original = NULL, *passwd = NULL;
15✔
889
        _cleanup_(unlink_and_freep) char *passwd_tmp = NULL;
15✔
890
        int r;
15✔
891
        bool found = false;
15✔
892

893
        r = fopen_temporary_at_label(etc_fd, "passwd", "passwd", &passwd, &passwd_tmp);
15✔
894
        if (r < 0)
15✔
895
                return r;
896

897
        r = xfopenat(etc_fd, "passwd", "re", O_NOFOLLOW, &original);
15✔
898
        if (r < 0 && r != -ENOENT)
15✔
899
                return r;
900

901
        if (original) {
15✔
902
                struct passwd *i;
4✔
903

904
                r = copy_rights(fileno(original), fileno(passwd));
4✔
905
                if (r < 0)
4✔
906
                        return r;
×
907

908
                while ((r = fgetpwent_sane(original, &i)) > 0) {
7✔
909

910
                        if (streq(i->pw_name, "root")) {
3✔
911
                                if (password)
3✔
912
                                        i->pw_passwd = (char *) password;
2✔
913
                                if (shell)
3✔
914
                                        i->pw_shell = (char *) shell;
2✔
915
                                found = true;
916
                        }
917

918
                        r = putpwent_sane(i, passwd);
3✔
919
                        if (r < 0)
3✔
920
                                return r;
921
                }
922
                if (r < 0)
4✔
923
                        return r;
924

925
        } else {
926
                r = fchmod(fileno(passwd), 0644);
11✔
927
                if (r < 0)
11✔
928
                        return -errno;
×
929
        }
930

931
        if (!found) {
4✔
932
                struct passwd root = {
12✔
933
                        .pw_name = (char *) "root",
934
                        .pw_passwd = (char *) (password ?: PASSWORD_SEE_SHADOW),
12✔
935
                        .pw_uid = 0,
936
                        .pw_gid = 0,
937
                        .pw_gecos = (char *) "Super User",
938
                        .pw_dir = (char *) "/root",
939
                        .pw_shell = (char *) (shell ?: default_root_shell_at(rfd)),
6✔
940
                };
941

942
                if (errno != ENOENT)
12✔
943
                        return -errno;
×
944

945
                r = putpwent_sane(&root, passwd);
12✔
946
                if (r < 0)
12✔
947
                        return r;
948
        }
949

950
        r = fflush_sync_and_check(passwd);
15✔
951
        if (r < 0)
15✔
952
                return r;
953

954
        r = renameat_and_apply_smack_floor_label(etc_fd, passwd_tmp, etc_fd, "passwd");
15✔
955
        if (r < 0)
15✔
956
                return r;
×
957

958
        return 0;
959
}
960

961
static int write_root_shadow(int etc_fd, const char *hashed_password) {
15✔
962
        _cleanup_fclose_ FILE *original = NULL, *shadow = NULL;
15✔
963
        _cleanup_(unlink_and_freep) char *shadow_tmp = NULL;
15✔
964
        int r;
15✔
965
        bool found = false;
15✔
966

967
        r = fopen_temporary_at_label(etc_fd, "shadow", "shadow", &shadow, &shadow_tmp);
15✔
968
        if (r < 0)
15✔
969
                return r;
970

971
        r = xfopenat(etc_fd, "shadow", "re", O_NOFOLLOW, &original);
15✔
972
        if (r < 0 && r != -ENOENT)
15✔
973
                return r;
974

975
        if (original) {
15✔
976
                struct spwd *i;
4✔
977

978
                r = copy_rights(fileno(original), fileno(shadow));
4✔
979
                if (r < 0)
4✔
980
                        return r;
×
981

982
                while ((r = fgetspent_sane(original, &i)) > 0) {
7✔
983

984
                        if (streq(i->sp_namp, "root")) {
3✔
985
                                if (hashed_password) {
3✔
986
                                        i->sp_pwdp = (char *) hashed_password;
2✔
987
                                        i->sp_lstchg = (long) (now(CLOCK_REALTIME) / USEC_PER_DAY);
2✔
988
                                }
989
                                found = true;
990
                        }
991

992
                        r = putspent_sane(i, shadow);
3✔
993
                        if (r < 0)
3✔
994
                                return r;
995
                }
996
                if (r < 0)
4✔
997
                        return r;
998

999
        } else {
1000
                r = fchmod(fileno(shadow), 0000);
11✔
1001
                if (r < 0)
11✔
1002
                        return -errno;
×
1003
        }
1004

1005
        if (!found) {
4✔
1006
                struct spwd root = {
36✔
1007
                        .sp_namp = (char*) "root",
1008
                        .sp_pwdp = (char *) (hashed_password ?: PASSWORD_LOCKED_AND_INVALID),
12✔
1009
                        .sp_lstchg = (long) (now(CLOCK_REALTIME) / USEC_PER_DAY),
12✔
1010
                        .sp_min = -1,
1011
                        .sp_max = -1,
1012
                        .sp_warn = -1,
1013
                        .sp_inact = -1,
1014
                        .sp_expire = -1,
1015
                        .sp_flag = ULONG_MAX, /* this appears to be what everybody does ... */
1016
                };
1017

1018
                if (errno != ENOENT)
12✔
1019
                        return -errno;
×
1020

1021
                r = putspent_sane(&root, shadow);
12✔
1022
                if (r < 0)
12✔
1023
                        return r;
1024
        }
1025

1026
        r = fflush_sync_and_check(shadow);
15✔
1027
        if (r < 0)
15✔
1028
                return r;
1029

1030
        r = renameat_and_apply_smack_floor_label(etc_fd, shadow_tmp, etc_fd, "shadow");
15✔
1031
        if (r < 0)
15✔
1032
                return r;
×
1033

1034
        return 0;
1035
}
1036

1037
static int process_root_account(int rfd) {
133✔
1038
        _cleanup_close_ int pfd = -EBADF;
133✔
1039
        _cleanup_(release_lock_file) LockFile lock = LOCK_FILE_INIT;
×
1040
        _cleanup_(erase_and_freep) char *_hashed_password = NULL;
133✔
1041
        const char *password, *hashed_password;
133✔
1042
        int k = 0, r;
133✔
1043

1044
        assert(rfd >= 0);
133✔
1045

1046
        pfd = chase_and_open_parent_at(rfd, "/etc/passwd",
133✔
1047
                                       CHASE_AT_RESOLVE_IN_ROOT|CHASE_MKDIR_0755|CHASE_WARN|CHASE_NOFOLLOW,
1048
                                       NULL);
1049
        if (pfd < 0)
133✔
1050
                return log_error_errno(pfd, "Failed to chase /etc/passwd: %m");
×
1051

1052
        /* Ensure that passwd and shadow are in the same directory and are not symlinks. */
1053

1054
        FOREACH_STRING(s, "passwd", "shadow") {
399✔
1055
                r = verify_regular_at(pfd, s, /* follow = */ false);
266✔
1056
                if (r < 0 && r != -ENOENT)
266✔
1057
                        return log_error_errno(r, "Verification of /etc/%s being regular file failed: %m", s);
×
1058

1059
                r = should_configure(pfd, s);
266✔
1060
                if (r < 0)
266✔
1061
                        return r;
1062

1063
                k += r;
266✔
1064
        }
1065

1066
        if (k == 0) {
133✔
1067
                log_debug("Found /etc/passwd and /etc/shadow, assuming root account has been initialized.");
106✔
1068
                return 0;
106✔
1069
        }
1070

1071
        r = make_lock_file_at(pfd, ETC_PASSWD_LOCK_FILENAME, LOCK_EX, &lock);
27✔
1072
        if (r < 0)
27✔
1073
                return log_error_errno(r, "Failed to take a lock on /etc/passwd: %m");
×
1074

1075
        k = dir_fd_is_root(rfd);
27✔
1076
        if (k < 0)
27✔
1077
                return log_error_errno(k, "Failed to check if directory file descriptor is root: %m");
×
1078

1079
        if (arg_copy_root_shell && k == 0) {
27✔
1080
                _cleanup_free_ struct passwd *p = NULL;
2✔
1081

1082
                r = getpwnam_malloc("root", &p);
2✔
1083
                if (r < 0)
2✔
1084
                        return log_error_errno(r, "Failed to find passwd entry for root: %m");
×
1085

1086
                r = free_and_strdup(&arg_root_shell, p->pw_shell);
2✔
1087
                if (r < 0)
2✔
1088
                        return log_oom();
×
1089
        }
1090

1091
        r = prompt_root_shell(rfd);
27✔
1092
        if (r < 0)
27✔
1093
                return r;
1094

1095
        if (arg_copy_root_password && k == 0) {
27✔
1096
                struct spwd *p;
2✔
1097

1098
                errno = 0;
2✔
1099
                p = getspnam("root");
2✔
1100
                if (!p)
2✔
1101
                        return log_error_errno(errno_or_else(EIO), "Failed to find shadow entry for root: %m");
×
1102

1103
                r = free_and_strdup(&arg_root_password, p->sp_pwdp);
2✔
1104
                if (r < 0)
2✔
1105
                        return log_oom();
×
1106

1107
                arg_root_password_is_hashed = true;
2✔
1108
        }
1109

1110
        r = prompt_root_password(rfd);
27✔
1111
        if (r < 0)
27✔
1112
                return r;
1113

1114
        if (arg_root_password && arg_root_password_is_hashed) {
27✔
1115
                password = PASSWORD_SEE_SHADOW;
1116
                hashed_password = arg_root_password;
1117
        } else if (arg_root_password) {
21✔
1118
                r = hash_password(arg_root_password, &_hashed_password);
4✔
1119
                if (r < 0)
4✔
1120
                        return log_error_errno(r, "Failed to hash password: %m");
×
1121

1122
                password = PASSWORD_SEE_SHADOW;
4✔
1123
                hashed_password = _hashed_password;
4✔
1124

1125
        } else if (arg_delete_root_password) {
17✔
1126
                password = PASSWORD_SEE_SHADOW;
1127
                hashed_password = PASSWORD_NONE;
1128
        } else if (!arg_root_password && arg_prompt_root_password) {
16✔
1129
                /* If the user was prompted, but no password was supplied, lock the account. */
1130
                password = PASSWORD_SEE_SHADOW;
1131
                hashed_password = PASSWORD_LOCKED_AND_INVALID;
1132
        } else
1133
                /* Leave the password as is. */
1134
                password = hashed_password = NULL;
15✔
1135

1136
        /* Don't create/modify passwd and shadow if there's nothing to do. */
1137
        if (!(password || hashed_password || arg_root_shell)) {
27✔
1138
                log_debug("Initialization of root account was not requested, skipping.");
12✔
1139
                return 0;
12✔
1140
        }
1141

1142
        r = write_root_passwd(rfd, pfd, password, arg_root_shell);
15✔
1143
        if (r < 0)
15✔
1144
                return log_error_errno(r, "Failed to write /etc/passwd: %m");
×
1145

1146
        log_info("/etc/passwd written.");
15✔
1147

1148
        r = write_root_shadow(pfd, hashed_password);
15✔
1149
        if (r < 0)
15✔
1150
                return log_error_errno(r, "Failed to write /etc/shadow: %m");
×
1151

1152
        log_info("/etc/shadow written.");
133✔
1153
        return 0;
1154
}
1155

1156
static int process_kernel_cmdline(int rfd) {
133✔
1157
        _cleanup_close_ int pfd = -EBADF;
133✔
1158
        _cleanup_free_ char *f = NULL;
133✔
1159
        int r;
133✔
1160

1161
        assert(rfd >= 0);
133✔
1162

1163
        pfd = chase_and_open_parent_at(rfd, "/etc/kernel/cmdline",
133✔
1164
                                       CHASE_AT_RESOLVE_IN_ROOT|CHASE_MKDIR_0755|CHASE_WARN|CHASE_NOFOLLOW,
1165
                                       &f);
1166
        if (pfd < 0)
133✔
1167
                return log_error_errno(pfd, "Failed to chase /etc/kernel/cmdline: %m");
×
1168

1169
        r = should_configure(pfd, f);
133✔
1170
        if (r == 0)
133✔
1171
                log_debug("Found /etc/kernel/cmdline, assuming kernel command line has been configured.");
1✔
1172
        if (r <= 0)
133✔
1173
                return r;
1174

1175
        if (!arg_kernel_cmdline) {
132✔
1176
                log_debug("Creation of /etc/kernel/cmdline was not requested, skipping.");
130✔
1177
                return 0;
130✔
1178
        }
1179

1180
        r = write_string_file_at(pfd, "cmdline", arg_kernel_cmdline,
2✔
1181
                                 WRITE_STRING_FILE_CREATE|WRITE_STRING_FILE_SYNC|WRITE_STRING_FILE_ATOMIC);
1182
        if (r < 0)
2✔
1183
                return log_error_errno(r, "Failed to write /etc/kernel/cmdline: %m");
×
1184

1185
        log_info("/etc/kernel/cmdline written.");
133✔
1186
        return 0;
1187
}
1188

1189
static int reset_one(int rfd, const char *path) {
6✔
1190
        _cleanup_close_ int pfd = -EBADF;
6✔
1191
        _cleanup_free_ char *f = NULL;
6✔
1192

1193
        assert(rfd >= 0);
6✔
1194
        assert(path);
6✔
1195

1196
        pfd = chase_and_open_parent_at(rfd, path, CHASE_AT_RESOLVE_IN_ROOT|CHASE_WARN|CHASE_NOFOLLOW, &f);
6✔
1197
        if (pfd == -ENOENT)
6✔
1198
                return 0;
1199
        if (pfd < 0)
6✔
1200
                return log_error_errno(pfd, "Failed to resolve %s: %m", path);
×
1201

1202
        if (unlinkat(pfd, f, 0) < 0)
6✔
1203
                return errno == ENOENT ? 0 : log_error_errno(errno, "Failed to remove %s: %m", path);
×
1204

1205
        log_info("Removed %s", path);
6✔
1206
        return 0;
1207
}
1208

1209
static int process_reset(int rfd) {
133✔
1210
        int r;
133✔
1211

1212
        assert(rfd >= 0);
133✔
1213

1214
        if (!arg_reset)
133✔
1215
                return 0;
1216

1217
        FOREACH_STRING(p,
7✔
1218
                       "/etc/locale.conf",
1219
                       "/etc/vconsole.conf",
1220
                       "/etc/hostname",
1221
                       "/etc/machine-id",
1222
                       "/etc/kernel/cmdline",
1223
                       "/etc/localtime") {
1224
                r = reset_one(rfd, p);
6✔
1225
                if (r < 0)
6✔
1226
                        return r;
×
1227
        }
1228

1229
        return 0;
1✔
1230
}
1231

1232
static int help(void) {
×
1233
        _cleanup_free_ char *link = NULL;
×
1234
        int r;
×
1235

1236
        r = terminal_urlify_man("systemd-firstboot", "1", &link);
×
1237
        if (r < 0)
×
1238
                return log_oom();
×
1239

1240
        printf("%s [OPTIONS...]\n\n"
×
1241
               "Configures basic settings of the system.\n\n"
1242
               "  -h --help                       Show this help\n"
1243
               "     --version                    Show package version\n"
1244
               "     --root=PATH                  Operate on an alternate filesystem root\n"
1245
               "     --image=PATH                 Operate on disk image as filesystem root\n"
1246
               "     --image-policy=POLICY        Specify disk image dissection policy\n"
1247
               "     --locale=LOCALE              Set primary locale (LANG=)\n"
1248
               "     --locale-messages=LOCALE     Set message locale (LC_MESSAGES=)\n"
1249
               "     --keymap=KEYMAP              Set keymap\n"
1250
               "     --timezone=TIMEZONE          Set timezone\n"
1251
               "     --hostname=NAME              Set hostname\n"
1252
               "     --setup-machine-id           Set a random machine ID\n"
1253
               "     --machine-id=ID              Set specified machine ID\n"
1254
               "     --root-password=PASSWORD     Set root password from plaintext password\n"
1255
               "     --root-password-file=FILE    Set root password from file\n"
1256
               "     --root-password-hashed=HASH  Set root password from hashed password\n"
1257
               "     --root-shell=SHELL           Set root shell\n"
1258
               "     --kernel-command-line=CMDLINE\n"
1259
               "                                  Set kernel command line\n"
1260
               "     --prompt-locale              Prompt the user for locale settings\n"
1261
               "     --prompt-keymap              Prompt the user for keymap settings\n"
1262
               "     --prompt-timezone            Prompt the user for timezone\n"
1263
               "     --prompt-hostname            Prompt the user for hostname\n"
1264
               "     --prompt-root-password       Prompt the user for root password\n"
1265
               "     --prompt-root-shell          Prompt the user for root shell\n"
1266
               "     --prompt                     Prompt for all of the above\n"
1267
               "     --copy-locale                Copy locale from host\n"
1268
               "     --copy-keymap                Copy keymap from host\n"
1269
               "     --copy-timezone              Copy timezone from host\n"
1270
               "     --copy-root-password         Copy root password from host\n"
1271
               "     --copy-root-shell            Copy root shell from host\n"
1272
               "     --copy                       Copy locale, keymap, timezone, root password\n"
1273
               "     --force                      Overwrite existing files\n"
1274
               "     --delete-root-password       Delete root password\n"
1275
               "     --welcome=no                 Disable the welcome text\n"
1276
               "     --reset                      Remove existing files\n"
1277
               "\nSee the %s for details.\n",
1278
               program_invocation_short_name,
1279
               link);
1280

1281
        return 0;
1282
}
1283

1284
static int parse_argv(int argc, char *argv[]) {
136✔
1285

1286
        enum {
136✔
1287
                ARG_VERSION = 0x100,
1288
                ARG_ROOT,
1289
                ARG_IMAGE,
1290
                ARG_IMAGE_POLICY,
1291
                ARG_LOCALE,
1292
                ARG_LOCALE_MESSAGES,
1293
                ARG_KEYMAP,
1294
                ARG_TIMEZONE,
1295
                ARG_HOSTNAME,
1296
                ARG_SETUP_MACHINE_ID,
1297
                ARG_MACHINE_ID,
1298
                ARG_ROOT_PASSWORD,
1299
                ARG_ROOT_PASSWORD_FILE,
1300
                ARG_ROOT_PASSWORD_HASHED,
1301
                ARG_ROOT_SHELL,
1302
                ARG_KERNEL_COMMAND_LINE,
1303
                ARG_PROMPT,
1304
                ARG_PROMPT_LOCALE,
1305
                ARG_PROMPT_KEYMAP,
1306
                ARG_PROMPT_TIMEZONE,
1307
                ARG_PROMPT_HOSTNAME,
1308
                ARG_PROMPT_ROOT_PASSWORD,
1309
                ARG_PROMPT_ROOT_SHELL,
1310
                ARG_COPY,
1311
                ARG_COPY_LOCALE,
1312
                ARG_COPY_KEYMAP,
1313
                ARG_COPY_TIMEZONE,
1314
                ARG_COPY_ROOT_PASSWORD,
1315
                ARG_COPY_ROOT_SHELL,
1316
                ARG_FORCE,
1317
                ARG_DELETE_ROOT_PASSWORD,
1318
                ARG_WELCOME,
1319
                ARG_RESET,
1320
        };
1321

1322
        static const struct option options[] = {
136✔
1323
                { "help",                    no_argument,       NULL, 'h'                         },
1324
                { "version",                 no_argument,       NULL, ARG_VERSION                 },
1325
                { "root",                    required_argument, NULL, ARG_ROOT                    },
1326
                { "image",                   required_argument, NULL, ARG_IMAGE                   },
1327
                { "image-policy",            required_argument, NULL, ARG_IMAGE_POLICY            },
1328
                { "locale",                  required_argument, NULL, ARG_LOCALE                  },
1329
                { "locale-messages",         required_argument, NULL, ARG_LOCALE_MESSAGES         },
1330
                { "keymap",                  required_argument, NULL, ARG_KEYMAP                  },
1331
                { "timezone",                required_argument, NULL, ARG_TIMEZONE                },
1332
                { "hostname",                required_argument, NULL, ARG_HOSTNAME                },
1333
                { "setup-machine-id",        no_argument,       NULL, ARG_SETUP_MACHINE_ID        },
1334
                { "machine-id",              required_argument, NULL, ARG_MACHINE_ID              },
1335
                { "root-password",           required_argument, NULL, ARG_ROOT_PASSWORD           },
1336
                { "root-password-file",      required_argument, NULL, ARG_ROOT_PASSWORD_FILE      },
1337
                { "root-password-hashed",    required_argument, NULL, ARG_ROOT_PASSWORD_HASHED    },
1338
                { "root-shell",              required_argument, NULL, ARG_ROOT_SHELL              },
1339
                { "kernel-command-line",     required_argument, NULL, ARG_KERNEL_COMMAND_LINE     },
1340
                { "prompt",                  no_argument,       NULL, ARG_PROMPT                  },
1341
                { "prompt-locale",           no_argument,       NULL, ARG_PROMPT_LOCALE           },
1342
                { "prompt-keymap",           no_argument,       NULL, ARG_PROMPT_KEYMAP           },
1343
                { "prompt-timezone",         no_argument,       NULL, ARG_PROMPT_TIMEZONE         },
1344
                { "prompt-hostname",         no_argument,       NULL, ARG_PROMPT_HOSTNAME         },
1345
                { "prompt-root-password",    no_argument,       NULL, ARG_PROMPT_ROOT_PASSWORD    },
1346
                { "prompt-root-shell",       no_argument,       NULL, ARG_PROMPT_ROOT_SHELL       },
1347
                { "copy",                    no_argument,       NULL, ARG_COPY                    },
1348
                { "copy-locale",             no_argument,       NULL, ARG_COPY_LOCALE             },
1349
                { "copy-keymap",             no_argument,       NULL, ARG_COPY_KEYMAP             },
1350
                { "copy-timezone",           no_argument,       NULL, ARG_COPY_TIMEZONE           },
1351
                { "copy-root-password",      no_argument,       NULL, ARG_COPY_ROOT_PASSWORD      },
1352
                { "copy-root-shell",         no_argument,       NULL, ARG_COPY_ROOT_SHELL         },
1353
                { "force",                   no_argument,       NULL, ARG_FORCE                   },
1354
                { "delete-root-password",    no_argument,       NULL, ARG_DELETE_ROOT_PASSWORD    },
1355
                { "welcome",                 required_argument, NULL, ARG_WELCOME                 },
1356
                { "reset",                   no_argument,       NULL, ARG_RESET                   },
1357
                {}
1358
        };
1359

1360
        int r, c;
136✔
1361

1362
        assert(argc >= 0);
136✔
1363
        assert(argv);
136✔
1364

1365
        while ((c = getopt_long(argc, argv, "h", options, NULL)) >= 0)
637✔
1366

1367
                switch (c) {
503✔
1368

1369
                case 'h':
×
1370
                        return help();
×
1371

1372
                case ARG_VERSION:
×
1373
                        return version();
×
1374

1375
                case ARG_ROOT:
35✔
1376
                        r = parse_path_argument(optarg, true, &arg_root);
35✔
1377
                        if (r < 0)
35✔
1378
                                return r;
1379
                        break;
1380

1381
                case ARG_IMAGE:
×
1382
                        r = parse_path_argument(optarg, false, &arg_image);
×
1383
                        if (r < 0)
×
1384
                                return r;
1385
                        break;
1386

1387
                case ARG_IMAGE_POLICY:
×
1388
                        r = parse_image_policy_argument(optarg, &arg_image_policy);
×
1389
                        if (r < 0)
×
1390
                                return r;
1391
                        break;
1392

1393
                case ARG_LOCALE:
4✔
1394
                        r = free_and_strdup(&arg_locale, optarg);
4✔
1395
                        if (r < 0)
4✔
1396
                                return log_oom();
×
1397

1398
                        break;
1399

1400
                case ARG_LOCALE_MESSAGES:
4✔
1401
                        r = free_and_strdup(&arg_locale_messages, optarg);
4✔
1402
                        if (r < 0)
4✔
1403
                                return log_oom();
×
1404

1405
                        break;
1406

1407
                case ARG_KEYMAP:
3✔
1408
                        if (!keymap_is_valid(optarg))
3✔
1409
                                return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
×
1410
                                                       "Keymap %s is not valid.", optarg);
1411

1412
                        r = free_and_strdup(&arg_keymap, optarg);
3✔
1413
                        if (r < 0)
3✔
1414
                                return log_oom();
×
1415

1416
                        break;
1417

1418
                case ARG_TIMEZONE:
4✔
1419
                        if (!timezone_is_valid(optarg, LOG_ERR))
4✔
1420
                                return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
1✔
1421
                                                       "Timezone %s is not valid.", optarg);
1422

1423
                        r = free_and_strdup(&arg_timezone, optarg);
3✔
1424
                        if (r < 0)
3✔
1425
                                return log_oom();
×
1426

1427
                        break;
1428

1429
                case ARG_ROOT_PASSWORD:
4✔
1430
                        r = free_and_strdup(&arg_root_password, optarg);
4✔
1431
                        if (r < 0)
4✔
1432
                                return log_oom();
×
1433

1434
                        arg_root_password_is_hashed = false;
4✔
1435
                        break;
4✔
1436

1437
                case ARG_ROOT_PASSWORD_FILE:
1✔
1438
                        arg_root_password = mfree(arg_root_password);
1✔
1439

1440
                        r = read_one_line_file(optarg, &arg_root_password);
1✔
1441
                        if (r < 0)
1✔
1442
                                return log_error_errno(r, "Failed to read %s: %m", optarg);
×
1443

1444
                        arg_root_password_is_hashed = false;
1✔
1445
                        break;
1✔
1446

1447
                case ARG_ROOT_PASSWORD_HASHED:
4✔
1448
                        r = free_and_strdup(&arg_root_password, optarg);
4✔
1449
                        if (r < 0)
4✔
1450
                                return log_oom();
×
1451

1452
                        arg_root_password_is_hashed = true;
4✔
1453
                        break;
4✔
1454

1455
                case ARG_ROOT_SHELL:
5✔
1456
                        r = free_and_strdup(&arg_root_shell, optarg);
5✔
1457
                        if (r < 0)
5✔
1458
                                return log_oom();
×
1459

1460
                        break;
1461

1462
                case ARG_HOSTNAME:
3✔
1463
                        if (!hostname_is_valid(optarg, VALID_HOSTNAME_TRAILING_DOT))
3✔
1464
                                return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
×
1465
                                                       "Host name %s is not valid.", optarg);
1466

1467
                        r = free_and_strdup(&arg_hostname, optarg);
3✔
1468
                        if (r < 0)
3✔
1469
                                return log_oom();
×
1470

1471
                        hostname_cleanup(arg_hostname);
3✔
1472
                        break;
3✔
1473

1474
                case ARG_SETUP_MACHINE_ID:
1✔
1475
                        r = sd_id128_randomize(&arg_machine_id);
1✔
1476
                        if (r < 0)
1✔
1477
                                return log_error_errno(r, "Failed to generate randomized machine ID: %m");
×
1478

1479
                        break;
1480

1481
                case ARG_MACHINE_ID:
4✔
1482
                        r = sd_id128_from_string(optarg, &arg_machine_id);
4✔
1483
                        if (r < 0)
4✔
1484
                                return log_error_errno(r, "Failed to parse machine id %s.", optarg);
1✔
1485

1486
                        break;
1487

1488
                case ARG_KERNEL_COMMAND_LINE:
3✔
1489
                        r = free_and_strdup(&arg_kernel_cmdline, optarg);
3✔
1490
                        if (r < 0)
3✔
1491
                                return log_oom();
×
1492

1493
                        break;
1494

1495
                case ARG_PROMPT:
×
1496
                        arg_prompt_locale = arg_prompt_keymap = arg_prompt_timezone = arg_prompt_hostname =
×
1497
                                arg_prompt_root_password = arg_prompt_root_shell = true;
×
1498
                        break;
×
1499

1500
                case ARG_PROMPT_LOCALE:
103✔
1501
                        arg_prompt_locale = true;
103✔
1502
                        break;
103✔
1503

1504
                case ARG_PROMPT_KEYMAP:
103✔
1505
                        arg_prompt_keymap = true;
103✔
1506
                        break;
103✔
1507

1508
                case ARG_PROMPT_TIMEZONE:
103✔
1509
                        arg_prompt_timezone = true;
103✔
1510
                        break;
103✔
1511

1512
                case ARG_PROMPT_HOSTNAME:
1✔
1513
                        arg_prompt_hostname = true;
1✔
1514
                        break;
1✔
1515

1516
                case ARG_PROMPT_ROOT_PASSWORD:
103✔
1517
                        arg_prompt_root_password = true;
103✔
1518
                        break;
103✔
1519

1520
                case ARG_PROMPT_ROOT_SHELL:
4✔
1521
                        arg_prompt_root_shell = true;
4✔
1522
                        break;
4✔
1523

1524
                case ARG_COPY:
1✔
1525
                        arg_copy_locale = arg_copy_keymap = arg_copy_timezone = arg_copy_root_password =
1✔
1526
                                arg_copy_root_shell = true;
1✔
1527
                        break;
1✔
1528

1529
                case ARG_COPY_LOCALE:
1✔
1530
                        arg_copy_locale = true;
1✔
1531
                        break;
1✔
1532

1533
                case ARG_COPY_KEYMAP:
1✔
1534
                        arg_copy_keymap = true;
1✔
1535
                        break;
1✔
1536

1537
                case ARG_COPY_TIMEZONE:
1✔
1538
                        arg_copy_timezone = true;
1✔
1539
                        break;
1✔
1540

1541
                case ARG_COPY_ROOT_PASSWORD:
1✔
1542
                        arg_copy_root_password = true;
1✔
1543
                        break;
1✔
1544

1545
                case ARG_COPY_ROOT_SHELL:
1✔
1546
                        arg_copy_root_shell = true;
1✔
1547
                        break;
1✔
1548

1549
                case ARG_FORCE:
2✔
1550
                        arg_force = true;
2✔
1551
                        break;
2✔
1552

1553
                case ARG_DELETE_ROOT_PASSWORD:
1✔
1554
                        arg_delete_root_password = true;
1✔
1555
                        break;
1✔
1556

1557
                case ARG_WELCOME:
1✔
1558
                        r = parse_boolean(optarg);
1✔
1559
                        if (r < 0)
1✔
1560
                                return log_error_errno(r, "Failed to parse --welcome= argument: %s", optarg);
×
1561

1562
                        arg_welcome = r;
1✔
1563
                        break;
1✔
1564

1565
                case ARG_RESET:
1✔
1566
                        arg_reset = true;
1✔
1567
                        break;
1✔
1568

1569
                case '?':
1570
                        return -EINVAL;
1571

1572
                default:
×
1573
                        assert_not_reached();
×
1574
                }
1575

1576
        if (arg_delete_root_password && (arg_copy_root_password || arg_root_password || arg_prompt_root_password))
134✔
1577
                return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
×
1578
                                       "--delete-root-password cannot be combined with other root password options.");
1579

1580
        if (arg_image && arg_root)
134✔
1581
                return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
×
1582
                                       "--root= and --image= cannot be used together.");
1583

1584
        if (!sd_id128_is_null(arg_machine_id) && !(arg_image || arg_root) && !arg_force)
264✔
1585
                return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
×
1586
                                       "--machine-id=/--setup-machine-id only works with --root= or --image=.");
1587

1588
        return 1;
1589
}
1590

1591
static int reload_system_manager(sd_bus **bus) {
×
1592
        int r;
×
1593

1594
        assert(bus);
×
1595

1596
        if (!*bus) {
×
1597
                r = bus_connect_transport_systemd(BUS_TRANSPORT_LOCAL, NULL, RUNTIME_SCOPE_SYSTEM, bus);
×
1598
                if (r < 0)
×
1599
                        return bus_log_connect_error(r, BUS_TRANSPORT_LOCAL, RUNTIME_SCOPE_SYSTEM);
×
1600
        }
1601

1602
        r = bus_service_manager_reload(*bus);
×
1603
        if (r < 0)
×
1604
                return r;
1605

1606
        log_info("Requested manager reload to apply locale configuration.");
×
1607
        return 0;
1608
}
1609

1610
static int reload_vconsole(sd_bus **bus) {
×
1611
        _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
×
1612
        _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
×
1613
        _cleanup_(bus_wait_for_jobs_freep) BusWaitForJobs *w = NULL;
×
1614
        const char *object;
×
1615
        int r;
×
1616

1617
        assert(bus);
×
1618

1619
        if (!*bus) {
×
1620
                r = bus_connect_transport_systemd(BUS_TRANSPORT_LOCAL, NULL, RUNTIME_SCOPE_SYSTEM, bus);
×
1621
                if (r < 0)
×
1622
                        return bus_log_connect_error(r, BUS_TRANSPORT_LOCAL, RUNTIME_SCOPE_SYSTEM);
×
1623
        }
1624

1625
        r = bus_wait_for_jobs_new(*bus, &w);
×
1626
        if (r < 0)
×
1627
                return log_error_errno(r, "Could not watch jobs: %m");
×
1628

1629
        r = bus_call_method(*bus, bus_systemd_mgr, "RestartUnit", &error, &reply,
×
1630
                            "ss", "systemd-vconsole-setup.service", "replace");
1631
        if (r < 0)
×
1632
                return log_error_errno(r, "Failed to issue method call: %s", bus_error_message(&error, r));
×
1633

1634
        r = sd_bus_message_read(reply, "o", &object);
×
1635
        if (r < 0)
×
1636
                return bus_log_parse_error(r);
×
1637

1638
        r = bus_wait_for_jobs_one(w, object, BUS_WAIT_JOBS_LOG_ERROR, NULL);
×
1639
        if (r < 0)
×
1640
                return log_error_errno(r, "Failed to wait for systemd-vconsole-setup.service/restart: %m");
×
1641
        return 0;
1642
}
1643

1644
static int run(int argc, char *argv[]) {
136✔
1645
        _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
136✔
1646
        _cleanup_(loop_device_unrefp) LoopDevice *loop_device = NULL;
136✔
1647
        _cleanup_(umount_and_freep) char *mounted_dir = NULL;
×
1648
        _cleanup_close_ int rfd = -EBADF;
136✔
1649
        int r;
136✔
1650

1651
        r = parse_argv(argc, argv);
136✔
1652
        if (r <= 0)
136✔
1653
                return r;
1654

1655
        log_setup();
134✔
1656

1657
        umask(0022);
134✔
1658

1659
        bool offline = arg_root || arg_image;
134✔
1660

1661
        if (!offline) {
101✔
1662
                /* If we are called without --root=/--image= let's honour the systemd.firstboot kernel
1663
                 * command line option, because we are called to provision the host with basic settings (as
1664
                 * opposed to some other file system tree/image) */
1665

1666
                bool enabled;
101✔
1667
                r = proc_cmdline_get_bool("systemd.firstboot", /* flags = */ 0, &enabled);
101✔
1668
                if (r < 0)
101✔
1669
                        return log_error_errno(r, "Failed to parse systemd.firstboot= kernel command line argument, ignoring: %m");
×
1670
                if (r > 0 && !enabled) {
101✔
1671
                        log_debug("Found systemd.firstboot=no kernel command line argument, turning off all prompts.");
101✔
1672
                        arg_prompt_locale = arg_prompt_keymap = arg_prompt_timezone = arg_prompt_hostname = arg_prompt_root_password = arg_prompt_root_shell = false;
101✔
1673
                }
1674
        }
1675

1676
        if (arg_image) {
134✔
1677
                assert(!arg_root);
×
1678

1679
                r = mount_image_privately_interactively(
×
1680
                                arg_image,
1681
                                arg_image_policy,
1682
                                DISSECT_IMAGE_GENERIC_ROOT |
1683
                                DISSECT_IMAGE_REQUIRE_ROOT |
1684
                                DISSECT_IMAGE_VALIDATE_OS |
1685
                                DISSECT_IMAGE_RELAX_VAR_CHECK |
1686
                                DISSECT_IMAGE_FSCK |
1687
                                DISSECT_IMAGE_GROWFS |
1688
                                DISSECT_IMAGE_ALLOW_USERSPACE_VERITY,
1689
                                &mounted_dir,
1690
                                &rfd,
1691
                                &loop_device);
1692
                if (r < 0)
×
1693
                        return r;
1694

1695
                arg_root = strdup(mounted_dir);
×
1696
                if (!arg_root)
×
1697
                        return log_oom();
×
1698
        } else {
1699
                rfd = open(empty_to_root(arg_root), O_DIRECTORY|O_CLOEXEC);
167✔
1700
                if (rfd < 0)
134✔
1701
                        return log_error_errno(errno, "Failed to open %s: %m", empty_to_root(arg_root));
×
1702
        }
1703

1704
        LOG_SET_PREFIX(arg_image ?: arg_root);
270✔
1705

1706
        /* We check these conditions here instead of in parse_argv() so that we can take the root directory
1707
         * into account. */
1708

1709
        if (arg_keymap && !keymap_is_ok(rfd, arg_keymap))
134✔
1710
                return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Keymap %s is not installed.", arg_keymap);
×
1711
        if (arg_locale && !locale_is_ok(rfd, arg_locale))
134✔
1712
                return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Locale %s is not installed.", arg_locale);
×
1713
        if (arg_locale_messages && !locale_is_ok(rfd, arg_locale_messages))
134✔
1714
                return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Locale %s is not installed.", arg_locale_messages);
×
1715

1716
        if (arg_root_shell) {
134✔
1717
                r = find_shell(rfd, arg_root_shell);
5✔
1718
                if (r < 0)
5✔
1719
                        return r;
1720
        }
1721

1722
        r = process_reset(rfd);
133✔
1723
        if (r < 0)
133✔
1724
                return r;
1725

1726
        r = process_locale(rfd);
133✔
1727
        if (r < 0)
133✔
1728
                return r;
1729
        if (r > 0 && !offline)
133✔
1730
                (void) reload_system_manager(&bus);
×
1731

1732
        r = process_keymap(rfd);
133✔
1733
        if (r < 0)
133✔
1734
                return r;
1735
        if (r > 0 && !offline)
133✔
1736
                (void) reload_vconsole(&bus);
×
1737

1738
        r = process_timezone(rfd);
133✔
1739
        if (r < 0)
133✔
1740
                return r;
1741

1742
        r = process_hostname(rfd);
133✔
1743
        if (r < 0)
133✔
1744
                return r;
1745

1746
        r = process_root_account(rfd);
133✔
1747
        if (r < 0)
133✔
1748
                return r;
1749

1750
        r = process_kernel_cmdline(rfd);
133✔
1751
        if (r < 0)
133✔
1752
                return r;
1753

1754
        r = process_machine_id(rfd);
133✔
1755
        if (r < 0)
133✔
1756
                return r;
×
1757

1758
        return 0;
1759
}
1760

1761
DEFINE_MAIN_FUNCTION(run);
272✔
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc