#include <fcntl.h>
#include <sched.h>
#include <sys/prctl.h>
+#include <sys/mount.h>
+#include <linux/fs.h>
#include "unit.h"
#include "strv.h"
if (!k)
return -ENOMEM;
- r = unit_add_dependency_by_name(u, d, k, NULL);
+ r = unit_add_dependency_by_name(u, d, k, NULL, true);
free(k);
if (r < 0)
return 0;
}
+static int config_parse_description(
+ const char *filename,
+ unsigned line,
+ const char *section,
+ const char *lvalue,
+ const char *rvalue,
+ void *data,
+ void *userdata) {
+
+ Unit *u = userdata;
+ char *k;
+
+ assert(filename);
+ assert(lvalue);
+ assert(rvalue);
+ assert(data);
+
+ if (!(k = unit_full_printf(u, rvalue)))
+ return -ENOMEM;
+
+ free(u->meta.description);
+
+ if (*k)
+ u->meta.description = k;
+ else {
+ free(k);
+ u->meta.description = NULL;
+ }
+
+ return 0;
+}
+
static int config_parse_listen(
const char *filename,
unsigned line,
void *userdata) {
usec_t *usec = data;
- unsigned long long u;
int r;
assert(filename);
assert(rvalue);
assert(data);
- if ((r = safe_atollu(rvalue, &u)) < 0) {
+ if ((r = parse_usec(rvalue, usec)) < 0) {
log_error("[%s:%u] Failed to parse time value: %s", filename, line, rvalue);
return r;
}
- /* We actually assume the user configures seconds. Later on we
- * might choose to support suffixes for time values, to
- * configure bigger or smaller units */
-
- *usec = u * USEC_PER_SEC;
-
return 0;
}
DEFINE_CONFIG_PARSE_ENUM(config_parse_kill_mode, kill_mode, KillMode, "Failed to parse kill mode");
+static int config_parse_mount_flags(
+ const char *filename,
+ unsigned line,
+ const char *section,
+ const char *lvalue,
+ const char *rvalue,
+ void *data,
+ void *userdata) {
+
+ ExecContext *c = data;
+ char *w;
+ size_t l;
+ char *state;
+ unsigned long flags = 0;
+
+ assert(filename);
+ assert(lvalue);
+ assert(rvalue);
+ assert(data);
+
+ FOREACH_WORD(w, l, rvalue, state) {
+ if (strncmp(w, "shared", l) == 0)
+ flags |= MS_SHARED;
+ else if (strncmp(w, "slave", l) == 0)
+ flags |= MS_SLAVE;
+ else if (strncmp(w, "private", l) == 0)
+ flags |= MS_PRIVATE;
+ else {
+ log_error("[%s:%u] Failed to parse mount flags: %s", filename, line, rvalue);
+ return -EINVAL;
+ }
+ }
+
+ c->mount_flags = flags;
+ return 0;
+}
+
#define FOLLOW_MAX 8
static int open_follow(char **filename, FILE **_f, Set *names, char **_final) {
{ config_parse_kill_mode, "KILLMODE" },
{ config_parse_listen, "SOCKET [...]" },
{ config_parse_socket_bind, "SOCKETBIND" },
- { config_parse_bindtodevice, "NETWORKINTERFACE" }
+ { config_parse_bindtodevice, "NETWORKINTERFACE" },
+ { config_parse_usec, "SECONDS" },
+ { config_parse_path_strv, "PATH [...]" },
+ { config_parse_mount_flags, "MOUNTFLAG [...]" },
+ { config_parse_description, "DESCRIPTION" },
};
assert(f);
[UNIT_DEVICE] = "Device",
[UNIT_MOUNT] = "Mount",
[UNIT_AUTOMOUNT] = "Automount",
- [UNIT_SNAPSHOT] = "Snapshot"
+ [UNIT_SNAPSHOT] = "Snapshot",
+ [UNIT_SWAP] = "Swap"
};
#define EXEC_CONTEXT_CONFIG_ITEMS(context, section) \
{ "SyslogIdentifier", config_parse_string, &(context).syslog_identifier, section }, \
{ "SyslogFacility", config_parse_facility, &(context).syslog_priority, section }, \
{ "SyslogLevel", config_parse_level, &(context).syslog_priority, section }, \
+ { "SyslogNoPrefix", config_parse_bool, &(context).syslog_no_prefix, section }, \
{ "Capabilities", config_parse_capabilities, &(context), section }, \
{ "SecureBits", config_parse_secure_bits, &(context), section }, \
{ "CapabilityBoundingSetDrop", config_parse_bounding_set, &(context), section }, \
{ "LimitNICE", config_parse_limit, &(context).rlimit[RLIMIT_NICE], section }, \
{ "LimitRTPRIO", config_parse_limit, &(context).rlimit[RLIMIT_RTPRIO], section }, \
{ "LimitRTTIME", config_parse_limit, &(context).rlimit[RLIMIT_RTTIME], section }, \
- { "ControlGroup", config_parse_cgroup, u, section }
+ { "ControlGroup", config_parse_cgroup, u, section }, \
+ { "ReadWriteDirectories", config_parse_path_strv, &(context).read_write_dirs, section }, \
+ { "ReadOnlyDirectories", config_parse_path_strv, &(context).read_only_dirs, section }, \
+ { "InaccessibleDirectories",config_parse_path_strv, &(context).inaccessible_dirs, section }, \
+ { "PrivateTmp", config_parse_bool, &(context).private_tmp, section }, \
+ { "MountFlags", config_parse_mount_flags, &(context), section }
const ConfigItem items[] = {
- { "Names", config_parse_names, u, "Meta" },
- { "Description", config_parse_string, &u->meta.description, "Meta" },
- { "Requires", config_parse_deps, UINT_TO_PTR(UNIT_REQUIRES), "Meta" },
- { "RequiresOverridable", config_parse_deps, UINT_TO_PTR(UNIT_REQUIRES_OVERRIDABLE), "Meta" },
- { "Requisite", config_parse_deps, UINT_TO_PTR(UNIT_REQUISITE), "Meta" },
- { "RequisiteOverridable", config_parse_deps, UINT_TO_PTR(UNIT_REQUISITE_OVERRIDABLE), "Meta" },
- { "Wants", config_parse_deps, UINT_TO_PTR(UNIT_WANTS), "Meta" },
- { "Conflicts", config_parse_deps, UINT_TO_PTR(UNIT_CONFLICTS), "Meta" },
- { "Before", config_parse_deps, UINT_TO_PTR(UNIT_BEFORE), "Meta" },
- { "After", config_parse_deps, UINT_TO_PTR(UNIT_AFTER), "Meta" },
- { "RecursiveStop", config_parse_bool, &u->meta.recursive_stop, "Meta" },
- { "StopWhenUnneeded", config_parse_bool, &u->meta.stop_when_unneeded, "Meta" },
+ { "Names", config_parse_names, u, "Unit" },
+ { "Description", config_parse_description, u, "Unit" },
+ { "Requires", config_parse_deps, UINT_TO_PTR(UNIT_REQUIRES), "Unit" },
+ { "RequiresOverridable", config_parse_deps, UINT_TO_PTR(UNIT_REQUIRES_OVERRIDABLE), "Unit" },
+ { "Requisite", config_parse_deps, UINT_TO_PTR(UNIT_REQUISITE), "Unit" },
+ { "RequisiteOverridable", config_parse_deps, UINT_TO_PTR(UNIT_REQUISITE_OVERRIDABLE), "Unit" },
+ { "Wants", config_parse_deps, UINT_TO_PTR(UNIT_WANTS), "Unit" },
+ { "Conflicts", config_parse_deps, UINT_TO_PTR(UNIT_CONFLICTS), "Unit" },
+ { "Before", config_parse_deps, UINT_TO_PTR(UNIT_BEFORE), "Unit" },
+ { "After", config_parse_deps, UINT_TO_PTR(UNIT_AFTER), "Unit" },
+ { "RecursiveStop", config_parse_bool, &u->meta.recursive_stop, "Unit" },
+ { "StopWhenUnneeded", config_parse_bool, &u->meta.stop_when_unneeded, "Unit" },
{ "PIDFile", config_parse_path, &u->service.pid_file, "Service" },
{ "ExecStartPre", config_parse_exec, u->service.exec_command+SERVICE_EXEC_START_PRE, "Service" },
{ "SysVStartPriority", config_parse_sysv_priority, &u->service.sysv_start_priority, "Service" },
{ "KillMode", config_parse_kill_mode, &u->service.kill_mode, "Service" },
{ "NonBlocking", config_parse_bool, &u->service.exec_context.non_blocking, "Service" },
+ { "BusName", config_parse_string, &u->service.bus_name, "Service" },
EXEC_CONTEXT_CONFIG_ITEMS(u->service.exec_context, "Service"),
{ "ListenStream", config_parse_listen, &u->socket, "Socket" },
{ "DirectoryMode", config_parse_mode, &u->socket.directory_mode, "Socket" },
{ "SocketMode", config_parse_mode, &u->socket.socket_mode, "Socket" },
{ "KillMode", config_parse_kill_mode, &u->socket.kill_mode, "Socket" },
+ { "Accept", config_parse_bool, &u->socket.accept, "Socket" },
EXEC_CONTEXT_CONFIG_ITEMS(u->socket.exec_context, "Socket"),
{ "What", config_parse_string, &u->mount.parameters_fragment.what, "Mount" },
{ "KillMode", config_parse_kill_mode, &u->mount.kill_mode, "Mount" },
EXEC_CONTEXT_CONFIG_ITEMS(u->mount.exec_context, "Mount"),
+ { "Where", config_parse_path, &u->automount.where, "Automount" },
+
+ { "What", config_parse_path, &u->swap.parameters_fragment.what, "Swap" },
+ { "Priority", config_parse_int, &u->swap.parameters_fragment.priority, "Swap" },
+
{ NULL, NULL, NULL, NULL }
};
assert(u);
assert(path);
- sections[0] = "Meta";
+ sections[0] = "Unit";
sections[1] = section_table[u->meta.type];
sections[2] = NULL;