static int add_mount( const char *what, const char *where, const char *type, const char *opts, int passno, bool noauto, bool nofail, bool automount, bool isbind, const char *pre, const char *pre2, const char *online, const char *post, const char *source) { _cleanup_free_ char *name = NULL, *unit = NULL, *lnk = NULL, *device = NULL, *automount_name = NULL, *automount_unit = NULL; _cleanup_fclose_ FILE *f = NULL; int r; assert(what); assert(where); assert(type); assert(opts); assert(source); if (streq(type, "autofs")) return 0; if (!is_path(where)) { log_warning("Mount point %s is not a valid path, ignoring.", where); return 0; } if (mount_point_is_api(where) || mount_point_ignore(where)) return 0; name = unit_name_from_path(where, ".mount"); if (!name) return log_oom(); unit = strjoin(arg_dest, "/", name, NULL); if (!unit) return log_oom(); f = fopen(unit, "wxe"); if (!f) { if (errno == EEXIST) log_error("Failed to create mount unit file %s, as it already exists. Duplicate entry in /etc/fstab?", unit); else log_error("Failed to create unit file %s: %m", unit); return -errno; } fprintf(f, "# Automatically generated by systemd-fstab-generator\n\n" "[Unit]\n" "SourcePath=%s\n" "DefaultDependencies=no\n", source); if (!path_equal(where, "/")) { if (pre) fprintf(f, "After=%s\n", pre); if (pre2) fprintf(f, "After=%s\n", pre2); if (online) fprintf(f, "After=%s\n" "Wants=%s\n", online, online); fprintf(f, "Conflicts=" SPECIAL_UMOUNT_TARGET "\n" "Before=" SPECIAL_UMOUNT_TARGET "\n"); } if (post && !noauto && !nofail && !automount) fprintf(f, "Before=%s\n", post); fprintf(f, "\n" "[Mount]\n" "What=%s\n" "Where=%s\n" "Type=%s\n" "FsckPassNo=%i\n", what, where, type, passno); if (!isempty(opts) && !streq(opts, "defaults")) fprintf(f, "Options=%s\n", opts); fflush(f); if (ferror(f)) { log_error("Failed to write unit file %s: %m", unit); return -errno; } if (!noauto) { /* don't start network mounts automatically, we do that via ifupdown hooks for now */ if (post && !streq(post, SPECIAL_REMOTE_FS_TARGET)) { lnk = strjoin(arg_dest, "/", post, nofail || automount ? ".wants/" : ".requires/", name, NULL); if (!lnk) return log_oom(); mkdir_parents_label(lnk, 0755); if (symlink(unit, lnk) < 0) { log_error("Failed to create symlink %s: %m", lnk); return -errno; } } if (!isbind && !path_equal(where, "/")) { r = device_name(what, &device); if (r < 0) return r; if (r > 0) { free(lnk); lnk = strjoin(arg_dest, "/", device, ".wants/", name, NULL); if (!lnk) return log_oom(); mkdir_parents_label(lnk, 0755); if (symlink(unit, lnk) < 0) { log_error("Failed to create symlink %s: %m", lnk); return -errno; } } } } if (automount && !path_equal(where, "/")) { automount_name = unit_name_from_path(where, ".automount"); if (!name) return log_oom(); automount_unit = strjoin(arg_dest, "/", automount_name, NULL); if (!automount_unit) return log_oom(); fclose(f); f = fopen(automount_unit, "wxe"); if (!f) { log_error("Failed to create unit file %s: %m", automount_unit); return -errno; } fprintf(f, "# Automatically generated by systemd-fstab-generator\n\n" "[Unit]\n" "SourcePath=%s\n" "DefaultDependencies=no\n" "Conflicts=" SPECIAL_UMOUNT_TARGET "\n" "Before=" SPECIAL_UMOUNT_TARGET "\n", source); if (post) fprintf(f, "Before= %s\n", post); fprintf(f, "[Automount]\n" "Where=%s\n", where); fflush(f); if (ferror(f)) { log_error("Failed to write unit file %s: %m", automount_unit); return -errno; } free(lnk); lnk = strjoin(arg_dest, "/", post, nofail ? ".wants/" : ".requires/", automount_name, NULL); if (!lnk) return log_oom(); mkdir_parents_label(lnk, 0755); if (symlink(automount_unit, lnk) < 0) { log_error("Failed to create symlink %s: %m", lnk); return -errno; } } return 0; }
static int add_mount( const char *what, const char *where, const char *fstype, const char *opts, int passno, bool noauto, bool nofail, bool automount, const char *post, const char *source) { _cleanup_free_ char *name = NULL, *unit = NULL, *lnk = NULL, *automount_name = NULL, *automount_unit = NULL, *filtered = NULL; _cleanup_fclose_ FILE *f = NULL; int r; assert(what); assert(where); assert(opts); assert(source); if (streq_ptr(fstype, "autofs")) return 0; if (!is_path(where)) { log_warning("Mount point %s is not a valid path, ignoring.", where); return 0; } if (mount_point_is_api(where) || mount_point_ignore(where)) return 0; if (path_equal(where, "/")) { /* The root disk is not an option */ automount = false; noauto = false; nofail = false; } name = unit_name_from_path(where, ".mount"); if (!name) return log_oom(); unit = strjoin(arg_dest, "/", name, NULL); if (!unit) return log_oom(); f = fopen(unit, "wxe"); if (!f) { if (errno == EEXIST) log_error("Failed to create mount unit file %s, as it already exists. Duplicate entry in /etc/fstab?", unit); else log_error_errno(errno, "Failed to create unit file %s: %m", unit); return -errno; } fprintf(f, "# Automatically generated by systemd-fstab-generator\n\n" "[Unit]\n" "SourcePath=%s\n" "Documentation=man:fstab(5) man:systemd-fstab-generator(8)\n", source); if (post && !noauto && !nofail && !automount) fprintf(f, "Before=%s\n", post); if (passno != 0) { r = generator_write_fsck_deps(f, arg_dest, what, where, fstype); if (r < 0) return r; } fprintf(f, "\n" "[Mount]\n" "What=%s\n" "Where=%s\n", what, where); if (!isempty(fstype) && !streq(fstype, "auto")) fprintf(f, "Type=%s\n", fstype); r = generator_write_timeouts(arg_dest, what, where, opts, &filtered); if (r < 0) return r; if (!isempty(filtered) && !streq(filtered, "defaults")) fprintf(f, "Options=%s\n", filtered); fflush(f); if (ferror(f)) return log_error_errno(errno, "Failed to write unit file %s: %m", unit); if (!noauto && post) { lnk = strjoin(arg_dest, "/", post, nofail || automount ? ".wants/" : ".requires/", name, NULL); if (!lnk) return log_oom(); mkdir_parents_label(lnk, 0755); if (symlink(unit, lnk) < 0) return log_error_errno(errno, "Failed to create symlink %s: %m", lnk); } if (automount) { automount_name = unit_name_from_path(where, ".automount"); if (!automount_name) return log_oom(); automount_unit = strjoin(arg_dest, "/", automount_name, NULL); if (!automount_unit) return log_oom(); fclose(f); f = fopen(automount_unit, "wxe"); if (!f) return log_error_errno(errno, "Failed to create unit file %s: %m", automount_unit); fprintf(f, "# Automatically generated by systemd-fstab-generator\n\n" "[Unit]\n" "SourcePath=%s\n" "Documentation=man:fstab(5) man:systemd-fstab-generator(8)\n", source); if (post) fprintf(f, "Before=%s\n", post); fprintf(f, "[Automount]\n" "Where=%s\n", where); fflush(f); if (ferror(f)) return log_error_errno(errno, "Failed to write unit file %s: %m", automount_unit); free(lnk); lnk = strjoin(arg_dest, "/", post, nofail ? ".wants/" : ".requires/", automount_name, NULL); if (!lnk) return log_oom(); mkdir_parents_label(lnk, 0755); if (symlink(automount_unit, lnk) < 0) return log_error_errno(errno, "Failed to create symlink %s: %m", lnk); } return 0; }
static int add_mount(const char *what, const char *where, struct mntent *me) { char *name = NULL, *unit = NULL, *lnk = NULL, *device = NULL, *automount_name = NULL, *automount_unit = NULL; FILE *f = NULL; bool noauto, nofail, automount, isbind, isnetwork; int r; const char *post, *pre; assert(what); assert(where); assert(me); if (streq(me->mnt_type, "autofs")) return 0; if (!is_path(where)) { log_warning("Mount point %s is not a valid path, ignoring.", where); return 0; } if (mount_point_is_api(where) || mount_point_ignore(where)) return 0; isnetwork = mount_is_network(me); isbind = mount_is_bind(me); noauto = !!hasmntopt(me, "noauto"); nofail = !!hasmntopt(me, "nofail"); automount = hasmntopt(me, "comment=systemd.automount") || hasmntopt(me, "x-systemd.automount"); if (isnetwork) { post = SPECIAL_REMOTE_FS_TARGET; pre = SPECIAL_REMOTE_FS_PRE_TARGET; } else { post = SPECIAL_LOCAL_FS_TARGET; pre = SPECIAL_LOCAL_FS_PRE_TARGET; } name = unit_name_from_path(where, ".mount"); if (!name) { r = log_oom(); goto finish; } unit = strjoin(arg_dest, "/", name, NULL); if (!unit) { r = log_oom(); goto finish; } f = fopen(unit, "wxe"); if (!f) { r = -errno; log_error("Failed to create unit file: %m"); goto finish; } fputs("# Automatically generated by systemd-fstab-generator\n\n" "[Unit]\n" "SourcePath=/etc/fstab\n" "DefaultDependencies=no\n", f); if (!path_equal(where, "/")) fprintf(f, "After=%s\n" "Wants=%s\n" "Conflicts=" SPECIAL_UMOUNT_TARGET "\n" "Before=" SPECIAL_UMOUNT_TARGET "\n", pre, pre); if (!noauto && !nofail && !automount) fprintf(f, "Before=%s\n", post); fprintf(f, "\n" "[Mount]\n" "What=%s\n" "Where=%s\n" "Type=%s\n" "FsckPassNo=%i\n", what, where, me->mnt_type, me->mnt_passno); if (!isempty(me->mnt_opts) && !streq(me->mnt_opts, "defaults")) fprintf(f, "Options=%s\n", me->mnt_opts); fflush(f); if (ferror(f)) { log_error("Failed to write unit file: %m"); r = -errno; goto finish; } if (!noauto) { lnk = strjoin(arg_dest, "/", post, nofail || automount ? ".wants/" : ".requires/", name, NULL); if (!lnk) { r = log_oom(); goto finish; } mkdir_parents_label(lnk, 0755); if (symlink(unit, lnk) < 0) { log_error("Failed to create symlink: %m"); r = -errno; goto finish; } if (!isbind && !path_equal(where, "/")) { r = device_name(what, &device); if (r < 0) goto finish; if (r > 0) { free(lnk); lnk = strjoin(arg_dest, "/", device, ".wants/", name, NULL); if (!lnk) { r = log_oom(); goto finish; } mkdir_parents_label(lnk, 0755); if (symlink(unit, lnk) < 0) { log_error("Failed to create symlink: %m"); r = -errno; goto finish; } } } } if (automount && !path_equal(where, "/")) { automount_name = unit_name_from_path(where, ".automount"); if (!name) { r = log_oom(); goto finish; } automount_unit = strjoin(arg_dest, "/", automount_name, NULL); if (!automount_unit) { r = log_oom(); goto finish; } fclose(f); f = fopen(automount_unit, "wxe"); if (!f) { r = -errno; log_error("Failed to create unit file: %m"); goto finish; } fprintf(f, "# Automatically generated by systemd-fstab-generator\n\n" "[Unit]\n" "SourcePath=/etc/fstab\n" "DefaultDependencies=no\n" "Conflicts=" SPECIAL_UMOUNT_TARGET "\n" "Before=" SPECIAL_UMOUNT_TARGET " %s\n" "\n" "[Automount]\n" "Where=%s\n", post, where); fflush(f); if (ferror(f)) { log_error("Failed to write unit file: %m"); r = -errno; goto finish; } free(lnk); lnk = strjoin(arg_dest, "/", post, nofail ? ".wants/" : ".requires/", automount_name, NULL); if (!lnk) { r = log_oom(); goto finish; } mkdir_parents_label(lnk, 0755); if (symlink(automount_unit, lnk) < 0) { log_error("Failed to create symlink: %m"); r = -errno; goto finish; } } r = 0; finish: if (f) fclose(f); free(unit); free(lnk); free(name); free(device); free(automount_name); free(automount_unit); return r; }
static int add_mount( const char *what, const char *where, const char *type, const char *opts, int passno, bool noauto, bool nofail, bool automount, const char *post, const char *source) { _cleanup_free_ char *name = NULL, *unit = NULL, *lnk = NULL, *automount_name = NULL, *automount_unit = NULL; _cleanup_fclose_ FILE *f = NULL; assert(what); assert(where); assert(type); assert(opts); assert(source); if (streq(type, "autofs")) return 0; if (!is_path(where)) { log_warning("Mount point %s is not a valid path, ignoring.", where); return 0; } if (mount_point_is_api(where) || mount_point_ignore(where)) return 0; name = unit_name_from_path(where, ".mount"); if (!name) return log_oom(); unit = strjoin(arg_dest, "/", name, NULL); if (!unit) return log_oom(); f = fopen(unit, "wxe"); if (!f) { if (errno == EEXIST) log_error("Failed to create mount unit file %s, as it already exists. Duplicate entry in /etc/fstab?", unit); else log_error("Failed to create unit file %s: %m", unit); return -errno; } fprintf(f, "# Automatically generated by systemd-fstab-generator\n\n" "[Unit]\n" "SourcePath=%s\n", source); if (post && !noauto && !nofail && !automount) fprintf(f, "Before=%s\n", post); if (passno > 0) { if (streq(where, "/")) { lnk = strjoin(arg_dest, "/", SPECIAL_LOCAL_FS_TARGET, ".wants/", "systemd-fsck-root.service", NULL); if (!lnk) return log_oom(); mkdir_parents_label(lnk, 0755); if (symlink("systemd-fsck-root.service", lnk) < 0) { log_error("Failed to create symlink %s: %m", lnk); return -errno; } } else { _cleanup_free_ char *fsck = NULL; fsck = unit_name_from_path_instance("systemd-fsck", what, ".service"); if (!fsck) return log_oom(); fprintf(f, "Requires=%s\n" "After=%s\n", fsck, fsck); } } fprintf(f, "\n" "[Mount]\n" "What=%s\n" "Where=%s\n" "Type=%s\n", what, where, type); if (!isempty(opts) && !streq(opts, "defaults")) fprintf(f, "Options=%s\n", opts); fflush(f); if (ferror(f)) { log_error("Failed to write unit file %s: %m", unit); return -errno; } if (!noauto) { if (post) { free(lnk); lnk = strjoin(arg_dest, "/", post, nofail || automount ? ".wants/" : ".requires/", name, NULL); if (!lnk) return log_oom(); mkdir_parents_label(lnk, 0755); if (symlink(unit, lnk) < 0) { log_error("Failed to create symlink %s: %m", lnk); return -errno; } } } if (automount && !path_equal(where, "/")) { automount_name = unit_name_from_path(where, ".automount"); if (!automount_name) return log_oom(); automount_unit = strjoin(arg_dest, "/", automount_name, NULL); if (!automount_unit) return log_oom(); fclose(f); f = fopen(automount_unit, "wxe"); if (!f) { log_error("Failed to create unit file %s: %m", automount_unit); return -errno; } fprintf(f, "# Automatically generated by systemd-fstab-generator\n\n" "[Unit]\n" "SourcePath=%s\n", source); if (post) fprintf(f, "Before= %s\n", post); fprintf(f, "[Automount]\n" "Where=%s\n", where); fflush(f); if (ferror(f)) { log_error("Failed to write unit file %s: %m", automount_unit); return -errno; } free(lnk); lnk = strjoin(arg_dest, "/", post, nofail ? ".wants/" : ".requires/", automount_name, NULL); if (!lnk) return log_oom(); mkdir_parents_label(lnk, 0755); if (symlink(automount_unit, lnk) < 0) { log_error("Failed to create symlink %s: %m", lnk); return -errno; } } return 0; }
static int mount_points_list_get(MountPoint **head) { _cleanup_fclose_ FILE *proc_self_mountinfo = NULL; unsigned int i; int r; assert(head); proc_self_mountinfo = fopen("/proc/self/mountinfo", "re"); if (!proc_self_mountinfo) return -errno; for (i = 1;; i++) { _cleanup_free_ char *path = NULL; char *p = NULL; MountPoint *m; int k; k = fscanf(proc_self_mountinfo, "%*s " /* (1) mount id */ "%*s " /* (2) parent id */ "%*s " /* (3) major:minor */ "%*s " /* (4) root */ "%ms " /* (5) mount point */ "%*s" /* (6) mount options */ "%*[^-]" /* (7) optional fields */ "- " /* (8) separator */ "%*s " /* (9) file system type */ "%*s" /* (10) mount source */ "%*s" /* (11) mount options 2 */ "%*[^\n]", /* some rubbish at the end */ &path); if (k != 1) { if (k == EOF) break; log_warning("Failed to parse /proc/self/mountinfo:%u.", i); continue; } r = cunescape(path, UNESCAPE_RELAX, &p); if (r < 0) return r; /* Ignore mount points we can't unmount because they * are API or because we are keeping them open (like * /dev/console). Also, ignore all mounts below API * file systems, since they are likely virtual too, * and hence not worth spending time on. Also, in * unprivileged containers we might lack the rights to * unmount these things, hence don't bother. */ if (mount_point_is_api(p) || mount_point_ignore(p) || path_startswith(p, "/dev") || path_startswith(p, "/sys") || path_startswith(p, "/proc")) { free(p); continue; } m = new0(MountPoint, 1); if (!m) { free(p); return -ENOMEM; } m->path = p; LIST_PREPEND(mount_point, *head, m); } return 0; }