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