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