static int automount_verify(Automount *a) { bool b; char *e; assert(a); if (UNIT(a)->load_state != UNIT_LOADED) return 0; if (path_equal(a->where, "/")) { log_error_unit(UNIT(a)->id, "Cannot have an automount unit for the root directory. Refusing."); return -EINVAL; } e = unit_name_from_path(a->where, ".automount"); if (!e) return -ENOMEM; b = unit_has_name(UNIT(a), e); free(e); if (!b) { log_error_unit(UNIT(a)->id, "%s's Where setting doesn't match unit name. Refusing.", UNIT(a)->id); return -EINVAL; } return 0; }
static int automount_verify(Automount *a) { _cleanup_free_ char *e = NULL; int r; assert(a); if (UNIT(a)->load_state != UNIT_LOADED) return 0; if (path_equal(a->where, "/")) { log_unit_error(UNIT(a), "Cannot have an automount unit for the root directory. Refusing."); return -EINVAL; } r = unit_name_from_path(a->where, ".automount", &e); if (r < 0) return log_unit_error(UNIT(a), "Failed to generate unit name from path: %m"); if (!unit_has_name(UNIT(a), e)) { log_unit_error(UNIT(a), "Where= setting doesn't match unit name. Refusing."); return -EINVAL; } return 0; }
int generator_hook_up_growfs( const char *dir, const char *where, const char *target) { _cleanup_free_ char *unit = NULL, *escaped = NULL, *where_unit = NULL; _cleanup_fclose_ FILE *f = NULL; const char *unit_file; int r; escaped = cescape(where); if (!escaped) return log_oom(); r = unit_name_from_path_instance("systemd-growfs", where, ".service", &unit); if (r < 0) return log_error_errno(r, "Failed to make unit instance name from path \"%s\": %m", where); r = unit_name_from_path(where, ".mount", &where_unit); if (r < 0) return log_error_errno(r, "Failed to make unit name from path \"%s\": %m", where); unit_file = strjoina(dir, "/", unit); log_debug("Creating %s", unit_file); f = fopen(unit_file, "wxe"); if (!f) return log_error_errno(errno, "Failed to create unit file %s: %m", unit_file); fprintf(f, "# Automatically generated by %s\n\n" "[Unit]\n" "Description=Grow File System on %%f\n" "Documentation=man:[email protected](8)\n" "DefaultDependencies=no\n" "BindsTo=%%i.mount\n" "After=%%i.mount\n" "Before=shutdown.target\n" "Before=%s\n" "\n" "[Service]\n" "Type=oneshot\n" "RemainAfterExit=yes\n" "ExecStart="SYSTEMD_GROWFS_PATH " %s\n" "TimeoutSec=0\n", program_invocation_short_name, target, escaped); return generator_add_symlink(dir, where_unit, "wants", unit); }
int generator_write_initrd_root_device_deps(const char *dir, const char *what) { _cleanup_free_ char *unit = NULL; int r; r = unit_name_from_path(what, ".device", &unit); if (r < 0) return log_error_errno(r, "Failed to make unit name from path: %m"); return write_drop_in_format(dir, SPECIAL_INITRD_ROOT_DEVICE_TARGET, 50, "root-device", "# Automatically generated by %s\n\n" "[Unit]\nRequires=%s\nAfter=%s", program_invocation_short_name, unit, unit); }
static int write_fsck_sysroot_service(const char *dir, const char *what) { _cleanup_free_ char *device = NULL, *escaped = NULL, *escaped2 = NULL; _cleanup_fclose_ FILE *f = NULL; const char *unit; int r; escaped = specifier_escape(what); if (!escaped) return log_oom(); escaped2 = cescape(escaped); if (!escaped2) return log_oom(); unit = strjoina(dir, "/systemd-fsck-root.service"); log_debug("Creating %s", unit); r = unit_name_from_path(what, ".device", &device); if (r < 0) return log_error_errno(r, "Failed to convert device \"%s\" to unit name: %m", what); f = fopen(unit, "wxe"); if (!f) return log_error_errno(errno, "Failed to create unit file %s: %m", unit); fprintf(f, "# Automatically generated by %1$s\n\n" "[Unit]\n" "Description=File System Check on %2$s\n" "Documentation=man:systemd-fsck-root.service(8)\n" "DefaultDependencies=no\n" "BindsTo=%3$s\n" "After=initrd-root-device.target local-fs-pre.target %3$s\n" "Before=shutdown.target\n" "\n" "[Service]\n" "Type=oneshot\n" "RemainAfterExit=yes\n" "ExecStart=" SYSTEMD_FSCK_PATH " %4$s\n" "TimeoutSec=0\n", program_invocation_short_name, escaped, device, escaped2); r = fflush_and_check(f); if (r < 0) return log_error_errno(r, "Failed to write unit file %s: %m", unit); return 0; }
static void test_u_n_f_p_one(const char *path, const char *suffix, const char *expected, int ret) { _cleanup_free_ char *t = NULL; assert_se(unit_name_from_path(path, suffix, &t) == ret); puts(strna(t)); assert_se(streq_ptr(t, expected)); if (t) { _cleanup_free_ char *k = NULL; assert_se(unit_name_to_path(t, &k) == 0); puts(strna(k)); assert_se(path_equal(k, isempty(path) ? "/" : path)); } }
static int add_swap(const char *path) { _cleanup_free_ char *name = NULL, *unit = NULL, *lnk = NULL; _cleanup_fclose_ FILE *f = NULL; assert(path); log_debug("Adding swap: %s", path); name = unit_name_from_path(path, ".swap"); if (!name) return log_oom(); unit = strjoin(arg_dest, "/", name, NULL); if (!unit) return log_oom(); f = fopen(unit, "wxe"); if (!f) { log_error("Failed to create unit file %s: %m", unit); return -errno; } fprintf(f, "# Automatically generated by systemd-gpt-auto-generator\n\n" "[Unit]\n" "Description=Swap Partition\n" "Documentation=man:systemd-gpt-auto-generator(8)\n\n" "[Swap]\n" "What=%s\n", path); fflush(f); if (ferror(f)) { log_error("Failed to write unit file %s: %m", unit); return -errno; } lnk = strjoin(arg_dest, "/" SPECIAL_SWAP_TARGET ".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; } return 0; }
static int device_name(const char *path, char **unit) { char *p; assert(path); if (!is_device_path(path)) return 0; p = unit_name_from_path(path, ".device"); if (!p) return log_oom(); *unit = p; return 1; }
int generator_write_timeouts( const char *dir, const char *what, const char *where, const char *opts, char **filtered) { /* Allow configuration how long we wait for a device that * backs a mount point to show up. This is useful to support * endless device timeouts for devices that show up only after * user input, like crypto devices. */ _cleanup_free_ char *node = NULL, *unit = NULL, *timeout = NULL; usec_t u; int r; r = fstab_filter_options(opts, "comment=systemd.device-timeout\0" "x-systemd.device-timeout\0", NULL, &timeout, filtered); if (r <= 0) return r; r = parse_sec_fix_0(timeout, &u); if (r < 0) { log_warning("Failed to parse timeout for %s, ignoring: %s", where, timeout); return 0; } node = fstab_node_to_udev_node(what); if (!node) return log_oom(); if (!is_device_path(node)) { log_warning("x-systemd.device-timeout ignored for %s", what); return 0; } r = unit_name_from_path(node, ".device", &unit); if (r < 0) return log_error_errno(r, "Failed to make unit name from path: %m"); return write_drop_in_format(dir, unit, 50, "device-timeout", "# Automatically generated by %s\n\n" "[Unit]\n" "JobRunningTimeoutSec=%s", program_invocation_short_name, timeout); }
static int device_setup_unit(Manager *m, struct udev_device *dev, const char *path, bool main) { _cleanup_free_ char *e = NULL; const char *sysfs = NULL; Unit *u = NULL; bool delete; int r; assert(m); assert(path); if (dev) { sysfs = udev_device_get_syspath(dev); if (!sysfs) return 0; } r = unit_name_from_path(path, ".device", &e); if (r < 0) return log_error_errno(r, "Failed to generate unit name from device path: %m"); u = manager_get_unit(m, e); /* The device unit can still be present even if the device was * unplugged: a mount unit can reference it hence preventing * the GC to have garbaged it. That's desired since the device * unit may have a dependency on the mount unit which was * added during the loading of the later. */ if (dev && u && DEVICE(u)->state == DEVICE_PLUGGED) { /* This unit is in plugged state: we're sure it's * attached to a device. */ if (!path_equal(DEVICE(u)->sysfs, sysfs)) { log_unit_debug(u, "Dev %s appeared twice with different sysfs paths %s and %s", e, DEVICE(u)->sysfs, sysfs); return -EEXIST; } } if (!u) { delete = true; r = unit_new_for_name(m, sizeof(Device), e, &u); if (r < 0) goto fail; unit_add_to_load_queue(u); } else
static int device_add_escaped_name(Unit *u, const char *dn) { _cleanup_free_ char *e = NULL; int r; assert(u); assert(dn); assert(dn[0] == '/'); e = unit_name_from_path(dn, ".device"); if (!e) return -ENOMEM; r = unit_add_name(u, e); if (r < 0 && r != -EEXIST) return r; return 0; }
static int device_add_escaped_name(Unit *u, const char *dn) { char *e; int r; assert(u); assert(dn); assert(dn[0] == '/'); if (!(e = unit_name_from_path(dn, ".device"))) return -ENOMEM; r = unit_add_name(u, e); free(e); if (r < 0 && r != -EEXIST) return r; return 0; }
static int device_find_escape_name(Manager *m, const char *dn, Unit **_u) { _cleanup_free_ char *e = NULL; Unit *u; assert(m); assert(dn); assert(dn[0] == '/'); assert(_u); e = unit_name_from_path(dn, ".device"); if (!e) return -ENOMEM; u = manager_get_unit(m, e); if (u) { *_u = u; return 1; } return 0; }
int generator_write_device_deps( const char *dir, const char *what, const char *where, const char *opts) { /* fstab records that specify _netdev option should apply the network * ordering on the actual device depending on network connection. If we * are not mounting real device (NFS, CIFS), we rely on _netdev effect * on the mount unit itself. */ _cleanup_free_ char *node = NULL, *unit = NULL; int r; if (!fstab_test_option(opts, "_netdev\0")) return 0; node = fstab_node_to_udev_node(what); if (!node) return log_oom(); /* Nothing to apply dependencies to. */ if (!is_device_path(node)) return 0; r = unit_name_from_path(node, ".device", &unit); if (r < 0) return log_error_errno(r, "Failed to make unit name from path \"%s\": %m", node); /* See mount_add_default_dependencies for explanation why we create such * dependencies. */ return write_drop_in_format(dir, unit, 50, "netdev-dependencies", "# Automatically generated by %s\n\n" "[Unit]\n" "After=" SPECIAL_NETWORK_ONLINE_TARGET " " SPECIAL_NETWORK_TARGET "\n" "Wants=" SPECIAL_NETWORK_ONLINE_TARGET "\n", program_invocation_short_name); }
static int add_automount( const char *id, const char *what, const char *where, const char *fstype, bool rw, const char *options, const char *description, usec_t timeout) { _cleanup_free_ char *unit = NULL, *lnk = NULL; _cleanup_free_ char *opt, *p = NULL; _cleanup_fclose_ FILE *f = NULL; int r; assert(id); assert(where); assert(description); if (options) opt = strjoin(options, ",noauto", NULL); else opt = strdup("noauto"); if (!opt) return log_oom(); r = add_mount(id, what, where, fstype, rw, opt, description, NULL); if (r < 0) return r; r = unit_name_from_path(where, ".automount", &unit); if (r < 0) return log_error_errno(r, "Failed to generate unit name: %m"); p = strjoin(arg_dest, "/", unit, NULL); if (!p) return log_oom(); f = fopen(p, "wxe"); if (!f) return log_error_errno(errno, "Failed to create unit file %s: %m", unit); fprintf(f, "# Automatically generated by systemd-gpt-auto-generator\n\n" "[Unit]\n" "Description=%s\n" "Documentation=man:systemd-gpt-auto-generator(8)\n" "[Automount]\n" "Where=%s\n" "TimeoutIdleSec=%lld\n", description, where, (unsigned long long)timeout / USEC_PER_SEC); r = fflush_and_check(f); if (r < 0) return log_error_errno(r, "Failed to write unit file %s: %m", p); lnk = strjoin(arg_dest, "/" SPECIAL_LOCAL_FS_TARGET ".wants/", unit, NULL); if (!lnk) return log_oom(); mkdir_parents_label(lnk, 0755); if (symlink(p, 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_swap(const char *what, struct mntent *me) { char *name = NULL, *unit = NULL, *lnk = NULL, *device = NULL; FILE *f = NULL; bool noauto, nofail; int r, pri = -1; assert(what); assert(me); r = mount_find_pri(me, &pri); if (r < 0) { log_error("Failed to parse priority"); return pri; } noauto = !!hasmntopt(me, "noauto"); nofail = !!hasmntopt(me, "nofail"); name = unit_name_from_path(what, ".swap"); 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" "Conflicts=" SPECIAL_UMOUNT_TARGET "\n" "Before=" SPECIAL_UMOUNT_TARGET "\n", f); if (!noauto && !nofail) fputs("Before=" SPECIAL_SWAP_TARGET "\n", f); fprintf(f, "\n" "[Swap]\n" "What=%s\n", what); if (pri >= 0) fprintf(f, "Priority=%i\n", pri); fflush(f); if (ferror(f)) { log_error("Failed to write unit file: %m"); r = -errno; goto finish; } if (!noauto) { lnk = strjoin(arg_dest, "/" SPECIAL_SWAP_TARGET ".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; } 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; } } } r = 0; finish: if (f) fclose(f); free(unit); free(lnk); free(name); free(device); return r; }
static int add_swap(const char *what, struct mntent *me) { _cleanup_free_ char *name = NULL, *unit = NULL, *lnk = NULL; _cleanup_fclose_ FILE *f = NULL; _cleanup_free_ char *discard = NULL; bool noauto; int r, pri = -1; assert(what); assert(me); if (detect_container(NULL) > 0) { log_info("Running in a container, ignoring fstab swap entry for %s.", what); return 0; } r = mount_find_pri(me, &pri); if (r < 0) { log_error("Failed to parse priority"); return r; } r = mount_find_discard(me, &discard); if (r < 0) { log_error("Failed to parse discard"); return r; } noauto = !!hasmntopt(me, "noauto"); name = unit_name_from_path(what, ".swap"); 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 swap 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=/etc/fstab\n" "Documentation=man:fstab(5) man:systemd-fstab-generator(8)\n\n" "[Swap]\n" "What=%s\n", what); if (pri >= 0) fprintf(f, "Priority=%i\n", pri); if (discard) fprintf(f, "Discard=%s\n", discard); fflush(f); if (ferror(f)) { log_error("Failed to write unit file %s: %m", unit); return -errno; } /* use what as where, to have a nicer error message */ r = generator_write_timeouts(arg_dest, what, what, me->mnt_opts, NULL); if (r < 0) return r; if (!noauto) { lnk = strjoin(arg_dest, "/" SPECIAL_SWAP_TARGET ".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; } } return 0; }
int generator_hook_up_mkfs( const char *dir, const char *what, const char *where, const char *type) { _cleanup_free_ char *node = NULL, *unit = NULL, *escaped = NULL, *where_unit = NULL; _cleanup_fclose_ FILE *f = NULL; const char *unit_file; int r; node = fstab_node_to_udev_node(what); if (!node) return log_oom(); /* Nothing to work on. */ if (!is_device_path(node)) { log_error("Cannot format something that is not a device node: %s", node); return -EINVAL; } if (!type || streq(type, "auto")) { log_error("Cannot format partition %s, filesystem type is not specified", node); return -EINVAL; } r = unit_name_from_path_instance("systemd-mkfs", node, ".service", &unit); if (r < 0) return log_error_errno(r, "Failed to make unit instance name from path \"%s\": %m", node); unit_file = strjoina(dir, "/", unit); log_debug("Creating %s", unit_file); escaped = cescape(node); if (!escaped) return log_oom(); r = unit_name_from_path(where, ".mount", &where_unit); if (r < 0) return log_error_errno(r, "Failed to make unit name from path \"%s\": %m", where); f = fopen(unit_file, "wxe"); if (!f) return log_error_errno(errno, "Failed to create unit file %s: %m", unit_file); fprintf(f, "# Automatically generated by %s\n\n" "[Unit]\n" "Description=Make File System on %%f\n" "Documentation=man:[email protected](8)\n" "DefaultDependencies=no\n" "BindsTo=%%i.device\n" "After=%%i.device\n" /* fsck might or might not be used, so let's be safe and order * ourselves before both [email protected] and the mount unit. */ "Before=systemd-fsck@%%i.service\n" "Before=%s\n" "Before=shutdown.target\n" "\n" "[Service]\n" "Type=oneshot\n" "RemainAfterExit=yes\n" "ExecStart="SYSTEMD_MAKEFS_PATH " %s %s\n" "TimeoutSec=0\n", program_invocation_short_name, where_unit, type, escaped); // XXX: what about local-fs-pre.target? r = fflush_and_check(f); if (r < 0) return log_error_errno(r, "Failed to write unit file %s: %m", unit_file); return generator_add_symlink(dir, where_unit, "requires", unit); }
int generator_hook_up_mkswap( const char *dir, const char *what) { _cleanup_free_ char *node = NULL, *unit = NULL, *escaped = NULL, *where_unit = NULL; _cleanup_fclose_ FILE *f = NULL; const char *unit_file; int r; node = fstab_node_to_udev_node(what); if (!node) return log_oom(); /* Nothing to work on. */ if (!is_device_path(node)) { log_error("Cannot format something that is not a device node: %s", node); return -EINVAL; } r = unit_name_from_path_instance("systemd-mkswap", node, ".service", &unit); if (r < 0) return log_error_errno(r, "Failed to make unit instance name from path \"%s\": %m", node); unit_file = strjoina(dir, "/", unit); log_debug("Creating %s", unit_file); escaped = cescape(node); if (!escaped) return log_oom(); r = unit_name_from_path(what, ".swap", &where_unit); if (r < 0) return log_error_errno(r, "Failed to make unit name from path \"%s\": %m", what); f = fopen(unit_file, "wxe"); if (!f) return log_error_errno(errno, "Failed to create unit file %s: %m", unit_file); fprintf(f, "# Automatically generated by %s\n\n" "[Unit]\n" "Description=Make Swap on %%f\n" "Documentation=man:[email protected](8)\n" "DefaultDependencies=no\n" "BindsTo=%%i.device\n" "After=%%i.device\n" "Before=%s\n" "Before=shutdown.target\n" "\n" "[Service]\n" "Type=oneshot\n" "RemainAfterExit=yes\n" "ExecStart="SYSTEMD_MAKEFS_PATH " swap %s\n" "TimeoutSec=0\n", program_invocation_short_name, where_unit, escaped); r = fflush_and_check(f); if (r < 0) return log_error_errno(r, "Failed to write unit file %s: %m", unit_file); return generator_add_symlink(dir, where_unit, "requires", unit); }
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 create_disk( const char *name, const char *device, const char *password, const char *options) { _cleanup_free_ char *p = NULL, *n = NULL, *d = NULL, *u = NULL, *to = NULL, *e = NULL, *filtered = NULL; _cleanup_fclose_ FILE *f = NULL; bool noauto, nofail, tmp, swap; char *from; int r; assert(name); assert(device); noauto = fstab_test_yes_no_option(options, "noauto\0" "auto\0"); nofail = fstab_test_yes_no_option(options, "nofail\0" "fail\0"); tmp = fstab_test_option(options, "tmp\0"); swap = fstab_test_option(options, "swap\0"); if (tmp && swap) { log_error("Device '%s' cannot be both 'tmp' and 'swap'. Ignoring.", name); return -EINVAL; } e = unit_name_escape(name); if (!e) return log_oom(); r = unit_name_build("systemd-cryptsetup", e, ".service", &n); if (r < 0) return log_error_errno(r, "Failed to generate unit name: %m"); p = strjoin(arg_dest, "/", n, NULL); if (!p) return log_oom(); u = fstab_node_to_udev_node(device); if (!u) return log_oom(); r = unit_name_from_path(u, ".device", &d); if (r < 0) return log_error_errno(r, "Failed to generate unit name: %m"); f = fopen(p, "wxe"); if (!f) return log_error_errno(errno, "Failed to create unit file %s: %m", p); fputs( "# Automatically generated by systemd-cryptsetup-generator\n\n" "[Unit]\n" "Description=Cryptography Setup for %I\n" "Documentation=man:crypttab(5) man:systemd-cryptsetup-generator(8) man:[email protected](8)\n" "SourcePath=/etc/crypttab\n" "DefaultDependencies=no\n" "Conflicts=umount.target\n" "BindsTo=dev-mapper-%i.device\n" "IgnoreOnIsolate=true\n" "After=cryptsetup-pre.target\n", f); if (!nofail) fprintf(f, "Before=cryptsetup.target\n"); if (password) { if (STR_IN_SET(password, "/dev/urandom", "/dev/random", "/dev/hw_random")) fputs("After=systemd-random-seed.service\n", f); else if (!streq(password, "-") && !streq(password, "none")) { _cleanup_free_ char *uu; uu = fstab_node_to_udev_node(password); if (!uu) return log_oom(); if (!path_equal(uu, "/dev/null")) { if (is_device_path(uu)) { _cleanup_free_ char *dd = NULL; r = unit_name_from_path(uu, ".device", &dd); if (r < 0) return log_error_errno(r, "Failed to generate unit name: %m"); fprintf(f, "After=%1$s\nRequires=%1$s\n", dd); } else fprintf(f, "RequiresMountsFor=%s\n", password); } } } if (is_device_path(u)) fprintf(f, "BindsTo=%s\n" "After=%s\n" "Before=umount.target\n", d, d); else fprintf(f, "RequiresMountsFor=%s\n", u); r = generator_write_timeouts(arg_dest, device, name, options, &filtered); if (r < 0) return r; fprintf(f, "\n[Service]\n" "Type=oneshot\n" "RemainAfterExit=yes\n" "TimeoutSec=0\n" /* the binary handles timeouts anyway */ "ExecStart=" SYSTEMD_CRYPTSETUP_PATH " attach '%s' '%s' '%s' '%s'\n" "ExecStop=" SYSTEMD_CRYPTSETUP_PATH " detach '%s'\n", name, u, strempty(password), strempty(filtered), name); if (tmp) fprintf(f, "ExecStartPost=/sbin/mke2fs '/dev/mapper/%s'\n", name); if (swap) fprintf(f, "ExecStartPost=/sbin/mkswap '/dev/mapper/%s'\n", name); r = fflush_and_check(f); if (r < 0) return log_error_errno(r, "Failed to write file %s: %m", p); from = strjoina("../", n); if (!noauto) { to = strjoin(arg_dest, "/", d, ".wants/", n, NULL); if (!to) return log_oom(); mkdir_parents_label(to, 0755); if (symlink(from, to) < 0) return log_error_errno(errno, "Failed to create symlink %s: %m", to); free(to); if (!nofail) to = strjoin(arg_dest, "/cryptsetup.target.requires/", n, NULL); else to = strjoin(arg_dest, "/cryptsetup.target.wants/", n, NULL); if (!to) return log_oom(); mkdir_parents_label(to, 0755); if (symlink(from, to) < 0) return log_error_errno(errno, "Failed to create symlink %s: %m", to); } free(to); to = strjoin(arg_dest, "/dev-mapper-", e, ".device.requires/", n, NULL); if (!to) return log_oom(); mkdir_parents_label(to, 0755); if (symlink(from, to) < 0) return log_error_errno(errno, "Failed to create symlink %s: %m", to); if (!noauto && !nofail) { _cleanup_free_ char *dmname; dmname = strjoin("dev-mapper-", e, ".device", NULL); if (!dmname) return log_oom(); r = write_drop_in(arg_dest, dmname, 90, "device-timeout", "# Automatically generated by systemd-cryptsetup-generator \n\n" "[Unit]\nJobTimeoutSec=0"); if (r < 0) return log_error_errno(r, "Failed to write device drop-in: %m"); } return 0; }
static int add_swap( const char *what, struct mntent *me, bool noauto, bool nofail) { _cleanup_free_ char *name = NULL, *unit = NULL, *lnk = NULL, *filtered = NULL; _cleanup_fclose_ FILE *f = NULL; int r, pri = -1; const char *opts; assert(what); assert(me); if (access("/proc/swaps", F_OK) < 0) { log_info("Swap not supported, ignoring fstab swap entry for %s.", what); return 0; } if (detect_container(NULL) > 0) { log_info("Running in a container, ignoring fstab swap entry for %s.", what); return 0; } opts = me->mnt_opts; r = fstab_find_pri(opts, &pri); if (r < 0) { log_error_errno(r, "Failed to parse priority, ignoring: %m"); /* Remove invalid pri field */ r = fstab_filter_options(opts, "pri\0", NULL, NULL, &filtered); if (r < 0) return log_error_errno(r, "Failed to parse options: %m"); opts = filtered; } name = unit_name_from_path(what, ".swap"); 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 swap 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=/etc/fstab\n" "Documentation=man:fstab(5) man:systemd-fstab-generator(8)\n\n" "[Swap]\n" "What=%s\n", what); /* Note that we currently pass the priority field twice, once * in Priority=, and once in Options= */ if (pri >= 0) fprintf(f, "Priority=%i\n", pri); if (!isempty(opts) && !streq(opts, "defaults")) fprintf(f, "Options=%s\n", opts); r = fflush_and_check(f); if (r < 0) return log_error_errno(r, "Failed to write unit file %s: %m", unit); /* use what as where, to have a nicer error message */ r = generator_write_timeouts(arg_dest, what, what, opts, NULL); if (r < 0) return r; if (!noauto) { lnk = strjoin(arg_dest, "/" SPECIAL_SWAP_TARGET, nofail ? ".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); } return 0; }
static int create_device(void) { _cleanup_free_ char *u = NULL, *v = NULL, *d = NULL, *e = NULL, *u_escaped = NULL, *v_escaped = NULL, *root_hash_escaped = NULL; _cleanup_fclose_ FILE *f = NULL; const char *to; int r; /* If all three pieces of information are missing, then verity is turned off */ if (!arg_root_hash && !arg_data_what && !arg_hash_what) return 0; /* if one of them is missing however, the data is simply incomplete and this is an error */ if (!arg_root_hash) log_error("Verity information incomplete, root hash unspecified."); if (!arg_data_what) log_error("Verity information incomplete, root data device unspecified."); if (!arg_hash_what) log_error("Verity information incomplete, root hash device unspecified."); if (!arg_root_hash || !arg_data_what || !arg_hash_what) return -EINVAL; log_debug("Using root verity data device %s,\n" " hash device %s,\n" " and root hash %s.", arg_data_what, arg_hash_what, arg_root_hash); u = fstab_node_to_udev_node(arg_data_what); if (!u) return log_oom(); v = fstab_node_to_udev_node(arg_hash_what); if (!v) return log_oom(); u_escaped = specifier_escape(u); if (!u_escaped) return log_oom(); v_escaped = specifier_escape(v); if (!v_escaped) return log_oom(); r = unit_name_from_path(u, ".device", &d); if (r < 0) return log_error_errno(r, "Failed to generate unit name: %m"); r = unit_name_from_path(v, ".device", &e); if (r < 0) return log_error_errno(r, "Failed to generate unit name: %m"); root_hash_escaped = specifier_escape(arg_root_hash); if (!root_hash_escaped) return log_oom(); r = generator_open_unit_file(arg_dest, NULL, SYSTEMD_VERITYSETUP_SERVICE, &f); if (r < 0) return r; fprintf(f, "[Unit]\n" "Description=Integrity Protection Setup for %%I\n" "Documentation=man:systemd-veritysetup-generator(8) man:[email protected](8)\n" "SourcePath=/proc/cmdline\n" "DefaultDependencies=no\n" "Conflicts=umount.target\n" "BindsTo=%s %s\n" "IgnoreOnIsolate=true\n" "After=cryptsetup-pre.target %s %s\n" "Before=cryptsetup.target umount.target\n" "\n[Service]\n" "Type=oneshot\n" "RemainAfterExit=yes\n" "ExecStart=" ROOTLIBEXECDIR "/systemd-veritysetup attach root '%s' '%s' '%s'\n" "ExecStop=" ROOTLIBEXECDIR "/systemd-veritysetup detach root\n", d, e, d, e, u_escaped, v_escaped, root_hash_escaped); r = fflush_and_check(f); if (r < 0) return log_error_errno(r, "Failed to write file unit "SYSTEMD_VERITYSETUP_SERVICE": %m"); to = strjoina(arg_dest, "/cryptsetup.target.requires/" SYSTEMD_VERITYSETUP_SERVICE); (void) mkdir_parents(to, 0755); if (symlink("../" SYSTEMD_VERITYSETUP_SERVICE, to) < 0) return log_error_errno(errno, "Failed to create symlink %s: %m", to); return 0; }
static int add_mount( const char *id, const char *what, const char *where, const char *fstype, bool rw, const char *options, const char *description, const char *post) { _cleanup_free_ char *unit = NULL, *lnk = NULL, *crypto_what = NULL, *p = NULL; _cleanup_fclose_ FILE *f = NULL; int r; assert(id); assert(what); assert(where); assert(description); log_debug("Adding %s: %s %s", where, what, strna(fstype)); if (streq_ptr(fstype, "crypto_LUKS")) { r = add_cryptsetup(id, what, rw, &crypto_what); if (r < 0) return r; what = crypto_what; fstype = NULL; } r = unit_name_from_path(where, ".mount", &unit); if (r < 0) return log_error_errno(r, "Failed to generate unit name: %m"); p = strjoin(arg_dest, "/", unit, NULL); if (!p) return log_oom(); f = fopen(p, "wxe"); if (!f) return log_error_errno(errno, "Failed to create unit file %s: %m", unit); fprintf(f, "# Automatically generated by systemd-gpt-auto-generator\n\n" "[Unit]\n" "Description=%s\n" "Documentation=man:systemd-gpt-auto-generator(8)\n", description); if (post) fprintf(f, "Before=%s\n", post); 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 (fstype) fprintf(f, "Type=%s\n", fstype); if (options) fprintf(f, "Options=%s,%s\n", options, rw ? "rw" : "ro"); else fprintf(f, "Options=%s\n", rw ? "rw" : "ro"); r = fflush_and_check(f); if (r < 0) return log_error_errno(r, "Failed to write unit file %s: %m", p); if (post) { lnk = strjoin(arg_dest, "/", post, ".requires/", unit, NULL); if (!lnk) return log_oom(); mkdir_parents_label(lnk, 0755); if (symlink(p, lnk) < 0) return log_error_errno(errno, "Failed to create symlink %s: %m", lnk); } return 0; }
static int add_swap( const char *what, struct mntent *me, bool noauto, bool nofail) { _cleanup_free_ char *name = NULL, *unit = NULL, *lnk = NULL; _cleanup_fclose_ FILE *f = NULL; int r; assert(what); assert(me); if (access("/proc/swaps", F_OK) < 0) { log_info("Swap not supported, ignoring fstab swap entry for %s.", what); return 0; } if (detect_container() > 0) { log_info("Running in a container, ignoring fstab swap entry for %s.", what); return 0; } r = unit_name_from_path(what, ".swap", &name); if (r < 0) return log_error_errno(r, "Failed to generate unit name: %m"); unit = strjoin(arg_dest, "/", name); if (!unit) return log_oom(); f = fopen(unit, "wxe"); if (!f) return log_error_errno(errno, errno == EEXIST ? "Failed to create swap unit file %s, as it already exists. Duplicate entry in /etc/fstab?" : "Failed to create unit file %s: %m", unit); fprintf(f, "# Automatically generated by systemd-fstab-generator\n\n" "[Unit]\n" "SourcePath=/etc/fstab\n" "Documentation=man:fstab(5) man:systemd-fstab-generator(8)\n\n" "[Swap]\n" "What=%s\n", what); if (!isempty(me->mnt_opts) && !streq(me->mnt_opts, "defaults")) fprintf(f, "Options=%s\n", me->mnt_opts); r = fflush_and_check(f); if (r < 0) return log_error_errno(r, "Failed to write unit file %s: %m", unit); /* use what as where, to have a nicer error message */ r = generator_write_timeouts(arg_dest, what, what, me->mnt_opts, NULL); if (r < 0) return r; if (!noauto) { lnk = strjoin(arg_dest, "/" SPECIAL_SWAP_TARGET, nofail ? ".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); } return 0; }
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_cryptsetup(const char *id, const char *what, bool rw, char **device) { _cleanup_free_ char *e = NULL, *n = NULL, *p = NULL, *d = NULL, *to = NULL; _cleanup_fclose_ FILE *f = NULL; char *from, *ret; int r; assert(id); assert(what); assert(device); r = unit_name_from_path(what, ".device", &d); if (r < 0) return log_error_errno(r, "Failed to generate unit name: %m"); e = unit_name_escape(id); if (!e) return log_oom(); r = unit_name_build("systemd-cryptsetup", e, ".service", &n); if (r < 0) return log_error_errno(r, "Failed to generate unit name: %m"); p = strjoin(arg_dest, "/", n, NULL); if (!p) return log_oom(); f = fopen(p, "wxe"); if (!f) return log_error_errno(errno, "Failed to create unit file %s: %m", p); fprintf(f, "# Automatically generated by systemd-gpt-auto-generator\n\n" "[Unit]\n" "Description=Cryptography Setup for %%I\n" "Documentation=man:systemd-gpt-auto-generator(8) man:[email protected](8)\n" "DefaultDependencies=no\n" "Conflicts=umount.target\n" "BindsTo=dev-mapper-%%i.device %s\n" "Before=umount.target cryptsetup.target\n" "After=%s\n" "IgnoreOnIsolate=true\n" "[Service]\n" "Type=oneshot\n" "RemainAfterExit=yes\n" "TimeoutSec=0\n" /* the binary handles timeouts anyway */ "ExecStart=" SYSTEMD_CRYPTSETUP_PATH " attach '%s' '%s' '' '%s'\n" "ExecStop=" SYSTEMD_CRYPTSETUP_PATH " detach '%s'\n", d, d, id, what, rw ? "" : "read-only", id); r = fflush_and_check(f); if (r < 0) return log_error_errno(r, "Failed to write file %s: %m", p); from = strjoina("../", n); to = strjoin(arg_dest, "/", d, ".wants/", n, NULL); if (!to) return log_oom(); mkdir_parents_label(to, 0755); if (symlink(from, to) < 0) return log_error_errno(errno, "Failed to create symlink %s: %m", to); free(to); to = strjoin(arg_dest, "/cryptsetup.target.requires/", n, NULL); if (!to) return log_oom(); mkdir_parents_label(to, 0755); if (symlink(from, to) < 0) return log_error_errno(errno, "Failed to create symlink %s: %m", to); free(to); to = strjoin(arg_dest, "/dev-mapper-", e, ".device.requires/", n, NULL); if (!to) return log_oom(); mkdir_parents_label(to, 0755); if (symlink(from, to) < 0) return log_error_errno(errno, "Failed to create symlink %s: %m", to); free(p); p = strjoin(arg_dest, "/dev-mapper-", e, ".device.d/50-job-timeout-sec-0.conf", NULL); if (!p) return log_oom(); mkdir_parents_label(p, 0755); r = write_string_file(p, "# Automatically generated by systemd-gpt-auto-generator\n\n" "[Unit]\n" "JobTimeoutSec=0\n", WRITE_STRING_FILE_CREATE); /* the binary handles timeouts anyway */ if (r < 0) return log_error_errno(r, "Failed to write device drop-in: %m"); ret = strappend("/dev/mapper/", id); if (!ret) return log_oom(); *device = ret; return 0; }
static int add_swap(const char *what, struct mntent *me) { _cleanup_free_ char *name = NULL, *unit = NULL, *lnk = NULL, *device = NULL; _cleanup_fclose_ FILE *f = NULL; bool noauto, nofail; int r, pri = -1; assert(what); assert(me); r = mount_find_pri(me, &pri); if (r < 0) { log_error("Failed to parse priority"); return pri; } noauto = !!hasmntopt(me, "noauto"); nofail = !!hasmntopt(me, "nofail"); name = unit_name_from_path(what, ".swap"); 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 swap 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; } fputs("# 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 "\n", f); if (!noauto && !nofail) fputs("Before=" SPECIAL_SWAP_TARGET "\n", f); fprintf(f, "\n" "[Swap]\n" "What=%s\n", what); if (pri >= 0) fprintf(f, "Priority=%i\n", pri); fflush(f); if (ferror(f)) { log_error("Failed to write unit file %s: %m", unit); return -errno; } if (!noauto) { lnk = strjoin(arg_dest, "/" SPECIAL_SWAP_TARGET ".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; } 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; } } } 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; }