summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/core/mount.c55
-rw-r--r--src/core/unit.c70
-rw-r--r--src/fstab-generator/fstab-generator.c12
-rw-r--r--src/shared/dropin.c98
-rw-r--r--src/shared/dropin.h31
-rw-r--r--src/shared/generator.c57
-rw-r--r--src/shared/generator.h3
-rw-r--r--src/shared/path-lookup.h2
8 files changed, 229 insertions, 99 deletions
diff --git a/src/core/mount.c b/src/core/mount.c
index aea2ab17c9..102bbef91b 100644
--- a/src/core/mount.c
+++ b/src/core/mount.c
@@ -418,57 +418,6 @@ static int mount_add_default_dependencies(Mount *m) {
return 0;
}
-static int mount_fix_timeouts(Mount *m) {
- MountParameters *p;
- const char *timeout = NULL;
- Unit *other;
- Iterator i;
- usec_t u;
- char *t;
- int r;
-
- assert(m);
-
- p = get_mount_parameters_fragment(m);
- if (!p)
- return 0;
-
- /* 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. */
-
- if ((timeout = mount_test_option(p->options, "comment=systemd.device-timeout")))
- timeout += 31;
- else if ((timeout = mount_test_option(p->options, "x-systemd.device-timeout")))
- timeout += 25;
- else
- return 0;
-
- t = strndup(timeout, strcspn(timeout, ",;" WHITESPACE));
- if (!t)
- return -ENOMEM;
-
- r = parse_sec(t, &u);
- free(t);
-
- if (r < 0) {
- log_warning_unit(UNIT(m)->id,
- "Failed to parse timeout for %s, ignoring: %s",
- m->where, timeout);
- return r;
- }
-
- SET_FOREACH(other, UNIT(m)->dependencies[UNIT_AFTER], i) {
- if (other->type != UNIT_DEVICE)
- continue;
-
- other->job_timeout = u;
- }
-
- return 0;
-}
-
static int mount_verify(Mount *m) {
_cleanup_free_ char *e = NULL;
bool b;
@@ -556,10 +505,6 @@ static int mount_add_extras(Mount *m) {
if (r < 0)
return r;
- r = mount_fix_timeouts(m);
- if (r < 0)
- return r;
-
if (u->default_dependencies) {
r = mount_add_default_dependencies(m);
if (r < 0)
diff --git a/src/core/unit.c b/src/core/unit.c
index 6e40bc6e9f..bace69f46a 100644
--- a/src/core/unit.c
+++ b/src/core/unit.c
@@ -51,6 +51,7 @@
#include "dbus.h"
#include "execute.h"
#include "virt.h"
+#include "dropin.h"
const UnitVTable * const unit_vtable[_UNIT_TYPE_MAX] = {
[UNIT_SERVICE] = &service_vtable,
@@ -2966,68 +2967,55 @@ ExecRuntime *unit_get_exec_runtime(Unit *u) {
return *(ExecRuntime**) ((uint8_t*) u + offset);
}
-static int drop_in_file(Unit *u, UnitSetPropertiesMode mode, const char *name, char **_p, char **_q) {
- _cleanup_free_ char *b = NULL;
- char *p, *q;
- int r;
-
- assert(u);
- assert(name);
- assert(_p);
- assert(_q);
-
- b = xescape(name, "/.");
- if (!b)
- return -ENOMEM;
-
- if (!filename_is_safe(b))
- return -EINVAL;
-
+static int unit_drop_in_dir(Unit *u, UnitSetPropertiesMode mode, bool transient, char **dir) {
if (u->manager->running_as == SYSTEMD_USER) {
- _cleanup_free_ char *c = NULL;
+ int r;
- r = user_config_home(&c);
- if (r < 0)
- return r;
+ r = user_config_home(dir);
if (r == 0)
return -ENOENT;
+ return r;
+ }
- p = strjoin(c, "/", u->id, ".d", NULL);
- } else if (mode == UNIT_PERSISTENT && !u->transient)
- p = strjoin("/etc/systemd/system/", u->id, ".d", NULL);
+ if (mode == UNIT_PERSISTENT && !transient)
+ *dir = strdup("/etc/systemd/system");
else
- p = strjoin("/run/systemd/system/", u->id, ".d", NULL);
- if (!p)
+ *dir = strdup("/run/systemd/system");
+ if (!*dir)
return -ENOMEM;
- q = strjoin(p, "/90-", b, ".conf", NULL);
- if (!q) {
- free(p);
- return -ENOMEM;
- }
-
- *_p = p;
- *_q = q;
return 0;
}
+static int unit_drop_in_file(Unit *u,
+ UnitSetPropertiesMode mode, const char *name, char **p, char **q) {
+ _cleanup_free_ char *dir = NULL;
+ int r;
+
+ assert(u);
+
+ r = unit_drop_in_dir(u, mode, u->transient, &dir);
+ if (r < 0)
+ return r;
+
+ return drop_in_file(dir, u->id, name, p, q);
+}
+
int unit_write_drop_in(Unit *u, UnitSetPropertiesMode mode, const char *name, const char *data) {
- _cleanup_free_ char *p = NULL, *q = NULL;
+
+ _cleanup_free_ char *dir = NULL;
int r;
assert(u);
- assert(name);
- assert(data);
if (!IN_SET(mode, UNIT_PERSISTENT, UNIT_RUNTIME))
return 0;
- r = drop_in_file(u, mode, name, &p, &q);
+ r = unit_drop_in_dir(u, mode, u->transient, &dir);
if (r < 0)
return r;
- mkdir_p(p, 0755);
- return write_string_file_atomic_label(q, data);
+ return write_drop_in(dir, u->id, name, data);
}
int unit_write_drop_in_format(Unit *u, UnitSetPropertiesMode mode, const char *name, const char *format, ...) {
@@ -3103,7 +3091,7 @@ int unit_remove_drop_in(Unit *u, UnitSetPropertiesMode mode, const char *name) {
if (!IN_SET(mode, UNIT_PERSISTENT, UNIT_RUNTIME))
return 0;
- r = drop_in_file(u, mode, name, &p, &q);
+ r = unit_drop_in_file(u, mode, name, &p, &q);
if (r < 0)
return r;
diff --git a/src/fstab-generator/fstab-generator.c b/src/fstab-generator/fstab-generator.c
index 98772fb56b..6f392dfd4d 100644
--- a/src/fstab-generator/fstab-generator.c
+++ b/src/fstab-generator/fstab-generator.c
@@ -44,6 +44,7 @@ static char *arg_root_fstype = NULL;
static char *arg_root_options = NULL;
static int arg_root_rw = -1;
+
static int mount_find_pri(struct mntent *me, int *ret) {
char *end, *pri;
unsigned long r;
@@ -173,7 +174,8 @@ static int add_mount(
_cleanup_free_ char
*name = NULL, *unit = NULL, *lnk = NULL,
- *automount_name = NULL, *automount_unit = NULL;
+ *automount_name = NULL, *automount_unit = NULL,
+ *filtered = NULL;
_cleanup_fclose_ FILE *f = NULL;
int r;
@@ -245,8 +247,12 @@ static int add_mount(
if (!isempty(fstype) && !streq(fstype, "auto"))
fprintf(f, "Type=%s\n", fstype);
- if (!isempty(opts) && !streq(opts, "defaults"))
- fprintf(f, "Options=%s\n", opts);
+ 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)) {
diff --git a/src/shared/dropin.c b/src/shared/dropin.c
new file mode 100644
index 0000000000..7774236f71
--- /dev/null
+++ b/src/shared/dropin.c
@@ -0,0 +1,98 @@
+/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
+
+/***
+ This file is part of systemd.
+
+ Copyright 2014 Zbigniew Jędrzejewski-Szmek
+
+ systemd is free software; you can redistribute it and/or modify it
+ under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+
+ systemd is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with systemd; If not, see <http://www.gnu.org/licenses/>.
+***/
+
+#include "dropin.h"
+#include "util.h"
+#include "mkdir.h"
+#include "fileio-label.h"
+
+int drop_in_file(const char *dir, const char *unit,
+ const char *name, char **_p, char **_q) {
+
+ _cleanup_free_ char *b = NULL;
+ char *p, *q;
+
+ assert(unit);
+ assert(name);
+ assert(_p);
+ assert(_q);
+
+ b = xescape(name, "/.");
+ if (!b)
+ return -ENOMEM;
+
+ if (!filename_is_safe(b))
+ return -EINVAL;
+
+ p = strjoin(dir, "/", unit, ".d", NULL);
+ if (!p)
+ return -ENOMEM;
+
+ q = strjoin(p, "/90-", b, ".conf", NULL);
+ if (!q) {
+ free(p);
+ return -ENOMEM;
+ }
+
+ *_p = p;
+ *_q = q;
+ return 0;
+}
+
+int write_drop_in(const char *dir, const char *unit,
+ const char *name, const char *data) {
+
+ _cleanup_free_ char *p = NULL, *q = NULL;
+ int r;
+
+ assert(dir);
+ assert(unit);
+ assert(name);
+ assert(data);
+
+ r = drop_in_file(dir, unit, name, &p, &q);
+ if (r < 0)
+ return r;
+
+ mkdir_p(p, 0755);
+ return write_string_file_atomic_label(q, data);
+}
+
+int write_drop_in_format(const char *dir, const char *unit,
+ const char *name, const char *format, ...) {
+ _cleanup_free_ char *p = NULL;
+ va_list ap;
+ int r;
+
+ assert(dir);
+ assert(unit);
+ assert(name);
+ assert(format);
+
+ va_start(ap, format);
+ r = vasprintf(&p, format, ap);
+ va_end(ap);
+
+ if (r < 0)
+ return -ENOMEM;
+
+ return write_drop_in(dir, unit, name, p);
+}
diff --git a/src/shared/dropin.h b/src/shared/dropin.h
new file mode 100644
index 0000000000..2958632963
--- /dev/null
+++ b/src/shared/dropin.h
@@ -0,0 +1,31 @@
+/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
+
+#pragma once
+
+/***
+ This file is part of systemd.
+
+ Copyright 2014 Zbigniew Jędrzejewski-Szmek
+
+ systemd is free software; you can redistribute it and/or modify it
+ under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+
+ systemd is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with systemd; If not, see <http://www.gnu.org/licenses/>.
+***/
+
+int drop_in_file(const char *dir, const char *unit,
+ const char *name, char **_p, char **_q);
+
+int write_drop_in(const char *dir, const char *unit,
+ const char *name, const char *data);
+
+int write_drop_in_format(const char *dir, const char *unit,
+ const char *name, const char *format, ...);
diff --git a/src/shared/generator.c b/src/shared/generator.c
index dcfddaa731..762033bbdf 100644
--- a/src/shared/generator.c
+++ b/src/shared/generator.c
@@ -28,6 +28,7 @@
#include "unit-name.h"
#include "generator.h"
#include "path-util.h"
+#include "dropin.h"
int generator_write_fsck_deps(
FILE *f,
@@ -86,3 +87,59 @@ int generator_write_fsck_deps(
return 0;
}
+
+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, *t = NULL;
+ char *prefix, *start, *timeout, *postfix;
+ usec_t u;
+ int r;
+ size_t len;
+
+ if ((start = mount_test_option(opts, "comment=systemd.device-timeout")))
+ timeout = start + 31;
+ else if ((start = mount_test_option(opts, "x-systemd.device-timeout")))
+ timeout = start + 25;
+ else {
+ *filtered = strdup(opts);
+ if (!*filtered)
+ return log_oom();
+
+ return 0;
+ }
+
+ len = strcspn(timeout, ",;" WHITESPACE);
+ t = strndup(timeout, len);
+ if (!t)
+ return -ENOMEM;
+
+ prefix = strndupa(opts, start - opts - (start != opts));
+ postfix = timeout + len + (timeout[len] != '\0');
+ *filtered = strjoin(prefix, *postfix ? postfix : NULL, NULL);
+ if (!*filtered)
+ return log_oom();
+
+ r = parse_sec(t, &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();
+
+ unit = unit_name_from_path(node, ".device");
+ if (!unit)
+ return -ENOMEM;
+
+ return write_drop_in_format(dir, unit, "device-timeout",
+ "[Unit]\nJobTimeoutSec=%u", u / USEC_PER_SEC);
+}
diff --git a/src/shared/generator.h b/src/shared/generator.h
index 0140aa943f..64bd28f596 100644
--- a/src/shared/generator.h
+++ b/src/shared/generator.h
@@ -24,3 +24,6 @@
#include <stdio.h>
int generator_write_fsck_deps(FILE *f, const char *dest, const char *what, const char *where, const char *type);
+
+int generator_write_timeouts(const char *dir, const char *what, const char *where,
+ const char *opts, char **filtered);
diff --git a/src/shared/path-lookup.h b/src/shared/path-lookup.h
index 847a52f20a..4c77bee393 100644
--- a/src/shared/path-lookup.h
+++ b/src/shared/path-lookup.h
@@ -21,6 +21,8 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
+#include "macro.h"
+
typedef struct LookupPaths {
char **unit_path;
#ifdef HAVE_SYSV_COMPAT