diff options
-rw-r--r-- | TODO | 2 | ||||
-rw-r--r-- | man/systemd.unit.xml | 21 | ||||
-rw-r--r-- | src/condition.c | 27 | ||||
-rw-r--r-- | src/condition.h | 6 | ||||
-rw-r--r-- | src/load-fragment.c | 28 | ||||
-rw-r--r-- | units/systemd-sysctl.service.in | 4 |
6 files changed, 62 insertions, 26 deletions
@@ -14,8 +14,6 @@ F15: * hook emergency.target into local-fs.target in some way as OnFailure with isolate -* introduce simple way to do mandatory conditions (make current conditions mandatory, and introduce =| as non-mandatory conditions) - * mount /dev/.run and /var/run as bind mounts * Make use of UnknownInterface, UnknownObject diff --git a/man/systemd.unit.xml b/man/systemd.unit.xml index fa8821afe5..54903fb52f 100644 --- a/man/systemd.unit.xml +++ b/man/systemd.unit.xml @@ -622,8 +622,8 @@ environment and optionally test whether it is a specific implementation. Takes either boolean - value to check if being executed in any - virtual environment or one of the + value to check if being executed in + any virtual environment or one of the <varname>qemu</varname>, <varname>kvm</varname>, <varname>vmware</varname>, @@ -642,9 +642,20 @@ will always fail, otherwise succeed. If multiple conditions are specified the unit will be executed if - at least one of them applies (i.e. a - logical OR is - applied).</para></listitem> + all of them apply (i.e. a logical AND + is applied). Condition checks can be + prefixed with a pipe symbol (|) in + which case a condition becomes a + triggering condition. If at least one + triggering condition is defined for a + unit then the unit will be executed if + at least one of the triggering + conditions apply and all of the + non-triggering conditions. If you + prefix an argument with the pipe + symbol and an exclamation mark the + pipe symbol must be passed first, the + exclamation second.</para></listitem> </varlistentry> </variablelist> diff --git a/src/condition.c b/src/condition.c index 630350ed36..1d6cf12ad4 100644 --- a/src/condition.c +++ b/src/condition.c @@ -27,11 +27,12 @@ #include "util.h" #include "condition.h" -Condition* condition_new(ConditionType type, const char *parameter, bool negate) { +Condition* condition_new(ConditionType type, const char *parameter, bool trigger, bool negate) { Condition *c; c = new0(Condition, 1); c->type = type; + c->trigger = trigger; c->negate = negate; if (parameter) @@ -153,17 +154,28 @@ bool condition_test(Condition *c) { bool condition_test_list(Condition *first) { Condition *c; + int triggered = -1; /* If the condition list is empty, then it is true */ if (!first) return true; - /* Otherwise, if any of the conditions apply we return true */ - LIST_FOREACH(conditions, c, first) - if (condition_test(c)) - return true; + /* Otherwise, if all of the non-trigger conditions apply and + * if any of the trigger conditions apply (unless there are + * none) we return true */ + LIST_FOREACH(conditions, c, first) { + bool b; + + b = condition_test(c); + + if (!c->trigger && !b) + return false; + + if (c->trigger && triggered <= 0) + triggered = b; + } - return false; + return triggered != 0; } void condition_dump(Condition *c, FILE *f, const char *prefix) { @@ -174,9 +186,10 @@ void condition_dump(Condition *c, FILE *f, const char *prefix) { prefix = ""; fprintf(f, - "%s%s: %s%s\n", + "%s%s: %s%s%s\n", prefix, condition_type_to_string(c->type), + c->trigger ? "|" : "", c->negate ? "!" : "", c->parameter); } diff --git a/src/condition.h b/src/condition.h index f4903d76d9..0ce713bc16 100644 --- a/src/condition.h +++ b/src/condition.h @@ -39,12 +39,14 @@ typedef enum ConditionType { typedef struct Condition { ConditionType type; char *parameter; - bool negate; + + bool trigger:1; + bool negate:1; LIST_FIELDS(struct Condition, conditions); } Condition; -Condition* condition_new(ConditionType type, const char *parameter, bool negate); +Condition* condition_new(ConditionType type, const char *parameter, bool trigger, bool negate); void condition_free(Condition *c); void condition_free_list(Condition *c); diff --git a/src/load-fragment.c b/src/load-fragment.c index bd7529ff95..334bc713be 100644 --- a/src/load-fragment.c +++ b/src/load-fragment.c @@ -1397,7 +1397,7 @@ static int config_parse_condition_path( void *userdata) { Unit *u = data; - bool negate; + bool trigger, negate; Condition *c; assert(filename); @@ -1405,6 +1405,9 @@ static int config_parse_condition_path( assert(rvalue); assert(data); + if ((trigger = rvalue[0] == '|')) + rvalue++; + if ((negate = rvalue[0] == '!')) rvalue++; @@ -1414,7 +1417,7 @@ static int config_parse_condition_path( } if (!(c = condition_new(streq(lvalue, "ConditionPathExists") ? CONDITION_PATH_EXISTS : CONDITION_DIRECTORY_NOT_EMPTY, - rvalue, negate))) + rvalue, trigger, negate))) return -ENOMEM; LIST_PREPEND(Condition, conditions, u->meta.conditions, c); @@ -1431,7 +1434,7 @@ static int config_parse_condition_kernel( void *userdata) { Unit *u = data; - bool negate; + bool trigger, negate; Condition *c; assert(filename); @@ -1439,10 +1442,13 @@ static int config_parse_condition_kernel( assert(rvalue); assert(data); + if ((trigger = rvalue[0] == '|')) + rvalue++; + if ((negate = rvalue[0] == '!')) rvalue++; - if (!(c = condition_new(CONDITION_KERNEL_COMMAND_LINE, rvalue, negate))) + if (!(c = condition_new(CONDITION_KERNEL_COMMAND_LINE, rvalue, trigger, negate))) return -ENOMEM; LIST_PREPEND(Condition, conditions, u->meta.conditions, c); @@ -1459,7 +1465,7 @@ static int config_parse_condition_virt( void *userdata) { Unit *u = data; - bool negate; + bool trigger, negate; Condition *c; assert(filename); @@ -1467,10 +1473,13 @@ static int config_parse_condition_virt( assert(rvalue); assert(data); + if ((trigger = rvalue[0] == '|')) + rvalue++; + if ((negate = rvalue[0] == '!')) rvalue++; - if (!(c = condition_new(CONDITION_VIRTUALIZATION, rvalue, negate))) + if (!(c = condition_new(CONDITION_VIRTUALIZATION, rvalue, trigger, negate))) return -ENOMEM; LIST_PREPEND(Condition, conditions, u->meta.conditions, c); @@ -1488,7 +1497,7 @@ static int config_parse_condition_null( Unit *u = data; Condition *c; - bool negate; + bool trigger, negate; int b; assert(filename); @@ -1496,6 +1505,9 @@ static int config_parse_condition_null( assert(rvalue); assert(data); + if ((trigger = rvalue[0] == '|')) + rvalue++; + if ((negate = rvalue[0] == '!')) rvalue++; @@ -1507,7 +1519,7 @@ static int config_parse_condition_null( if (!b) negate = !negate; - if (!(c = condition_new(CONDITION_NULL, NULL, negate))) + if (!(c = condition_new(CONDITION_NULL, NULL, trigger, negate))) return -ENOMEM; LIST_PREPEND(Condition, conditions, u->meta.conditions, c); diff --git a/units/systemd-sysctl.service.in b/units/systemd-sysctl.service.in index ada447885f..ea78230d7c 100644 --- a/units/systemd-sysctl.service.in +++ b/units/systemd-sysctl.service.in @@ -11,8 +11,8 @@ DefaultDependencies=no Conflicts=shutdown.target After=systemd-readahead-collect.service systemd-readahead-replay.service Before=sysinit.target shutdown.target -ConditionPathExists=/etc/sysctl.conf -ConditionDirectoryNotEmpty=/etc/sysctl.d +ConditionPathExists=|/etc/sysctl.conf +ConditionDirectoryNotEmpty=|/etc/sysctl.d [Service] Type=oneshot |