Bug Summary

File:build-scan/../src/firstboot/firstboot.c
Warning:line 320, column 28
Null pointer passed to 1st parameter expecting 'nonnull'

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-unknown-linux-gnu -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name firstboot.c -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model static -mframe-pointer=all -relaxed-aliasing -menable-no-infs -menable-no-nans -menable-unsafe-fp-math -fno-signed-zeros -mreassociate -freciprocal-math -fdenormal-fp-math=preserve-sign,preserve-sign -ffp-contract=fast -fno-rounding-math -ffast-math -ffinite-math-only -mconstructor-aliases -munwind-tables -target-cpu x86-64 -tune-cpu generic -fno-split-dwarf-inlining -debugger-tuning=gdb -resource-dir /usr/lib64/clang/12.0.0 -include config.h -I systemd-firstboot.p -I . -I .. -I src/basic -I ../src/basic -I src/shared -I ../src/shared -I src/systemd -I ../src/systemd -I src/journal -I ../src/journal -I src/journal-remote -I ../src/journal-remote -I src/nspawn -I ../src/nspawn -I src/resolve -I ../src/resolve -I src/timesync -I ../src/timesync -I ../src/time-wait-sync -I src/login -I ../src/login -I src/udev -I ../src/udev -I src/libudev -I ../src/libudev -I src/core -I ../src/core -I ../src/libsystemd/sd-bus -I ../src/libsystemd/sd-device -I ../src/libsystemd/sd-hwdb -I ../src/libsystemd/sd-id128 -I ../src/libsystemd/sd-netlink -I ../src/libsystemd/sd-network -I src/libsystemd-network -I ../src/libsystemd-network -D _FILE_OFFSET_BITS=64 -internal-isystem /usr/local/include -internal-isystem /usr/lib64/clang/12.0.0/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -Wwrite-strings -Wno-unused-parameter -Wno-missing-field-initializers -Wno-unused-result -Wno-format-signedness -Wno-error=nonnull -std=gnu99 -fconst-strings -fdebug-compilation-dir /home/mrc0mmand/repos/@redhat-plumbers/systemd-rhel8/build-scan -ferror-limit 19 -fvisibility hidden -stack-protector 2 -fgnuc-version=4.2.1 -fcolor-diagnostics -analyzer-output=html -faddrsig -o /tmp/scan-build-2021-07-16-221226-1465241-1 -x c ../src/firstboot/firstboot.c
1/* SPDX-License-Identifier: LGPL-2.1+ */
2
3#include <fcntl.h>
4#include <getopt.h>
5#include <unistd.h>
6
7#ifdef HAVE_CRYPT_H1
8/* libxcrypt is a replacement for glibc's libcrypt, and libcrypt might be
9 * removed from glibc at some point. As part of the removal, defines for
10 * crypt(3) are dropped from unistd.h, and we must include crypt.h instead.
11 *
12 * Newer versions of glibc (v2.0+) already ship crypt.h with a definition
13 * of crypt(3) as well, so we simply include it if it is present. MariaDB,
14 * MySQL, PostgreSQL, Perl and some other wide-spread packages do it the
15 * same way since ages without any problems.
16 */
17# include <crypt.h>
18#endif
19
20#include "sd-id128.h"
21
22#include "alloc-util.h"
23#include "ask-password-api.h"
24#include "copy.h"
25#include "fd-util.h"
26#include "fileio.h"
27#include "fs-util.h"
28#include "hostname-util.h"
29#include "locale-util.h"
30#include "mkdir.h"
31#include "os-util.h"
32#include "parse-util.h"
33#include "path-util.h"
34#include "proc-cmdline.h"
35#include "random-util.h"
36#include "string-util.h"
37#include "strv.h"
38#include "terminal-util.h"
39#include "time-util.h"
40#include "umask-util.h"
41#include "user-util.h"
42
43static char *arg_root = NULL((void*)0);
44static char *arg_locale = NULL((void*)0); /* $LANG */
45static char *arg_keymap = NULL((void*)0);
46static char *arg_locale_messages = NULL((void*)0); /* $LC_MESSAGES */
47static char *arg_timezone = NULL((void*)0);
48static char *arg_hostname = NULL((void*)0);
49static sd_id128_t arg_machine_id = {};
50static char *arg_root_password = NULL((void*)0);
51static bool_Bool arg_prompt_locale = false0;
52static bool_Bool arg_prompt_keymap = false0;
53static bool_Bool arg_prompt_timezone = false0;
54static bool_Bool arg_prompt_hostname = false0;
55static bool_Bool arg_prompt_root_password = false0;
56static bool_Bool arg_copy_locale = false0;
57static bool_Bool arg_copy_keymap = false0;
58static bool_Bool arg_copy_timezone = false0;
59static bool_Bool arg_copy_root_password = false0;
60
61static bool_Bool press_any_key(void) {
62 char k = 0;
63 bool_Bool need_nl = true1;
64
65 printf("-- Press any key to proceed --");
66 fflush(stdoutstdout);
67
68 (void) read_one_char(stdinstdin, &k, USEC_INFINITY((usec_t) -1), &need_nl);
69
70 if (need_nl)
71 putchar('\n');
72
73 return k != 'q';
74}
75
76static void print_welcome(void) {
77 _cleanup_free___attribute__((cleanup(freep))) char *pretty_name = NULL((void*)0);
78 static bool_Bool done = false0;
79 int r;
80
81 if (done)
82 return;
83
84 r = parse_os_release(arg_root, "PRETTY_NAME", &pretty_name, NULL((void*)0));
85 if (r < 0)
86 log_full_errno(r == -ENOENT ? LOG_DEBUG : LOG_WARNING, r,({ int _level = ((r == -2 ? 7 : 4)), _e = ((r)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/firstboot/firstboot.c", 87, __func__, "Failed to read os-release file, ignoring: %m"
) : -abs(_e); })
87 "Failed to read os-release file, ignoring: %m")({ int _level = ((r == -2 ? 7 : 4)), _e = ((r)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/firstboot/firstboot.c", 87, __func__, "Failed to read os-release file, ignoring: %m"
) : -abs(_e); })
;
88
89 printf("\nWelcome to your new installation of %s!\nPlease configure a few basic system settings:\n\n",
90 isempty(pretty_name) ? "Linux" : pretty_name);
91
92 press_any_key();
93
94 done = true1;
95}
96
97static int show_menu(char **x, unsigned n_columns, unsigned width, unsigned percentage) {
98 unsigned break_lines, break_modulo;
99 size_t n, per_column, i, j;
100
101 assert(n_columns > 0)do { if ((__builtin_expect(!!(!(n_columns > 0)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("n_columns > 0"), "../src/firstboot/firstboot.c"
, 101, __PRETTY_FUNCTION__); } while (0)
;
102
103 n = strv_length(x);
104 per_column = DIV_ROUND_UP(n, n_columns)({ const typeof((n)) __unique_prefix_X14 = ((n)); const typeof
((n_columns)) __unique_prefix_Y15 = ((n_columns)); (__unique_prefix_X14
/ __unique_prefix_Y15 + !!(__unique_prefix_X14 % __unique_prefix_Y15
)); })
;
105
106 break_lines = lines();
107 if (break_lines > 2)
108 break_lines--;
109
110 /* The first page gets two extra lines, since we want to show
111 * a title */
112 break_modulo = break_lines;
113 if (break_modulo > 3)
114 break_modulo -= 3;
115
116 for (i = 0; i < per_column; i++) {
117
118 for (j = 0; j < n_columns; j ++) {
119 _cleanup_free___attribute__((cleanup(freep))) char *e = NULL((void*)0);
120
121 if (j * per_column + i >= n)
122 break;
123
124 e = ellipsize(x[j * per_column + i], width, percentage);
125 if (!e)
126 return log_oom()log_oom_internal(LOG_REALM_SYSTEMD, "../src/firstboot/firstboot.c"
, 126, __func__)
;
127
128 printf("%4zu) %-*s", j * per_column + i + 1, width, e);
129 }
130
131 putchar('\n');
132
133 /* on the first screen we reserve 2 extra lines for the title */
134 if (i % break_lines == break_modulo) {
135 if (!press_any_key())
136 return 0;
137 }
138 }
139
140 return 0;
141}
142
143static int prompt_loop(const char *text, char **l, bool_Bool (*is_valid)(const char *name), char **ret) {
144 int r;
145
146 assert(text)do { if ((__builtin_expect(!!(!(text)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("text"), "../src/firstboot/firstboot.c",
146, __PRETTY_FUNCTION__); } while (0)
;
147 assert(is_valid)do { if ((__builtin_expect(!!(!(is_valid)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("is_valid"), "../src/firstboot/firstboot.c"
, 147, __PRETTY_FUNCTION__); } while (0)
;
148 assert(ret)do { if ((__builtin_expect(!!(!(ret)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("ret"), "../src/firstboot/firstboot.c", 148
, __PRETTY_FUNCTION__); } while (0)
;
149
150 for (;;) {
151 _cleanup_free___attribute__((cleanup(freep))) char *p = NULL((void*)0);
152 unsigned u;
153
154 r = ask_string(&p, "%s %s (empty to skip): ", special_glyph(TRIANGULAR_BULLET), text);
155 if (r < 0)
156 return log_error_errno(r, "Failed to query user: %m")({ int _level = ((3)), _e = ((r)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/firstboot/firstboot.c", 156, __func__, "Failed to query user: %m"
) : -abs(_e); })
;
157
158 if (isempty(p)) {
159 log_warning("No data entered, skipping.")({ int _level = (((4))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/firstboot/firstboot.c", 159, __func__, "No data entered, skipping."
) : -abs(_e); })
;
160 return 0;
161 }
162
163 r = safe_atou(p, &u);
164 if (r >= 0) {
165 char *c;
166
167 if (u <= 0 || u > strv_length(l)) {
168 log_error("Specified entry number out of range.")({ int _level = (((3))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/firstboot/firstboot.c", 168, __func__, "Specified entry number out of range."
) : -abs(_e); })
;
169 continue;
170 }
171
172 log_info("Selected '%s'.", l[u-1])({ int _level = (((6))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/firstboot/firstboot.c", 172, __func__, "Selected '%s'."
, l[u-1]) : -abs(_e); })
;
173
174 c = strdup(l[u-1]);
175 if (!c)
176 return log_oom()log_oom_internal(LOG_REALM_SYSTEMD, "../src/firstboot/firstboot.c"
, 176, __func__)
;
177
178 free(*ret);
179 *ret = c;
180 return 0;
181 }
182
183 if (!is_valid(p)) {
184 log_error("Entered data invalid.")({ int _level = (((3))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/firstboot/firstboot.c", 184, __func__, "Entered data invalid."
) : -abs(_e); })
;
185 continue;
186 }
187
188 free(*ret);
189 *ret = p;
190 p = 0;
191 return 0;
192 }
193}
194
195static bool_Bool locale_is_ok(const char *name) {
196
197 if (arg_root)
198 return locale_is_valid(name);
199
200 return locale_is_installed(name) > 0;
201}
202
203static int prompt_locale(void) {
204 _cleanup_strv_free___attribute__((cleanup(strv_freep))) char **locales = NULL((void*)0);
205 int r;
206
207 if (arg_locale || arg_locale_messages)
208 return 0;
209
210 if (!arg_prompt_locale)
211 return 0;
212
213 r = get_locales(&locales);
214 if (r < 0)
215 return log_error_errno(r, "Cannot query locales list: %m")({ int _level = ((3)), _e = ((r)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/firstboot/firstboot.c", 215, __func__, "Cannot query locales list: %m"
) : -abs(_e); })
;
216
217 print_welcome();
218
219 printf("\nAvailable Locales:\n\n");
220 r = show_menu(locales, 3, 22, 60);
221 if (r < 0)
222 return r;
223
224 putchar('\n');
225
226 r = prompt_loop("Please enter system locale name or number", locales, locale_is_ok, &arg_locale);
227 if (r < 0)
228 return r;
229
230 if (isempty(arg_locale))
231 return 0;
232
233 r = prompt_loop("Please enter system message locale name or number", locales, locale_is_ok, &arg_locale_messages);
234 if (r < 0)
235 return r;
236
237 return 0;
238}
239
240static int process_locale(void) {
241 const char *etc_localeconf;
242 char* locales[3];
243 unsigned i = 0;
244 int r;
245
246 etc_localeconf = prefix_roota(arg_root, "/etc/locale.conf")({ const char* _path = ("/etc/locale.conf"), *_root = (arg_root
), *_ret; char *_p, *_n; size_t _l; while (_path[0] == '/' &&
_path[1] == '/') _path ++; if (empty_or_root(_root)) _ret = _path
; else { _l = strlen(_root) + 1 + strlen(_path) + 1; _n = __builtin_alloca
(_l); _p = stpcpy(_n, _root); while (_p > _n && _p
[-1] == '/') _p--; if (_path[0] != '/') *(_p++) = '/'; strcpy
(_p, _path); _ret = _n; } _ret; })
;
247 if (laccess(etc_localeconf, F_OK)faccessat(-100, (etc_localeconf), (0), 0x100) >= 0)
248 return 0;
249
250 if (arg_copy_locale && arg_root) {
251
252 mkdir_parents(etc_localeconf, 0755);
253 r = copy_file("/etc/locale.conf", etc_localeconf, 0, 0644, 0, COPY_REFLINK);
254 if (r != -ENOENT2) {
255 if (r < 0)
256 return log_error_errno(r, "Failed to copy %s: %m", etc_localeconf)({ int _level = ((3)), _e = ((r)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/firstboot/firstboot.c", 256, __func__, "Failed to copy %s: %m"
, etc_localeconf) : -abs(_e); })
;
257
258 log_info("%s copied.", etc_localeconf)({ int _level = (((6))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/firstboot/firstboot.c", 258, __func__, "%s copied."
, etc_localeconf) : -abs(_e); })
;
259 return 0;
260 }
261 }
262
263 r = prompt_locale();
264 if (r < 0)
265 return r;
266
267 if (!isempty(arg_locale))
268 locales[i++] = strjoina("LANG=", arg_locale)({ const char *_appendees_[] = { "LANG=", arg_locale }; char *
_d_, *_p_; size_t _len_ = 0; size_t _i_; for (_i_ = 0; _i_ <
__extension__ (__builtin_choose_expr( !__builtin_types_compatible_p
(typeof(_appendees_), typeof(&*(_appendees_))), sizeof(_appendees_
)/sizeof((_appendees_)[0]), ((void)0))) && _appendees_
[_i_]; _i_++) _len_ += strlen(_appendees_[_i_]); _p_ = _d_ = __builtin_alloca
(_len_ + 1); for (_i_ = 0; _i_ < __extension__ (__builtin_choose_expr
( !__builtin_types_compatible_p(typeof(_appendees_), typeof(&
*(_appendees_))), sizeof(_appendees_)/sizeof((_appendees_)[0]
), ((void)0))) && _appendees_[_i_]; _i_++) _p_ = stpcpy
(_p_, _appendees_[_i_]); *_p_ = 0; _d_; })
;
269 if (!isempty(arg_locale_messages) && !streq(arg_locale_messages, arg_locale)(strcmp((arg_locale_messages),(arg_locale)) == 0))
270 locales[i++] = strjoina("LC_MESSAGES=", arg_locale_messages)({ const char *_appendees_[] = { "LC_MESSAGES=", arg_locale_messages
}; char *_d_, *_p_; size_t _len_ = 0; size_t _i_; for (_i_ =
0; _i_ < __extension__ (__builtin_choose_expr( !__builtin_types_compatible_p
(typeof(_appendees_), typeof(&*(_appendees_))), sizeof(_appendees_
)/sizeof((_appendees_)[0]), ((void)0))) && _appendees_
[_i_]; _i_++) _len_ += strlen(_appendees_[_i_]); _p_ = _d_ = __builtin_alloca
(_len_ + 1); for (_i_ = 0; _i_ < __extension__ (__builtin_choose_expr
( !__builtin_types_compatible_p(typeof(_appendees_), typeof(&
*(_appendees_))), sizeof(_appendees_)/sizeof((_appendees_)[0]
), ((void)0))) && _appendees_[_i_]; _i_++) _p_ = stpcpy
(_p_, _appendees_[_i_]); *_p_ = 0; _d_; })
;
271
272 if (i == 0)
273 return 0;
274
275 locales[i] = NULL((void*)0);
276
277 mkdir_parents(etc_localeconf, 0755);
278 r = write_env_file(etc_localeconf, locales);
279 if (r < 0)
280 return log_error_errno(r, "Failed to write %s: %m", etc_localeconf)({ int _level = ((3)), _e = ((r)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/firstboot/firstboot.c", 280, __func__, "Failed to write %s: %m"
, etc_localeconf) : -abs(_e); })
;
281
282 log_info("%s written.", etc_localeconf)({ int _level = (((6))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/firstboot/firstboot.c", 282, __func__, "%s written."
, etc_localeconf) : -abs(_e); })
;
283 return 0;
284}
285
286static int prompt_keymap(void) {
287 _cleanup_strv_free___attribute__((cleanup(strv_freep))) char **kmaps = NULL((void*)0);
288 int r;
289
290 if (arg_keymap)
291 return 0;
292
293 if (!arg_prompt_keymap)
294 return 0;
295
296 r = get_keymaps(&kmaps);
297 if (r == -ENOENT2) /* no keymaps installed */
298 return r;
299 if (r < 0)
300 return log_error_errno(r, "Failed to read keymaps: %m")({ int _level = ((3)), _e = ((r)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/firstboot/firstboot.c", 300, __func__, "Failed to read keymaps: %m"
) : -abs(_e); })
;
301
302 print_welcome();
303
304 printf("\nAvailable keymaps:\n\n");
305 r = show_menu(kmaps, 3, 22, 60);
306 if (r < 0)
307 return r;
308
309 putchar('\n');
310
311 return prompt_loop("Please enter system keymap name or number",
312 kmaps, keymap_is_valid, &arg_keymap);
313}
314
315static int process_keymap(void) {
316 const char *etc_vconsoleconf;
317 char **keymap;
318 int r;
319
320 etc_vconsoleconf = prefix_roota(arg_root, "/etc/vconsole.conf")({ const char* _path = ("/etc/vconsole.conf"), *_root = (arg_root
), *_ret; char *_p, *_n; size_t _l; while (_path[0] == '/' &&
_path[1] == '/') _path ++; if (empty_or_root(_root)) _ret = _path
; else { _l = strlen(_root) + 1 + strlen(_path) + 1; _n = __builtin_alloca
(_l); _p = stpcpy(_n, _root); while (_p > _n && _p
[-1] == '/') _p--; if (_path[0] != '/') *(_p++) = '/'; strcpy
(_p, _path); _ret = _n; } _ret; })
;
8
'_root' initialized to a null pointer value
9
Loop condition is false. Execution continues on line 320
10
Assuming the condition is false
11
Taking false branch
12
Null pointer passed to 1st parameter expecting 'nonnull'
321 if (laccess(etc_vconsoleconf, F_OK)faccessat(-100, (etc_vconsoleconf), (0), 0x100) >= 0)
322 return 0;
323
324 if (arg_copy_keymap && arg_root) {
325
326 mkdir_parents(etc_vconsoleconf, 0755);
327 r = copy_file("/etc/vconsole.conf", etc_vconsoleconf, 0, 0644, 0, COPY_REFLINK);
328 if (r != -ENOENT2) {
329 if (r < 0)
330 return log_error_errno(r, "Failed to copy %s: %m", etc_vconsoleconf)({ int _level = ((3)), _e = ((r)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/firstboot/firstboot.c", 330, __func__, "Failed to copy %s: %m"
, etc_vconsoleconf) : -abs(_e); })
;
331
332 log_info("%s copied.", etc_vconsoleconf)({ int _level = (((6))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/firstboot/firstboot.c", 332, __func__, "%s copied."
, etc_vconsoleconf) : -abs(_e); })
;
333 return 0;
334 }
335 }
336
337 r = prompt_keymap();
338 if (r == -ENOENT2)
339 return 0; /* don't fail if no keymaps are installed */
340 if (r < 0)
341 return r;
342
343 if (isempty(arg_keymap))
344 return 0;
345
346 keymap = STRV_MAKE(strjoina("KEYMAP=", arg_keymap))((char**) ((const char*[]) { ({ const char *_appendees_[] = {
"KEYMAP=", arg_keymap }; char *_d_, *_p_; size_t _len_ = 0; size_t
_i_; for (_i_ = 0; _i_ < __extension__ (__builtin_choose_expr
( !__builtin_types_compatible_p(typeof(_appendees_), typeof(&
*(_appendees_))), sizeof(_appendees_)/sizeof((_appendees_)[0]
), ((void)0))) && _appendees_[_i_]; _i_++) _len_ += strlen
(_appendees_[_i_]); _p_ = _d_ = __builtin_alloca (_len_ + 1);
for (_i_ = 0; _i_ < __extension__ (__builtin_choose_expr(
!__builtin_types_compatible_p(typeof(_appendees_), typeof(&
*(_appendees_))), sizeof(_appendees_)/sizeof((_appendees_)[0]
), ((void)0))) && _appendees_[_i_]; _i_++) _p_ = stpcpy
(_p_, _appendees_[_i_]); *_p_ = 0; _d_; }), ((void*)0) }))
;
347
348 r = mkdir_parents(etc_vconsoleconf, 0755);
349 if (r < 0)
350 return log_error_errno(r, "Failed to create the parent directory of %s: %m", etc_vconsoleconf)({ int _level = ((3)), _e = ((r)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/firstboot/firstboot.c", 350, __func__, "Failed to create the parent directory of %s: %m"
, etc_vconsoleconf) : -abs(_e); })
;
351
352 r = write_env_file(etc_vconsoleconf, keymap);
353 if (r < 0)
354 return log_error_errno(r, "Failed to write %s: %m", etc_vconsoleconf)({ int _level = ((3)), _e = ((r)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/firstboot/firstboot.c", 354, __func__, "Failed to write %s: %m"
, etc_vconsoleconf) : -abs(_e); })
;
355
356 log_info("%s written.", etc_vconsoleconf)({ int _level = (((6))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/firstboot/firstboot.c", 356, __func__, "%s written."
, etc_vconsoleconf) : -abs(_e); })
;
357 return 0;
358}
359
360static bool_Bool timezone_is_valid_log_error(const char *name) {
361 return timezone_is_valid(name, LOG_ERR3);
362}
363
364static int prompt_timezone(void) {
365 _cleanup_strv_free___attribute__((cleanup(strv_freep))) char **zones = NULL((void*)0);
366 int r;
367
368 if (arg_timezone)
369 return 0;
370
371 if (!arg_prompt_timezone)
372 return 0;
373
374 r = get_timezones(&zones);
375 if (r < 0)
376 return log_error_errno(r, "Cannot query timezone list: %m")({ int _level = ((3)), _e = ((r)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/firstboot/firstboot.c", 376, __func__, "Cannot query timezone list: %m"
) : -abs(_e); })
;
377
378 print_welcome();
379
380 printf("\nAvailable Time Zones:\n\n");
381 r = show_menu(zones, 3, 22, 30);
382 if (r < 0)
383 return r;
384
385 putchar('\n');
386
387 r = prompt_loop("Please enter timezone name or number", zones, timezone_is_valid_log_error, &arg_timezone);
388 if (r < 0)
389 return r;
390
391 return 0;
392}
393
394static int process_timezone(void) {
395 const char *etc_localtime, *e;
396 int r;
397
398 etc_localtime = prefix_roota(arg_root, "/etc/localtime")({ const char* _path = ("/etc/localtime"), *_root = (arg_root
), *_ret; char *_p, *_n; size_t _l; while (_path[0] == '/' &&
_path[1] == '/') _path ++; if (empty_or_root(_root)) _ret = _path
; else { _l = strlen(_root) + 1 + strlen(_path) + 1; _n = __builtin_alloca
(_l); _p = stpcpy(_n, _root); while (_p > _n && _p
[-1] == '/') _p--; if (_path[0] != '/') *(_p++) = '/'; strcpy
(_p, _path); _ret = _n; } _ret; })
;
399 if (laccess(etc_localtime, F_OK)faccessat(-100, (etc_localtime), (0), 0x100) >= 0)
400 return 0;
401
402 if (arg_copy_timezone && arg_root) {
403 _cleanup_free___attribute__((cleanup(freep))) char *p = NULL((void*)0);
404
405 r = readlink_malloc("/etc/localtime", &p);
406 if (r != -ENOENT2) {
407 if (r < 0)
408 return log_error_errno(r, "Failed to read host timezone: %m")({ int _level = ((3)), _e = ((r)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/firstboot/firstboot.c", 408, __func__, "Failed to read host timezone: %m"
) : -abs(_e); })
;
409
410 mkdir_parents(etc_localtime, 0755);
411 if (symlink(p, etc_localtime) < 0)
412 return log_error_errno(errno, "Failed to create %s symlink: %m", etc_localtime)({ int _level = ((3)), _e = (((*__errno_location ()))), _realm
= (LOG_REALM_SYSTEMD); (log_get_max_level_realm(_realm) >=
((_level) & 0x07)) ? log_internal_realm(((_realm) <<
10 | (_level)), _e, "../src/firstboot/firstboot.c", 412, __func__
, "Failed to create %s symlink: %m", etc_localtime) : -abs(_e
); })
;
413
414 log_info("%s copied.", etc_localtime)({ int _level = (((6))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/firstboot/firstboot.c", 414, __func__, "%s copied."
, etc_localtime) : -abs(_e); })
;
415 return 0;
416 }
417 }
418
419 r = prompt_timezone();
420 if (r < 0)
421 return r;
422
423 if (isempty(arg_timezone))
424 return 0;
425
426 e = strjoina("../usr/share/zoneinfo/", arg_timezone)({ const char *_appendees_[] = { "../usr/share/zoneinfo/", arg_timezone
}; char *_d_, *_p_; size_t _len_ = 0; size_t _i_; for (_i_ =
0; _i_ < __extension__ (__builtin_choose_expr( !__builtin_types_compatible_p
(typeof(_appendees_), typeof(&*(_appendees_))), sizeof(_appendees_
)/sizeof((_appendees_)[0]), ((void)0))) && _appendees_
[_i_]; _i_++) _len_ += strlen(_appendees_[_i_]); _p_ = _d_ = __builtin_alloca
(_len_ + 1); for (_i_ = 0; _i_ < __extension__ (__builtin_choose_expr
( !__builtin_types_compatible_p(typeof(_appendees_), typeof(&
*(_appendees_))), sizeof(_appendees_)/sizeof((_appendees_)[0]
), ((void)0))) && _appendees_[_i_]; _i_++) _p_ = stpcpy
(_p_, _appendees_[_i_]); *_p_ = 0; _d_; })
;
427
428 mkdir_parents(etc_localtime, 0755);
429 if (symlink(e, etc_localtime) < 0)
430 return log_error_errno(errno, "Failed to create %s symlink: %m", etc_localtime)({ int _level = ((3)), _e = (((*__errno_location ()))), _realm
= (LOG_REALM_SYSTEMD); (log_get_max_level_realm(_realm) >=
((_level) & 0x07)) ? log_internal_realm(((_realm) <<
10 | (_level)), _e, "../src/firstboot/firstboot.c", 430, __func__
, "Failed to create %s symlink: %m", etc_localtime) : -abs(_e
); })
;
431
432 log_info("%s written", etc_localtime)({ int _level = (((6))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/firstboot/firstboot.c", 432, __func__, "%s written"
, etc_localtime) : -abs(_e); })
;
433 return 0;
434}
435
436static int prompt_hostname(void) {
437 int r;
438
439 if (arg_hostname)
440 return 0;
441
442 if (!arg_prompt_hostname)
443 return 0;
444
445 print_welcome();
446 putchar('\n');
447
448 for (;;) {
449 _cleanup_free___attribute__((cleanup(freep))) char *h = NULL((void*)0);
450
451 r = ask_string(&h, "%s Please enter hostname for new system (empty to skip): ", special_glyph(TRIANGULAR_BULLET));
452 if (r < 0)
453 return log_error_errno(r, "Failed to query hostname: %m")({ int _level = ((3)), _e = ((r)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/firstboot/firstboot.c", 453, __func__, "Failed to query hostname: %m"
) : -abs(_e); })
;
454
455 if (isempty(h)) {
456 log_warning("No hostname entered, skipping.")({ int _level = (((4))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/firstboot/firstboot.c", 456, __func__, "No hostname entered, skipping."
) : -abs(_e); })
;
457 break;
458 }
459
460 if (!hostname_is_valid(h, true1)) {
461 log_error("Specified hostname invalid.")({ int _level = (((3))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/firstboot/firstboot.c", 461, __func__, "Specified hostname invalid."
) : -abs(_e); })
;
462 continue;
463 }
464
465 /* Get rid of the trailing dot that we allow, but don't want to see */
466 arg_hostname = hostname_cleanup(h);
467 h = NULL((void*)0);
468 break;
469 }
470
471 return 0;
472}
473
474static int process_hostname(void) {
475 const char *etc_hostname;
476 int r;
477
478 etc_hostname = prefix_roota(arg_root, "/etc/hostname")({ const char* _path = ("/etc/hostname"), *_root = (arg_root)
, *_ret; char *_p, *_n; size_t _l; while (_path[0] == '/' &&
_path[1] == '/') _path ++; if (empty_or_root(_root)) _ret = _path
; else { _l = strlen(_root) + 1 + strlen(_path) + 1; _n = __builtin_alloca
(_l); _p = stpcpy(_n, _root); while (_p > _n && _p
[-1] == '/') _p--; if (_path[0] != '/') *(_p++) = '/'; strcpy
(_p, _path); _ret = _n; } _ret; })
;
479 if (laccess(etc_hostname, F_OK)faccessat(-100, (etc_hostname), (0), 0x100) >= 0)
480 return 0;
481
482 r = prompt_hostname();
483 if (r < 0)
484 return r;
485
486 if (isempty(arg_hostname))
487 return 0;
488
489 mkdir_parents(etc_hostname, 0755);
490 r = write_string_file(etc_hostname, arg_hostname,
491 WRITE_STRING_FILE_CREATE | WRITE_STRING_FILE_SYNC);
492 if (r < 0)
493 return log_error_errno(r, "Failed to write %s: %m", etc_hostname)({ int _level = ((3)), _e = ((r)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/firstboot/firstboot.c", 493, __func__, "Failed to write %s: %m"
, etc_hostname) : -abs(_e); })
;
494
495 log_info("%s written.", etc_hostname)({ int _level = (((6))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/firstboot/firstboot.c", 495, __func__, "%s written."
, etc_hostname) : -abs(_e); })
;
496 return 0;
497}
498
499static int process_machine_id(void) {
500 const char *etc_machine_id;
501 char id[SD_ID128_STRING_MAX33];
502 int r;
503
504 etc_machine_id = prefix_roota(arg_root, "/etc/machine-id")({ const char* _path = ("/etc/machine-id"), *_root = (arg_root
), *_ret; char *_p, *_n; size_t _l; while (_path[0] == '/' &&
_path[1] == '/') _path ++; if (empty_or_root(_root)) _ret = _path
; else { _l = strlen(_root) + 1 + strlen(_path) + 1; _n = __builtin_alloca
(_l); _p = stpcpy(_n, _root); while (_p > _n && _p
[-1] == '/') _p--; if (_path[0] != '/') *(_p++) = '/'; strcpy
(_p, _path); _ret = _n; } _ret; })
;
505 if (laccess(etc_machine_id, F_OK)faccessat(-100, (etc_machine_id), (0), 0x100) >= 0)
506 return 0;
507
508 if (sd_id128_is_null(arg_machine_id))
509 return 0;
510
511 mkdir_parents(etc_machine_id, 0755);
512 r = write_string_file(etc_machine_id, sd_id128_to_string(arg_machine_id, id),
513 WRITE_STRING_FILE_CREATE | WRITE_STRING_FILE_SYNC);
514 if (r < 0)
515 return log_error_errno(r, "Failed to write machine id: %m")({ int _level = ((3)), _e = ((r)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/firstboot/firstboot.c", 515, __func__, "Failed to write machine id: %m"
) : -abs(_e); })
;
516
517 log_info("%s written.", etc_machine_id)({ int _level = (((6))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/firstboot/firstboot.c", 517, __func__, "%s written."
, etc_machine_id) : -abs(_e); })
;
518 return 0;
519}
520
521static int prompt_root_password(void) {
522 const char *msg1, *msg2, *etc_shadow;
523 int r;
524
525 if (arg_root_password)
526 return 0;
527
528 if (!arg_prompt_root_password)
529 return 0;
530
531 etc_shadow = prefix_roota(arg_root, "/etc/shadow")({ const char* _path = ("/etc/shadow"), *_root = (arg_root), *
_ret; char *_p, *_n; size_t _l; while (_path[0] == '/' &&
_path[1] == '/') _path ++; if (empty_or_root(_root)) _ret = _path
; else { _l = strlen(_root) + 1 + strlen(_path) + 1; _n = __builtin_alloca
(_l); _p = stpcpy(_n, _root); while (_p > _n && _p
[-1] == '/') _p--; if (_path[0] != '/') *(_p++) = '/'; strcpy
(_p, _path); _ret = _n; } _ret; })
;
532 if (laccess(etc_shadow, F_OK)faccessat(-100, (etc_shadow), (0), 0x100) >= 0)
533 return 0;
534
535 print_welcome();
536 putchar('\n');
537
538 msg1 = strjoina(special_glyph(TRIANGULAR_BULLET), " Please enter a new root password (empty to skip): ")({ const char *_appendees_[] = { special_glyph(TRIANGULAR_BULLET
), " Please enter a new root password (empty to skip): " }; char
*_d_, *_p_; size_t _len_ = 0; size_t _i_; for (_i_ = 0; _i_ <
__extension__ (__builtin_choose_expr( !__builtin_types_compatible_p
(typeof(_appendees_), typeof(&*(_appendees_))), sizeof(_appendees_
)/sizeof((_appendees_)[0]), ((void)0))) && _appendees_
[_i_]; _i_++) _len_ += strlen(_appendees_[_i_]); _p_ = _d_ = __builtin_alloca
(_len_ + 1); for (_i_ = 0; _i_ < __extension__ (__builtin_choose_expr
( !__builtin_types_compatible_p(typeof(_appendees_), typeof(&
*(_appendees_))), sizeof(_appendees_)/sizeof((_appendees_)[0]
), ((void)0))) && _appendees_[_i_]; _i_++) _p_ = stpcpy
(_p_, _appendees_[_i_]); *_p_ = 0; _d_; })
;
539 msg2 = strjoina(special_glyph(TRIANGULAR_BULLET), " Please enter new root password again: ")({ const char *_appendees_[] = { special_glyph(TRIANGULAR_BULLET
), " Please enter new root password again: " }; char *_d_, *_p_
; size_t _len_ = 0; size_t _i_; for (_i_ = 0; _i_ < __extension__
(__builtin_choose_expr( !__builtin_types_compatible_p(typeof
(_appendees_), typeof(&*(_appendees_))), sizeof(_appendees_
)/sizeof((_appendees_)[0]), ((void)0))) && _appendees_
[_i_]; _i_++) _len_ += strlen(_appendees_[_i_]); _p_ = _d_ = __builtin_alloca
(_len_ + 1); for (_i_ = 0; _i_ < __extension__ (__builtin_choose_expr
( !__builtin_types_compatible_p(typeof(_appendees_), typeof(&
*(_appendees_))), sizeof(_appendees_)/sizeof((_appendees_)[0]
), ((void)0))) && _appendees_[_i_]; _i_++) _p_ = stpcpy
(_p_, _appendees_[_i_]); *_p_ = 0; _d_; })
;
540
541 for (;;) {
542 _cleanup_string_free_erase___attribute__((cleanup(string_free_erasep))) char *a = NULL((void*)0), *b = NULL((void*)0);
543
544 r = ask_password_tty(-1, msg1, NULL((void*)0), 0, 0, NULL((void*)0), &a);
545 if (r < 0)
546 return log_error_errno(r, "Failed to query root password: %m")({ int _level = ((3)), _e = ((r)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/firstboot/firstboot.c", 546, __func__, "Failed to query root password: %m"
) : -abs(_e); })
;
547
548 if (isempty(a)) {
549 log_warning("No password entered, skipping.")({ int _level = (((4))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/firstboot/firstboot.c", 549, __func__, "No password entered, skipping."
) : -abs(_e); })
;
550 break;
551 }
552
553 r = ask_password_tty(-1, msg2, NULL((void*)0), 0, 0, NULL((void*)0), &b);
554 if (r < 0)
555 return log_error_errno(r, "Failed to query root password: %m")({ int _level = ((3)), _e = ((r)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/firstboot/firstboot.c", 555, __func__, "Failed to query root password: %m"
) : -abs(_e); })
;
556
557 if (!streq(a, b)(strcmp((a),(b)) == 0)) {
558 log_error("Entered passwords did not match, please try again.")({ int _level = (((3))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/firstboot/firstboot.c", 558, __func__, "Entered passwords did not match, please try again."
) : -abs(_e); })
;
559 continue;
560 }
561
562 arg_root_password = TAKE_PTR(a)({ typeof(a) _ptr_ = (a); (a) = ((void*)0); _ptr_; });
563 break;
564 }
565
566 return 0;
567}
568
569static int write_root_shadow(const char *path, const struct spwd *p) {
570 _cleanup_fclose___attribute__((cleanup(fclosep))) FILE *f = NULL((void*)0);
571 int r;
572
573 assert(path)do { if ((__builtin_expect(!!(!(path)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("path"), "../src/firstboot/firstboot.c",
573, __PRETTY_FUNCTION__); } while (0)
;
574 assert(p)do { if ((__builtin_expect(!!(!(p)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("p"), "../src/firstboot/firstboot.c", 574
, __PRETTY_FUNCTION__); } while (0)
;
575
576 RUN_WITH_UMASK(0777)for (__attribute__((cleanup(_reset_umask_))) struct _umask_struct_
_saved_umask_ = { umask(0777), 0 }; !_saved_umask_.quit ; _saved_umask_
.quit = 1)
577 f = fopen(path, "wex");
578 if (!f)
579 return -errno(*__errno_location ());
580
581 r = putspent_sane(p, f);
582 if (r < 0)
583 return r;
584
585 return fflush_sync_and_check(f);
586}
587
588static int process_root_password(void) {
589
590 static const char table[] =
591 "abcdefghijklmnopqrstuvwxyz"
592 "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
593 "0123456789"
594 "./";
595
596 struct spwd item = {
597 .sp_namp = (char*) "root",
598 .sp_min = -1,
599 .sp_max = -1,
600 .sp_warn = -1,
601 .sp_inact = -1,
602 .sp_expire = -1,
603 .sp_flag = (unsigned long) -1, /* this appears to be what everybody does ... */
604 };
605
606 _cleanup_close___attribute__((cleanup(closep))) int lock = -1;
607 char salt[3+16+1+1];
608 uint8_t raw[16];
609 unsigned i;
610 char *j;
611
612 const char *etc_shadow;
613 int r;
614
615 etc_shadow = prefix_roota(arg_root, "/etc/shadow")({ const char* _path = ("/etc/shadow"), *_root = (arg_root), *
_ret; char *_p, *_n; size_t _l; while (_path[0] == '/' &&
_path[1] == '/') _path ++; if (empty_or_root(_root)) _ret = _path
; else { _l = strlen(_root) + 1 + strlen(_path) + 1; _n = __builtin_alloca
(_l); _p = stpcpy(_n, _root); while (_p > _n && _p
[-1] == '/') _p--; if (_path[0] != '/') *(_p++) = '/'; strcpy
(_p, _path); _ret = _n; } _ret; })
;
616 if (laccess(etc_shadow, F_OK)faccessat(-100, (etc_shadow), (0), 0x100) >= 0)
617 return 0;
618
619 mkdir_parents(etc_shadow, 0755);
620
621 lock = take_etc_passwd_lock(arg_root);
622 if (lock < 0)
623 return log_error_errno(lock, "Failed to take a lock: %m")({ int _level = ((3)), _e = ((lock)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/firstboot/firstboot.c", 623, __func__, "Failed to take a lock: %m"
) : -abs(_e); })
;
624
625 if (arg_copy_root_password && arg_root) {
626 struct spwd *p;
627
628 errno(*__errno_location ()) = 0;
629 p = getspnam("root");
630 if (p || errno(*__errno_location ()) != ENOENT2) {
631 if (!p) {
632 if (!errno(*__errno_location ()))
633 errno(*__errno_location ()) = EIO5;
634
635 return log_error_errno(errno, "Failed to find shadow entry for root: %m")({ int _level = ((3)), _e = (((*__errno_location ()))), _realm
= (LOG_REALM_SYSTEMD); (log_get_max_level_realm(_realm) >=
((_level) & 0x07)) ? log_internal_realm(((_realm) <<
10 | (_level)), _e, "../src/firstboot/firstboot.c", 635, __func__
, "Failed to find shadow entry for root: %m") : -abs(_e); })
;
636 }
637
638 r = write_root_shadow(etc_shadow, p);
639 if (r < 0)
640 return log_error_errno(r, "Failed to write %s: %m", etc_shadow)({ int _level = ((3)), _e = ((r)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/firstboot/firstboot.c", 640, __func__, "Failed to write %s: %m"
, etc_shadow) : -abs(_e); })
;
641
642 log_info("%s copied.", etc_shadow)({ int _level = (((6))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/firstboot/firstboot.c", 642, __func__, "%s copied."
, etc_shadow) : -abs(_e); })
;
643 return 0;
644 }
645 }
646
647 r = prompt_root_password();
648 if (r < 0)
649 return r;
650
651 if (!arg_root_password)
652 return 0;
653
654 r = acquire_random_bytes(raw, 16, true1);
655 if (r < 0)
656 return log_error_errno(r, "Failed to get salt: %m")({ int _level = ((3)), _e = ((r)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/firstboot/firstboot.c", 656, __func__, "Failed to get salt: %m"
) : -abs(_e); })
;
657
658 /* We only bother with SHA512 hashed passwords, the rest is legacy, and we don't do legacy. */
659 assert_cc(sizeof(table) == 64 + 1)GCC diagnostic push ; GCC diagnostic ignored "-Wdeclaration-after-statement"
; struct _assert_struct_16 { char x[(sizeof(table) == 64 + 1
) ? 0 : -1]; }; GCC diagnostic pop
;
660 j = stpcpy(salt, "$6$");
661 for (i = 0; i < 16; i++)
662 j[i] = table[raw[i] & 63];
663 j[i++] = '$';
664 j[i] = 0;
665
666 errno(*__errno_location ()) = 0;
667 item.sp_pwdp = crypt(arg_root_password, salt);
668 if (!item.sp_pwdp) {
669 if (!errno(*__errno_location ()))
670 errno(*__errno_location ()) = EINVAL22;
671
672 return log_error_errno(errno, "Failed to encrypt password: %m")({ int _level = ((3)), _e = (((*__errno_location ()))), _realm
= (LOG_REALM_SYSTEMD); (log_get_max_level_realm(_realm) >=
((_level) & 0x07)) ? log_internal_realm(((_realm) <<
10 | (_level)), _e, "../src/firstboot/firstboot.c", 672, __func__
, "Failed to encrypt password: %m") : -abs(_e); })
;
673 }
674
675 item.sp_lstchg = (long) (now(CLOCK_REALTIME0) / USEC_PER_DAY((usec_t) (24ULL*((usec_t) (60ULL*((usec_t) (60ULL*((usec_t) 1000000ULL
)))))))
);
676
677 r = write_root_shadow(etc_shadow, &item);
678 if (r < 0)
679 return log_error_errno(r, "Failed to write %s: %m", etc_shadow)({ int _level = ((3)), _e = ((r)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/firstboot/firstboot.c", 679, __func__, "Failed to write %s: %m"
, etc_shadow) : -abs(_e); })
;
680
681 log_info("%s written.", etc_shadow)({ int _level = (((6))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/firstboot/firstboot.c", 681, __func__, "%s written."
, etc_shadow) : -abs(_e); })
;
682 return 0;
683}
684
685static void help(void) {
686 printf("%s [OPTIONS...]\n\n"
687 "Configures basic settings of the system.\n\n"
688 " -h --help Show this help\n"
689 " --version Show package version\n"
690 " --root=PATH Operate on an alternate filesystem root\n"
691 " --locale=LOCALE Set primary locale (LANG=)\n"
692 " --locale-messages=LOCALE Set message locale (LC_MESSAGES=)\n"
693 " --keymap=KEYMAP Set keymap\n"
694 " --timezone=TIMEZONE Set timezone\n"
695 " --hostname=NAME Set host name\n"
696 " --machine-ID=ID Set machine ID\n"
697 " --root-password=PASSWORD Set root password\n"
698 " --root-password-file=FILE Set root password from file\n"
699 " --prompt-locale Prompt the user for locale settings\n"
700 " --prompt-keymap Prompt the user for keymap settings\n"
701 " --prompt-timezone Prompt the user for timezone\n"
702 " --prompt-hostname Prompt the user for hostname\n"
703 " --prompt-root-password Prompt the user for root password\n"
704 " --prompt Prompt for all of the above\n"
705 " --copy-locale Copy locale from host\n"
706 " --copy-keymap Copy keymap from host\n"
707 " --copy-timezone Copy timezone from host\n"
708 " --copy-root-password Copy root password from host\n"
709 " --copy Copy locale, keymap, timezone, root password\n"
710 " --setup-machine-id Generate a new random machine ID\n"
711 , program_invocation_short_name);
712}
713
714static int parse_argv(int argc, char *argv[]) {
715
716 enum {
717 ARG_VERSION = 0x100,
718 ARG_ROOT,
719 ARG_LOCALE,
720 ARG_LOCALE_MESSAGES,
721 ARG_KEYMAP,
722 ARG_TIMEZONE,
723 ARG_HOSTNAME,
724 ARG_MACHINE_ID,
725 ARG_ROOT_PASSWORD,
726 ARG_ROOT_PASSWORD_FILE,
727 ARG_PROMPT,
728 ARG_PROMPT_LOCALE,
729 ARG_PROMPT_KEYMAP,
730 ARG_PROMPT_TIMEZONE,
731 ARG_PROMPT_HOSTNAME,
732 ARG_PROMPT_ROOT_PASSWORD,
733 ARG_COPY,
734 ARG_COPY_LOCALE,
735 ARG_COPY_KEYMAP,
736 ARG_COPY_TIMEZONE,
737 ARG_COPY_ROOT_PASSWORD,
738 ARG_SETUP_MACHINE_ID,
739 };
740
741 static const struct option options[] = {
742 { "help", no_argument0, NULL((void*)0), 'h' },
743 { "version", no_argument0, NULL((void*)0), ARG_VERSION },
744 { "root", required_argument1, NULL((void*)0), ARG_ROOT },
745 { "locale", required_argument1, NULL((void*)0), ARG_LOCALE },
746 { "locale-messages", required_argument1, NULL((void*)0), ARG_LOCALE_MESSAGES },
747 { "keymap", required_argument1, NULL((void*)0), ARG_KEYMAP },
748 { "timezone", required_argument1, NULL((void*)0), ARG_TIMEZONE },
749 { "hostname", required_argument1, NULL((void*)0), ARG_HOSTNAME },
750 { "machine-id", required_argument1, NULL((void*)0), ARG_MACHINE_ID },
751 { "root-password", required_argument1, NULL((void*)0), ARG_ROOT_PASSWORD },
752 { "root-password-file", required_argument1, NULL((void*)0), ARG_ROOT_PASSWORD_FILE },
753 { "prompt", no_argument0, NULL((void*)0), ARG_PROMPT },
754 { "prompt-locale", no_argument0, NULL((void*)0), ARG_PROMPT_LOCALE },
755 { "prompt-keymap", no_argument0, NULL((void*)0), ARG_PROMPT_KEYMAP },
756 { "prompt-timezone", no_argument0, NULL((void*)0), ARG_PROMPT_TIMEZONE },
757 { "prompt-hostname", no_argument0, NULL((void*)0), ARG_PROMPT_HOSTNAME },
758 { "prompt-root-password", no_argument0, NULL((void*)0), ARG_PROMPT_ROOT_PASSWORD },
759 { "copy", no_argument0, NULL((void*)0), ARG_COPY },
760 { "copy-locale", no_argument0, NULL((void*)0), ARG_COPY_LOCALE },
761 { "copy-keymap", no_argument0, NULL((void*)0), ARG_COPY_KEYMAP },
762 { "copy-timezone", no_argument0, NULL((void*)0), ARG_COPY_TIMEZONE },
763 { "copy-root-password", no_argument0, NULL((void*)0), ARG_COPY_ROOT_PASSWORD },
764 { "setup-machine-id", no_argument0, NULL((void*)0), ARG_SETUP_MACHINE_ID },
765 {}
766 };
767
768 int r, c;
769
770 assert(argc >= 0)do { if ((__builtin_expect(!!(!(argc >= 0)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("argc >= 0"), "../src/firstboot/firstboot.c"
, 770, __PRETTY_FUNCTION__); } while (0)
;
771 assert(argv)do { if ((__builtin_expect(!!(!(argv)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("argv"), "../src/firstboot/firstboot.c",
771, __PRETTY_FUNCTION__); } while (0)
;
772
773 while ((c = getopt_long(argc, argv, "h", options, NULL((void*)0))) >= 0)
774
775 switch (c) {
776
777 case 'h':
778 help();
779 return 0;
780
781 case ARG_VERSION:
782 return version();
783
784 case ARG_ROOT:
785 r = parse_path_argument_and_warn(optarg, true1, &arg_root);
786 if (r < 0)
787 return r;
788 break;
789
790 case ARG_LOCALE:
791 r = free_and_strdup(&arg_locale, optarg);
792 if (r < 0)
793 return log_oom()log_oom_internal(LOG_REALM_SYSTEMD, "../src/firstboot/firstboot.c"
, 793, __func__)
;
794
795 break;
796
797 case ARG_LOCALE_MESSAGES:
798 r = free_and_strdup(&arg_locale_messages, optarg);
799 if (r < 0)
800 return log_oom()log_oom_internal(LOG_REALM_SYSTEMD, "../src/firstboot/firstboot.c"
, 800, __func__)
;
801
802 break;
803
804 case ARG_KEYMAP:
805 if (!keymap_is_valid(optarg)) {
806 log_error("Keymap %s is not valid.", optarg)({ int _level = (((3))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/firstboot/firstboot.c", 806, __func__, "Keymap %s is not valid."
, optarg) : -abs(_e); })
;
807 return -EINVAL22;
808 }
809
810 r = free_and_strdup(&arg_keymap, optarg);
811 if (r < 0)
812 return log_oom()log_oom_internal(LOG_REALM_SYSTEMD, "../src/firstboot/firstboot.c"
, 812, __func__)
;
813
814 break;
815
816 case ARG_TIMEZONE:
817 if (!timezone_is_valid(optarg, LOG_ERR3)) {
818 log_error("Timezone %s is not valid.", optarg)({ int _level = (((3))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/firstboot/firstboot.c", 818, __func__, "Timezone %s is not valid."
, optarg) : -abs(_e); })
;
819 return -EINVAL22;
820 }
821
822 r = free_and_strdup(&arg_timezone, optarg);
823 if (r < 0)
824 return log_oom()log_oom_internal(LOG_REALM_SYSTEMD, "../src/firstboot/firstboot.c"
, 824, __func__)
;
825
826 break;
827
828 case ARG_ROOT_PASSWORD:
829 r = free_and_strdup(&arg_root_password, optarg);
830 if (r < 0)
831 return log_oom()log_oom_internal(LOG_REALM_SYSTEMD, "../src/firstboot/firstboot.c"
, 831, __func__)
;
832 break;
833
834 case ARG_ROOT_PASSWORD_FILE:
835 arg_root_password = mfree(arg_root_password);
836
837 r = read_one_line_file(optarg, &arg_root_password);
838 if (r < 0)
839 return log_error_errno(r, "Failed to read %s: %m", optarg)({ int _level = ((3)), _e = ((r)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/firstboot/firstboot.c", 839, __func__, "Failed to read %s: %m"
, optarg) : -abs(_e); })
;
840
841 break;
842
843 case ARG_HOSTNAME:
844 if (!hostname_is_valid(optarg, true1)) {
845 log_error("Host name %s is not valid.", optarg)({ int _level = (((3))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/firstboot/firstboot.c", 845, __func__, "Host name %s is not valid."
, optarg) : -abs(_e); })
;
846 return -EINVAL22;
847 }
848
849 hostname_cleanup(optarg);
850 r = free_and_strdup(&arg_hostname, optarg);
851 if (r < 0)
852 return log_oom()log_oom_internal(LOG_REALM_SYSTEMD, "../src/firstboot/firstboot.c"
, 852, __func__)
;
853
854 break;
855
856 case ARG_MACHINE_ID:
857 if (sd_id128_from_string(optarg, &arg_machine_id) < 0) {
858 log_error("Failed to parse machine id %s.", optarg)({ int _level = (((3))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/firstboot/firstboot.c", 858, __func__, "Failed to parse machine id %s."
, optarg) : -abs(_e); })
;
859 return -EINVAL22;
860 }
861
862 break;
863
864 case ARG_PROMPT:
865 arg_prompt_locale = arg_prompt_keymap = arg_prompt_timezone = arg_prompt_hostname = arg_prompt_root_password = true1;
866 break;
867
868 case ARG_PROMPT_LOCALE:
869 arg_prompt_locale = true1;
870 break;
871
872 case ARG_PROMPT_KEYMAP:
873 arg_prompt_keymap = true1;
874 break;
875
876 case ARG_PROMPT_TIMEZONE:
877 arg_prompt_timezone = true1;
878 break;
879
880 case ARG_PROMPT_HOSTNAME:
881 arg_prompt_hostname = true1;
882 break;
883
884 case ARG_PROMPT_ROOT_PASSWORD:
885 arg_prompt_root_password = true1;
886 break;
887
888 case ARG_COPY:
889 arg_copy_locale = arg_copy_keymap = arg_copy_timezone = arg_copy_root_password = true1;
890 break;
891
892 case ARG_COPY_LOCALE:
893 arg_copy_locale = true1;
894 break;
895
896 case ARG_COPY_KEYMAP:
897 arg_copy_keymap = true1;
898 break;
899
900 case ARG_COPY_TIMEZONE:
901 arg_copy_timezone = true1;
902 break;
903
904 case ARG_COPY_ROOT_PASSWORD:
905 arg_copy_root_password = true1;
906 break;
907
908 case ARG_SETUP_MACHINE_ID:
909
910 r = sd_id128_randomize(&arg_machine_id);
911 if (r < 0)
912 return log_error_errno(r, "Failed to generate randomized machine ID: %m")({ int _level = ((3)), _e = ((r)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/firstboot/firstboot.c", 912, __func__, "Failed to generate randomized machine ID: %m"
) : -abs(_e); })
;
913
914 break;
915
916 case '?':
917 return -EINVAL22;
918
919 default:
920 assert_not_reached("Unhandled option")do { log_assert_failed_unreachable_realm(LOG_REALM_SYSTEMD, (
"Unhandled option"), "../src/firstboot/firstboot.c", 920, __PRETTY_FUNCTION__
); } while (0)
;
921 }
922
923 /* We check if the specified locale strings are valid down here, so that we can take --root= into
924 * account when looking for the locale files. */
925
926 if (arg_locale && !locale_is_ok(arg_locale))
927 return log_error_errno(EINVAL, "Locale %s is not installed.", arg_locale)({ int _level = ((3)), _e = ((22)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/firstboot/firstboot.c", 927, __func__, "Locale %s is not installed."
, arg_locale) : -abs(_e); })
;
928 if (arg_locale_messages && !locale_is_ok(arg_locale_messages))
929 return log_error_errno(EINVAL, "Locale %s is not installed.", arg_locale_messages)({ int _level = ((3)), _e = ((22)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/firstboot/firstboot.c", 929, __func__, "Locale %s is not installed."
, arg_locale_messages) : -abs(_e); })
;
930
931 return 1;
932}
933
934int main(int argc, char *argv[]) {
935 bool_Bool enabled;
936 int r;
937
938 r = parse_argv(argc, argv);
939 if (r <= 0)
1
Assuming 'r' is > 0
2
Taking false branch
940 goto finish;
941
942 log_set_target(LOG_TARGET_AUTO);
943 log_parse_environment()log_parse_environment_realm(LOG_REALM_SYSTEMD);
944 log_open();
945
946 umask(0022);
947
948 r = proc_cmdline_get_bool("systemd.firstboot", &enabled);
949 if (r < 0) {
3
Assuming 'r' is >= 0
4
Taking false branch
950 log_error_errno(r, "Failed to parse systemd.firstboot= kernel command line argument, ignoring.")({ int _level = ((3)), _e = ((r)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/firstboot/firstboot.c", 950, __func__, "Failed to parse systemd.firstboot= kernel command line argument, ignoring."
) : -abs(_e); })
;
951 goto finish;
952 }
953 if (r > 0 && !enabled) {
5
Assuming 'r' is <= 0
954 r = 0; /* disabled */
955 goto finish;
956 }
957
958 r = process_locale();
959 if (r
5.1
'r' is >= 0
< 0)
6
Taking false branch
960 goto finish;
961
962 r = process_keymap();
7
Calling 'process_keymap'
963 if (r < 0)
964 goto finish;
965
966 r = process_timezone();
967 if (r < 0)
968 goto finish;
969
970 r = process_hostname();
971 if (r < 0)
972 goto finish;
973
974 r = process_machine_id();
975 if (r < 0)
976 goto finish;
977
978 r = process_root_password();
979 if (r < 0)
980 goto finish;
981
982finish:
983 free(arg_root);
984 free(arg_locale);
985 free(arg_locale_messages);
986 free(arg_keymap);
987 free(arg_timezone);
988 free(arg_hostname);
989 string_erase(arg_root_password);
990 free(arg_root_password);
991
992 return r < 0 ? EXIT_FAILURE1 : EXIT_SUCCESS0;
993}