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"
36 static const char *arg_dest = "/tmp";
38 static int device_name(const char *path, char **unit) {
43 if (!is_device_path(path))
46 p = unit_name_from_path(path, ".device");
54 static int mount_find_pri(struct mntent *me, int *ret) {
61 pri = hasmntopt(me, "pri");
68 r = strtoul(pri, &end, 10);
72 if (end == pri || (*end != ',' && *end != 0))
79 static int add_swap(const char *what, struct mntent *me) {
80 char *name = NULL, *unit = NULL, *lnk = NULL, *device = NULL;
88 r = mount_find_pri(me, &pri);
90 log_error("Failed to parse priority");
94 noauto = !!hasmntopt(me, "noauto");
95 nofail = !!hasmntopt(me, "nofail");
97 name = unit_name_from_path(what, ".swap");
99 log_error("Out of memory");
104 unit = join(arg_dest, "/", name, NULL);
106 log_error("Out of memory");
111 f = fopen(unit, "wxe");
114 log_error("Failed to create unit file: %m");
118 fputs("# Automatically generated by systemd-fstab-generator\n\n"
120 "DefaultDependencies=no\n"
121 "Conflicts=" SPECIAL_UMOUNT_TARGET "\n"
122 "Before=" SPECIAL_UMOUNT_TARGET "\n", f);
124 if (!noauto && !nofail)
125 fputs("Before=" SPECIAL_SWAP_TARGET "\n", f);
140 log_error("Failed to write unit file: %m");
146 lnk = join(arg_dest, "/" SPECIAL_SWAP_TARGET ".wants/", name, NULL);
148 log_error("Out of memory");
153 mkdir_parents(lnk, 0755);
154 if (symlink(unit, lnk) < 0) {
155 log_error("Failed to create symlink: %m");
160 r = device_name(what, &device);
162 log_error("Out of memory");
169 lnk = join(arg_dest, "/", device, ".wants/", name, NULL);
171 log_error("Out of memory");
176 mkdir_parents(lnk, 0755);
177 if (symlink(unit, lnk) < 0) {
178 log_error("Failed to create symlink: %m");
198 static bool mount_is_bind(struct mntent *me) {
202 hasmntopt(me, "bind") ||
203 streq(me->mnt_opts, "bind");
206 static bool mount_is_network(struct mntent *me) {
210 hasmntopt(me, "_netdev") ||
211 fstype_is_network(me->mnt_type);
214 static int add_mount(const char *what, const char *where, struct mntent *me) {
215 char *name = NULL, *unit = NULL, *lnk = NULL, *device = NULL, *automount_name = NULL, *automount_unit = NULL;
217 bool noauto, nofail, automount, isbind, isnetwork;
219 const char *post, *pre;
225 if (streq(me->mnt_type, "autofs"))
228 if (!is_path(where)) {
229 log_warning("Mount point %s is not a valid path, ignoring.", where);
233 if (mount_point_is_api(where) ||
234 mount_point_ignore(where))
237 isnetwork = mount_is_network(me);
238 isbind = mount_is_bind(me);
240 noauto = !!hasmntopt(me, "noauto");
241 nofail = !!hasmntopt(me, "nofail");
243 hasmntopt(me, "comment=systemd.automount") ||
244 hasmntopt(me, "x-systemd.automount");
247 post = SPECIAL_REMOTE_FS_TARGET;
248 pre = SPECIAL_REMOTE_FS_PRE_TARGET;
250 post = SPECIAL_LOCAL_FS_TARGET;
251 pre = SPECIAL_LOCAL_FS_PRE_TARGET;
254 name = unit_name_from_path(where, ".mount");
256 log_error("Out of memory");
261 unit = join(arg_dest, "/", name, NULL);
263 log_error("Out of memory");
268 f = fopen(unit, "wxe");
271 log_error("Failed to create unit file: %m");
275 fputs("# Automatically generated by systemd-fstab-generator\n\n"
277 "DefaultDependencies=no\n", f);
279 if (!path_equal(where, "/"))
283 "Conflicts=" SPECIAL_UMOUNT_TARGET "\n"
284 "Before=" SPECIAL_UMOUNT_TARGET "\n",
289 if (!noauto && !nofail && !automount)
306 if (!isempty(me->mnt_opts) &&
307 !streq(me->mnt_opts, "defaults"))
314 log_error("Failed to write unit file: %m");
320 lnk = join(arg_dest, "/", post, nofail || automount ? ".wants/" : ".requires/", name, NULL);
322 log_error("Out of memory");
327 mkdir_parents(lnk, 0755);
328 if (symlink(unit, lnk) < 0) {
329 log_error("Failed to create symlink: %m");
335 !path_equal(where, "/")) {
337 r = device_name(what, &device);
339 log_error("Out of memory");
346 lnk = join(arg_dest, "/", device, ".wants/", name, NULL);
348 log_error("Out of memory");
353 mkdir_parents(lnk, 0755);
354 if (symlink(unit, lnk) < 0) {
355 log_error("Failed to creat symlink: %m");
363 if (automount && !path_equal(where, "/")) {
364 automount_name = unit_name_from_path(where, ".automount");
366 log_error("Out of memory");
371 automount_unit = join(arg_dest, "/", automount_name, NULL);
372 if (!automount_unit) {
373 log_error("Out of memory");
379 f = fopen(automount_unit, "wxe");
382 log_error("Failed to create unit file: %m");
387 "# Automatically generated by systemd-fstab-generator\n\n"
389 "DefaultDependencies=no\n"
390 "Conflicts=" SPECIAL_UMOUNT_TARGET "\n"
391 "Before=" SPECIAL_UMOUNT_TARGET " %s\n"
400 log_error("Failed to write unit file: %m");
406 lnk = join(arg_dest, "/", post, nofail ? ".wants/" : ".requires/", automount_name, NULL);
408 log_error("Out of memory");
413 mkdir_parents(lnk, 0755);
414 if (symlink(automount_unit, lnk) < 0) {
415 log_error("Failed to create symlink: %m");
430 free(automount_name);
431 free(automount_unit);
436 static int parse_fstab(void) {
442 f = setmntent("/etc/fstab", "r");
447 log_error("Failed to open /etc/fstab: %m");
451 while ((me = getmntent(f))) {
455 what = fstab_node_to_udev_node(me->mnt_fsname);
457 log_error("Out of memory");
462 where = strdup(me->mnt_dir);
464 log_error("Out of memory");
471 path_kill_slashes(what);
474 path_kill_slashes(where);
476 log_debug("Found entry what=%s where=%s type=%s", what, where, me->mnt_type);
478 if (streq(me->mnt_type, "swap"))
479 k = add_swap(what, me);
481 k = add_mount(what, where, me);
495 int main(int argc, char *argv[]) {
499 log_error("This program takes one or no arguments.");
506 log_set_target(LOG_TARGET_AUTO);
507 log_parse_environment();
510 log_set_max_level(LOG_DEBUG);
516 return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;