static void do_fstab_filter_options(const char *opts, const char *remove, int r_expected, const char *name_expected, const char *value_expected, const char *filtered_expected) { int r; const char *name; _cleanup_free_ char *value, *filtered; r = fstab_filter_options(opts, remove, &name, &value, &filtered); log_info("\"%s\" → %d, \"%s\", \"%s\", \"%s\", expected %d, \"%s\", \"%s\", \"%s\"", opts, r, name, value, filtered, r_expected, name_expected, value_expected, filtered_expected ?: opts); assert_se(r == r_expected); assert_se(streq_ptr(name, name_expected)); assert_se(streq_ptr(value, value_expected)); assert_se(streq_ptr(filtered, filtered_expected ?: opts)); /* also test the malloc-less mode */ r = fstab_filter_options(opts, remove, &name, NULL, NULL); log_info("\"%s\" → %d, \"%s\", expected %d, \"%s\"", opts, r, name, r_expected, name_expected); assert_se(r == r_expected); assert_se(streq_ptr(name, name_expected)); }
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 write_idle_timeout(FILE *f, const char *where, const char *opts) { _cleanup_free_ char *timeout = NULL; char timespan[FORMAT_TIMESPAN_MAX]; usec_t u; int r; r = fstab_filter_options(opts, "x-systemd.idle-timeout\0", NULL, &timeout, NULL); if (r < 0) return log_warning_errno(r, "Failed to parse options: %m"); if (r == 0) return 0; r = parse_sec(timeout, &u); if (r < 0) { log_warning("Failed to parse timeout for %s, ignoring: %s", where, timeout); return 0; } fprintf(f, "TimeoutIdleSec=%s\n", format_timespan(timespan, sizeof(timespan), u, 0)); return 0; }
static int write_timeout(FILE *f, const char *where, const char *opts, const char *filter, const char *variable) { _cleanup_free_ char *timeout = NULL; char timespan[FORMAT_TIMESPAN_MAX]; usec_t u; int r; r = fstab_filter_options(opts, filter, NULL, &timeout, NULL); if (r < 0) return log_warning_errno(r, "Failed to parse options: %m"); if (r == 0) return 0; r = parse_sec_fix_0(timeout, &u); if (r < 0) { log_warning("Failed to parse timeout for %s, ignoring: %s", where, timeout); return 0; } fprintf(f, "%s=%s\n", variable, format_timespan(timespan, sizeof(timespan), u, 0)); 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; }