Bug Summary

File:build-scan/../src/firstboot/firstboot.c
Warning:line 246, column 26
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_X11 = ((n)); const typeof
((n_columns)) __unique_prefix_Y12 = ((n_columns)); (__unique_prefix_X11
/ __unique_prefix_Y12 + !!(__unique_prefix_X11 % __unique_prefix_Y12
)); })
;
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; })
;
7
'_root' initialized to a null pointer value
8
Loop condition is false. Execution continues on line 246
9
Assuming the condition is false
10
Taking false branch
11
Null pointer passed to 1st parameter expecting 'nonnull'
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; })
;
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_13 { 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();
6
Calling 'process_locale'
959 if (r < 0)
960 goto finish;
961
962 r = 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}