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 "SourcePath=/etc/fstab\n"
121 "DefaultDependencies=no\n"
122 "Conflicts=" SPECIAL_UMOUNT_TARGET "\n"
123 "Before=" SPECIAL_UMOUNT_TARGET "\n", f);
125 if (!noauto && !nofail)
126 fputs("Before=" SPECIAL_SWAP_TARGET "\n", f);
141 log_error("Failed to write unit file: %m");
147 lnk = join(arg_dest, "/" SPECIAL_SWAP_TARGET ".wants/", name, NULL);
149 log_error("Out of memory");
154 mkdir_parents_label(lnk, 0755);
155 if (symlink(unit, lnk) < 0) {
156 log_error("Failed to create symlink: %m");
161 r = device_name(what, &device);
163 log_error("Out of memory");
170 lnk = join(arg_dest, "/", device, ".wants/", name, NULL);
172 log_error("Out of memory");
177 mkdir_parents_label(lnk, 0755);
178 if (symlink(unit, lnk) < 0) {
179 log_error("Failed to create symlink: %m");
199 static bool mount_is_bind(struct mntent *me) {
203 hasmntopt(me, "bind") ||
204 streq(me->mnt_opts, "bind");
207 static bool mount_is_network(struct mntent *me) {
211 hasmntopt(me, "_netdev") ||
212 fstype_is_network(me->mnt_type);
215 static int add_mount(const char *what, const char *where, struct mntent *me) {
216 char *name = NULL, *unit = NULL, *lnk = NULL, *device = NULL, *automount_name = NULL, *automount_unit = NULL;
218 bool noauto, nofail, automount, isbind, isnetwork;
220 const char *post, *pre;
226 if (streq(me->mnt_type, "autofs"))
229 if (!is_path(where)) {
230 log_warning("Mount point %s is not a valid path, ignoring.", where);
234 if (mount_point_is_api(where) ||
235 mount_point_ignore(where))
238 isnetwork = mount_is_network(me);
239 isbind = mount_is_bind(me);
241 noauto = !!hasmntopt(me, "noauto");
242 nofail = !!hasmntopt(me, "nofail");
244 hasmntopt(me, "comment=systemd.automount") ||
245 hasmntopt(me, "x-systemd.automount");
248 post = SPECIAL_REMOTE_FS_TARGET;
249 pre = SPECIAL_REMOTE_FS_PRE_TARGET;
251 post = SPECIAL_LOCAL_FS_TARGET;
252 pre = SPECIAL_LOCAL_FS_PRE_TARGET;
255 name = unit_name_from_path(where, ".mount");
257 log_error("Out of memory");
262 unit = join(arg_dest, "/", name, NULL);
264 log_error("Out of memory");
269 f = fopen(unit, "wxe");
272 log_error("Failed to create unit file: %m");
276 fputs("# Automatically generated by systemd-fstab-generator\n\n"
278 "SourcePath=/etc/fstab\n"
279 "DefaultDependencies=no\n", f);
281 if (!path_equal(where, "/"))
285 "Conflicts=" SPECIAL_UMOUNT_TARGET "\n"
286 "Before=" SPECIAL_UMOUNT_TARGET "\n",
291 if (!noauto && !nofail && !automount)
308 if (!isempty(me->mnt_opts) &&
309 !streq(me->mnt_opts, "defaults"))
316 log_error("Failed to write unit file: %m");
322 lnk = join(arg_dest, "/", post, nofail || automount ? ".wants/" : ".requires/", name, NULL);
324 log_error("Out of memory");
329 mkdir_parents_label(lnk, 0755);
330 if (symlink(unit, lnk) < 0) {
331 log_error("Failed to create symlink: %m");
337 !path_equal(where, "/")) {
339 r = device_name(what, &device);
341 log_error("Out of memory");
348 lnk = join(arg_dest, "/", device, ".wants/", name, NULL);
350 log_error("Out of memory");
355 mkdir_parents_label(lnk, 0755);
356 if (symlink(unit, lnk) < 0) {
357 log_error("Failed to creat symlink: %m");
365 if (automount && !path_equal(where, "/")) {
366 automount_name = unit_name_from_path(where, ".automount");
368 log_error("Out of memory");
373 automount_unit = join(arg_dest, "/", automount_name, NULL);
374 if (!automount_unit) {
375 log_error("Out of memory");
381 f = fopen(automount_unit, "wxe");
384 log_error("Failed to create unit file: %m");
389 "# Automatically generated by systemd-fstab-generator\n\n"
391 "SourcePath=/etc/fstab\n"
392 "DefaultDependencies=no\n"
393 "Conflicts=" SPECIAL_UMOUNT_TARGET "\n"
394 "Before=" SPECIAL_UMOUNT_TARGET " %s\n"
403 log_error("Failed to write unit file: %m");
409 lnk = join(arg_dest, "/", post, nofail ? ".wants/" : ".requires/", automount_name, NULL);
411 log_error("Out of memory");
416 mkdir_parents_label(lnk, 0755);
417 if (symlink(automount_unit, lnk) < 0) {
418 log_error("Failed to create symlink: %m");
433 free(automount_name);
434 free(automount_unit);
439 static int parse_fstab(void) {
445 f = setmntent("/etc/fstab", "r");
450 log_error("Failed to open /etc/fstab: %m");
454 while ((me = getmntent(f))) {
458 what = fstab_node_to_udev_node(me->mnt_fsname);
460 log_error("Out of memory");
465 where = strdup(me->mnt_dir);
467 log_error("Out of memory");
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[]) {
498 if (argc > 1 && argc != 4) {
499 log_error("This program takes three or no arguments.");
506 log_set_target(LOG_TARGET_SAFE);
507 log_parse_environment();
514 return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;