1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
4 This file is part of systemd.
6 Copyright 2012 Lennart Poettering
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.
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.
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/>.
30 #include "unit-name.h"
31 #include "path-util.h"
32 #include "mount-setup.h"
37 static const char *arg_dest = "/tmp";
38 static bool arg_enabled = true;
40 static int device_name(const char *path, char **unit) {
45 if (!is_device_path(path))
48 p = unit_name_from_path(path, ".device");
56 static int mount_find_pri(struct mntent *me, int *ret) {
63 pri = hasmntopt(me, "pri");
70 r = strtoul(pri, &end, 10);
74 if (end == pri || (*end != ',' && *end != 0))
81 static int add_swap(const char *what, struct mntent *me) {
82 char *name = NULL, *unit = NULL, *lnk = NULL, *device = NULL;
90 r = mount_find_pri(me, &pri);
92 log_error("Failed to parse priority");
96 noauto = !!hasmntopt(me, "noauto");
97 nofail = !!hasmntopt(me, "nofail");
99 name = unit_name_from_path(what, ".swap");
101 log_error("Out of memory");
106 unit = strjoin(arg_dest, "/", name, NULL);
108 log_error("Out of memory");
113 f = fopen(unit, "wxe");
116 log_error("Failed to create unit file: %m");
120 fputs("# Automatically generated by systemd-fstab-generator\n\n"
122 "SourcePath=/etc/fstab\n"
123 "DefaultDependencies=no\n"
124 "Conflicts=" SPECIAL_UMOUNT_TARGET "\n"
125 "Before=" SPECIAL_UMOUNT_TARGET "\n", f);
127 if (!noauto && !nofail)
128 fputs("Before=" SPECIAL_SWAP_TARGET "\n", f);
143 log_error("Failed to write unit file: %m");
149 lnk = strjoin(arg_dest, "/" SPECIAL_SWAP_TARGET ".wants/", name, NULL);
151 log_error("Out of memory");
156 mkdir_parents_label(lnk, 0755);
157 if (symlink(unit, lnk) < 0) {
158 log_error("Failed to create symlink: %m");
163 r = device_name(what, &device);
165 log_error("Out of memory");
172 lnk = strjoin(arg_dest, "/", device, ".wants/", name, NULL);
174 log_error("Out of memory");
179 mkdir_parents_label(lnk, 0755);
180 if (symlink(unit, lnk) < 0) {
181 log_error("Failed to create symlink: %m");
201 static bool mount_is_bind(struct mntent *me) {
205 hasmntopt(me, "bind") ||
206 streq(me->mnt_opts, "bind");
209 static bool mount_is_network(struct mntent *me) {
213 hasmntopt(me, "_netdev") ||
214 fstype_is_network(me->mnt_type);
217 static int add_mount(const char *what, const char *where, struct mntent *me) {
218 char *name = NULL, *unit = NULL, *lnk = NULL, *device = NULL, *automount_name = NULL, *automount_unit = NULL;
220 bool noauto, nofail, automount, isbind, isnetwork;
222 const char *post, *pre;
228 if (streq(me->mnt_type, "autofs"))
231 if (!is_path(where)) {
232 log_warning("Mount point %s is not a valid path, ignoring.", where);
236 if (mount_point_is_api(where) ||
237 mount_point_ignore(where))
240 isnetwork = mount_is_network(me);
241 isbind = mount_is_bind(me);
243 noauto = !!hasmntopt(me, "noauto");
244 nofail = !!hasmntopt(me, "nofail");
246 hasmntopt(me, "comment=systemd.automount") ||
247 hasmntopt(me, "x-systemd.automount");
250 post = SPECIAL_REMOTE_FS_TARGET;
251 pre = SPECIAL_REMOTE_FS_PRE_TARGET;
253 post = SPECIAL_LOCAL_FS_TARGET;
254 pre = SPECIAL_LOCAL_FS_PRE_TARGET;
257 name = unit_name_from_path(where, ".mount");
259 log_error("Out of memory");
264 unit = strjoin(arg_dest, "/", name, NULL);
266 log_error("Out of memory");
271 f = fopen(unit, "wxe");
274 log_error("Failed to create unit file: %m");
278 fputs("# Automatically generated by systemd-fstab-generator\n\n"
280 "SourcePath=/etc/fstab\n"
281 "DefaultDependencies=no\n", f);
283 if (!path_equal(where, "/"))
287 "Conflicts=" SPECIAL_UMOUNT_TARGET "\n"
288 "Before=" SPECIAL_UMOUNT_TARGET "\n",
293 if (!noauto && !nofail && !automount)
310 if (!isempty(me->mnt_opts) &&
311 !streq(me->mnt_opts, "defaults"))
318 log_error("Failed to write unit file: %m");
324 lnk = strjoin(arg_dest, "/", post, nofail || automount ? ".wants/" : ".requires/", name, NULL);
326 log_error("Out of memory");
331 mkdir_parents_label(lnk, 0755);
332 if (symlink(unit, lnk) < 0) {
333 log_error("Failed to create symlink: %m");
339 !path_equal(where, "/")) {
341 r = device_name(what, &device);
343 log_error("Out of memory");
350 lnk = strjoin(arg_dest, "/", device, ".wants/", name, NULL);
352 log_error("Out of memory");
357 mkdir_parents_label(lnk, 0755);
358 if (symlink(unit, lnk) < 0) {
359 log_error("Failed to creat symlink: %m");
367 if (automount && !path_equal(where, "/")) {
368 automount_name = unit_name_from_path(where, ".automount");
370 log_error("Out of memory");
375 automount_unit = strjoin(arg_dest, "/", automount_name, NULL);
376 if (!automount_unit) {
377 log_error("Out of memory");
383 f = fopen(automount_unit, "wxe");
386 log_error("Failed to create unit file: %m");
391 "# Automatically generated by systemd-fstab-generator\n\n"
393 "SourcePath=/etc/fstab\n"
394 "DefaultDependencies=no\n"
395 "Conflicts=" SPECIAL_UMOUNT_TARGET "\n"
396 "Before=" SPECIAL_UMOUNT_TARGET " %s\n"
405 log_error("Failed to write unit file: %m");
411 lnk = strjoin(arg_dest, "/", post, nofail ? ".wants/" : ".requires/", automount_name, NULL);
413 log_error("Out of memory");
418 mkdir_parents_label(lnk, 0755);
419 if (symlink(automount_unit, lnk) < 0) {
420 log_error("Failed to create symlink: %m");
435 free(automount_name);
436 free(automount_unit);
441 static int parse_fstab(void) {
447 f = setmntent("/etc/fstab", "r");
452 log_error("Failed to open /etc/fstab: %m");
456 while ((me = getmntent(f))) {
460 what = fstab_node_to_udev_node(me->mnt_fsname);
462 log_error("Out of memory");
467 where = strdup(me->mnt_dir);
469 log_error("Out of memory");
476 path_kill_slashes(where);
478 log_debug("Found entry what=%s where=%s type=%s", what, where, me->mnt_type);
480 if (streq(me->mnt_type, "swap"))
481 k = add_swap(what, me);
483 k = add_mount(what, where, me);
497 static int parse_proc_cmdline(void) {
498 char *line, *w, *state;
502 if (detect_container(NULL) > 0)
505 r = read_one_line_file("/proc/cmdline", &line);
507 log_warning("Failed to read /proc/cmdline, ignoring: %s", strerror(-r));
511 FOREACH_WORD_QUOTED(w, l, line, state) {
514 word = strndup(w, l);
520 if (startswith(word, "fstab=")) {
521 r = parse_boolean(word + 6);
523 log_warning("Failed to parse fstab switch %s. Ignoring.", word + 6);
527 } else if (startswith(word, "rd.fstab=")) {
530 r = parse_boolean(word + 6);
532 log_warning("Failed to parse fstab switch %s. Ignoring.", word + 6);
537 } else if (startswith(word, "fstab.") ||
538 (in_initrd() && startswith(word, "rd.fstab."))) {
540 log_warning("Unknown kernel switch %s. Ignoring.", word);
553 int main(int argc, char *argv[]) {
556 if (argc > 1 && argc != 4) {
557 log_error("This program takes three or no arguments.");
564 log_set_target(LOG_TARGET_SAFE);
565 log_parse_environment();
570 if (parse_proc_cmdline() < 0)
578 return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;