]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/fstab-generator/fstab-generator.c
util-lib: split out allocation calls into alloc-util.[ch]
[thirdparty/systemd.git] / src / fstab-generator / fstab-generator.c
CommitLineData
6b1dc2bd
LP
1/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
2
3/***
4 This file is part of systemd.
5
6 Copyright 2012 Lennart Poettering
7
8 systemd is free software; you can redistribute it and/or modify it
9 under the terms of the GNU Lesser General Public License as published by
10 the Free Software Foundation; either version 2.1 of the License, or
11 (at your option) any later version.
12
13 systemd is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Lesser General Public License for more details.
17
18 You should have received a copy of the GNU Lesser General Public License
19 along with systemd; If not, see <http://www.gnu.org/licenses/>.
20***/
21
6b1dc2bd 22#include <errno.h>
07630cea
LP
23#include <mntent.h>
24#include <stdio.h>
6b1dc2bd
LP
25#include <string.h>
26#include <unistd.h>
27
b5efdb8a 28#include "alloc-util.h"
3ffd4af2 29#include "fd-util.h"
0d39fa9c 30#include "fileio.h"
d15d0333 31#include "fstab-util.h"
07630cea
LP
32#include "generator.h"
33#include "log.h"
34#include "mkdir.h"
6b1dc2bd 35#include "mount-setup.h"
4349cd7c 36#include "mount-util.h"
6bedfcbb 37#include "parse-util.h"
07630cea 38#include "path-util.h"
4e731273 39#include "proc-cmdline.h"
6b1dc2bd 40#include "special.h"
8fcde012 41#include "stat-util.h"
07630cea 42#include "string-util.h"
059cb385 43#include "strv.h"
07630cea
LP
44#include "unit-name.h"
45#include "util.h"
689aede8 46#include "virt.h"
6b1dc2bd
LP
47
48static const char *arg_dest = "/tmp";
e48fdd84 49static bool arg_fstab_enabled = true;
6db615c1
LP
50static char *arg_root_what = NULL;
51static char *arg_root_fstype = NULL;
52static char *arg_root_options = NULL;
53static int arg_root_rw = -1;
9f103625
TH
54static char *arg_usr_what = NULL;
55static char *arg_usr_fstype = NULL;
56static char *arg_usr_options = NULL;
6b1dc2bd 57
5607d856
ZJS
58static int add_swap(
59 const char *what,
60 struct mntent *me,
61 bool noauto,
62 bool nofail) {
63
bf1d7ba7 64 _cleanup_free_ char *name = NULL, *unit = NULL, *lnk = NULL;
7fd1b19b 65 _cleanup_fclose_ FILE *f = NULL;
bf1d7ba7 66 int r;
6b1dc2bd
LP
67
68 assert(what);
69 assert(me);
70
00b4ffde
LP
71 if (access("/proc/swaps", F_OK) < 0) {
72 log_info("Swap not supported, ignoring fstab swap entry for %s.", what);
73 return 0;
74 }
75
75f86906 76 if (detect_container() > 0) {
689aede8
LP
77 log_info("Running in a container, ignoring fstab swap entry for %s.", what);
78 return 0;
79 }
80
7410616c
LP
81 r = unit_name_from_path(what, ".swap", &name);
82 if (r < 0)
83 return log_error_errno(r, "Failed to generate unit name: %m");
6b1dc2bd 84
b7def684 85 unit = strjoin(arg_dest, "/", name, NULL);
d0aa9ce5
ZJS
86 if (!unit)
87 return log_oom();
6b1dc2bd
LP
88
89 f = fopen(unit, "wxe");
90 if (!f) {
67ab5f76
TG
91 if (errno == EEXIST)
92 log_error("Failed to create swap unit file %s, as it already exists. Duplicate entry in /etc/fstab?", unit);
93 else
56f64d95 94 log_error_errno(errno, "Failed to create unit file %s: %m", unit);
d0aa9ce5 95 return -errno;
6b1dc2bd
LP
96 }
97
6b1dc2bd 98 fprintf(f,
64347fc2
TG
99 "# Automatically generated by systemd-fstab-generator\n\n"
100 "[Unit]\n"
c3834f9b
LP
101 "SourcePath=/etc/fstab\n"
102 "Documentation=man:fstab(5) man:systemd-fstab-generator(8)\n\n"
6b1dc2bd
LP
103 "[Swap]\n"
104 "What=%s\n",
105 what);
106
bf1d7ba7
KZ
107 if (!isempty(me->mnt_opts) && !streq(me->mnt_opts, "defaults"))
108 fprintf(f, "Options=%s\n", me->mnt_opts);
6b1dc2bd 109
47cb901e 110 r = fflush_and_check(f);
23bbb0de
MS
111 if (r < 0)
112 return log_error_errno(r, "Failed to write unit file %s: %m", unit);
6b1dc2bd 113
b3208b66 114 /* use what as where, to have a nicer error message */
bf1d7ba7 115 r = generator_write_timeouts(arg_dest, what, what, me->mnt_opts, NULL);
b3208b66
ZJS
116 if (r < 0)
117 return r;
118
4e82fe52 119 if (!noauto) {
5607d856
ZJS
120 lnk = strjoin(arg_dest, "/" SPECIAL_SWAP_TARGET,
121 nofail ? ".wants/" : ".requires/", name, NULL);
4e82fe52
TG
122 if (!lnk)
123 return log_oom();
124
125 mkdir_parents_label(lnk, 0755);
4a62c710
MS
126 if (symlink(unit, lnk) < 0)
127 return log_error_errno(errno, "Failed to create symlink %s: %m", lnk);
4e82fe52
TG
128 }
129
d0aa9ce5 130 return 0;
6b1dc2bd
LP
131}
132
6b1dc2bd
LP
133static bool mount_is_network(struct mntent *me) {
134 assert(me);
135
b9f111b9
ZJS
136 return fstab_test_option(me->mnt_opts, "_netdev\0") ||
137 fstype_is_network(me->mnt_type);
6b1dc2bd
LP
138}
139
3d22d1ab
TG
140static bool mount_in_initrd(struct mntent *me) {
141 assert(me);
142
b9f111b9
ZJS
143 return fstab_test_option(me->mnt_opts, "x-initrd.mount\0") ||
144 streq(me->mnt_dir, "/usr");
3d22d1ab
TG
145}
146
336b5c61 147static int write_idle_timeout(FILE *f, const char *where, const char *opts) {
deb0a77c
MO
148 _cleanup_free_ char *timeout = NULL;
149 char timespan[FORMAT_TIMESPAN_MAX];
150 usec_t u;
151 int r;
152
336b5c61 153 r = fstab_filter_options(opts, "x-systemd.idle-timeout\0", NULL, &timeout, NULL);
deb0a77c
MO
154 if (r < 0)
155 return log_warning_errno(r, "Failed to parse options: %m");
156 if (r == 0)
157 return 0;
158
159 r = parse_sec(timeout, &u);
160 if (r < 0) {
161 log_warning("Failed to parse timeout for %s, ignoring: %s", where, timeout);
162 return 0;
163 }
164
165 fprintf(f, "TimeoutIdleSec=%s\n", format_timespan(timespan, sizeof(timespan), u, 0));
166
167 return 0;
168}
2e852276 169
3519d230
KZ
170static int write_requires_after(FILE *f, const char *opts) {
171 _cleanup_strv_free_ char **names = NULL, **units = NULL;
172 _cleanup_free_ char *res = NULL;
173 char **s;
174 int r;
175
176 assert(f);
177 assert(opts);
178
179 r = fstab_extract_values(opts, "x-systemd.requires", &names);
180 if (r < 0)
181 return log_warning_errno(r, "Failed to parse options: %m");
182 if (r == 0)
183 return 0;
184
185 STRV_FOREACH(s, names) {
186 char *x;
187
188 r = unit_name_mangle_with_suffix(*s, UNIT_NAME_NOGLOB, ".mount", &x);
189 if (r < 0)
190 return log_error_errno(r, "Failed to generate unit name: %m");
191 r = strv_consume(&units, x);
192 if (r < 0)
193 return log_oom();
194 }
195
196 if (units) {
197 res = strv_join(units, " ");
198 if (!res)
199 return log_oom();
200 fprintf(f, "After=%1$s\nRequires=%1$s\n", res);
201 }
202
203 return 0;
204}
205
206static int write_requires_mounts_for(FILE *f, const char *opts) {
207 _cleanup_strv_free_ char **paths = NULL;
208 _cleanup_free_ char *res = NULL;
209 int r;
210
211 assert(f);
212 assert(opts);
213
214 r = fstab_extract_values(opts, "x-systemd.requires-mounts-for", &paths);
215 if (r < 0)
216 return log_warning_errno(r, "Failed to parse options: %m");
217 if (r == 0)
218 return 0;
219
220 res = strv_join(paths, " ");
221 if (!res)
222 return log_oom();
223
224 fprintf(f, "RequiresMountsFor=%s\n", res);
225
226 return 0;
227}
228
e8d2f6cd
LP
229static int add_mount(
230 const char *what,
231 const char *where,
6db615c1 232 const char *fstype,
e8d2f6cd
LP
233 const char *opts,
234 int passno,
235 bool noauto,
236 bool nofail,
237 bool automount,
e8d2f6cd 238 const char *post,
e8d2f6cd 239 const char *source) {
e48fdd84 240
7fd1b19b 241 _cleanup_free_ char
1dc2ced4 242 *name = NULL, *unit = NULL, *lnk = NULL,
29686440
ZJS
243 *automount_name = NULL, *automount_unit = NULL,
244 *filtered = NULL;
7fd1b19b 245 _cleanup_fclose_ FILE *f = NULL;
94192cda 246 int r;
6b1dc2bd
LP
247
248 assert(what);
249 assert(where);
5e398e54
TG
250 assert(opts);
251 assert(source);
6b1dc2bd 252
6db615c1 253 if (streq_ptr(fstype, "autofs"))
6b1dc2bd
LP
254 return 0;
255
256 if (!is_path(where)) {
257 log_warning("Mount point %s is not a valid path, ignoring.", where);
258 return 0;
259 }
260
261 if (mount_point_is_api(where) ||
262 mount_point_ignore(where))
263 return 0;
264
e48fdd84 265 if (path_equal(where, "/")) {
2e852276
ZJS
266 if (noauto)
267 log_warning("Ignoring \"noauto\" for root device");
268 if (nofail)
269 log_warning("Ignoring \"nofail\" for root device");
270 if (automount)
271 log_warning("Ignoring automount option for root device");
272
273 noauto = nofail = automount = false;
e48fdd84
LP
274 }
275
7410616c
LP
276 r = unit_name_from_path(where, ".mount", &name);
277 if (r < 0)
278 return log_error_errno(r, "Failed to generate unit name: %m");
6b1dc2bd 279
b7def684 280 unit = strjoin(arg_dest, "/", name, NULL);
d0aa9ce5
ZJS
281 if (!unit)
282 return log_oom();
6b1dc2bd
LP
283
284 f = fopen(unit, "wxe");
285 if (!f) {
67ab5f76
TG
286 if (errno == EEXIST)
287 log_error("Failed to create mount unit file %s, as it already exists. Duplicate entry in /etc/fstab?", unit);
288 else
56f64d95 289 log_error_errno(errno, "Failed to create unit file %s: %m", unit);
d0aa9ce5 290 return -errno;
6b1dc2bd
LP
291 }
292
5e398e54 293 fprintf(f,
c3834f9b
LP
294 "# Automatically generated by systemd-fstab-generator\n\n"
295 "[Unit]\n"
296 "SourcePath=%s\n"
297 "Documentation=man:fstab(5) man:systemd-fstab-generator(8)\n",
298 source);
6b1dc2bd 299
700e07ff 300 if (post && !noauto && !nofail && !automount)
5ecdcf41 301 fprintf(f, "Before=%s\n", post);
6b1dc2bd 302
3519d230
KZ
303 if (!automount && opts) {
304 r = write_requires_after(f, opts);
305 if (r < 0)
306 return r;
307 r = write_requires_mounts_for(f, opts);
308 if (r < 0)
309 return r;
310 }
311
e48fdd84 312 if (passno != 0) {
6db615c1 313 r = generator_write_fsck_deps(f, arg_dest, what, where, fstype);
e48fdd84
LP
314 if (r < 0)
315 return r;
316 }
64e70e4b 317
6b1dc2bd
LP
318 fprintf(f,
319 "\n"
320 "[Mount]\n"
321 "What=%s\n"
6db615c1 322 "Where=%s\n",
6b1dc2bd 323 what,
6db615c1
LP
324 where);
325
326 if (!isempty(fstype) && !streq(fstype, "auto"))
327 fprintf(f, "Type=%s\n", fstype);
6b1dc2bd 328
29686440
ZJS
329 r = generator_write_timeouts(arg_dest, what, where, opts, &filtered);
330 if (r < 0)
331 return r;
332
333 if (!isempty(filtered) && !streq(filtered, "defaults"))
334 fprintf(f, "Options=%s\n", filtered);
5e398e54 335
4652c56c
ZJS
336 r = fflush_and_check(f);
337 if (r < 0)
338 return log_error_errno(r, "Failed to write unit file %s: %m", unit);
6b1dc2bd 339
5ecdcf41
LP
340 if (!noauto && post) {
341 lnk = strjoin(arg_dest, "/", post, nofail || automount ? ".wants/" : ".requires/", name, NULL);
342 if (!lnk)
343 return log_oom();
344
345 mkdir_parents_label(lnk, 0755);
4a62c710
MS
346 if (symlink(unit, lnk) < 0)
347 return log_error_errno(errno, "Failed to create symlink %s: %m", lnk);
6b1dc2bd
LP
348 }
349
e48fdd84 350 if (automount) {
7410616c
LP
351 r = unit_name_from_path(where, ".automount", &automount_name);
352 if (r < 0)
353 return log_error_errno(r, "Failed to generate unit name: %m");
6b1dc2bd 354
b7def684 355 automount_unit = strjoin(arg_dest, "/", automount_name, NULL);
d0aa9ce5
ZJS
356 if (!automount_unit)
357 return log_oom();
6b1dc2bd
LP
358
359 fclose(f);
360 f = fopen(automount_unit, "wxe");
4a62c710
MS
361 if (!f)
362 return log_error_errno(errno, "Failed to create unit file %s: %m", automount_unit);
6b1dc2bd
LP
363
364 fprintf(f,
365 "# Automatically generated by systemd-fstab-generator\n\n"
366 "[Unit]\n"
c3834f9b
LP
367 "SourcePath=%s\n"
368 "Documentation=man:fstab(5) man:systemd-fstab-generator(8)\n",
700e07ff
HH
369 source);
370
371 if (post)
372 fprintf(f,
e48fdd84 373 "Before=%s\n",
700e07ff
HH
374 post);
375
3519d230
KZ
376 if (opts) {
377 r = write_requires_after(f, opts);
378 if (r < 0)
379 return r;
380 r = write_requires_mounts_for(f, opts);
381 if (r < 0)
382 return r;
383 }
384
700e07ff 385 fprintf(f,
6b1dc2bd
LP
386 "[Automount]\n"
387 "Where=%s\n",
6b1dc2bd
LP
388 where);
389
336b5c61 390 r = write_idle_timeout(f, where, opts);
deb0a77c
MO
391 if (r < 0)
392 return r;
393
4652c56c
ZJS
394 r = fflush_and_check(f);
395 if (r < 0)
396 return log_error_errno(r, "Failed to write unit file %s: %m", automount_unit);
6b1dc2bd
LP
397
398 free(lnk);
b7def684 399 lnk = strjoin(arg_dest, "/", post, nofail ? ".wants/" : ".requires/", automount_name, NULL);
d0aa9ce5
ZJS
400 if (!lnk)
401 return log_oom();
6b1dc2bd 402
d2e54fae 403 mkdir_parents_label(lnk, 0755);
4a62c710
MS
404 if (symlink(automount_unit, lnk) < 0)
405 return log_error_errno(errno, "Failed to create symlink %s: %m", lnk);
6b1dc2bd
LP
406 }
407
d0aa9ce5 408 return 0;
6b1dc2bd
LP
409}
410
e48fdd84 411static int parse_fstab(bool initrd) {
6db615c1 412 _cleanup_endmntent_ FILE *f = NULL;
e48fdd84 413 const char *fstab_path;
6b1dc2bd 414 struct mntent *me;
e48fdd84 415 int r = 0;
6b1dc2bd 416
e48fdd84
LP
417 fstab_path = initrd ? "/sysroot/etc/fstab" : "/etc/fstab";
418 f = setmntent(fstab_path, "re");
6b1dc2bd
LP
419 if (!f) {
420 if (errno == ENOENT)
421 return 0;
422
56f64d95 423 log_error_errno(errno, "Failed to open %s: %m", fstab_path);
6b1dc2bd
LP
424 return -errno;
425 }
426
427 while ((me = getmntent(f))) {
7fd1b19b 428 _cleanup_free_ char *where = NULL, *what = NULL;
5607d856 429 bool noauto, nofail;
6b1dc2bd
LP
430 int k;
431
3d22d1ab
TG
432 if (initrd && !mount_in_initrd(me))
433 continue;
434
6b1dc2bd 435 what = fstab_node_to_udev_node(me->mnt_fsname);
e48fdd84
LP
436 if (!what)
437 return log_oom();
438
00b4ffde 439 if (is_device_path(what) && path_is_read_only_fs("sys") > 0) {
689aede8
LP
440 log_info("Running in a container, ignoring fstab device entry for %s.", what);
441 continue;
442 }
443
e48fdd84
LP
444 where = initrd ? strappend("/sysroot/", me->mnt_dir) : strdup(me->mnt_dir);
445 if (!where)
5862d652 446 return log_oom();
6b1dc2bd 447
ec6ceb18 448 if (is_path(where))
6b1dc2bd
LP
449 path_kill_slashes(where);
450
b9f111b9
ZJS
451 noauto = fstab_test_yes_no_option(me->mnt_opts, "noauto\0" "auto\0");
452 nofail = fstab_test_yes_no_option(me->mnt_opts, "nofail\0" "fail\0");
5607d856
ZJS
453 log_debug("Found entry what=%s where=%s type=%s nofail=%s noauto=%s",
454 what, where, me->mnt_type,
455 yes_no(noauto), yes_no(nofail));
6b1dc2bd
LP
456
457 if (streq(me->mnt_type, "swap"))
5607d856 458 k = add_swap(what, me, noauto, nofail);
5e398e54 459 else {
5607d856 460 bool automount;
80c3b720 461 const char *post;
5e398e54 462
b9f111b9
ZJS
463 automount = fstab_test_option(me->mnt_opts,
464 "comment=systemd.automount\0"
465 "x-systemd.automount\0");
e48fdd84 466 if (initrd)
700e07ff 467 post = SPECIAL_INITRD_FS_TARGET;
e48fdd84 468 else if (mount_in_initrd(me))
9e5f0f92 469 post = SPECIAL_INITRD_ROOT_FS_TARGET;
e48fdd84 470 else if (mount_is_network(me))
0c17fbce 471 post = SPECIAL_REMOTE_FS_TARGET;
e48fdd84 472 else
0c17fbce 473 post = SPECIAL_LOCAL_FS_TARGET;
5e398e54 474
6db615c1
LP
475 k = add_mount(what,
476 where,
477 me->mnt_type,
478 me->mnt_opts,
479 me->mnt_passno,
480 noauto,
481 nofail,
482 automount,
483 post,
484 fstab_path);
5e398e54 485 }
6b1dc2bd 486
6b1dc2bd
LP
487 if (k < 0)
488 r = k;
489 }
490
6b1dc2bd
LP
491 return r;
492}
493
2e852276 494static int add_sysroot_mount(void) {
75a59316
ZJS
495 _cleanup_free_ char *what = NULL;
496 const char *opts;
5e398e54 497
093c2cfe
TH
498 if (isempty(arg_root_what)) {
499 log_debug("Could not find a root= entry on the kernel command line.");
500 return 0;
135b5212 501 }
5e398e54 502
093c2cfe
TH
503 what = fstab_node_to_udev_node(arg_root_what);
504 if (!what)
171181bc 505 return log_oom();
093c2cfe 506
6db615c1 507 if (!arg_root_options)
75a59316
ZJS
508 opts = arg_root_rw > 0 ? "rw" : "ro";
509 else if (arg_root_rw >= 0 ||
d15d0333 510 !fstab_test_option(arg_root_options, "ro\0" "rw\0"))
63c372cb 511 opts = strjoina(arg_root_options, ",", arg_root_rw > 0 ? "rw" : "ro");
75a59316
ZJS
512 else
513 opts = arg_root_options;
5e398e54 514
6db615c1
LP
515 log_debug("Found entry what=%s where=/sysroot type=%s", what, strna(arg_root_fstype));
516 return add_mount(what,
517 "/sysroot",
518 arg_root_fstype,
75a59316 519 opts,
093c2cfe 520 is_device_path(what) ? 1 : 0,
5ecdcf41
LP
521 false,
522 false,
6db615c1
LP
523 false,
524 SPECIAL_INITRD_ROOT_FS_TARGET,
525 "/proc/cmdline");
5e398e54
TG
526}
527
2e852276 528static int add_sysroot_usr_mount(void) {
9f103625
TH
529 _cleanup_free_ char *what = NULL;
530 const char *opts;
531
532 if (!arg_usr_what && !arg_usr_fstype && !arg_usr_options)
533 return 0;
534
535 if (arg_root_what && !arg_usr_what) {
536 arg_usr_what = strdup(arg_root_what);
537
538 if (!arg_usr_what)
539 return log_oom();
540 }
541
542 if (arg_root_fstype && !arg_usr_fstype) {
543 arg_usr_fstype = strdup(arg_root_fstype);
544
545 if (!arg_usr_fstype)
546 return log_oom();
547 }
548
549 if (arg_root_options && !arg_usr_options) {
550 arg_usr_options = strdup(arg_root_options);
551
552 if (!arg_usr_options)
553 return log_oom();
554 }
555
eb580002 556 if (!arg_usr_what)
9f103625
TH
557 return 0;
558
559 what = fstab_node_to_udev_node(arg_usr_what);
560 if (!path_is_absolute(what)) {
561 log_debug("Skipping entry what=%s where=/sysroot/usr type=%s", what, strna(arg_usr_fstype));
562 return -1;
563 }
564
eb580002
MM
565 if (!arg_usr_options)
566 opts = arg_root_rw > 0 ? "rw" : "ro";
d15d0333 567 else if (!fstab_test_option(arg_usr_options, "ro\0" "rw\0"))
63c372cb 568 opts = strjoina(arg_usr_options, ",", arg_root_rw > 0 ? "rw" : "ro");
eb580002
MM
569 else
570 opts = arg_usr_options;
9f103625
TH
571
572 log_debug("Found entry what=%s where=/sysroot/usr type=%s", what, strna(arg_usr_fstype));
573 return add_mount(what,
574 "/sysroot/usr",
575 arg_usr_fstype,
576 opts,
577 1,
578 false,
579 false,
580 false,
581 SPECIAL_INITRD_ROOT_FS_TARGET,
582 "/proc/cmdline");
583}
584
059cb385 585static int parse_proc_cmdline_item(const char *key, const char *value) {
74df0fca 586 int r;
94734142 587
9f103625
TH
588 /* root=, usr=, usrfstype= and roofstype= may occur more than once, the last
589 * instance should take precedence. In the case of multiple rootflags=
590 * or usrflags= the arguments should be concatenated */
6db615c1 591
059cb385 592 if (STR_IN_SET(key, "fstab", "rd.fstab") && value) {
e48fdd84 593
059cb385 594 r = parse_boolean(value);
141a79f4 595 if (r < 0)
059cb385 596 log_warning("Failed to parse fstab switch %s. Ignoring.", value);
141a79f4 597 else
e48fdd84 598 arg_fstab_enabled = r;
94734142 599
6db615c1
LP
600 } else if (streq(key, "root") && value) {
601
f88dc3ed 602 if (free_and_strdup(&arg_root_what, value) < 0)
6db615c1
LP
603 return log_oom();
604
605 } else if (streq(key, "rootfstype") && value) {
606
f88dc3ed 607 if (free_and_strdup(&arg_root_fstype, value) < 0)
6db615c1
LP
608 return log_oom();
609
610 } else if (streq(key, "rootflags") && value) {
611 char *o;
612
613 o = arg_root_options ?
614 strjoin(arg_root_options, ",", value, NULL) :
615 strdup(value);
616 if (!o)
617 return log_oom();
618
619 free(arg_root_options);
620 arg_root_options = o;
621
9f103625
TH
622 } else if (streq(key, "mount.usr") && value) {
623
624 if (free_and_strdup(&arg_usr_what, value) < 0)
625 return log_oom();
626
627 } else if (streq(key, "mount.usrfstype") && value) {
628
629 if (free_and_strdup(&arg_usr_fstype, value) < 0)
630 return log_oom();
631
632 } else if (streq(key, "mount.usrflags") && value) {
633 char *o;
634
635 o = arg_usr_options ?
636 strjoin(arg_usr_options, ",", value, NULL) :
637 strdup(value);
638 if (!o)
639 return log_oom();
640
641 free(arg_usr_options);
642 arg_usr_options = o;
643
6db615c1
LP
644 } else if (streq(key, "rw") && !value)
645 arg_root_rw = true;
646 else if (streq(key, "ro") && !value)
647 arg_root_rw = false;
94734142 648
d0aa9ce5 649 return 0;
94734142
LP
650}
651
6b1dc2bd 652int main(int argc, char *argv[]) {
e48fdd84 653 int r = 0;
6b1dc2bd 654
07719a21
LP
655 if (argc > 1 && argc != 4) {
656 log_error("This program takes three or no arguments.");
6b1dc2bd
LP
657 return EXIT_FAILURE;
658 }
659
660 if (argc > 1)
661 arg_dest = argv[1];
662
a6903061 663 log_set_target(LOG_TARGET_SAFE);
6b1dc2bd
LP
664 log_parse_environment();
665 log_open();
666
6b1dc2bd
LP
667 umask(0022);
668
b5884878
LP
669 r = parse_proc_cmdline(parse_proc_cmdline_item);
670 if (r < 0)
da927ba9 671 log_warning_errno(r, "Failed to parse kernel command line, ignoring: %m");
94734142 672
9f103625
TH
673 /* Always honour root= and usr= in the kernel command line if we are in an initrd */
674 if (in_initrd()) {
2e852276 675 r = add_sysroot_mount();
9f103625 676 if (r == 0)
2e852276 677 r = add_sysroot_usr_mount();
9f103625 678 }
5e398e54 679
e48fdd84
LP
680 /* Honour /etc/fstab only when that's enabled */
681 if (arg_fstab_enabled) {
682 int k;
ac4785b0 683
75a59316
ZJS
684 log_debug("Parsing /etc/fstab");
685
e48fdd84
LP
686 /* Parse the local /etc/fstab, possibly from the initrd */
687 k = parse_fstab(false);
688 if (k < 0)
689 r = k;
ac4785b0 690
e48fdd84
LP
691 /* If running in the initrd also parse the /etc/fstab from the host */
692 if (in_initrd()) {
75a59316
ZJS
693 log_debug("Parsing /sysroot/etc/fstab");
694
e48fdd84
LP
695 k = parse_fstab(true);
696 if (k < 0)
697 r = k;
698 }
699 }
6b1dc2bd 700
126cc760 701 free(arg_root_what);
59cfa62f
LP
702 free(arg_root_fstype);
703 free(arg_root_options);
704
705 free(arg_usr_what);
706 free(arg_usr_fstype);
707 free(arg_usr_options);
126cc760 708
e48fdd84 709 return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
6b1dc2bd 710}