<varlistentry>
<term><varname>What=</varname></term>
- <listitem><para>Takes an absolute path of a device node, file or other resource to mount. See
- <citerefentry
+ <listitem><para>Takes an absolute path or a fstab-style identifier of a device node, file or
+ other resource to mount. See <citerefentry
project='man-pages'><refentrytitle>mount</refentrytitle><manvolnum>8</manvolnum></citerefentry> for
details. If this refers to a device node, a dependency on the respective device unit is automatically
created. (See
<varlistentry>
<term><varname>What=</varname></term>
- <listitem><para>Takes an absolute path of a device node or file to use for paging. See <citerefentry
+ <listitem><para>Takes an absolute path or a fstab-style identifier of a device node or file to use
+ for paging. See <citerefentry
project='man-pages'><refentrytitle>swapon</refentrytitle><manvolnum>8</manvolnum></citerefentry> for
details. If this refers to a device node, a dependency on the respective device unit is automatically
created. (See
#include "dbus-kill.h"
#include "dbus-mount.h"
#include "dbus-util.h"
+#include "fstab-util.h"
#include "mount.h"
#include "string-util.h"
#include "unit.h"
sd_bus_error *error) {
Unit *u = UNIT(m);
+ int r;
assert(m);
assert(name);
if (streq(name, "Where"))
return bus_set_transient_path(u, name, &m->where, message, flags, error);
- if (streq(name, "What"))
- return bus_set_transient_string(u, name, &m->parameters_fragment.what, message, flags, error);
+ if (streq(name, "What")) {
+ _cleanup_free_ char *path = NULL;
+ const char *v;
+
+ r = sd_bus_message_read(message, "s", &v);
+ if (r < 0)
+ return r;
+
+ if (!isempty(v)) {
+ path = fstab_node_to_udev_node(v);
+ if (!path)
+ return -ENOMEM;
+
+ /* path_is_valid is not used - see the comment for config_parse_mount_node */
+ if (strlen(path) >= PATH_MAX)
+ return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Resolved What=%s too long", path);
+ }
+
+ if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
+ free_and_replace(m->parameters_fragment.what, path);
+ unit_write_settingf(u, flags|UNIT_ESCAPE_SPECIFIERS, name, "What=%s", strempty(m->parameters_fragment.what));
+ }
+
+ return 1;
+ }
if (streq(name, "Options"))
return bus_set_transient_string(u, name, &m->parameters_fragment.options, message, flags, error);
{{ EXEC_CONTEXT_CONFIG_ITEMS('Socket') }}
{{ CGROUP_CONTEXT_CONFIG_ITEMS('Socket') }}
{{ KILL_CONTEXT_CONFIG_ITEMS('Socket') }}
-Mount.What, config_parse_unit_string_printf, 0, offsetof(Mount, parameters_fragment.what)
+Mount.What, config_parse_mount_node, 0, offsetof(Mount, parameters_fragment.what)
Mount.Where, config_parse_unit_path_printf, 0, offsetof(Mount, where)
Mount.Options, config_parse_unit_string_printf, 0, offsetof(Mount, parameters_fragment.options)
Mount.Type, config_parse_unit_string_printf, 0, offsetof(Mount, parameters_fragment.fstype)
Automount.ExtraOptions, config_parse_unit_string_printf, 0, offsetof(Automount, extra_options)
Automount.DirectoryMode, config_parse_mode, 0, offsetof(Automount, directory_mode)
Automount.TimeoutIdleSec, config_parse_sec_fix_0, 0, offsetof(Automount, timeout_idle_usec)
-Swap.What, config_parse_unit_path_printf, 0, offsetof(Swap, parameters_fragment.what)
+Swap.What, config_parse_mount_node, 0, offsetof(Swap, parameters_fragment.what)
Swap.Priority, config_parse_swap_priority, 0, 0
Swap.Options, config_parse_unit_string_printf, 0, offsetof(Swap, parameters_fragment.options)
Swap.TimeoutSec, config_parse_sec_fix_0, 0, offsetof(Swap, timeout_usec)
#include "fileio.h"
#include "firewall-util.h"
#include "fs-util.h"
+#include "fstab-util.h"
#include "hexdecoct.h"
#include "iovec-util.h"
#include "ioprio-util.h"
return 0;
}
+int config_parse_mount_node(
+ const char *unit,
+ const char *filename,
+ unsigned line,
+ const char *section,
+ unsigned section_line,
+ const char *lvalue,
+ int ltype,
+ const char *rvalue,
+ void *data,
+ void *userdata) {
+
+ const Unit *u = ASSERT_PTR(userdata);
+ _cleanup_free_ char *resolved = NULL, *path = NULL;
+ int r;
+
+ assert(filename);
+ assert(lvalue);
+ assert(rvalue);
+
+ r = unit_full_printf(u, rvalue, &resolved);
+ if (r < 0) {
+ log_syntax(unit, LOG_WARNING, filename, line, r, "Failed to resolve unit specifiers in '%s', ignoring: %m", rvalue);
+ return 0;
+ }
+
+ path = fstab_node_to_udev_node(resolved);
+ if (!path)
+ return log_oom();
+
+ /* The source passed is not necessarily something we understand, and we pass it as-is to mount/swapon,
+ * so path_is_valid is not used. But let's check for basic sanety, i.e. if the source is longer than
+ * PATH_MAX, you're likely doing something wrong. */
+ if (strlen(path) >= PATH_MAX) {
+ log_syntax(unit, LOG_WARNING, filename, line, 0, "Resolved mount path '%s' too long, ignoring.", path);
+ return 0;
+ }
+
+ return config_parse_string(unit, filename, line, section, section_line, lvalue, ltype, path, data, userdata);
+}
+
static int merge_by_names(Unit *u, Set *names, const char *id) {
char *k;
int r;
{ config_parse_job_mode_isolate, "BOOLEAN" },
{ config_parse_personality, "PERSONALITY" },
{ config_parse_log_filter_patterns, "REGEX" },
+ { config_parse_mount_node, "NODE" },
};
const char *prev = NULL;
CONFIG_PARSER_PROTOTYPE(config_parse_open_file);
CONFIG_PARSER_PROTOTYPE(config_parse_memory_pressure_watch);
CONFIG_PARSER_PROTOTYPE(config_parse_cgroup_nft_set);
+CONFIG_PARSER_PROTOTYPE(config_parse_mount_node);
/* gperf prototypes */
const struct ConfigPerfItem* load_fragment_gperf_lookup(const char *key, GPERF_LEN_TYPE length);