[systemd-commits] 13 commits - .gitignore Makefile.am TODO man/systemd.unit.xml src/core src/journal src/libsystemd-network src/network src/shared src/systemctl src/test src/udev
Lennart Poettering
lennart at kemper.freedesktop.org
Thu Nov 6 05:31:23 PST 2014
.gitignore | 2
Makefile.am | 34 -
TODO | 2
man/systemd.unit.xml | 51 ++
src/core/condition.c | 267 ---------------
src/core/condition.h | 26 -
src/core/dbus-unit.c | 25 +
src/core/job.c | 8
src/core/job.h | 1
src/core/load-fragment-gperf.gperf.m4 | 57 ++-
src/core/load-fragment.c | 131 +++----
src/core/unit.c | 100 +++++
src/core/unit.h | 3
src/journal/journald-audit.c | 4
src/libsystemd-network/network-internal.c | 8
src/libsystemd-network/network-internal.h | 2
src/network/networkd-netdev.h | 1
src/network/networkd.h | 2
src/shared/architecture.c | 8
src/shared/architecture.h | 10
src/shared/condition-util.c | 260 --------------
src/shared/condition-util.h | 81 ----
src/shared/condition.c | 529 ++++++++++++++++++++++++++++++
src/shared/condition.h | 96 +++++
src/shared/util.c | 14
src/systemctl/systemctl.c | 61 +++
src/test/test-architecture.c | 3
src/test/test-condition-util.c | 120 ------
src/test/test-condition.c | 194 +++++++++++
src/test/test-tables.c | 2
src/udev/net/link-config.h | 5
31 files changed, 1188 insertions(+), 919 deletions(-)
New commits:
commit 7fd682bbebabe140e0d07a468e8f87cde380b859
Author: Lennart Poettering <lennart at poettering.net>
Date: Thu Nov 6 14:31:04 2014 +0100
update TODO
diff --git a/TODO b/TODO
index 8339b93..9243b3d 100644
--- a/TODO
+++ b/TODO
@@ -85,8 +85,6 @@ Features:
* maybe add "systemctl edit" that copies unit files from /usr/lib/systemd/system to /etc/systemd/system and invokes vim on them
-* maybe introduce AssertXYZ= similar to ConditionXYZ= that causes a unit to fail (instead of skipping it) if some condition is not true...
-
* refcounting in sd-resolve is borked
* exponential backoff in timesyncd and resolved when we cannot reach a server
commit 134e56dcc53970a20a858283650bb92cd5da1d17
Author: Lennart Poettering <lennart at poettering.net>
Date: Thu Nov 6 14:19:05 2014 +0100
shared: rename condition-util.[ch] to condition.[ch]
Now that we only have one file with condition implementations around, we
can drop the -util suffix and simplify things a bit.
diff --git a/.gitignore b/.gitignore
index 6649d19..4c66564 100644
--- a/.gitignore
+++ b/.gitignore
@@ -157,7 +157,7 @@
/test-cgroup-util
/test-compress
/test-compress-benchmark
-/test-condition-util
+/test-condition
/test-conf-files
/test-copy
/test-coredump-vacuum
diff --git a/Makefile.am b/Makefile.am
index a10c306..461ffa9 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -861,8 +861,8 @@ libsystemd_shared_la_SOURCES = \
src/shared/audit.h \
src/shared/xml.c \
src/shared/xml.h \
- src/shared/condition-util.c \
- src/shared/condition-util.h \
+ src/shared/condition.c \
+ src/shared/condition.h \
src/shared/bus-label.c \
src/shared/bus-label.h \
src/shared/gpt.h \
@@ -1357,7 +1357,7 @@ tests += \
test-capability \
test-async \
test-ratelimit \
- test-condition-util \
+ test-condition \
test-uid-range \
test-bus-policy \
test-locale-util \
@@ -1517,10 +1517,10 @@ test_copy_SOURCES = \
test_copy_LDADD = \
libsystemd-shared.la
-test_condition_util_SOURCES = \
- src/test/test-condition-util.c
+test_condition_SOURCES = \
+ src/test/test-condition.c
-test_condition_util_LDADD = \
+test_condition_LDADD = \
libsystemd-shared.la \
libsystemd-internal.la \
libsystemd-capability.la \
diff --git a/src/core/unit.h b/src/core/unit.h
index b5a224b..8b24272 100644
--- a/src/core/unit.h
+++ b/src/core/unit.h
@@ -38,7 +38,7 @@ typedef struct UnitStatusMessageFormats UnitStatusMessageFormats;
#include "socket-util.h"
#include "execute.h"
#include "cgroup.h"
-#include "condition-util.h"
+#include "condition.h"
#include "install.h"
#include "unit-name.h"
#include "failure-action.h"
diff --git a/src/libsystemd-network/network-internal.c b/src/libsystemd-network/network-internal.c
index f3141f7..6f16050 100644
--- a/src/libsystemd-network/network-internal.c
+++ b/src/libsystemd-network/network-internal.c
@@ -32,7 +32,7 @@
#include "utf8.h"
#include "util.h"
#include "conf-parser.h"
-#include "condition-util.h"
+#include "condition.h"
#include "network-internal.h"
const char *net_get_name(struct udev_device *device) {
diff --git a/src/libsystemd-network/network-internal.h b/src/libsystemd-network/network-internal.h
index 49387d0..c64db2e 100644
--- a/src/libsystemd-network/network-internal.h
+++ b/src/libsystemd-network/network-internal.h
@@ -26,7 +26,7 @@
#include <stdbool.h>
#include "udev.h"
-#include "condition-util.h"
+#include "condition.h"
bool net_match_config(const struct ether_addr *match_mac,
const char *match_path,
diff --git a/src/network/networkd-netdev.h b/src/network/networkd-netdev.h
index e9a8a16..a6fad2d 100644
--- a/src/network/networkd-netdev.h
+++ b/src/network/networkd-netdev.h
@@ -25,7 +25,6 @@
#include "hashmap.h"
#include "list.h"
#include "set.h"
-#include "condition-util.h"
#include "in-addr-util.h"
typedef struct NetDevVTable NetDevVTable;
diff --git a/src/network/networkd.h b/src/network/networkd.h
index d4e79ab..19a661e 100644
--- a/src/network/networkd.h
+++ b/src/network/networkd.h
@@ -37,7 +37,7 @@
#include "hashmap.h"
#include "list.h"
#include "set.h"
-#include "condition-util.h"
+#include "condition.h"
#include "in-addr-util.h"
#define CACHE_INFO_INFINITY_LIFE_TIME 0xFFFFFFFFU
diff --git a/src/shared/condition-util.c b/src/shared/condition-util.c
deleted file mode 100644
index 5db20a7..0000000
--- a/src/shared/condition-util.c
+++ /dev/null
@@ -1,529 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- 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 <stdlib.h>
-#include <errno.h>
-#include <string.h>
-#include <unistd.h>
-#include <sys/statvfs.h>
-#include <fnmatch.h>
-
-#include "sd-id128.h"
-#include "util.h"
-#include "condition-util.h"
-#include "virt.h"
-#include "path-util.h"
-#include "fileio.h"
-#include "unit.h"
-#include "architecture.h"
-#include "virt.h"
-#include "smack-util.h"
-#include "apparmor-util.h"
-#include "ima-util.h"
-#include "selinux-util.h"
-#include "audit.h"
-
-Condition* condition_new(ConditionType type, const char *parameter, bool trigger, bool negate) {
- Condition *c;
- int r;
-
- assert(type >= 0);
- assert(type < _CONDITION_TYPE_MAX);
- assert(!parameter == (type == CONDITION_NULL));
-
- c = new0(Condition, 1);
- if (!c)
- return NULL;
-
- c->type = type;
- c->trigger = trigger;
- c->negate = negate;
-
- r = free_and_strdup(&c->parameter, parameter);
- if (r < 0) {
- free(c);
- return NULL;
- }
-
- return c;
-}
-
-void condition_free(Condition *c) {
- assert(c);
-
- free(c->parameter);
- free(c);
-}
-
-void condition_free_list(Condition *first) {
- Condition *c, *n;
-
- LIST_FOREACH_SAFE(conditions, c, n, first)
- condition_free(c);
-}
-
-static int condition_test_kernel_command_line(Condition *c) {
- _cleanup_free_ char *line = NULL;
- const char *p;
- bool equal;
- int r;
-
- assert(c);
- assert(c->parameter);
- assert(c->type == CONDITION_KERNEL_COMMAND_LINE);
-
- r = proc_cmdline(&line);
- if (r < 0)
- return r;
- if (r == 0)
- return false;
-
- equal = !!strchr(c->parameter, '=');
- p = line;
-
- for (;;) {
- _cleanup_free_ char *word = NULL;
- bool found;
-
- r = unquote_first_word(&p, &word);
- if (r < 0)
- return r;
- if (r == 0)
- break;
-
- if (equal)
- found = streq(word, c->parameter);
- else {
- const char *f;
-
- f = startswith(word, c->parameter);
- found = f && (*f == '=' || *f == 0);
- }
-
- if (found)
- return true;
- }
-
- return false;
-}
-
-static int condition_test_virtualization(Condition *c) {
- int b, v;
- const char *id;
-
- assert(c);
- assert(c->parameter);
- assert(c->type == CONDITION_VIRTUALIZATION);
-
- v = detect_virtualization(&id);
- if (v < 0)
- return v;
-
- /* First, compare with yes/no */
- b = parse_boolean(c->parameter);
-
- if (v > 0 && b > 0)
- return true;
-
- if (v == 0 && b == 0)
- return true;
-
- /* Then, compare categorization */
- if (v == VIRTUALIZATION_VM && streq(c->parameter, "vm"))
- return true;
-
- if (v == VIRTUALIZATION_CONTAINER && streq(c->parameter, "container"))
- return true;
-
- /* Finally compare id */
- return v > 0 && streq(c->parameter, id);
-}
-
-static int condition_test_architecture(Condition *c) {
- int a, b;
-
- assert(c);
- assert(c->parameter);
- assert(c->type == CONDITION_ARCHITECTURE);
-
- a = uname_architecture();
- if (a < 0)
- return a;
-
- if (streq(c->parameter, "native"))
- b = native_architecture();
- else
- b = architecture_from_string(c->parameter);
- if (b < 0)
- return b;
-
- return a == b;
-}
-
-static int condition_test_host(Condition *c) {
- _cleanup_free_ char *h = NULL;
- sd_id128_t x, y;
- int r;
-
- assert(c);
- assert(c->parameter);
- assert(c->type == CONDITION_HOST);
-
- if (sd_id128_from_string(c->parameter, &x) >= 0) {
-
- r = sd_id128_get_machine(&y);
- if (r < 0)
- return r;
-
- return sd_id128_equal(x, y);
- }
-
- h = gethostname_malloc();
- if (!h)
- return -ENOMEM;
-
- return fnmatch(c->parameter, h, FNM_CASEFOLD) == 0;
-}
-
-static int condition_test_ac_power(Condition *c) {
- int r;
-
- assert(c);
- assert(c->parameter);
- assert(c->type == CONDITION_AC_POWER);
-
- r = parse_boolean(c->parameter);
- if (r < 0)
- return r;
-
- return (on_ac_power() != 0) == !!r;
-}
-
-static int condition_test_security(Condition *c) {
- assert(c);
- assert(c->parameter);
- assert(c->type == CONDITION_SECURITY);
-
- if (streq(c->parameter, "selinux"))
- return mac_selinux_use();
- if (streq(c->parameter, "smack"))
- return mac_smack_use();
- if (streq(c->parameter, "apparmor"))
- return mac_apparmor_use();
- if (streq(c->parameter, "audit"))
- return use_audit();
- if (streq(c->parameter, "ima"))
- return use_ima();
-
- return false;
-}
-
-static int condition_test_capability(Condition *c) {
- _cleanup_fclose_ FILE *f = NULL;
- cap_value_t value;
- char line[LINE_MAX];
- unsigned long long capabilities = -1;
-
- assert(c);
- assert(c->parameter);
- assert(c->type == CONDITION_CAPABILITY);
-
- /* If it's an invalid capability, we don't have it */
-
- if (cap_from_name(c->parameter, &value) < 0)
- return -EINVAL;
-
- /* If it's a valid capability we default to assume
- * that we have it */
-
- f = fopen("/proc/self/status", "re");
- if (!f)
- return -errno;
-
- while (fgets(line, sizeof(line), f)) {
- truncate_nl(line);
-
- if (startswith(line, "CapBnd:")) {
- (void) sscanf(line+7, "%llx", &capabilities);
- break;
- }
- }
-
- return !!(capabilities & (1ULL << value));
-}
-
-static int condition_test_needs_update(Condition *c) {
- const char *p;
- struct stat usr, other;
-
- assert(c);
- assert(c->parameter);
- assert(c->type == CONDITION_NEEDS_UPDATE);
-
- /* If the file system is read-only we shouldn't suggest an update */
- if (path_is_read_only_fs(c->parameter) > 0)
- return false;
-
- /* Any other failure means we should allow the condition to be true,
- * so that we rather invoke too many update tools then too
- * few. */
-
- if (!path_is_absolute(c->parameter))
- return true;
-
- p = strappenda(c->parameter, "/.updated");
- if (lstat(p, &other) < 0)
- return true;
-
- if (lstat("/usr/", &usr) < 0)
- return true;
-
- return usr.st_mtim.tv_sec > other.st_mtim.tv_sec ||
- (usr.st_mtim.tv_sec == other.st_mtim.tv_sec && usr.st_mtim.tv_nsec > other.st_mtim.tv_nsec);
-}
-
-static int condition_test_first_boot(Condition *c) {
- int r;
-
- assert(c);
- assert(c->parameter);
- assert(c->type == CONDITION_FIRST_BOOT);
-
- r = parse_boolean(c->parameter);
- if (r < 0)
- return r;
-
- return (access("/run/systemd/first-boot", F_OK) >= 0) == !!r;
-}
-
-static int condition_test_path_exists(Condition *c) {
- assert(c);
- assert(c->parameter);
- assert(c->type == CONDITION_PATH_EXISTS);
-
- return access(c->parameter, F_OK) >= 0;
-}
-
-static int condition_test_path_exists_glob(Condition *c) {
- assert(c);
- assert(c->parameter);
- assert(c->type == CONDITION_PATH_EXISTS_GLOB);
-
- return glob_exists(c->parameter) > 0;
-}
-
-static int condition_test_path_is_directory(Condition *c) {
- assert(c);
- assert(c->parameter);
- assert(c->type == CONDITION_PATH_IS_DIRECTORY);
-
- return is_dir(c->parameter, true) > 0;
-}
-
-static int condition_test_path_is_symbolic_link(Condition *c) {
- assert(c);
- assert(c->parameter);
- assert(c->type == CONDITION_PATH_IS_SYMBOLIC_LINK);
-
- return is_symlink(c->parameter) > 0;
-}
-
-static int condition_test_path_is_mount_point(Condition *c) {
- assert(c);
- assert(c->parameter);
- assert(c->type == CONDITION_PATH_IS_MOUNT_POINT);
-
- return path_is_mount_point(c->parameter, true) > 0;
-}
-
-static int condition_test_path_is_read_write(Condition *c) {
- assert(c);
- assert(c->parameter);
- assert(c->type == CONDITION_PATH_IS_READ_WRITE);
-
- return path_is_read_only_fs(c->parameter) <= 0;
-}
-
-static int condition_test_directory_not_empty(Condition *c) {
- int r;
-
- assert(c);
- assert(c->parameter);
- assert(c->type == CONDITION_DIRECTORY_NOT_EMPTY);
-
- r = dir_is_empty(c->parameter);
- return r <= 0 && r != -ENOENT;
-}
-
-static int condition_test_file_not_empty(Condition *c) {
- struct stat st;
-
- assert(c);
- assert(c->parameter);
- assert(c->type == CONDITION_FILE_NOT_EMPTY);
-
- return (stat(c->parameter, &st) >= 0 &&
- S_ISREG(st.st_mode) &&
- st.st_size > 0);
-}
-
-static int condition_test_file_is_executable(Condition *c) {
- struct stat st;
-
- assert(c);
- assert(c->parameter);
- assert(c->type == CONDITION_FILE_IS_EXECUTABLE);
-
- return (stat(c->parameter, &st) >= 0 &&
- S_ISREG(st.st_mode) &&
- (st.st_mode & 0111));
-}
-
-static int condition_test_null(Condition *c) {
- assert(c);
- assert(c->type == CONDITION_NULL);
-
- /* Note that during parsing we already evaluate the string and
- * store it in c->negate */
- return true;
-}
-
-int condition_test(Condition *c) {
-
- static int (*const condition_tests[_CONDITION_TYPE_MAX])(Condition *c) = {
- [CONDITION_PATH_EXISTS] = condition_test_path_exists,
- [CONDITION_PATH_EXISTS_GLOB] = condition_test_path_exists_glob,
- [CONDITION_PATH_IS_DIRECTORY] = condition_test_path_is_directory,
- [CONDITION_PATH_IS_SYMBOLIC_LINK] = condition_test_path_is_symbolic_link,
- [CONDITION_PATH_IS_MOUNT_POINT] = condition_test_path_is_mount_point,
- [CONDITION_PATH_IS_READ_WRITE] = condition_test_path_is_read_write,
- [CONDITION_DIRECTORY_NOT_EMPTY] = condition_test_directory_not_empty,
- [CONDITION_FILE_NOT_EMPTY] = condition_test_file_not_empty,
- [CONDITION_FILE_IS_EXECUTABLE] = condition_test_file_is_executable,
- [CONDITION_KERNEL_COMMAND_LINE] = condition_test_kernel_command_line,
- [CONDITION_VIRTUALIZATION] = condition_test_virtualization,
- [CONDITION_SECURITY] = condition_test_security,
- [CONDITION_CAPABILITY] = condition_test_capability,
- [CONDITION_HOST] = condition_test_host,
- [CONDITION_AC_POWER] = condition_test_ac_power,
- [CONDITION_ARCHITECTURE] = condition_test_architecture,
- [CONDITION_NEEDS_UPDATE] = condition_test_needs_update,
- [CONDITION_FIRST_BOOT] = condition_test_first_boot,
- [CONDITION_NULL] = condition_test_null,
- };
-
- int r, b;
-
- assert(c);
- assert(c->type >= 0);
- assert(c->type < _CONDITION_TYPE_MAX);
-
- r = condition_tests[c->type](c);
- if (r < 0) {
- c->result = CONDITION_ERROR;
- return r;
- }
-
- b = (r > 0) == !c->negate;
- c->result = b ? CONDITION_SUCCEEDED : CONDITION_FAILED;
- return b;
-}
-
-void condition_dump(Condition *c, FILE *f, const char *prefix, const char *(*to_string)(ConditionType t)) {
- assert(c);
- assert(f);
-
- if (!prefix)
- prefix = "";
-
- fprintf(f,
- "%s\t%s: %s%s%s %s\n",
- prefix,
- to_string(c->type),
- c->trigger ? "|" : "",
- c->negate ? "!" : "",
- c->parameter,
- condition_result_to_string(c->result));
-}
-
-void condition_dump_list(Condition *first, FILE *f, const char *prefix, const char *(*to_string)(ConditionType t)) {
- Condition *c;
-
- LIST_FOREACH(conditions, c, first)
- condition_dump(c, f, prefix, to_string);
-}
-
-static const char* const condition_type_table[_CONDITION_TYPE_MAX] = {
- [CONDITION_ARCHITECTURE] = "ConditionArchitecture",
- [CONDITION_VIRTUALIZATION] = "ConditionVirtualization",
- [CONDITION_HOST] = "ConditionHost",
- [CONDITION_KERNEL_COMMAND_LINE] = "ConditionKernelCommandLine",
- [CONDITION_SECURITY] = "ConditionSecurity",
- [CONDITION_CAPABILITY] = "ConditionCapability",
- [CONDITION_AC_POWER] = "ConditionACPower",
- [CONDITION_NEEDS_UPDATE] = "ConditionNeedsUpdate",
- [CONDITION_FIRST_BOOT] = "ConditionFirstBoot",
- [CONDITION_PATH_EXISTS] = "ConditionPathExists",
- [CONDITION_PATH_EXISTS_GLOB] = "ConditionPathExistsGlob",
- [CONDITION_PATH_IS_DIRECTORY] = "ConditionPathIsDirectory",
- [CONDITION_PATH_IS_SYMBOLIC_LINK] = "ConditionPathIsSymbolicLink",
- [CONDITION_PATH_IS_MOUNT_POINT] = "ConditionPathIsMountPoint",
- [CONDITION_PATH_IS_READ_WRITE] = "ConditionPathIsReadWrite",
- [CONDITION_DIRECTORY_NOT_EMPTY] = "ConditionDirectoryNotEmpty",
- [CONDITION_FILE_NOT_EMPTY] = "ConditionFileNotEmpty",
- [CONDITION_FILE_IS_EXECUTABLE] = "ConditionFileIsExecutable",
- [CONDITION_NULL] = "ConditionNull"
-};
-
-DEFINE_STRING_TABLE_LOOKUP(condition_type, ConditionType);
-
-static const char* const assert_type_table[_CONDITION_TYPE_MAX] = {
- [CONDITION_ARCHITECTURE] = "AssertArchitecture",
- [CONDITION_VIRTUALIZATION] = "AssertVirtualization",
- [CONDITION_HOST] = "AssertHost",
- [CONDITION_KERNEL_COMMAND_LINE] = "AssertKernelCommandLine",
- [CONDITION_SECURITY] = "AssertSecurity",
- [CONDITION_CAPABILITY] = "AssertCapability",
- [CONDITION_AC_POWER] = "AssertACPower",
- [CONDITION_NEEDS_UPDATE] = "AssertNeedsUpdate",
- [CONDITION_FIRST_BOOT] = "AssertFirstBoot",
- [CONDITION_PATH_EXISTS] = "AssertPathExists",
- [CONDITION_PATH_EXISTS_GLOB] = "AssertPathExistsGlob",
- [CONDITION_PATH_IS_DIRECTORY] = "AssertPathIsDirectory",
- [CONDITION_PATH_IS_SYMBOLIC_LINK] = "AssertPathIsSymbolicLink",
- [CONDITION_PATH_IS_MOUNT_POINT] = "AssertPathIsMountPoint",
- [CONDITION_PATH_IS_READ_WRITE] = "AssertPathIsReadWrite",
- [CONDITION_DIRECTORY_NOT_EMPTY] = "AssertDirectoryNotEmpty",
- [CONDITION_FILE_NOT_EMPTY] = "AssertFileNotEmpty",
- [CONDITION_FILE_IS_EXECUTABLE] = "AssertFileIsExecutable",
- [CONDITION_NULL] = "AssertNull"
-};
-
-DEFINE_STRING_TABLE_LOOKUP(assert_type, ConditionType);
-
-static const char* const condition_result_table[_CONDITION_RESULT_MAX] = {
- [CONDITION_UNTESTED] = "untested",
- [CONDITION_SUCCEEDED] = "succeeded",
- [CONDITION_FAILED] = "failed",
- [CONDITION_ERROR] = "error",
-};
-
-DEFINE_STRING_TABLE_LOOKUP(condition_result, ConditionResult);
diff --git a/src/shared/condition-util.h b/src/shared/condition-util.h
deleted file mode 100644
index 28d1d94..0000000
--- a/src/shared/condition-util.h
+++ /dev/null
@@ -1,96 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-#pragma once
-
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- 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 <stdbool.h>
-#include <stdio.h>
-
-#include "list.h"
-#include "macro.h"
-
-typedef enum ConditionType {
- CONDITION_ARCHITECTURE,
- CONDITION_VIRTUALIZATION,
- CONDITION_HOST,
- CONDITION_KERNEL_COMMAND_LINE,
- CONDITION_SECURITY,
- CONDITION_CAPABILITY,
- CONDITION_AC_POWER,
-
- CONDITION_NEEDS_UPDATE,
- CONDITION_FIRST_BOOT,
-
- CONDITION_PATH_EXISTS,
- CONDITION_PATH_EXISTS_GLOB,
- CONDITION_PATH_IS_DIRECTORY,
- CONDITION_PATH_IS_SYMBOLIC_LINK,
- CONDITION_PATH_IS_MOUNT_POINT,
- CONDITION_PATH_IS_READ_WRITE,
- CONDITION_DIRECTORY_NOT_EMPTY,
- CONDITION_FILE_NOT_EMPTY,
- CONDITION_FILE_IS_EXECUTABLE,
-
- CONDITION_NULL,
-
- _CONDITION_TYPE_MAX,
- _CONDITION_TYPE_INVALID = -1
-} ConditionType;
-
-typedef enum ConditionResult {
- CONDITION_UNTESTED,
- CONDITION_SUCCEEDED,
- CONDITION_FAILED,
- CONDITION_ERROR,
- _CONDITION_RESULT_MAX,
- _CONDITION_RESULT_INVALID = -1
-} ConditionResult;
-
-typedef struct Condition {
- ConditionType type:8;
-
- bool trigger:1;
- bool negate:1;
-
- ConditionResult result:6;
-
- char *parameter;
-
- LIST_FIELDS(struct Condition, conditions);
-} Condition;
-
-Condition* condition_new(ConditionType type, const char *parameter, bool trigger, bool negate);
-void condition_free(Condition *c);
-void condition_free_list(Condition *c);
-
-int condition_test(Condition *c);
-
-void condition_dump(Condition *c, FILE *f, const char *prefix, const char *(*to_string)(ConditionType t));
-void condition_dump_list(Condition *c, FILE *f, const char *prefix, const char *(*to_string)(ConditionType t));
-
-const char* condition_type_to_string(ConditionType t) _const_;
-ConditionType condition_type_from_string(const char *s) _pure_;
-
-const char* assert_type_to_string(ConditionType t) _const_;
-ConditionType assert_type_from_string(const char *s) _pure_;
-
-const char* condition_result_to_string(ConditionResult r) _const_;
-ConditionResult condition_result_from_string(const char *s) _pure_;
diff --git a/src/shared/condition.c b/src/shared/condition.c
new file mode 100644
index 0000000..08bebee
--- /dev/null
+++ b/src/shared/condition.c
@@ -0,0 +1,529 @@
+/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
+
+/***
+ This file is part of systemd.
+
+ Copyright 2010 Lennart Poettering
+
+ 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 <stdlib.h>
+#include <errno.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/statvfs.h>
+#include <fnmatch.h>
+
+#include "sd-id128.h"
+#include "util.h"
+#include "virt.h"
+#include "path-util.h"
+#include "fileio.h"
+#include "unit.h"
+#include "architecture.h"
+#include "virt.h"
+#include "smack-util.h"
+#include "apparmor-util.h"
+#include "ima-util.h"
+#include "selinux-util.h"
+#include "audit.h"
+#include "condition.h"
+
+Condition* condition_new(ConditionType type, const char *parameter, bool trigger, bool negate) {
+ Condition *c;
+ int r;
+
+ assert(type >= 0);
+ assert(type < _CONDITION_TYPE_MAX);
+ assert(!parameter == (type == CONDITION_NULL));
+
+ c = new0(Condition, 1);
+ if (!c)
+ return NULL;
+
+ c->type = type;
+ c->trigger = trigger;
+ c->negate = negate;
+
+ r = free_and_strdup(&c->parameter, parameter);
+ if (r < 0) {
+ free(c);
+ return NULL;
+ }
+
+ return c;
+}
+
+void condition_free(Condition *c) {
+ assert(c);
+
+ free(c->parameter);
+ free(c);
+}
+
+void condition_free_list(Condition *first) {
+ Condition *c, *n;
+
+ LIST_FOREACH_SAFE(conditions, c, n, first)
+ condition_free(c);
+}
+
+static int condition_test_kernel_command_line(Condition *c) {
+ _cleanup_free_ char *line = NULL;
+ const char *p;
+ bool equal;
+ int r;
+
+ assert(c);
+ assert(c->parameter);
+ assert(c->type == CONDITION_KERNEL_COMMAND_LINE);
+
+ r = proc_cmdline(&line);
+ if (r < 0)
+ return r;
+ if (r == 0)
+ return false;
+
+ equal = !!strchr(c->parameter, '=');
+ p = line;
+
+ for (;;) {
+ _cleanup_free_ char *word = NULL;
+ bool found;
+
+ r = unquote_first_word(&p, &word);
+ if (r < 0)
+ return r;
+ if (r == 0)
+ break;
+
+ if (equal)
+ found = streq(word, c->parameter);
+ else {
+ const char *f;
+
+ f = startswith(word, c->parameter);
+ found = f && (*f == '=' || *f == 0);
+ }
+
+ if (found)
+ return true;
+ }
+
+ return false;
+}
+
+static int condition_test_virtualization(Condition *c) {
+ int b, v;
+ const char *id;
+
+ assert(c);
+ assert(c->parameter);
+ assert(c->type == CONDITION_VIRTUALIZATION);
+
+ v = detect_virtualization(&id);
+ if (v < 0)
+ return v;
+
+ /* First, compare with yes/no */
+ b = parse_boolean(c->parameter);
+
+ if (v > 0 && b > 0)
+ return true;
+
+ if (v == 0 && b == 0)
+ return true;
+
+ /* Then, compare categorization */
+ if (v == VIRTUALIZATION_VM && streq(c->parameter, "vm"))
+ return true;
+
+ if (v == VIRTUALIZATION_CONTAINER && streq(c->parameter, "container"))
+ return true;
+
+ /* Finally compare id */
+ return v > 0 && streq(c->parameter, id);
+}
+
+static int condition_test_architecture(Condition *c) {
+ int a, b;
+
+ assert(c);
+ assert(c->parameter);
+ assert(c->type == CONDITION_ARCHITECTURE);
+
+ a = uname_architecture();
+ if (a < 0)
+ return a;
+
+ if (streq(c->parameter, "native"))
+ b = native_architecture();
+ else
+ b = architecture_from_string(c->parameter);
+ if (b < 0)
+ return b;
+
+ return a == b;
+}
+
+static int condition_test_host(Condition *c) {
+ _cleanup_free_ char *h = NULL;
+ sd_id128_t x, y;
+ int r;
+
+ assert(c);
+ assert(c->parameter);
+ assert(c->type == CONDITION_HOST);
+
+ if (sd_id128_from_string(c->parameter, &x) >= 0) {
+
+ r = sd_id128_get_machine(&y);
+ if (r < 0)
+ return r;
+
+ return sd_id128_equal(x, y);
+ }
+
+ h = gethostname_malloc();
+ if (!h)
+ return -ENOMEM;
+
+ return fnmatch(c->parameter, h, FNM_CASEFOLD) == 0;
+}
+
+static int condition_test_ac_power(Condition *c) {
+ int r;
+
+ assert(c);
+ assert(c->parameter);
+ assert(c->type == CONDITION_AC_POWER);
+
+ r = parse_boolean(c->parameter);
+ if (r < 0)
+ return r;
+
+ return (on_ac_power() != 0) == !!r;
+}
+
+static int condition_test_security(Condition *c) {
+ assert(c);
+ assert(c->parameter);
+ assert(c->type == CONDITION_SECURITY);
+
+ if (streq(c->parameter, "selinux"))
+ return mac_selinux_use();
+ if (streq(c->parameter, "smack"))
+ return mac_smack_use();
+ if (streq(c->parameter, "apparmor"))
+ return mac_apparmor_use();
+ if (streq(c->parameter, "audit"))
+ return use_audit();
+ if (streq(c->parameter, "ima"))
+ return use_ima();
+
+ return false;
+}
+
+static int condition_test_capability(Condition *c) {
+ _cleanup_fclose_ FILE *f = NULL;
+ cap_value_t value;
+ char line[LINE_MAX];
+ unsigned long long capabilities = -1;
+
+ assert(c);
+ assert(c->parameter);
+ assert(c->type == CONDITION_CAPABILITY);
+
+ /* If it's an invalid capability, we don't have it */
+
+ if (cap_from_name(c->parameter, &value) < 0)
+ return -EINVAL;
+
+ /* If it's a valid capability we default to assume
+ * that we have it */
+
+ f = fopen("/proc/self/status", "re");
+ if (!f)
+ return -errno;
+
+ while (fgets(line, sizeof(line), f)) {
+ truncate_nl(line);
+
+ if (startswith(line, "CapBnd:")) {
+ (void) sscanf(line+7, "%llx", &capabilities);
+ break;
+ }
+ }
+
+ return !!(capabilities & (1ULL << value));
+}
+
+static int condition_test_needs_update(Condition *c) {
+ const char *p;
+ struct stat usr, other;
+
+ assert(c);
+ assert(c->parameter);
+ assert(c->type == CONDITION_NEEDS_UPDATE);
+
+ /* If the file system is read-only we shouldn't suggest an update */
+ if (path_is_read_only_fs(c->parameter) > 0)
+ return false;
+
+ /* Any other failure means we should allow the condition to be true,
+ * so that we rather invoke too many update tools then too
+ * few. */
+
+ if (!path_is_absolute(c->parameter))
+ return true;
+
+ p = strappenda(c->parameter, "/.updated");
+ if (lstat(p, &other) < 0)
+ return true;
+
+ if (lstat("/usr/", &usr) < 0)
+ return true;
+
+ return usr.st_mtim.tv_sec > other.st_mtim.tv_sec ||
+ (usr.st_mtim.tv_sec == other.st_mtim.tv_sec && usr.st_mtim.tv_nsec > other.st_mtim.tv_nsec);
+}
+
+static int condition_test_first_boot(Condition *c) {
+ int r;
+
+ assert(c);
+ assert(c->parameter);
+ assert(c->type == CONDITION_FIRST_BOOT);
+
+ r = parse_boolean(c->parameter);
+ if (r < 0)
+ return r;
+
+ return (access("/run/systemd/first-boot", F_OK) >= 0) == !!r;
+}
+
+static int condition_test_path_exists(Condition *c) {
+ assert(c);
+ assert(c->parameter);
+ assert(c->type == CONDITION_PATH_EXISTS);
+
+ return access(c->parameter, F_OK) >= 0;
+}
+
+static int condition_test_path_exists_glob(Condition *c) {
+ assert(c);
+ assert(c->parameter);
+ assert(c->type == CONDITION_PATH_EXISTS_GLOB);
+
+ return glob_exists(c->parameter) > 0;
+}
+
+static int condition_test_path_is_directory(Condition *c) {
+ assert(c);
+ assert(c->parameter);
+ assert(c->type == CONDITION_PATH_IS_DIRECTORY);
+
+ return is_dir(c->parameter, true) > 0;
+}
+
+static int condition_test_path_is_symbolic_link(Condition *c) {
+ assert(c);
+ assert(c->parameter);
+ assert(c->type == CONDITION_PATH_IS_SYMBOLIC_LINK);
+
+ return is_symlink(c->parameter) > 0;
+}
+
+static int condition_test_path_is_mount_point(Condition *c) {
+ assert(c);
+ assert(c->parameter);
+ assert(c->type == CONDITION_PATH_IS_MOUNT_POINT);
+
+ return path_is_mount_point(c->parameter, true) > 0;
+}
+
+static int condition_test_path_is_read_write(Condition *c) {
+ assert(c);
+ assert(c->parameter);
+ assert(c->type == CONDITION_PATH_IS_READ_WRITE);
+
+ return path_is_read_only_fs(c->parameter) <= 0;
+}
+
+static int condition_test_directory_not_empty(Condition *c) {
+ int r;
+
+ assert(c);
+ assert(c->parameter);
+ assert(c->type == CONDITION_DIRECTORY_NOT_EMPTY);
+
+ r = dir_is_empty(c->parameter);
+ return r <= 0 && r != -ENOENT;
+}
+
+static int condition_test_file_not_empty(Condition *c) {
+ struct stat st;
+
+ assert(c);
+ assert(c->parameter);
+ assert(c->type == CONDITION_FILE_NOT_EMPTY);
+
+ return (stat(c->parameter, &st) >= 0 &&
+ S_ISREG(st.st_mode) &&
+ st.st_size > 0);
+}
+
+static int condition_test_file_is_executable(Condition *c) {
+ struct stat st;
+
+ assert(c);
+ assert(c->parameter);
+ assert(c->type == CONDITION_FILE_IS_EXECUTABLE);
+
+ return (stat(c->parameter, &st) >= 0 &&
+ S_ISREG(st.st_mode) &&
+ (st.st_mode & 0111));
+}
+
+static int condition_test_null(Condition *c) {
+ assert(c);
+ assert(c->type == CONDITION_NULL);
+
+ /* Note that during parsing we already evaluate the string and
+ * store it in c->negate */
+ return true;
+}
+
+int condition_test(Condition *c) {
+
+ static int (*const condition_tests[_CONDITION_TYPE_MAX])(Condition *c) = {
+ [CONDITION_PATH_EXISTS] = condition_test_path_exists,
+ [CONDITION_PATH_EXISTS_GLOB] = condition_test_path_exists_glob,
+ [CONDITION_PATH_IS_DIRECTORY] = condition_test_path_is_directory,
+ [CONDITION_PATH_IS_SYMBOLIC_LINK] = condition_test_path_is_symbolic_link,
+ [CONDITION_PATH_IS_MOUNT_POINT] = condition_test_path_is_mount_point,
+ [CONDITION_PATH_IS_READ_WRITE] = condition_test_path_is_read_write,
+ [CONDITION_DIRECTORY_NOT_EMPTY] = condition_test_directory_not_empty,
+ [CONDITION_FILE_NOT_EMPTY] = condition_test_file_not_empty,
+ [CONDITION_FILE_IS_EXECUTABLE] = condition_test_file_is_executable,
+ [CONDITION_KERNEL_COMMAND_LINE] = condition_test_kernel_command_line,
+ [CONDITION_VIRTUALIZATION] = condition_test_virtualization,
+ [CONDITION_SECURITY] = condition_test_security,
+ [CONDITION_CAPABILITY] = condition_test_capability,
+ [CONDITION_HOST] = condition_test_host,
+ [CONDITION_AC_POWER] = condition_test_ac_power,
+ [CONDITION_ARCHITECTURE] = condition_test_architecture,
+ [CONDITION_NEEDS_UPDATE] = condition_test_needs_update,
+ [CONDITION_FIRST_BOOT] = condition_test_first_boot,
+ [CONDITION_NULL] = condition_test_null,
+ };
+
+ int r, b;
+
+ assert(c);
+ assert(c->type >= 0);
+ assert(c->type < _CONDITION_TYPE_MAX);
+
+ r = condition_tests[c->type](c);
+ if (r < 0) {
+ c->result = CONDITION_ERROR;
+ return r;
+ }
+
+ b = (r > 0) == !c->negate;
+ c->result = b ? CONDITION_SUCCEEDED : CONDITION_FAILED;
+ return b;
+}
+
+void condition_dump(Condition *c, FILE *f, const char *prefix, const char *(*to_string)(ConditionType t)) {
+ assert(c);
+ assert(f);
+
+ if (!prefix)
+ prefix = "";
+
+ fprintf(f,
+ "%s\t%s: %s%s%s %s\n",
+ prefix,
+ to_string(c->type),
+ c->trigger ? "|" : "",
+ c->negate ? "!" : "",
+ c->parameter,
+ condition_result_to_string(c->result));
+}
+
+void condition_dump_list(Condition *first, FILE *f, const char *prefix, const char *(*to_string)(ConditionType t)) {
+ Condition *c;
+
+ LIST_FOREACH(conditions, c, first)
+ condition_dump(c, f, prefix, to_string);
+}
+
+static const char* const condition_type_table[_CONDITION_TYPE_MAX] = {
+ [CONDITION_ARCHITECTURE] = "ConditionArchitecture",
+ [CONDITION_VIRTUALIZATION] = "ConditionVirtualization",
+ [CONDITION_HOST] = "ConditionHost",
+ [CONDITION_KERNEL_COMMAND_LINE] = "ConditionKernelCommandLine",
+ [CONDITION_SECURITY] = "ConditionSecurity",
+ [CONDITION_CAPABILITY] = "ConditionCapability",
+ [CONDITION_AC_POWER] = "ConditionACPower",
+ [CONDITION_NEEDS_UPDATE] = "ConditionNeedsUpdate",
+ [CONDITION_FIRST_BOOT] = "ConditionFirstBoot",
+ [CONDITION_PATH_EXISTS] = "ConditionPathExists",
+ [CONDITION_PATH_EXISTS_GLOB] = "ConditionPathExistsGlob",
+ [CONDITION_PATH_IS_DIRECTORY] = "ConditionPathIsDirectory",
+ [CONDITION_PATH_IS_SYMBOLIC_LINK] = "ConditionPathIsSymbolicLink",
+ [CONDITION_PATH_IS_MOUNT_POINT] = "ConditionPathIsMountPoint",
+ [CONDITION_PATH_IS_READ_WRITE] = "ConditionPathIsReadWrite",
+ [CONDITION_DIRECTORY_NOT_EMPTY] = "ConditionDirectoryNotEmpty",
+ [CONDITION_FILE_NOT_EMPTY] = "ConditionFileNotEmpty",
+ [CONDITION_FILE_IS_EXECUTABLE] = "ConditionFileIsExecutable",
+ [CONDITION_NULL] = "ConditionNull"
+};
+
+DEFINE_STRING_TABLE_LOOKUP(condition_type, ConditionType);
+
+static const char* const assert_type_table[_CONDITION_TYPE_MAX] = {
+ [CONDITION_ARCHITECTURE] = "AssertArchitecture",
+ [CONDITION_VIRTUALIZATION] = "AssertVirtualization",
+ [CONDITION_HOST] = "AssertHost",
+ [CONDITION_KERNEL_COMMAND_LINE] = "AssertKernelCommandLine",
+ [CONDITION_SECURITY] = "AssertSecurity",
+ [CONDITION_CAPABILITY] = "AssertCapability",
+ [CONDITION_AC_POWER] = "AssertACPower",
+ [CONDITION_NEEDS_UPDATE] = "AssertNeedsUpdate",
+ [CONDITION_FIRST_BOOT] = "AssertFirstBoot",
+ [CONDITION_PATH_EXISTS] = "AssertPathExists",
+ [CONDITION_PATH_EXISTS_GLOB] = "AssertPathExistsGlob",
+ [CONDITION_PATH_IS_DIRECTORY] = "AssertPathIsDirectory",
+ [CONDITION_PATH_IS_SYMBOLIC_LINK] = "AssertPathIsSymbolicLink",
+ [CONDITION_PATH_IS_MOUNT_POINT] = "AssertPathIsMountPoint",
+ [CONDITION_PATH_IS_READ_WRITE] = "AssertPathIsReadWrite",
+ [CONDITION_DIRECTORY_NOT_EMPTY] = "AssertDirectoryNotEmpty",
+ [CONDITION_FILE_NOT_EMPTY] = "AssertFileNotEmpty",
+ [CONDITION_FILE_IS_EXECUTABLE] = "AssertFileIsExecutable",
+ [CONDITION_NULL] = "AssertNull"
+};
+
+DEFINE_STRING_TABLE_LOOKUP(assert_type, ConditionType);
+
+static const char* const condition_result_table[_CONDITION_RESULT_MAX] = {
+ [CONDITION_UNTESTED] = "untested",
+ [CONDITION_SUCCEEDED] = "succeeded",
+ [CONDITION_FAILED] = "failed",
+ [CONDITION_ERROR] = "error",
+};
+
+DEFINE_STRING_TABLE_LOOKUP(condition_result, ConditionResult);
diff --git a/src/shared/condition.h b/src/shared/condition.h
new file mode 100644
index 0000000..28d1d94
--- /dev/null
+++ b/src/shared/condition.h
@@ -0,0 +1,96 @@
+/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
+
+#pragma once
+
+/***
+ This file is part of systemd.
+
+ Copyright 2010 Lennart Poettering
+
+ 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 <stdbool.h>
+#include <stdio.h>
+
+#include "list.h"
+#include "macro.h"
+
+typedef enum ConditionType {
+ CONDITION_ARCHITECTURE,
+ CONDITION_VIRTUALIZATION,
+ CONDITION_HOST,
+ CONDITION_KERNEL_COMMAND_LINE,
+ CONDITION_SECURITY,
+ CONDITION_CAPABILITY,
+ CONDITION_AC_POWER,
+
+ CONDITION_NEEDS_UPDATE,
+ CONDITION_FIRST_BOOT,
+
+ CONDITION_PATH_EXISTS,
+ CONDITION_PATH_EXISTS_GLOB,
+ CONDITION_PATH_IS_DIRECTORY,
+ CONDITION_PATH_IS_SYMBOLIC_LINK,
+ CONDITION_PATH_IS_MOUNT_POINT,
+ CONDITION_PATH_IS_READ_WRITE,
+ CONDITION_DIRECTORY_NOT_EMPTY,
+ CONDITION_FILE_NOT_EMPTY,
+ CONDITION_FILE_IS_EXECUTABLE,
+
+ CONDITION_NULL,
+
+ _CONDITION_TYPE_MAX,
+ _CONDITION_TYPE_INVALID = -1
+} ConditionType;
+
+typedef enum ConditionResult {
+ CONDITION_UNTESTED,
+ CONDITION_SUCCEEDED,
+ CONDITION_FAILED,
+ CONDITION_ERROR,
+ _CONDITION_RESULT_MAX,
+ _CONDITION_RESULT_INVALID = -1
+} ConditionResult;
+
+typedef struct Condition {
+ ConditionType type:8;
+
+ bool trigger:1;
+ bool negate:1;
+
+ ConditionResult result:6;
+
+ char *parameter;
+
+ LIST_FIELDS(struct Condition, conditions);
+} Condition;
+
+Condition* condition_new(ConditionType type, const char *parameter, bool trigger, bool negate);
+void condition_free(Condition *c);
+void condition_free_list(Condition *c);
+
+int condition_test(Condition *c);
+
+void condition_dump(Condition *c, FILE *f, const char *prefix, const char *(*to_string)(ConditionType t));
+void condition_dump_list(Condition *c, FILE *f, const char *prefix, const char *(*to_string)(ConditionType t));
+
+const char* condition_type_to_string(ConditionType t) _const_;
+ConditionType condition_type_from_string(const char *s) _pure_;
+
+const char* assert_type_to_string(ConditionType t) _const_;
+ConditionType assert_type_from_string(const char *s) _pure_;
+
+const char* condition_result_to_string(ConditionResult r) _const_;
+ConditionResult condition_result_from_string(const char *s) _pure_;
diff --git a/src/test/test-condition-util.c b/src/test/test-condition-util.c
deleted file mode 100644
index b69e62b..0000000
--- a/src/test/test-condition-util.c
+++ /dev/null
@@ -1,194 +0,0 @@
-/***
- This file is part of systemd
-
- Copyright 2014 Ronny Chevalier
-
- 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 "condition-util.h"
-#include "macro.h"
-#include "util.h"
-#include "log.h"
-#include "architecture.h"
-#include "sd-id128.h"
-
-static void test_condition_test_path_exists(void) {
- Condition *condition;
-
- condition = condition_new(CONDITION_PATH_EXISTS, "/bin/sh", false, false);
- assert_se(condition_test(condition));
- condition_free(condition);
-
- condition = condition_new(CONDITION_PATH_EXISTS, "/bin/s?", false, false);
- assert_se(!condition_test(condition));
- condition_free(condition);
-
- condition = condition_new(CONDITION_PATH_EXISTS_GLOB, "/bin/s?", false, false);
- assert_se(condition_test(condition));
- condition_free(condition);
-
- condition = condition_new(CONDITION_PATH_EXISTS_GLOB, "/bin/s?", false, true);
- assert_se(!condition_test(condition));
- condition_free(condition);
-
- condition = condition_new(CONDITION_PATH_EXISTS, "/thiscertainlywontexist", false, false);
- assert_se(!condition_test(condition));
- condition_free(condition);
-
- condition = condition_new(CONDITION_PATH_EXISTS, "/thiscertainlywontexist", false, true);
- assert_se(condition_test(condition));
- condition_free(condition);
-
- condition = condition_new(CONDITION_PATH_IS_DIRECTORY, "/bin", false, false);
- assert_se(condition_test(condition));
- condition_free(condition);
-
- condition = condition_new(CONDITION_DIRECTORY_NOT_EMPTY, "/bin", false, false);
- assert_se(condition_test(condition));
- condition_free(condition);
-
- condition = condition_new(CONDITION_FILE_NOT_EMPTY, "/bin/sh", false, false);
- assert_se(condition_test(condition));
- condition_free(condition);
-
- condition = condition_new(CONDITION_FILE_IS_EXECUTABLE, "/bin/sh", false, false);
- assert_se(condition_test(condition));
- condition_free(condition);
-
- condition = condition_new(CONDITION_FILE_IS_EXECUTABLE, "/etc/passwd", false, false);
- assert_se(!condition_test(condition));
- condition_free(condition);
-
- condition = condition_new(CONDITION_PATH_IS_MOUNT_POINT, "/proc", false, false);
- assert_se(condition_test(condition));
- condition_free(condition);
-
- condition = condition_new(CONDITION_PATH_IS_MOUNT_POINT, "/", false, false);
- assert_se(condition_test(condition));
- condition_free(condition);
-
- condition = condition_new(CONDITION_PATH_IS_MOUNT_POINT, "/bin", false, false);
- assert_se(!condition_test(condition));
- condition_free(condition);
-}
-
-static void test_condition_test_ac_power(void) {
- Condition *condition;
-
- condition = condition_new(CONDITION_AC_POWER, "true", false, false);
- assert_se(condition_test(condition) == on_ac_power());
- condition_free(condition);
-
- condition = condition_new(CONDITION_AC_POWER, "false", false, false);
- assert_se(condition_test(condition) != on_ac_power());
- condition_free(condition);
-
- condition = condition_new(CONDITION_AC_POWER, "false", false, true);
- assert_se(condition_test(condition) == on_ac_power());
- condition_free(condition);
-}
-
-static void test_condition_test_host(void) {
- Condition *condition;
- sd_id128_t id;
- int r;
- char sid[SD_ID128_STRING_MAX];
- _cleanup_free_ char *hostname = NULL;
-
- r = sd_id128_get_machine(&id);
- assert_se(r >= 0);
- assert_se(sd_id128_to_string(id, sid));
-
- condition = condition_new(CONDITION_HOST, sid, false, false);
- assert_se(condition_test(condition));
- condition_free(condition);
-
- condition = condition_new(CONDITION_HOST, "garbage value jjjjjjjjjjjjjj", false, false);
- assert_se(!condition_test(condition));
- condition_free(condition);
-
- condition = condition_new(CONDITION_HOST, sid, false, true);
- assert_se(!condition_test(condition));
- condition_free(condition);
-
- hostname = gethostname_malloc();
- assert_se(hostname);
-
- condition = condition_new(CONDITION_HOST, hostname, false, false);
- assert_se(condition_test(condition));
- condition_free(condition);
-}
-
-static void test_condition_test_architecture(void) {
- Condition *condition;
- const char *sa;
- int a;
-
- a = uname_architecture();
- assert_se(a >= 0);
-
- sa = architecture_to_string(a);
- assert_se(sa);
-
- condition = condition_new(CONDITION_ARCHITECTURE, sa, false, false);
- assert_se(condition_test(condition));
- condition_free(condition);
-
- condition = condition_new(CONDITION_ARCHITECTURE, "garbage value", false, false);
- assert_se(condition_test(condition) < 0);
- condition_free(condition);
-
- condition = condition_new(CONDITION_ARCHITECTURE, sa, false, true);
- assert_se(!condition_test(condition));
- condition_free(condition);
-}
-
-static void test_condition_test_kernel_command_line(void) {
- Condition *condition;
-
- condition = condition_new(CONDITION_KERNEL_COMMAND_LINE, "thisreallyshouldntbeonthekernelcommandline", false, false);
- assert_se(!condition_test(condition));
- condition_free(condition);
-
- condition = condition_new(CONDITION_KERNEL_COMMAND_LINE, "andthis=neither", false, false);
- assert_se(!condition_test(condition));
- condition_free(condition);
-}
-
-static void test_condition_test_null(void) {
- Condition *condition;
-
- condition = condition_new(CONDITION_NULL, NULL, false, false);
- assert_se(condition_test(condition));
- condition_free(condition);
-
- condition = condition_new(CONDITION_NULL, NULL, false, true);
- assert_se(!condition_test(condition));
- condition_free(condition);
-}
-
-int main(int argc, char *argv[]) {
- log_parse_environment();
- log_open();
-
- test_condition_test_path_exists();
- test_condition_test_ac_power();
- test_condition_test_host();
- test_condition_test_architecture();
- test_condition_test_kernel_command_line();
- test_condition_test_null();
-
- return 0;
-}
diff --git a/src/test/test-condition.c b/src/test/test-condition.c
new file mode 100644
index 0000000..349c647
--- /dev/null
+++ b/src/test/test-condition.c
@@ -0,0 +1,194 @@
+/***
+ This file is part of systemd
+
+ Copyright 2014 Ronny Chevalier
+
+ 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 "condition.h"
+#include "macro.h"
+#include "util.h"
+#include "log.h"
+#include "architecture.h"
+#include "sd-id128.h"
+
+static void test_condition_test_path_exists(void) {
+ Condition *condition;
+
+ condition = condition_new(CONDITION_PATH_EXISTS, "/bin/sh", false, false);
+ assert_se(condition_test(condition));
+ condition_free(condition);
+
+ condition = condition_new(CONDITION_PATH_EXISTS, "/bin/s?", false, false);
+ assert_se(!condition_test(condition));
+ condition_free(condition);
+
+ condition = condition_new(CONDITION_PATH_EXISTS_GLOB, "/bin/s?", false, false);
+ assert_se(condition_test(condition));
+ condition_free(condition);
+
+ condition = condition_new(CONDITION_PATH_EXISTS_GLOB, "/bin/s?", false, true);
+ assert_se(!condition_test(condition));
+ condition_free(condition);
+
+ condition = condition_new(CONDITION_PATH_EXISTS, "/thiscertainlywontexist", false, false);
+ assert_se(!condition_test(condition));
+ condition_free(condition);
+
+ condition = condition_new(CONDITION_PATH_EXISTS, "/thiscertainlywontexist", false, true);
+ assert_se(condition_test(condition));
+ condition_free(condition);
+
+ condition = condition_new(CONDITION_PATH_IS_DIRECTORY, "/bin", false, false);
+ assert_se(condition_test(condition));
+ condition_free(condition);
+
+ condition = condition_new(CONDITION_DIRECTORY_NOT_EMPTY, "/bin", false, false);
+ assert_se(condition_test(condition));
+ condition_free(condition);
+
+ condition = condition_new(CONDITION_FILE_NOT_EMPTY, "/bin/sh", false, false);
+ assert_se(condition_test(condition));
+ condition_free(condition);
+
+ condition = condition_new(CONDITION_FILE_IS_EXECUTABLE, "/bin/sh", false, false);
+ assert_se(condition_test(condition));
+ condition_free(condition);
+
+ condition = condition_new(CONDITION_FILE_IS_EXECUTABLE, "/etc/passwd", false, false);
+ assert_se(!condition_test(condition));
+ condition_free(condition);
+
+ condition = condition_new(CONDITION_PATH_IS_MOUNT_POINT, "/proc", false, false);
+ assert_se(condition_test(condition));
+ condition_free(condition);
+
+ condition = condition_new(CONDITION_PATH_IS_MOUNT_POINT, "/", false, false);
+ assert_se(condition_test(condition));
+ condition_free(condition);
+
+ condition = condition_new(CONDITION_PATH_IS_MOUNT_POINT, "/bin", false, false);
+ assert_se(!condition_test(condition));
+ condition_free(condition);
+}
+
+static void test_condition_test_ac_power(void) {
+ Condition *condition;
+
+ condition = condition_new(CONDITION_AC_POWER, "true", false, false);
+ assert_se(condition_test(condition) == on_ac_power());
+ condition_free(condition);
+
+ condition = condition_new(CONDITION_AC_POWER, "false", false, false);
+ assert_se(condition_test(condition) != on_ac_power());
+ condition_free(condition);
+
+ condition = condition_new(CONDITION_AC_POWER, "false", false, true);
+ assert_se(condition_test(condition) == on_ac_power());
+ condition_free(condition);
+}
+
+static void test_condition_test_host(void) {
+ Condition *condition;
+ sd_id128_t id;
+ int r;
+ char sid[SD_ID128_STRING_MAX];
+ _cleanup_free_ char *hostname = NULL;
+
+ r = sd_id128_get_machine(&id);
+ assert_se(r >= 0);
+ assert_se(sd_id128_to_string(id, sid));
+
+ condition = condition_new(CONDITION_HOST, sid, false, false);
+ assert_se(condition_test(condition));
+ condition_free(condition);
+
+ condition = condition_new(CONDITION_HOST, "garbage value jjjjjjjjjjjjjj", false, false);
+ assert_se(!condition_test(condition));
+ condition_free(condition);
+
+ condition = condition_new(CONDITION_HOST, sid, false, true);
+ assert_se(!condition_test(condition));
+ condition_free(condition);
+
+ hostname = gethostname_malloc();
+ assert_se(hostname);
+
+ condition = condition_new(CONDITION_HOST, hostname, false, false);
+ assert_se(condition_test(condition));
+ condition_free(condition);
+}
+
+static void test_condition_test_architecture(void) {
+ Condition *condition;
+ const char *sa;
+ int a;
+
+ a = uname_architecture();
+ assert_se(a >= 0);
+
+ sa = architecture_to_string(a);
+ assert_se(sa);
+
+ condition = condition_new(CONDITION_ARCHITECTURE, sa, false, false);
+ assert_se(condition_test(condition));
+ condition_free(condition);
+
+ condition = condition_new(CONDITION_ARCHITECTURE, "garbage value", false, false);
+ assert_se(condition_test(condition) < 0);
+ condition_free(condition);
+
+ condition = condition_new(CONDITION_ARCHITECTURE, sa, false, true);
+ assert_se(!condition_test(condition));
+ condition_free(condition);
+}
+
+static void test_condition_test_kernel_command_line(void) {
+ Condition *condition;
+
+ condition = condition_new(CONDITION_KERNEL_COMMAND_LINE, "thisreallyshouldntbeonthekernelcommandline", false, false);
+ assert_se(!condition_test(condition));
+ condition_free(condition);
+
+ condition = condition_new(CONDITION_KERNEL_COMMAND_LINE, "andthis=neither", false, false);
+ assert_se(!condition_test(condition));
+ condition_free(condition);
+}
+
+static void test_condition_test_null(void) {
+ Condition *condition;
+
+ condition = condition_new(CONDITION_NULL, NULL, false, false);
+ assert_se(condition_test(condition));
+ condition_free(condition);
+
+ condition = condition_new(CONDITION_NULL, NULL, false, true);
+ assert_se(!condition_test(condition));
+ condition_free(condition);
+}
+
+int main(int argc, char *argv[]) {
+ log_parse_environment();
+ log_open();
+
+ test_condition_test_path_exists();
+ test_condition_test_ac_power();
+ test_condition_test_host();
+ test_condition_test_architecture();
+ test_condition_test_kernel_command_line();
+ test_condition_test_null();
+
+ return 0;
+}
diff --git a/src/test/test-tables.c b/src/test/test-tables.c
index d0a621c..97d5609 100644
--- a/src/test/test-tables.c
+++ b/src/test/test-tables.c
@@ -20,7 +20,7 @@
#include "automount.h"
#include "cgroup.h"
#include "compress.h"
-#include "condition-util.h"
+#include "condition.h"
#include "device.h"
#include "execute.h"
#include "exit-status.h"
diff --git a/src/udev/net/link-config.h b/src/udev/net/link-config.h
index 5f3d4ad..844ea98 100644
--- a/src/udev/net/link-config.h
+++ b/src/udev/net/link-config.h
@@ -22,11 +22,10 @@
#pragma once
#include "ethtool-util.h"
-
-#include "condition-util.h"
-#include "libudev.h"
+#include "condition.h"
#include "util.h"
#include "list.h"
+#include "libudev.h"
typedef struct link_config_ctx link_config_ctx;
typedef struct link_config link_config;
commit 493657337ad8569e0998a3afa7d6fb357757364a
Author: Lennart Poettering <lennart at poettering.net>
Date: Thu Nov 6 14:09:51 2014 +0100
core: get rid of condition.c and move the remaining call into util.c
That way only one file with condition code remaining, in src/shared/,
rather than src/core/.
Next step: dropping the "-util" suffix from condition-util.[ch].
diff --git a/Makefile.am b/Makefile.am
index c5667c3..a10c306 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -1132,8 +1132,6 @@ libsystemd_core_la_SOURCES = \
src/core/mount-setup.h \
src/core/loopback-setup.h \
src/core/loopback-setup.c \
- src/core/condition.c \
- src/core/condition.h \
src/core/namespace.c \
src/core/namespace.h \
src/core/build.h \
diff --git a/src/core/condition.c b/src/core/condition.c
deleted file mode 100644
index c20c0f0..0000000
--- a/src/core/condition.c
+++ /dev/null
@@ -1,67 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- 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 "condition.h"
-#include "unit.h"
-
-bool condition_test_list(const char *unit, Condition *first, const char *(*to_string)(ConditionType t)) {
- Condition *c;
- int triggered = -1;
-
- /* If the condition list is empty, then it is true */
- if (!first)
- 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) {
- int r;
-
- r = condition_test(c);
- if (r < 0)
- log_warning_unit(unit,
- "Couldn't determine result for %s=%s%s%s for %s, assuming failed: %s",
- to_string(c->type),
- c->trigger ? "|" : "",
- c->negate ? "!" : "",
- c->parameter,
- unit,
- strerror(-r));
- else
- log_debug_unit(unit,
- "%s=%s%s%s %s for %s.",
- to_string(c->type),
- c->trigger ? "|" : "",
- c->negate ? "!" : "",
- c->parameter,
- condition_result_to_string(c->result),
- unit);
-
- if (!c->trigger && r <= 0)
- return false;
-
- if (c->trigger && triggered <= 0)
- triggered = r > 0;
- }
-
- return triggered != 0;
-}
diff --git a/src/core/condition.h b/src/core/condition.h
deleted file mode 100644
index a6a31ed..0000000
--- a/src/core/condition.h
+++ /dev/null
@@ -1,26 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-#pragma once
-
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- 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 "condition-util.h"
-
-bool condition_test_list(const char *unit, Condition *c, const char *(*to_string)(ConditionType t));
diff --git a/src/core/unit.c b/src/core/unit.c
index 66f53dd..948f8e2 100644
--- a/src/core/unit.c
+++ b/src/core/unit.c
@@ -1245,11 +1245,58 @@ fail:
return r;
}
+static bool unit_condition_test_list(Unit *u, Condition *first, const char *(*to_string)(ConditionType t)) {
+ Condition *c;
+ int triggered = -1;
+
+ assert(u);
+ assert(to_string);
+
+ /* If the condition list is empty, then it is true */
+ if (!first)
+ 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) {
+ int r;
+
+ r = condition_test(c);
+ if (r < 0)
+ log_warning_unit(u->id,
+ "Couldn't determine result for %s=%s%s%s for %s, assuming failed: %s",
+ to_string(c->type),
+ c->trigger ? "|" : "",
+ c->negate ? "!" : "",
+ c->parameter,
+ u->id,
+ strerror(-r));
+ else
+ log_debug_unit(u->id,
+ "%s=%s%s%s %s for %s.",
+ to_string(c->type),
+ c->trigger ? "|" : "",
+ c->negate ? "!" : "",
+ c->parameter,
+ condition_result_to_string(c->result),
+ u->id);
+
+ if (!c->trigger && r <= 0)
+ return false;
+
+ if (c->trigger && triggered <= 0)
+ triggered = r > 0;
+ }
+
+ return triggered != 0;
+}
+
static bool unit_condition_test(Unit *u) {
assert(u);
dual_timestamp_get(&u->condition_timestamp);
- u->condition_result = condition_test_list(u->id, u->conditions, condition_type_to_string);
+ u->condition_result = unit_condition_test_list(u, u->conditions, condition_type_to_string);
return u->condition_result;
}
@@ -1258,7 +1305,7 @@ static bool unit_assert_test(Unit *u) {
assert(u);
dual_timestamp_get(&u->assert_timestamp);
- u->assert_result = condition_test_list(u->id, u->asserts, assert_type_to_string);
+ u->assert_result = unit_condition_test_list(u, u->asserts, assert_type_to_string);
return u->assert_result;
}
diff --git a/src/core/unit.h b/src/core/unit.h
index 8b24272..b5a224b 100644
--- a/src/core/unit.h
+++ b/src/core/unit.h
@@ -38,7 +38,7 @@ typedef struct UnitStatusMessageFormats UnitStatusMessageFormats;
#include "socket-util.h"
#include "execute.h"
#include "cgroup.h"
-#include "condition.h"
+#include "condition-util.h"
#include "install.h"
#include "unit-name.h"
#include "failure-action.h"
diff --git a/src/libsystemd-network/network-internal.c b/src/libsystemd-network/network-internal.c
index 6f16050..f3141f7 100644
--- a/src/libsystemd-network/network-internal.c
+++ b/src/libsystemd-network/network-internal.c
@@ -32,7 +32,7 @@
#include "utf8.h"
#include "util.h"
#include "conf-parser.h"
-#include "condition.h"
+#include "condition-util.h"
#include "network-internal.h"
const char *net_get_name(struct udev_device *device) {
diff --git a/src/test/test-tables.c b/src/test/test-tables.c
index 97d5609..d0a621c 100644
--- a/src/test/test-tables.c
+++ b/src/test/test-tables.c
@@ -20,7 +20,7 @@
#include "automount.h"
#include "cgroup.h"
#include "compress.h"
-#include "condition.h"
+#include "condition-util.h"
#include "device.h"
#include "execute.h"
#include "exit-status.h"
commit c073a0c4a5ffbf6677dd6af02e7c7d59b2b901ab
Author: Lennart Poettering <lennart at poettering.net>
Date: Thu Nov 6 14:00:05 2014 +0100
man: document that we don't document .include on purpose
<!-- xml comments are useful! -->
diff --git a/man/systemd.unit.xml b/man/systemd.unit.xml
index dddcf09..2e298ca 100644
--- a/man/systemd.unit.xml
+++ b/man/systemd.unit.xml
@@ -211,6 +211,10 @@
template <literal>.d/</literal> subdirectory and reads
its <literal>.conf</literal> files.</para>
+ <!-- Note that we do not document .include here, as we
+ consider it mostly obsolete, and want people to
+ use .d/ drop-ins instead. -->
+
<para>Note that while systemd offers a flexible
dependency system between units it is recommended to
use this functionality only sparingly and instead rely
commit 90a2ec10f2d43a8530aae856013518eb567c4039
Author: Lennart Poettering <lennart at poettering.net>
Date: Thu Nov 6 13:59:41 2014 +0100
man: don't document ConditionNull=/AssertNull= as the are not particularly useful and simply confusing
diff --git a/man/systemd.unit.xml b/man/systemd.unit.xml
index 5d6f6eb..dddcf09 100644
--- a/man/systemd.unit.xml
+++ b/man/systemd.unit.xml
@@ -950,7 +950,11 @@
<term><varname>ConditionDirectoryNotEmpty=</varname></term>
<term><varname>ConditionFileNotEmpty=</varname></term>
<term><varname>ConditionFileIsExecutable=</varname></term>
- <term><varname>ConditionNull=</varname></term>
+
+ <!-- We don't document ConditionNull=
+ here as it is not particularly
+ useful and probably just
+ confusing. -->
<listitem><para>Before starting a unit
verify that the specified condition is
@@ -1230,15 +1234,6 @@
exists, is a regular file and marked
executable.</para>
- <para>Finally,
- <varname>ConditionNull=</varname> may
- be used to add a constant condition
- check value to the unit. It takes a
- boolean argument. If set to
- <varname>false</varname>, the condition
- will always fail, otherwise
- succeed.</para>
-
<para>If multiple conditions are
specified, the unit will be executed if
all of them apply (i.e. a logical AND
@@ -1283,7 +1278,6 @@
<term><varname>AssertDirectoryNotEmpty=</varname></term>
<term><varname>AssertFileNotEmpty=</varname></term>
<term><varname>AssertFileIsExecutable=</varname></term>
- <term><varname>AssertNull=</varname></term>
<listitem><para>Similar to the
<varname>ConditionArchitecture=</varname>,
commit 651c33185eeb449385b471fffa8882a163c496f0
Author: Lennart Poettering <lennart at poettering.net>
Date: Thu Nov 6 13:56:22 2014 +0100
condition: order condition types the same way in man page, enum, tables
Yes, sometimes I develop OCD.
diff --git a/src/shared/condition-util.c b/src/shared/condition-util.c
index ee9d11e..5db20a7 100644
--- a/src/shared/condition-util.c
+++ b/src/shared/condition-util.c
@@ -472,6 +472,15 @@ void condition_dump_list(Condition *first, FILE *f, const char *prefix, const ch
}
static const char* const condition_type_table[_CONDITION_TYPE_MAX] = {
+ [CONDITION_ARCHITECTURE] = "ConditionArchitecture",
+ [CONDITION_VIRTUALIZATION] = "ConditionVirtualization",
+ [CONDITION_HOST] = "ConditionHost",
+ [CONDITION_KERNEL_COMMAND_LINE] = "ConditionKernelCommandLine",
+ [CONDITION_SECURITY] = "ConditionSecurity",
+ [CONDITION_CAPABILITY] = "ConditionCapability",
+ [CONDITION_AC_POWER] = "ConditionACPower",
+ [CONDITION_NEEDS_UPDATE] = "ConditionNeedsUpdate",
+ [CONDITION_FIRST_BOOT] = "ConditionFirstBoot",
[CONDITION_PATH_EXISTS] = "ConditionPathExists",
[CONDITION_PATH_EXISTS_GLOB] = "ConditionPathExistsGlob",
[CONDITION_PATH_IS_DIRECTORY] = "ConditionPathIsDirectory",
@@ -481,21 +490,21 @@ static const char* const condition_type_table[_CONDITION_TYPE_MAX] = {
[CONDITION_DIRECTORY_NOT_EMPTY] = "ConditionDirectoryNotEmpty",
[CONDITION_FILE_NOT_EMPTY] = "ConditionFileNotEmpty",
[CONDITION_FILE_IS_EXECUTABLE] = "ConditionFileIsExecutable",
- [CONDITION_KERNEL_COMMAND_LINE] = "ConditionKernelCommandLine",
- [CONDITION_VIRTUALIZATION] = "ConditionVirtualization",
- [CONDITION_SECURITY] = "ConditionSecurity",
- [CONDITION_CAPABILITY] = "ConditionCapability",
- [CONDITION_HOST] = "ConditionHost",
- [CONDITION_AC_POWER] = "ConditionACPower",
- [CONDITION_ARCHITECTURE] = "ConditionArchitecture",
- [CONDITION_NEEDS_UPDATE] = "ConditionNeedsUpdate",
- [CONDITION_FIRST_BOOT] = "ConditionFirstBoot",
[CONDITION_NULL] = "ConditionNull"
};
DEFINE_STRING_TABLE_LOOKUP(condition_type, ConditionType);
static const char* const assert_type_table[_CONDITION_TYPE_MAX] = {
+ [CONDITION_ARCHITECTURE] = "AssertArchitecture",
+ [CONDITION_VIRTUALIZATION] = "AssertVirtualization",
+ [CONDITION_HOST] = "AssertHost",
+ [CONDITION_KERNEL_COMMAND_LINE] = "AssertKernelCommandLine",
+ [CONDITION_SECURITY] = "AssertSecurity",
+ [CONDITION_CAPABILITY] = "AssertCapability",
+ [CONDITION_AC_POWER] = "AssertACPower",
+ [CONDITION_NEEDS_UPDATE] = "AssertNeedsUpdate",
+ [CONDITION_FIRST_BOOT] = "AssertFirstBoot",
[CONDITION_PATH_EXISTS] = "AssertPathExists",
[CONDITION_PATH_EXISTS_GLOB] = "AssertPathExistsGlob",
[CONDITION_PATH_IS_DIRECTORY] = "AssertPathIsDirectory",
@@ -505,15 +514,6 @@ static const char* const assert_type_table[_CONDITION_TYPE_MAX] = {
[CONDITION_DIRECTORY_NOT_EMPTY] = "AssertDirectoryNotEmpty",
[CONDITION_FILE_NOT_EMPTY] = "AssertFileNotEmpty",
[CONDITION_FILE_IS_EXECUTABLE] = "AssertFileIsExecutable",
- [CONDITION_KERNEL_COMMAND_LINE] = "AssertKernelCommandLine",
- [CONDITION_VIRTUALIZATION] = "AssertVirtualization",
- [CONDITION_SECURITY] = "AssertSecurity",
- [CONDITION_CAPABILITY] = "AssertCapability",
- [CONDITION_HOST] = "AssertHost",
- [CONDITION_AC_POWER] = "AssertACPower",
- [CONDITION_ARCHITECTURE] = "AssertArchitecture",
- [CONDITION_NEEDS_UPDATE] = "AssertNeedsUpdate",
- [CONDITION_FIRST_BOOT] = "AssertFirstBoot",
[CONDITION_NULL] = "AssertNull"
};
diff --git a/src/shared/condition-util.h b/src/shared/condition-util.h
index 9aaaee9..28d1d94 100644
--- a/src/shared/condition-util.h
+++ b/src/shared/condition-util.h
@@ -28,7 +28,16 @@
#include "macro.h"
typedef enum ConditionType {
- CONDITION_NULL,
+ CONDITION_ARCHITECTURE,
+ CONDITION_VIRTUALIZATION,
+ CONDITION_HOST,
+ CONDITION_KERNEL_COMMAND_LINE,
+ CONDITION_SECURITY,
+ CONDITION_CAPABILITY,
+ CONDITION_AC_POWER,
+
+ CONDITION_NEEDS_UPDATE,
+ CONDITION_FIRST_BOOT,
CONDITION_PATH_EXISTS,
CONDITION_PATH_EXISTS_GLOB,
@@ -40,16 +49,7 @@ typedef enum ConditionType {
CONDITION_FILE_NOT_EMPTY,
CONDITION_FILE_IS_EXECUTABLE,
- CONDITION_KERNEL_COMMAND_LINE,
- CONDITION_VIRTUALIZATION,
- CONDITION_ARCHITECTURE,
- CONDITION_SECURITY,
- CONDITION_CAPABILITY,
- CONDITION_HOST,
- CONDITION_AC_POWER,
-
- CONDITION_NEEDS_UPDATE,
- CONDITION_FIRST_BOOT,
+ CONDITION_NULL,
_CONDITION_TYPE_MAX,
_CONDITION_TYPE_INVALID = -1
commit 59fccdc587bc179c1638916ee16a24099f94f81f
Author: Lennart Poettering <lennart at poettering.net>
Date: Thu Nov 6 13:43:45 2014 +0100
core: introduce the concept of AssertXYZ= similar to ConditionXYZ=, but fatal for a start job if not met
diff --git a/man/systemd.unit.xml b/man/systemd.unit.xml
index 6d4c5c1..5d6f6eb 100644
--- a/man/systemd.unit.xml
+++ b/man/systemd.unit.xml
@@ -1265,6 +1265,39 @@
</varlistentry>
<varlistentry>
+ <term><varname>AssertArchitecture=</varname></term>
+ <term><varname>AssertVirtualization=</varname></term>
+ <term><varname>AssertHost=</varname></term>
+ <term><varname>AssertKernelCommandLine=</varname></term>
+ <term><varname>AssertSecurity=</varname></term>
+ <term><varname>AssertCapability=</varname></term>
+ <term><varname>AssertACPower=</varname></term>
+ <term><varname>AssertNeedsUpdate=</varname></term>
+ <term><varname>AssertFirstBoot=</varname></term>
+ <term><varname>AssertPathExists=</varname></term>
+ <term><varname>AssertPathExistsGlob=</varname></term>
+ <term><varname>AssertPathIsDirectory=</varname></term>
+ <term><varname>AssertPathIsSymbolicLink=</varname></term>
+ <term><varname>AssertPathIsMountPoint=</varname></term>
+ <term><varname>AssertPathIsReadWrite=</varname></term>
+ <term><varname>AssertDirectoryNotEmpty=</varname></term>
+ <term><varname>AssertFileNotEmpty=</varname></term>
+ <term><varname>AssertFileIsExecutable=</varname></term>
+ <term><varname>AssertNull=</varname></term>
+
+ <listitem><para>Similar to the
+ <varname>ConditionArchitecture=</varname>,
+ <varname>ConditionVirtualization=</varname>,
+ ... condition settings described above
+ these settings add assertion checks to
+ the start-up of the unit. However,
+ unlike the conditions settings any
+ assertion setting that is not met
+ results in failure of the start
+ job it was triggered by.</para></listitem>
+ </varlistentry>
+
+ <varlistentry>
<term><varname>SourcePath=</varname></term>
<listitem><para>A path to a
configuration file this unit has been
diff --git a/src/core/condition.c b/src/core/condition.c
index 8475258..c20c0f0 100644
--- a/src/core/condition.c
+++ b/src/core/condition.c
@@ -22,7 +22,7 @@
#include "condition.h"
#include "unit.h"
-bool condition_test_list(const char *unit, Condition *first) {
+bool condition_test_list(const char *unit, Condition *first, const char *(*to_string)(ConditionType t)) {
Condition *c;
int triggered = -1;
@@ -40,7 +40,7 @@ bool condition_test_list(const char *unit, Condition *first) {
if (r < 0)
log_warning_unit(unit,
"Couldn't determine result for %s=%s%s%s for %s, assuming failed: %s",
- condition_type_to_string(c->type),
+ to_string(c->type),
c->trigger ? "|" : "",
c->negate ? "!" : "",
c->parameter,
@@ -49,7 +49,7 @@ bool condition_test_list(const char *unit, Condition *first) {
else
log_debug_unit(unit,
"%s=%s%s%s %s for %s.",
- condition_type_to_string(c->type),
+ to_string(c->type),
c->trigger ? "|" : "",
c->negate ? "!" : "",
c->parameter,
diff --git a/src/core/condition.h b/src/core/condition.h
index 6dd77bb..a6a31ed 100644
--- a/src/core/condition.h
+++ b/src/core/condition.h
@@ -23,4 +23,4 @@
#include "condition-util.h"
-bool condition_test_list(const char *unit, Condition *c);
+bool condition_test_list(const char *unit, Condition *c, const char *(*to_string)(ConditionType t));
diff --git a/src/core/dbus-unit.c b/src/core/dbus-unit.c
index 3fa4271..5dcde25 100644
--- a/src/core/dbus-unit.c
+++ b/src/core/dbus-unit.c
@@ -315,19 +315,21 @@ static int property_get_conditions(
void *userdata,
sd_bus_error *error) {
- Unit *u = userdata;
- Condition *c;
+ const char *(*to_string)(ConditionType type) = NULL;
+ Condition **list = userdata, *c;
int r;
assert(bus);
assert(reply);
- assert(u);
+ assert(list);
+
+ to_string = streq(property, "Asserts") ? assert_type_to_string : condition_type_to_string;
r = sd_bus_message_open_container(reply, 'a', "(sbbsi)");
if (r < 0)
return r;
- LIST_FOREACH(conditions, c, u->conditions) {
+ LIST_FOREACH(conditions, c, *list) {
int tristate;
tristate =
@@ -335,7 +337,7 @@ static int property_get_conditions(
c->result == CONDITION_SUCCEEDED ? 1 : -1;
r = sd_bus_message_append(reply, "(sbbsi)",
- condition_type_to_string(c->type),
+ to_string(c->type),
c->trigger, c->negate,
c->parameter, tristate);
if (r < 0)
@@ -572,8 +574,11 @@ const sd_bus_vtable bus_unit_vtable[] = {
SD_BUS_PROPERTY("JobTimeoutAction", "s", property_get_failure_action, offsetof(Unit, job_timeout_action), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("JobTimeoutRebootArgument", "s", NULL, offsetof(Unit, job_timeout_reboot_arg), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("ConditionResult", "b", bus_property_get_bool, offsetof(Unit, condition_result), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
+ SD_BUS_PROPERTY("AssertResult", "b", bus_property_get_bool, offsetof(Unit, assert_result), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
BUS_PROPERTY_DUAL_TIMESTAMP("ConditionTimestamp", offsetof(Unit, condition_timestamp), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
- SD_BUS_PROPERTY("Conditions", "a(sbbsi)", property_get_conditions, 0, 0),
+ BUS_PROPERTY_DUAL_TIMESTAMP("AssertTimestamp", offsetof(Unit, assert_timestamp), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
+ SD_BUS_PROPERTY("Conditions", "a(sbbsi)", property_get_conditions, offsetof(Unit, conditions), 0),
+ SD_BUS_PROPERTY("Asserts", "a(sbbsi)", property_get_conditions, offsetof(Unit, asserts), 0),
SD_BUS_PROPERTY("LoadError", "(ss)", property_get_load_error, 0, SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("Transient", "b", bus_property_get_bool, offsetof(Unit, transient), SD_BUS_VTABLE_PROPERTY_CONST),
diff --git a/src/core/job.c b/src/core/job.c
index eaa4bb1..51d1581 100644
--- a/src/core/job.c
+++ b/src/core/job.c
@@ -542,6 +542,8 @@ int job_run_and_invalidate(Job *j) {
r = job_finish_and_invalidate(j, JOB_SKIPPED, true);
else if (r == -ENOEXEC)
r = job_finish_and_invalidate(j, JOB_INVALID, true);
+ else if (r == -EPROTO)
+ r = job_finish_and_invalidate(j, JOB_ASSERT, true);
else if (r == -EAGAIN) {
j->state = JOB_WAITING;
m->n_running_jobs--;
@@ -655,6 +657,11 @@ static void job_print_status_message(Unit *u, JobType t, JobResult result) {
unit_status_printf(u, ANSI_HIGHLIGHT_RED_ON " TIME " ANSI_HIGHLIGHT_OFF, format);
break;
+ case JOB_ASSERT:
+ manager_flip_auto_status(u->manager, true);
+ unit_status_printf(u, ANSI_HIGHLIGHT_YELLOW_ON "ASSERT" ANSI_HIGHLIGHT_OFF, format);
+ break;
+
default:
;
}
@@ -1189,6 +1196,7 @@ static const char* const job_result_table[_JOB_RESULT_MAX] = {
[JOB_DEPENDENCY] = "dependency",
[JOB_SKIPPED] = "skipped",
[JOB_INVALID] = "invalid",
+ [JOB_ASSERT] = "assert",
};
DEFINE_STRING_TABLE_LOOKUP(job_result, JobResult);
diff --git a/src/core/job.h b/src/core/job.h
index 1e7c61b..b7ebd8d 100644
--- a/src/core/job.h
+++ b/src/core/job.h
@@ -99,6 +99,7 @@ enum JobResult {
JOB_DEPENDENCY, /* A required dependency job did not result in JOB_DONE */
JOB_SKIPPED, /* Negative result of JOB_VERIFY_ACTIVE */
JOB_INVALID, /* JOB_RELOAD of inactive unit */
+ JOB_ASSERT, /* Couldn't start a unit, because an assert didn't hold */
_JOB_RESULT_MAX,
_JOB_RESULT_INVALID = -1
};
diff --git a/src/core/load-fragment-gperf.gperf.m4 b/src/core/load-fragment-gperf.gperf.m4
index 5158a9f..1d2debe 100644
--- a/src/core/load-fragment-gperf.gperf.m4
+++ b/src/core/load-fragment-gperf.gperf.m4
@@ -155,25 +155,44 @@ Unit.IgnoreOnSnapshot, config_parse_bool, 0,
Unit.JobTimeoutSec, config_parse_sec, 0, offsetof(Unit, job_timeout)
Unit.JobTimeoutAction, config_parse_failure_action, 0, offsetof(Unit, job_timeout_action)
Unit.JobTimeoutRebootArgument, config_parse_string, 0, offsetof(Unit, job_timeout_reboot_arg)
-Unit.ConditionPathExists, config_parse_unit_condition_path, CONDITION_PATH_EXISTS, 0
-Unit.ConditionPathExistsGlob, config_parse_unit_condition_path, CONDITION_PATH_EXISTS_GLOB, 0
-Unit.ConditionPathIsDirectory, config_parse_unit_condition_path, CONDITION_PATH_IS_DIRECTORY, 0
-Unit.ConditionPathIsSymbolicLink,config_parse_unit_condition_path, CONDITION_PATH_IS_SYMBOLIC_LINK,0
-Unit.ConditionPathIsMountPoint, config_parse_unit_condition_path, CONDITION_PATH_IS_MOUNT_POINT, 0
-Unit.ConditionPathIsReadWrite, config_parse_unit_condition_path, CONDITION_PATH_IS_READ_WRITE, 0
-Unit.ConditionDirectoryNotEmpty, config_parse_unit_condition_path, CONDITION_DIRECTORY_NOT_EMPTY, 0
-Unit.ConditionFileNotEmpty, config_parse_unit_condition_path, CONDITION_FILE_NOT_EMPTY, 0
-Unit.ConditionFileIsExecutable, config_parse_unit_condition_path, CONDITION_FILE_IS_EXECUTABLE, 0
-Unit.ConditionNeedsUpdate, config_parse_unit_condition_path, CONDITION_NEEDS_UPDATE, 0
-Unit.ConditionFirstBoot, config_parse_unit_condition_string, CONDITION_FIRST_BOOT, 0
-Unit.ConditionKernelCommandLine, config_parse_unit_condition_string, CONDITION_KERNEL_COMMAND_LINE, 0
-Unit.ConditionArchitecture, config_parse_unit_condition_string, CONDITION_ARCHITECTURE, 0
-Unit.ConditionVirtualization, config_parse_unit_condition_string, CONDITION_VIRTUALIZATION, 0
-Unit.ConditionSecurity, config_parse_unit_condition_string, CONDITION_SECURITY, 0
-Unit.ConditionCapability, config_parse_unit_condition_string, CONDITION_CAPABILITY, 0
-Unit.ConditionHost, config_parse_unit_condition_string, CONDITION_HOST, 0
-Unit.ConditionACPower, config_parse_unit_condition_string, CONDITION_AC_POWER, 0
-Unit.ConditionNull, config_parse_unit_condition_null, 0, 0
+Unit.ConditionPathExists, config_parse_unit_condition_path, CONDITION_PATH_EXISTS, offsetof(Unit, conditions)
+Unit.ConditionPathExistsGlob, config_parse_unit_condition_path, CONDITION_PATH_EXISTS_GLOB, offsetof(Unit, conditions)
+Unit.ConditionPathIsDirectory, config_parse_unit_condition_path, CONDITION_PATH_IS_DIRECTORY, offsetof(Unit, conditions)
+Unit.ConditionPathIsSymbolicLink,config_parse_unit_condition_path, CONDITION_PATH_IS_SYMBOLIC_LINK,offsetof(Unit, conditions)
+Unit.ConditionPathIsMountPoint, config_parse_unit_condition_path, CONDITION_PATH_IS_MOUNT_POINT, offsetof(Unit, conditions)
+Unit.ConditionPathIsReadWrite, config_parse_unit_condition_path, CONDITION_PATH_IS_READ_WRITE, offsetof(Unit, conditions)
+Unit.ConditionDirectoryNotEmpty, config_parse_unit_condition_path, CONDITION_DIRECTORY_NOT_EMPTY, offsetof(Unit, conditions)
+Unit.ConditionFileNotEmpty, config_parse_unit_condition_path, CONDITION_FILE_NOT_EMPTY, offsetof(Unit, conditions)
+Unit.ConditionFileIsExecutable, config_parse_unit_condition_path, CONDITION_FILE_IS_EXECUTABLE, offsetof(Unit, conditions)
+Unit.ConditionNeedsUpdate, config_parse_unit_condition_path, CONDITION_NEEDS_UPDATE, offsetof(Unit, conditions)
+Unit.ConditionFirstBoot, config_parse_unit_condition_string, CONDITION_FIRST_BOOT, offsetof(Unit, conditions)
+Unit.ConditionKernelCommandLine, config_parse_unit_condition_string, CONDITION_KERNEL_COMMAND_LINE, offsetof(Unit, conditions)
+Unit.ConditionArchitecture, config_parse_unit_condition_string, CONDITION_ARCHITECTURE, offsetof(Unit, conditions)
+Unit.ConditionVirtualization, config_parse_unit_condition_string, CONDITION_VIRTUALIZATION, offsetof(Unit, conditions)
+Unit.ConditionSecurity, config_parse_unit_condition_string, CONDITION_SECURITY, offsetof(Unit, conditions)
+Unit.ConditionCapability, config_parse_unit_condition_string, CONDITION_CAPABILITY, offsetof(Unit, conditions)
+Unit.ConditionHost, config_parse_unit_condition_string, CONDITION_HOST, offsetof(Unit, conditions)
+Unit.ConditionACPower, config_parse_unit_condition_string, CONDITION_AC_POWER, offsetof(Unit, conditions)
+Unit.ConditionNull, config_parse_unit_condition_null, 0, offsetof(Unit, conditions)
+Unit.AssertPathExists, config_parse_unit_condition_path, CONDITION_PATH_EXISTS, offsetof(Unit, asserts)
+Unit.AssertPathExistsGlob, config_parse_unit_condition_path, CONDITION_PATH_EXISTS_GLOB, offsetof(Unit, asserts)
+Unit.AssertPathIsDirectory, config_parse_unit_condition_path, CONDITION_PATH_IS_DIRECTORY, offsetof(Unit, asserts)
+Unit.AssertPathIsSymbolicLink, config_parse_unit_condition_path, CONDITION_PATH_IS_SYMBOLIC_LINK,offsetof(Unit, asserts)
+Unit.AssertPathIsMountPoint, config_parse_unit_condition_path, CONDITION_PATH_IS_MOUNT_POINT, offsetof(Unit, asserts)
+Unit.AssertPathIsReadWrite, config_parse_unit_condition_path, CONDITION_PATH_IS_READ_WRITE, offsetof(Unit, asserts)
+Unit.AssertDirectoryNotEmpty, config_parse_unit_condition_path, CONDITION_DIRECTORY_NOT_EMPTY, offsetof(Unit, asserts)
+Unit.AssertFileNotEmpty, config_parse_unit_condition_path, CONDITION_FILE_NOT_EMPTY, offsetof(Unit, asserts)
+Unit.AssertFileIsExecutable, config_parse_unit_condition_path, CONDITION_FILE_IS_EXECUTABLE, offsetof(Unit, asserts)
+Unit.AssertNeedsUpdate, config_parse_unit_condition_path, CONDITION_NEEDS_UPDATE, offsetof(Unit, asserts)
+Unit.AssertFirstBoot, config_parse_unit_condition_string, CONDITION_FIRST_BOOT, offsetof(Unit, asserts)
+Unit.AssertKernelCommandLine, config_parse_unit_condition_string, CONDITION_KERNEL_COMMAND_LINE, offsetof(Unit, asserts)
+Unit.AssertArchitecture, config_parse_unit_condition_string, CONDITION_ARCHITECTURE, offsetof(Unit, asserts)
+Unit.AssertVirtualization, config_parse_unit_condition_string, CONDITION_VIRTUALIZATION, offsetof(Unit, asserts)
+Unit.AssertSecurity, config_parse_unit_condition_string, CONDITION_SECURITY, offsetof(Unit, asserts)
+Unit.AssertCapability, config_parse_unit_condition_string, CONDITION_CAPABILITY, offsetof(Unit, asserts)
+Unit.AssertHost, config_parse_unit_condition_string, CONDITION_HOST, offsetof(Unit, asserts)
+Unit.AssertACPower, config_parse_unit_condition_string, CONDITION_AC_POWER, offsetof(Unit, asserts)
+Unit.AssertNull, config_parse_unit_condition_null, 0, offsetof(Unit, asserts)
m4_dnl
Service.PIDFile, config_parse_unit_path_printf, 0, offsetof(Service, pid_file)
Service.ExecStartPre, config_parse_exec, SERVICE_EXEC_START_PRE, offsetof(Service, exec_command)
diff --git a/src/core/load-fragment.c b/src/core/load-fragment.c
index e193a67..2ee16bd 100644
--- a/src/core/load-fragment.c
+++ b/src/core/load-fragment.c
@@ -1955,22 +1955,23 @@ int config_parse_ip_tos(const char *unit,
return 0;
}
-int config_parse_unit_condition_path(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) {
+int config_parse_unit_condition_path(
+ 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) {
- ConditionType cond = ltype;
- Unit *u = data;
- bool trigger, negate;
- Condition *c;
_cleanup_free_ char *p = NULL;
+ Condition **list = data, *c;
+ ConditionType t = ltype;
+ bool trigger, negate;
+ Unit *u = userdata;
int r;
assert(filename);
@@ -1980,8 +1981,8 @@ int config_parse_unit_condition_path(const char *unit,
if (isempty(rvalue)) {
/* Empty assignment resets the list */
- condition_free_list(u->conditions);
- u->conditions = NULL;
+ condition_free_list(*list);
+ *list = NULL;
return 0;
}
@@ -1994,45 +1995,41 @@ int config_parse_unit_condition_path(const char *unit,
rvalue++;
r = unit_full_printf(u, rvalue, &p);
- if (r < 0)
- log_syntax(unit, LOG_ERR, filename, line, -r,
- "Failed to resolve specifiers, ignoring: %s", rvalue);
- if (!p) {
- p = strdup(rvalue);
- if (!p)
- return log_oom();
+ if (r < 0) {
+ log_syntax(unit, LOG_ERR, filename, line, -r, "Failed to resolve specifiers, ignoring: %s", rvalue);
+ return 0;
}
if (!path_is_absolute(p)) {
- log_syntax(unit, LOG_ERR, filename, line, EINVAL,
- "Path in condition not absolute, ignoring: %s", p);
+ log_syntax(unit, LOG_ERR, filename, line, EINVAL, "Path in condition not absolute, ignoring: %s", p);
return 0;
}
- c = condition_new(cond, p, trigger, negate);
+ c = condition_new(t, p, trigger, negate);
if (!c)
return log_oom();
- LIST_PREPEND(conditions, u->conditions, c);
+ LIST_PREPEND(conditions, *list, c);
return 0;
}
-int config_parse_unit_condition_string(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) {
+int config_parse_unit_condition_string(
+ 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) {
- ConditionType cond = ltype;
- Unit *u = data;
- bool trigger, negate;
- Condition *c;
_cleanup_free_ char *s = NULL;
+ Condition **list = data, *c;
+ ConditionType t = ltype;
+ bool trigger, negate;
+ Unit *u = userdata;
int r;
assert(filename);
@@ -2042,8 +2039,8 @@ int config_parse_unit_condition_string(const char *unit,
if (isempty(rvalue)) {
/* Empty assignment resets the list */
- condition_free_list(u->conditions);
- u->conditions = NULL;
+ condition_free_list(*list);
+ *list = NULL;
return 0;
}
@@ -2056,36 +2053,32 @@ int config_parse_unit_condition_string(const char *unit,
rvalue++;
r = unit_full_printf(u, rvalue, &s);
- if (r < 0)
- log_syntax(unit, LOG_ERR, filename, line, -r,
- "Failed to resolve specifiers, ignoring: %s", rvalue);
- if (!s) {
- s = strdup(rvalue);
- if (!s)
- return log_oom();
+ if (r < 0) {
+ log_syntax(unit, LOG_ERR, filename, line, -r, "Failed to resolve specifiers, ignoring: %s", rvalue);
+ return 0;
}
- c = condition_new(cond, s, trigger, negate);
+ c = condition_new(t, s, trigger, negate);
if (!c)
return log_oom();
- LIST_PREPEND(conditions, u->conditions, c);
+ LIST_PREPEND(conditions, *list, c);
return 0;
}
-int config_parse_unit_condition_null(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) {
+int config_parse_unit_condition_null(
+ 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) {
- Unit *u = data;
- Condition *c;
+ Condition **list = data, *c;
bool trigger, negate;
int b;
@@ -2096,8 +2089,8 @@ int config_parse_unit_condition_null(const char *unit,
if (isempty(rvalue)) {
/* Empty assignment resets the list */
- condition_free_list(u->conditions);
- u->conditions = NULL;
+ condition_free_list(*list);
+ *list = NULL;
return 0;
}
@@ -2111,9 +2104,7 @@ int config_parse_unit_condition_null(const char *unit,
b = parse_boolean(rvalue);
if (b < 0) {
- log_syntax(unit, LOG_ERR, filename, line, -b,
- "Failed to parse boolean value in condition, ignoring: %s",
- rvalue);
+ log_syntax(unit, LOG_ERR, filename, line, -b, "Failed to parse boolean value in condition, ignoring: %s", rvalue);
return 0;
}
@@ -2124,7 +2115,7 @@ int config_parse_unit_condition_null(const char *unit,
if (!c)
return log_oom();
- LIST_PREPEND(conditions, u->conditions, c);
+ LIST_PREPEND(conditions, *list, c);
return 0;
}
diff --git a/src/core/unit.c b/src/core/unit.c
index d5acc72..66f53dd 100644
--- a/src/core/unit.c
+++ b/src/core/unit.c
@@ -527,6 +527,7 @@ void unit_free(Unit *u) {
unit_unwatch_all_pids(u);
condition_free_list(u->conditions);
+ condition_free_list(u->asserts);
unit_ref_unset(&u->slice);
@@ -929,7 +930,8 @@ void unit_dump(Unit *u, FILE *f, const char *prefix) {
if (u->job_timeout_reboot_arg)
fprintf(f, "%s\tJob Timeout Reboot Argument: %s\n", prefix, u->job_timeout_reboot_arg);
- condition_dump_list(u->conditions, f, prefix);
+ condition_dump_list(u->conditions, f, prefix, condition_type_to_string);
+ condition_dump_list(u->asserts, f, prefix, assert_type_to_string);
if (dual_timestamp_is_set(&u->condition_timestamp))
fprintf(f,
@@ -938,6 +940,13 @@ void unit_dump(Unit *u, FILE *f, const char *prefix) {
prefix, strna(format_timestamp(timestamp1, sizeof(timestamp1), u->condition_timestamp.realtime)),
prefix, yes_no(u->condition_result));
+ if (dual_timestamp_is_set(&u->assert_timestamp))
+ fprintf(f,
+ "%s\tAssert Timestamp: %s\n"
+ "%s\tAssert Result: %s\n",
+ prefix, strna(format_timestamp(timestamp1, sizeof(timestamp1), u->assert_timestamp.realtime)),
+ prefix, yes_no(u->assert_result));
+
for (d = 0; d < _UNIT_DEPENDENCY_MAX; d++) {
Unit *other;
@@ -1240,11 +1249,20 @@ static bool unit_condition_test(Unit *u) {
assert(u);
dual_timestamp_get(&u->condition_timestamp);
- u->condition_result = condition_test_list(u->id, u->conditions);
+ u->condition_result = condition_test_list(u->id, u->conditions, condition_type_to_string);
return u->condition_result;
}
+static bool unit_assert_test(Unit *u) {
+ assert(u);
+
+ dual_timestamp_get(&u->assert_timestamp);
+ u->assert_result = condition_test_list(u->id, u->asserts, assert_type_to_string);
+
+ return u->assert_result;
+}
+
_pure_ static const char* unit_get_status_message_format(Unit *u, JobType t) {
const UnitStatusMessageFormats *format_table;
@@ -1341,6 +1359,7 @@ static void unit_status_log_starting_stopping_reloading(Unit *u, JobType t) {
* -EALREADY: Unit is already started.
* -EAGAIN: An operation is already in progress. Retry later.
* -ECANCELED: Too many requests for now.
+ * -EPROTO: Assert failed
*/
int unit_start(Unit *u) {
UnitActiveState state;
@@ -1365,15 +1384,21 @@ int unit_start(Unit *u) {
* but we don't want to recheck the condition in that case. */
if (state != UNIT_ACTIVATING &&
!unit_condition_test(u)) {
- log_debug_unit(u->id, "Starting of %s requested but condition failed. Ignoring.", u->id);
+ log_debug_unit(u->id, "Starting of %s requested but condition failed. Not starting unit.", u->id);
return -EALREADY;
}
+ /* If the asserts failed, fail the entire job */
+ if (state != UNIT_ACTIVATING &&
+ !unit_assert_test(u)) {
+ log_debug_unit(u->id, "Starting of %s requested but asserts failed.", u->id);
+ return -EPROTO;
+ }
+
/* Forward to the main object, if we aren't it. */
following = unit_following(u);
if (following) {
- log_debug_unit(u->id, "Redirecting start request from %s to %s.",
- u->id, following->id);
+ log_debug_unit(u->id, "Redirecting start request from %s to %s.", u->id, following->id);
return unit_start(following);
}
@@ -2502,10 +2527,14 @@ int unit_serialize(Unit *u, FILE *f, FDSet *fds, bool serialize_jobs) {
dual_timestamp_serialize(f, "active-exit-timestamp", &u->active_exit_timestamp);
dual_timestamp_serialize(f, "inactive-enter-timestamp", &u->inactive_enter_timestamp);
dual_timestamp_serialize(f, "condition-timestamp", &u->condition_timestamp);
+ dual_timestamp_serialize(f, "assert-timestamp", &u->assert_timestamp);
if (dual_timestamp_is_set(&u->condition_timestamp))
unit_serialize_item(u, f, "condition-result", yes_no(u->condition_result));
+ if (dual_timestamp_is_set(&u->assert_timestamp))
+ unit_serialize_item(u, f, "assert-result", yes_no(u->assert_result));
+
unit_serialize_item(u, f, "transient", yes_no(u->transient));
if (u->cgroup_path)
@@ -2645,6 +2674,9 @@ int unit_deserialize(Unit *u, FILE *f, FDSet *fds) {
} else if (streq(l, "condition-timestamp")) {
dual_timestamp_deserialize(v, &u->condition_timestamp);
continue;
+ } else if (streq(l, "assert-timestamp")) {
+ dual_timestamp_deserialize(v, &u->assert_timestamp);
+ continue;
} else if (streq(l, "condition-result")) {
int b;
@@ -2656,6 +2688,17 @@ int unit_deserialize(Unit *u, FILE *f, FDSet *fds) {
continue;
+ } else if (streq(l, "assert-result")) {
+ int b;
+
+ b = parse_boolean(v);
+ if (b < 0)
+ log_debug("Failed to parse assert result value %s", v);
+ else
+ u->assert_result = b;
+
+ continue;
+
} else if (streq(l, "transient")) {
int b;
diff --git a/src/core/unit.h b/src/core/unit.h
index 081ab18..8b24272 100644
--- a/src/core/unit.h
+++ b/src/core/unit.h
@@ -129,8 +129,10 @@ struct Unit {
/* Conditions to check */
LIST_HEAD(Condition, conditions);
+ LIST_HEAD(Condition, asserts);
dual_timestamp condition_timestamp;
+ dual_timestamp assert_timestamp;
dual_timestamp inactive_exit_timestamp;
dual_timestamp active_enter_timestamp;
@@ -212,6 +214,7 @@ struct Unit {
/* Did the last condition check succeed? */
bool condition_result;
+ bool assert_result;
/* Is this a transient unit? */
bool transient;
diff --git a/src/shared/condition-util.c b/src/shared/condition-util.c
index 640a931..ee9d11e 100644
--- a/src/shared/condition-util.c
+++ b/src/shared/condition-util.c
@@ -447,7 +447,7 @@ int condition_test(Condition *c) {
return b;
}
-void condition_dump(Condition *c, FILE *f, const char *prefix) {
+void condition_dump(Condition *c, FILE *f, const char *prefix, const char *(*to_string)(ConditionType t)) {
assert(c);
assert(f);
@@ -457,18 +457,18 @@ void condition_dump(Condition *c, FILE *f, const char *prefix) {
fprintf(f,
"%s\t%s: %s%s%s %s\n",
prefix,
- condition_type_to_string(c->type),
+ to_string(c->type),
c->trigger ? "|" : "",
c->negate ? "!" : "",
c->parameter,
condition_result_to_string(c->result));
}
-void condition_dump_list(Condition *first, FILE *f, const char *prefix) {
+void condition_dump_list(Condition *first, FILE *f, const char *prefix, const char *(*to_string)(ConditionType t)) {
Condition *c;
LIST_FOREACH(conditions, c, first)
- condition_dump(c, f, prefix);
+ condition_dump(c, f, prefix, to_string);
}
static const char* const condition_type_table[_CONDITION_TYPE_MAX] = {
@@ -495,6 +495,30 @@ static const char* const condition_type_table[_CONDITION_TYPE_MAX] = {
DEFINE_STRING_TABLE_LOOKUP(condition_type, ConditionType);
+static const char* const assert_type_table[_CONDITION_TYPE_MAX] = {
+ [CONDITION_PATH_EXISTS] = "AssertPathExists",
+ [CONDITION_PATH_EXISTS_GLOB] = "AssertPathExistsGlob",
+ [CONDITION_PATH_IS_DIRECTORY] = "AssertPathIsDirectory",
+ [CONDITION_PATH_IS_SYMBOLIC_LINK] = "AssertPathIsSymbolicLink",
+ [CONDITION_PATH_IS_MOUNT_POINT] = "AssertPathIsMountPoint",
+ [CONDITION_PATH_IS_READ_WRITE] = "AssertPathIsReadWrite",
+ [CONDITION_DIRECTORY_NOT_EMPTY] = "AssertDirectoryNotEmpty",
+ [CONDITION_FILE_NOT_EMPTY] = "AssertFileNotEmpty",
+ [CONDITION_FILE_IS_EXECUTABLE] = "AssertFileIsExecutable",
+ [CONDITION_KERNEL_COMMAND_LINE] = "AssertKernelCommandLine",
+ [CONDITION_VIRTUALIZATION] = "AssertVirtualization",
+ [CONDITION_SECURITY] = "AssertSecurity",
+ [CONDITION_CAPABILITY] = "AssertCapability",
+ [CONDITION_HOST] = "AssertHost",
+ [CONDITION_AC_POWER] = "AssertACPower",
+ [CONDITION_ARCHITECTURE] = "AssertArchitecture",
+ [CONDITION_NEEDS_UPDATE] = "AssertNeedsUpdate",
+ [CONDITION_FIRST_BOOT] = "AssertFirstBoot",
+ [CONDITION_NULL] = "AssertNull"
+};
+
+DEFINE_STRING_TABLE_LOOKUP(assert_type, ConditionType);
+
static const char* const condition_result_table[_CONDITION_RESULT_MAX] = {
[CONDITION_UNTESTED] = "untested",
[CONDITION_SUCCEEDED] = "succeeded",
diff --git a/src/shared/condition-util.h b/src/shared/condition-util.h
index 08aee94..9aaaee9 100644
--- a/src/shared/condition-util.h
+++ b/src/shared/condition-util.h
@@ -28,6 +28,8 @@
#include "macro.h"
typedef enum ConditionType {
+ CONDITION_NULL,
+
CONDITION_PATH_EXISTS,
CONDITION_PATH_EXISTS_GLOB,
CONDITION_PATH_IS_DIRECTORY,
@@ -37,16 +39,18 @@ typedef enum ConditionType {
CONDITION_DIRECTORY_NOT_EMPTY,
CONDITION_FILE_NOT_EMPTY,
CONDITION_FILE_IS_EXECUTABLE,
+
CONDITION_KERNEL_COMMAND_LINE,
CONDITION_VIRTUALIZATION,
+ CONDITION_ARCHITECTURE,
CONDITION_SECURITY,
CONDITION_CAPABILITY,
CONDITION_HOST,
CONDITION_AC_POWER,
- CONDITION_ARCHITECTURE,
+
CONDITION_NEEDS_UPDATE,
CONDITION_FIRST_BOOT,
- CONDITION_NULL,
+
_CONDITION_TYPE_MAX,
_CONDITION_TYPE_INVALID = -1
} ConditionType;
@@ -61,13 +65,14 @@ typedef enum ConditionResult {
} ConditionResult;
typedef struct Condition {
- ConditionType type;
+ ConditionType type:8;
bool trigger:1;
bool negate:1;
+ ConditionResult result:6;
+
char *parameter;
- ConditionResult result;
LIST_FIELDS(struct Condition, conditions);
} Condition;
@@ -78,11 +83,14 @@ void condition_free_list(Condition *c);
int condition_test(Condition *c);
-void condition_dump(Condition *c, FILE *f, const char *prefix);
-void condition_dump_list(Condition *c, FILE *f, const char *prefix);
+void condition_dump(Condition *c, FILE *f, const char *prefix, const char *(*to_string)(ConditionType t));
+void condition_dump_list(Condition *c, FILE *f, const char *prefix, const char *(*to_string)(ConditionType t));
const char* condition_type_to_string(ConditionType t) _const_;
-int condition_type_from_string(const char *s) _pure_;
+ConditionType condition_type_from_string(const char *s) _pure_;
+
+const char* assert_type_to_string(ConditionType t) _const_;
+ConditionType assert_type_from_string(const char *s) _pure_;
const char* condition_result_to_string(ConditionResult r) _const_;
ConditionResult condition_result_from_string(const char *s) _pure_;
diff --git a/src/systemctl/systemctl.c b/src/systemctl/systemctl.c
index 8481a9b..8a3e203 100644
--- a/src/systemctl/systemctl.c
+++ b/src/systemctl/systemctl.c
@@ -3271,7 +3271,14 @@ typedef struct UnitStatusInfo {
bool failed_condition_trigger;
bool failed_condition_negate;
const char *failed_condition;
- const char *failed_condition_param;
+ const char *failed_condition_parameter;
+
+ usec_t assert_timestamp;
+ bool assert_result;
+ bool failed_assert_trigger;
+ bool failed_assert_negate;
+ const char *failed_assert;
+ const char *failed_assert_parameter;
/* Socket */
unsigned n_accepted;
@@ -3415,7 +3422,8 @@ static void print_status_info(
s1 = format_timestamp_relative(since1, sizeof(since1), i->condition_timestamp);
s2 = format_timestamp(since2, sizeof(since2), i->condition_timestamp);
- printf(" start condition failed at %s%s%s\n",
+ printf("Condition: start %scondition failed%s at %s%s%s\n",
+ ansi_highlight_yellow(), ansi_highlight_off(),
s2, s1 ? "; " : "", s1 ? s1 : "");
if (i->failed_condition_trigger)
printf(" none of the trigger conditions were met\n");
@@ -3423,7 +3431,23 @@ static void print_status_info(
printf(" %s=%s%s was not met\n",
i->failed_condition,
i->failed_condition_negate ? "!" : "",
- i->failed_condition_param);
+ i->failed_condition_parameter);
+ }
+
+ if (!i->assert_result && i->assert_timestamp > 0) {
+ s1 = format_timestamp_relative(since1, sizeof(since1), i->assert_timestamp);
+ s2 = format_timestamp(since2, sizeof(since2), i->assert_timestamp);
+
+ printf(" Assert: start %sassertion failed%s at %s%s%s\n",
+ ansi_highlight_red(), ansi_highlight_off(),
+ s2, s1 ? "; " : "", s1 ? s1 : "");
+ if (i->failed_assert_trigger)
+ printf(" none of the trigger assertions were met\n");
+ else if (i->failed_assert)
+ printf(" %s=%s%s was not met\n",
+ i->failed_assert,
+ i->failed_assert_negate ? "!" : "",
+ i->failed_assert_parameter);
}
if (i->sysfs_path)
@@ -3674,6 +3698,8 @@ static int status_property(const char *name, sd_bus_message *m, UnitStatusInfo *
i->need_daemon_reload = b;
else if (streq(name, "ConditionResult"))
i->condition_result = b;
+ else if (streq(name, "AssertResult"))
+ i->assert_result = b;
break;
}
@@ -3743,6 +3769,8 @@ static int status_property(const char *name, sd_bus_message *m, UnitStatusInfo *
i->active_exit_timestamp = (usec_t) u;
else if (streq(name, "ConditionTimestamp"))
i->condition_timestamp = (usec_t) u;
+ else if (streq(name, "AssertTimestamp"))
+ i->assert_timestamp = (usec_t) u;
break;
}
@@ -3835,7 +3863,32 @@ static int status_property(const char *name, sd_bus_message *m, UnitStatusInfo *
i->failed_condition = cond;
i->failed_condition_trigger = trigger;
i->failed_condition_negate = negate;
- i->failed_condition_param = param;
+ i->failed_condition_parameter = param;
+ }
+ }
+ if (r < 0)
+ return bus_log_parse_error(r);
+
+ r = sd_bus_message_exit_container(m);
+ if (r < 0)
+ return bus_log_parse_error(r);
+
+ } else if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "Asserts")) {
+ const char *cond, *param;
+ int trigger, negate;
+ int32_t state;
+
+ r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(sbbsi)");
+ if (r < 0)
+ return bus_log_parse_error(r);
+
+ while ((r = sd_bus_message_read(m, "(sbbsi)", &cond, &trigger, &negate, ¶m, &state)) > 0) {
+ log_debug("%s %d %d %s %d", cond, trigger, negate, param, state);
+ if (state < 0 && (!trigger || !i->failed_assert)) {
+ i->failed_assert = cond;
+ i->failed_assert_trigger = trigger;
+ i->failed_assert_negate = negate;
+ i->failed_assert_parameter = param;
}
}
if (r < 0)
diff --git a/src/test/test-tables.c b/src/test/test-tables.c
index 2138442..97d5609 100644
--- a/src/test/test-tables.c
+++ b/src/test/test-tables.c
@@ -61,6 +61,8 @@ int main(int argc, char **argv) {
test_table(busname_state, BUSNAME_STATE);
test_table(cgroup_device_policy, CGROUP_DEVICE_POLICY);
test_table(condition_type, CONDITION_TYPE);
+ test_table(assert_type, CONDITION_TYPE);
+ test_table(condition_result, CONDITION_RESULT);
test_table(device_state, DEVICE_STATE);
test_table(exec_input, EXEC_INPUT);
test_table(exec_output, EXEC_OUTPUT);
commit cc50ef134b4104cae8783a4ca40b1a70247e3ef9
Author: Lennart Poettering <lennart at poettering.net>
Date: Thu Nov 6 02:27:10 2014 +0100
condition: record test state internally and beef it up to be a full enum
diff --git a/src/core/condition.c b/src/core/condition.c
index d8d1152..8475258 100644
--- a/src/core/condition.c
+++ b/src/core/condition.c
@@ -53,11 +53,9 @@ bool condition_test_list(const char *unit, Condition *first) {
c->trigger ? "|" : "",
c->negate ? "!" : "",
c->parameter,
- r > 0 ? "succeeded" : "failed",
+ condition_result_to_string(c->result),
unit);
- c->state = r > 0 ? CONDITION_STATE_SUCCEEDED : CONDITION_STATE_FAILED;
-
if (!c->trigger && r <= 0)
return false;
diff --git a/src/core/dbus-unit.c b/src/core/dbus-unit.c
index 2d1862c..3fa4271 100644
--- a/src/core/dbus-unit.c
+++ b/src/core/dbus-unit.c
@@ -328,10 +328,16 @@ static int property_get_conditions(
return r;
LIST_FOREACH(conditions, c, u->conditions) {
+ int tristate;
+
+ tristate =
+ c->result == CONDITION_UNTESTED ? 0 :
+ c->result == CONDITION_SUCCEEDED ? 1 : -1;
+
r = sd_bus_message_append(reply, "(sbbsi)",
condition_type_to_string(c->type),
c->trigger, c->negate,
- c->parameter, c->state);
+ c->parameter, tristate);
if (r < 0)
return r;
diff --git a/src/shared/condition-util.c b/src/shared/condition-util.c
index 749b577..640a931 100644
--- a/src/shared/condition-util.c
+++ b/src/shared/condition-util.c
@@ -429,17 +429,22 @@ int condition_test(Condition *c) {
[CONDITION_FIRST_BOOT] = condition_test_first_boot,
[CONDITION_NULL] = condition_test_null,
};
- int r;
+
+ int r, b;
assert(c);
assert(c->type >= 0);
assert(c->type < _CONDITION_TYPE_MAX);
r = condition_tests[c->type](c);
- if (r < 0)
+ if (r < 0) {
+ c->result = CONDITION_ERROR;
return r;
+ }
- return (r > 0) == !c->negate;
+ b = (r > 0) == !c->negate;
+ c->result = b ? CONDITION_SUCCEEDED : CONDITION_FAILED;
+ return b;
}
void condition_dump(Condition *c, FILE *f, const char *prefix) {
@@ -456,7 +461,7 @@ void condition_dump(Condition *c, FILE *f, const char *prefix) {
c->trigger ? "|" : "",
c->negate ? "!" : "",
c->parameter,
- CONDITION_STATE_IS_FAILED(c->state) ? "failed" : CONDITION_STATE_IS_SUCCEEDED(c->state) ? "succeeded" : "untested");
+ condition_result_to_string(c->result));
}
void condition_dump_list(Condition *first, FILE *f, const char *prefix) {
@@ -489,3 +494,12 @@ static const char* const condition_type_table[_CONDITION_TYPE_MAX] = {
};
DEFINE_STRING_TABLE_LOOKUP(condition_type, ConditionType);
+
+static const char* const condition_result_table[_CONDITION_RESULT_MAX] = {
+ [CONDITION_UNTESTED] = "untested",
+ [CONDITION_SUCCEEDED] = "succeeded",
+ [CONDITION_FAILED] = "failed",
+ [CONDITION_ERROR] = "error",
+};
+
+DEFINE_STRING_TABLE_LOOKUP(condition_result, ConditionResult);
diff --git a/src/shared/condition-util.h b/src/shared/condition-util.h
index 44f672b..08aee94 100644
--- a/src/shared/condition-util.h
+++ b/src/shared/condition-util.h
@@ -51,15 +51,14 @@ typedef enum ConditionType {
_CONDITION_TYPE_INVALID = -1
} ConditionType;
-#define CONDITION_STATE_IS_SUCCEEDED(state) ((state) > 0)
-#define CONDITION_STATE_IS_UNKNOWN(state) ((state) == 0)
-#define CONDITION_STATE_IS_FAILED(state) ((state) < 0)
-
-enum {
- CONDITION_STATE_SUCCEEDED = -1,
- CONDITION_STATE_UNKNOWN = 0,
- CONDITION_STATE_FAILED = 1
-};
+typedef enum ConditionResult {
+ CONDITION_UNTESTED,
+ CONDITION_SUCCEEDED,
+ CONDITION_FAILED,
+ CONDITION_ERROR,
+ _CONDITION_RESULT_MAX,
+ _CONDITION_RESULT_INVALID = -1
+} ConditionResult;
typedef struct Condition {
ConditionType type;
@@ -68,7 +67,7 @@ typedef struct Condition {
bool negate:1;
char *parameter;
- int state;
+ ConditionResult result;
LIST_FIELDS(struct Condition, conditions);
} Condition;
@@ -84,3 +83,6 @@ void condition_dump_list(Condition *c, FILE *f, const char *prefix);
const char* condition_type_to_string(ConditionType t) _const_;
int condition_type_from_string(const char *s) _pure_;
+
+const char* condition_result_to_string(ConditionResult r) _const_;
+ConditionResult condition_result_from_string(const char *s) _pure_;
commit b80ba1da1c66f570c10a92a40f54a044fb865739
Author: Lennart Poettering <lennart at poettering.net>
Date: Thu Nov 6 02:11:08 2014 +0100
condition: add more test cases
diff --git a/src/shared/condition-util.c b/src/shared/condition-util.c
index 7569b40..749b577 100644
--- a/src/shared/condition-util.c
+++ b/src/shared/condition-util.c
@@ -45,7 +45,9 @@ Condition* condition_new(ConditionType type, const char *parameter, bool trigger
Condition *c;
int r;
+ assert(type >= 0);
assert(type < _CONDITION_TYPE_MAX);
+ assert(!parameter == (type == CONDITION_NULL));
c = new0(Condition, 1);
if (!c)
@@ -397,7 +399,6 @@ static int condition_test_file_is_executable(Condition *c) {
static int condition_test_null(Condition *c) {
assert(c);
- assert(c->parameter);
assert(c->type == CONDITION_NULL);
/* Note that during parsing we already evaluate the string and
diff --git a/src/test/test-condition-util.c b/src/test/test-condition-util.c
index 4f9ae8a..b69e62b 100644
--- a/src/test/test-condition-util.c
+++ b/src/test/test-condition-util.c
@@ -31,6 +31,18 @@ static void test_condition_test_path_exists(void) {
assert_se(condition_test(condition));
condition_free(condition);
+ condition = condition_new(CONDITION_PATH_EXISTS, "/bin/s?", false, false);
+ assert_se(!condition_test(condition));
+ condition_free(condition);
+
+ condition = condition_new(CONDITION_PATH_EXISTS_GLOB, "/bin/s?", false, false);
+ assert_se(condition_test(condition));
+ condition_free(condition);
+
+ condition = condition_new(CONDITION_PATH_EXISTS_GLOB, "/bin/s?", false, true);
+ assert_se(!condition_test(condition));
+ condition_free(condition);
+
condition = condition_new(CONDITION_PATH_EXISTS, "/thiscertainlywontexist", false, false);
assert_se(!condition_test(condition));
condition_free(condition);
@@ -38,6 +50,38 @@ static void test_condition_test_path_exists(void) {
condition = condition_new(CONDITION_PATH_EXISTS, "/thiscertainlywontexist", false, true);
assert_se(condition_test(condition));
condition_free(condition);
+
+ condition = condition_new(CONDITION_PATH_IS_DIRECTORY, "/bin", false, false);
+ assert_se(condition_test(condition));
+ condition_free(condition);
+
+ condition = condition_new(CONDITION_DIRECTORY_NOT_EMPTY, "/bin", false, false);
+ assert_se(condition_test(condition));
+ condition_free(condition);
+
+ condition = condition_new(CONDITION_FILE_NOT_EMPTY, "/bin/sh", false, false);
+ assert_se(condition_test(condition));
+ condition_free(condition);
+
+ condition = condition_new(CONDITION_FILE_IS_EXECUTABLE, "/bin/sh", false, false);
+ assert_se(condition_test(condition));
+ condition_free(condition);
+
+ condition = condition_new(CONDITION_FILE_IS_EXECUTABLE, "/etc/passwd", false, false);
+ assert_se(!condition_test(condition));
+ condition_free(condition);
+
+ condition = condition_new(CONDITION_PATH_IS_MOUNT_POINT, "/proc", false, false);
+ assert_se(condition_test(condition));
+ condition_free(condition);
+
+ condition = condition_new(CONDITION_PATH_IS_MOUNT_POINT, "/", false, false);
+ assert_se(condition_test(condition));
+ condition_free(condition);
+
+ condition = condition_new(CONDITION_PATH_IS_MOUNT_POINT, "/bin", false, false);
+ assert_se(!condition_test(condition));
+ condition_free(condition);
}
static void test_condition_test_ac_power(void) {
@@ -123,6 +167,18 @@ static void test_condition_test_kernel_command_line(void) {
condition_free(condition);
}
+static void test_condition_test_null(void) {
+ Condition *condition;
+
+ condition = condition_new(CONDITION_NULL, NULL, false, false);
+ assert_se(condition_test(condition));
+ condition_free(condition);
+
+ condition = condition_new(CONDITION_NULL, NULL, false, true);
+ assert_se(!condition_test(condition));
+ condition_free(condition);
+}
+
int main(int argc, char *argv[]) {
log_parse_environment();
log_open();
@@ -132,6 +188,7 @@ int main(int argc, char *argv[]) {
test_condition_test_host();
test_condition_test_architecture();
test_condition_test_kernel_command_line();
+ test_condition_test_null();
return 0;
}
commit 124aff6251c095367ce1323a21fa23235cbb0490
Author: Lennart Poettering <lennart at poettering.net>
Date: Thu Nov 6 02:10:56 2014 +0100
journal: adjust audit log messages a bit
diff --git a/src/journal/journald-audit.c b/src/journal/journald-audit.c
index f543732..341d748 100644
--- a/src/journal/journald-audit.c
+++ b/src/journal/journald-audit.c
@@ -396,8 +396,8 @@ static void process_audit_string(Server *s, int type, const char *data, size_t s
sprintf(id_field, "_AUDIT_ID=%" PRIu64, id);
IOVEC_SET_STRING(iov[n_iov++], id_field);
- m = alloca(strlen("MESSAGE=audit-") + DECIMAL_STR_MAX(int) + strlen(": ") + strlen(p) + 1);
- sprintf(m, "MESSAGE=audit-%i: %s", type, p);
+ m = alloca(strlen("MESSAGE=<audit-") + DECIMAL_STR_MAX(int) + strlen("> ") + strlen(p) + 1);
+ sprintf(m, "MESSAGE=<audit-%i> %s", type, p);
IOVEC_SET_STRING(iov[n_iov++], m);
z = n_iov;
commit a4705396adbf1a8a3e52ed133d9b1f12cb13e77e
Author: Lennart Poettering <lennart at poettering.net>
Date: Thu Nov 6 02:02:13 2014 +0100
condition: internalize condition test functions
Also, implement the negation check inside of condition_test() instead of
individually in each test function.
diff --git a/Makefile.am b/Makefile.am
index 452f07c..c5667c3 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -3488,7 +3488,8 @@ systemd_udevd_SOURCES = \
src/udev/udevd.c
systemd_udevd_LDADD = \
- libudev-core.la
+ libudev-core.la \
+ libsystemd-capability.la
udevadm_SOURCES = \
src/udev/udevadm.c \
@@ -3502,7 +3503,8 @@ udevadm_SOURCES = \
src/udev/udevadm-test-builtin.c
udevadm_LDADD = \
- libudev-core.la
+ libudev-core.la \
+ libsystemd-capability.la
# Update hwdb on installation. Do not bother if installing
# in DESTDIR, since this is likely for packaging purposes.
@@ -3536,7 +3538,8 @@ test_udev_SOURCES = \
src/test/test-udev.c
test_udev_LDADD = \
- libudev-core.la \
+ libudev-core.la \
+ libsystemd-capability.la \
$(BLKID_LIBS) \
$(KMOD_LIBS) \
$(SELINUX_LIBS)
@@ -5210,11 +5213,9 @@ networkctl_LDADD = \
test_network_SOURCES = \
src/network/test-network.c
-test_network_CFLAGS = \
- $(AM_CFLAGS)
-
test_network_LDADD = \
- libsystemd-networkd-core.la
+ libsystemd-networkd-core.la \
+ libsystemd-capability.la
test_network_tables_SOURCES = \
src/network/test-network-tables.c \
diff --git a/src/libsystemd-network/network-internal.c b/src/libsystemd-network/network-internal.c
index 372f3ed..6f16050 100644
--- a/src/libsystemd-network/network-internal.c
+++ b/src/libsystemd-network/network-internal.c
@@ -98,16 +98,16 @@ bool net_match_config(const struct ether_addr *match_mac,
const char *dev_type,
const char *dev_name) {
- if (match_host && !condition_test_host(match_host))
+ if (match_host && !condition_test(match_host))
return 0;
- if (match_virt && !condition_test_virtualization(match_virt))
+ if (match_virt && !condition_test(match_virt))
return 0;
- if (match_kernel && !condition_test_kernel_command_line(match_kernel))
+ if (match_kernel && !condition_test(match_kernel))
return 0;
- if (match_arch && !condition_test_architecture(match_arch))
+ if (match_arch && !condition_test(match_arch))
return 0;
if (match_mac && (!dev_mac || memcmp(match_mac, dev_mac, ETH_ALEN)))
diff --git a/src/shared/condition-util.c b/src/shared/condition-util.c
index ab889e3..7569b40 100644
--- a/src/shared/condition-util.c
+++ b/src/shared/condition-util.c
@@ -78,7 +78,7 @@ void condition_free_list(Condition *first) {
condition_free(c);
}
-int condition_test_kernel_command_line(Condition *c) {
+static int condition_test_kernel_command_line(Condition *c) {
_cleanup_free_ char *line = NULL;
const char *p;
bool equal;
@@ -92,7 +92,7 @@ int condition_test_kernel_command_line(Condition *c) {
if (r < 0)
return r;
if (r == 0)
- return c->negate;
+ return false;
equal = !!strchr(c->parameter, '=');
p = line;
@@ -105,7 +105,7 @@ int condition_test_kernel_command_line(Condition *c) {
if (r < 0)
return r;
if (r == 0)
- return c->negate;
+ break;
if (equal)
found = streq(word, c->parameter);
@@ -117,13 +117,13 @@ int condition_test_kernel_command_line(Condition *c) {
}
if (found)
- return !c->negate;
+ return true;
}
- return c->negate;
+ return false;
}
-int condition_test_virtualization(Condition *c) {
+static int condition_test_virtualization(Condition *c) {
int b, v;
const char *id;
@@ -139,23 +139,23 @@ int condition_test_virtualization(Condition *c) {
b = parse_boolean(c->parameter);
if (v > 0 && b > 0)
- return !c->negate;
+ return true;
if (v == 0 && b == 0)
- return !c->negate;
+ return true;
/* Then, compare categorization */
if (v == VIRTUALIZATION_VM && streq(c->parameter, "vm"))
- return !c->negate;
+ return true;
if (v == VIRTUALIZATION_CONTAINER && streq(c->parameter, "container"))
- return !c->negate;
+ return true;
/* Finally compare id */
- return (v > 0 && streq(c->parameter, id)) == !c->negate;
+ return v > 0 && streq(c->parameter, id);
}
-int condition_test_architecture(Condition *c) {
+static int condition_test_architecture(Condition *c) {
int a, b;
assert(c);
@@ -173,10 +173,10 @@ int condition_test_architecture(Condition *c) {
if (b < 0)
return b;
- return (a == b) == !c->negate;
+ return a == b;
}
-int condition_test_host(Condition *c) {
+static int condition_test_host(Condition *c) {
_cleanup_free_ char *h = NULL;
sd_id128_t x, y;
int r;
@@ -191,17 +191,17 @@ int condition_test_host(Condition *c) {
if (r < 0)
return r;
- return sd_id128_equal(x, y) == !c->negate;
+ return sd_id128_equal(x, y);
}
h = gethostname_malloc();
if (!h)
return -ENOMEM;
- return (fnmatch(c->parameter, h, FNM_CASEFOLD) == 0) == !c->negate;
+ return fnmatch(c->parameter, h, FNM_CASEFOLD) == 0;
}
-int condition_test_ac_power(Condition *c) {
+static int condition_test_ac_power(Condition *c) {
int r;
assert(c);
@@ -212,7 +212,7 @@ int condition_test_ac_power(Condition *c) {
if (r < 0)
return r;
- return ((on_ac_power() != 0) == !!r) == !c->negate;
+ return (on_ac_power() != 0) == !!r;
}
static int condition_test_security(Condition *c) {
@@ -221,17 +221,17 @@ static int condition_test_security(Condition *c) {
assert(c->type == CONDITION_SECURITY);
if (streq(c->parameter, "selinux"))
- return mac_selinux_use() == !c->negate;
+ return mac_selinux_use();
if (streq(c->parameter, "smack"))
- return mac_smack_use() == !c->negate;
+ return mac_smack_use();
if (streq(c->parameter, "apparmor"))
- return mac_apparmor_use() == !c->negate;
+ return mac_apparmor_use();
if (streq(c->parameter, "audit"))
- return use_audit() == !c->negate;
+ return use_audit();
if (streq(c->parameter, "ima"))
- return use_ima() == !c->negate;
+ return use_ima();
- return c->negate;
+ return false;
}
static int condition_test_capability(Condition *c) {
@@ -265,7 +265,7 @@ static int condition_test_capability(Condition *c) {
}
}
- return !!(capabilities & (1ULL << value)) == !c->negate;
+ return !!(capabilities & (1ULL << value));
}
static int condition_test_needs_update(Condition *c) {
@@ -278,24 +278,24 @@ static int condition_test_needs_update(Condition *c) {
/* If the file system is read-only we shouldn't suggest an update */
if (path_is_read_only_fs(c->parameter) > 0)
- return c->negate;
+ return false;
/* Any other failure means we should allow the condition to be true,
* so that we rather invoke too many update tools then too
* few. */
if (!path_is_absolute(c->parameter))
- return !c->negate;
+ return true;
p = strappenda(c->parameter, "/.updated");
if (lstat(p, &other) < 0)
- return !c->negate;
+ return true;
if (lstat("/usr/", &usr) < 0)
- return !c->negate;
+ return true;
- return (usr.st_mtim.tv_sec > other.st_mtim.tv_sec ||
- (usr.st_mtim.tv_sec == other.st_mtim.tv_sec && usr.st_mtim.tv_nsec > other.st_mtim.tv_nsec)) == !c->negate;
+ return usr.st_mtim.tv_sec > other.st_mtim.tv_sec ||
+ (usr.st_mtim.tv_sec == other.st_mtim.tv_sec && usr.st_mtim.tv_nsec > other.st_mtim.tv_nsec);
}
static int condition_test_first_boot(Condition *c) {
@@ -309,7 +309,7 @@ static int condition_test_first_boot(Condition *c) {
if (r < 0)
return r;
- return ((access("/run/systemd/first-boot", F_OK) >= 0) == !!r) == !c->negate;
+ return (access("/run/systemd/first-boot", F_OK) >= 0) == !!r;
}
static int condition_test_path_exists(Condition *c) {
@@ -317,7 +317,7 @@ static int condition_test_path_exists(Condition *c) {
assert(c->parameter);
assert(c->type == CONDITION_PATH_EXISTS);
- return (access(c->parameter, F_OK) >= 0) == !c->negate;
+ return access(c->parameter, F_OK) >= 0;
}
static int condition_test_path_exists_glob(Condition *c) {
@@ -325,7 +325,7 @@ static int condition_test_path_exists_glob(Condition *c) {
assert(c->parameter);
assert(c->type == CONDITION_PATH_EXISTS_GLOB);
- return (glob_exists(c->parameter) > 0) == !c->negate;
+ return glob_exists(c->parameter) > 0;
}
static int condition_test_path_is_directory(Condition *c) {
@@ -333,7 +333,7 @@ static int condition_test_path_is_directory(Condition *c) {
assert(c->parameter);
assert(c->type == CONDITION_PATH_IS_DIRECTORY);
- return (is_dir(c->parameter, true) > 0) == !c->negate;
+ return is_dir(c->parameter, true) > 0;
}
static int condition_test_path_is_symbolic_link(Condition *c) {
@@ -341,7 +341,7 @@ static int condition_test_path_is_symbolic_link(Condition *c) {
assert(c->parameter);
assert(c->type == CONDITION_PATH_IS_SYMBOLIC_LINK);
- return (is_symlink(c->parameter) > 0) == !c->negate;
+ return is_symlink(c->parameter) > 0;
}
static int condition_test_path_is_mount_point(Condition *c) {
@@ -349,7 +349,7 @@ static int condition_test_path_is_mount_point(Condition *c) {
assert(c->parameter);
assert(c->type == CONDITION_PATH_IS_MOUNT_POINT);
- return (path_is_mount_point(c->parameter, true) > 0) == !c->negate;
+ return path_is_mount_point(c->parameter, true) > 0;
}
static int condition_test_path_is_read_write(Condition *c) {
@@ -357,7 +357,7 @@ static int condition_test_path_is_read_write(Condition *c) {
assert(c->parameter);
assert(c->type == CONDITION_PATH_IS_READ_WRITE);
- return (path_is_read_only_fs(c->parameter) > 0) == c->negate;
+ return path_is_read_only_fs(c->parameter) <= 0;
}
static int condition_test_directory_not_empty(Condition *c) {
@@ -368,7 +368,7 @@ static int condition_test_directory_not_empty(Condition *c) {
assert(c->type == CONDITION_DIRECTORY_NOT_EMPTY);
r = dir_is_empty(c->parameter);
- return !(r == -ENOENT || r > 0) == !c->negate;
+ return r <= 0 && r != -ENOENT;
}
static int condition_test_file_not_empty(Condition *c) {
@@ -380,7 +380,7 @@ static int condition_test_file_not_empty(Condition *c) {
return (stat(c->parameter, &st) >= 0 &&
S_ISREG(st.st_mode) &&
- st.st_size > 0) == !c->negate;
+ st.st_size > 0);
}
static int condition_test_file_is_executable(Condition *c) {
@@ -392,7 +392,7 @@ static int condition_test_file_is_executable(Condition *c) {
return (stat(c->parameter, &st) >= 0 &&
S_ISREG(st.st_mode) &&
- (st.st_mode & 0111)) == !c->negate;
+ (st.st_mode & 0111));
}
static int condition_test_null(Condition *c) {
@@ -402,7 +402,7 @@ static int condition_test_null(Condition *c) {
/* Note that during parsing we already evaluate the string and
* store it in c->negate */
- return !c->negate;
+ return true;
}
int condition_test(Condition *c) {
@@ -428,12 +428,17 @@ int condition_test(Condition *c) {
[CONDITION_FIRST_BOOT] = condition_test_first_boot,
[CONDITION_NULL] = condition_test_null,
};
+ int r;
assert(c);
assert(c->type >= 0);
assert(c->type < _CONDITION_TYPE_MAX);
- return condition_tests[c->type](c);
+ r = condition_tests[c->type](c);
+ if (r < 0)
+ return r;
+
+ return (r > 0) == !c->negate;
}
void condition_dump(Condition *c, FILE *f, const char *prefix) {
diff --git a/src/shared/condition-util.h b/src/shared/condition-util.h
index deeb6b4..44f672b 100644
--- a/src/shared/condition-util.h
+++ b/src/shared/condition-util.h
@@ -77,12 +77,6 @@ Condition* condition_new(ConditionType type, const char *parameter, bool trigger
void condition_free(Condition *c);
void condition_free_list(Condition *c);
-int condition_test_kernel_command_line(Condition *c);
-int condition_test_virtualization(Condition *c);
-int condition_test_architecture(Condition *c);
-int condition_test_host(Condition *c);
-int condition_test_ac_power(Condition *c);
-
int condition_test(Condition *c);
void condition_dump(Condition *c, FILE *f, const char *prefix);
commit d1bddcec98551ea748f39a742a4cbcf9ea9254ef
Author: Lennart Poettering <lennart at poettering.net>
Date: Thu Nov 6 01:40:37 2014 +0100
condition: unify condition logic in one file
diff --git a/Makefile.am b/Makefile.am
index f614b86..452f07c 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -1524,8 +1524,9 @@ test_condition_util_SOURCES = \
test_condition_util_LDADD = \
libsystemd-shared.la \
- libsystemd-internal.la
-
+ libsystemd-internal.la \
+ libsystemd-capability.la \
+ libsystemd-label.la
test_fdset_SOURCES = \
src/test/test-fdset.c
diff --git a/src/core/condition.c b/src/core/condition.c
index 32135ec..d8d1152 100644
--- a/src/core/condition.c
+++ b/src/core/condition.c
@@ -19,216 +19,8 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
-#include <stdlib.h>
-#include <errno.h>
-#include <string.h>
-#include <unistd.h>
-#include <sys/capability.h>
-#include <sys/statvfs.h>
-#include <fnmatch.h>
-
-#include "sd-id128.h"
-#include "util.h"
#include "condition.h"
-#include "virt.h"
-#include "path-util.h"
-#include "fileio.h"
#include "unit.h"
-#include "smack-util.h"
-#include "apparmor-util.h"
-#include "ima-util.h"
-#include "selinux-util.h"
-#include "audit.h"
-
-static int condition_test_security(Condition *c) {
- assert(c);
- assert(c->parameter);
- assert(c->type == CONDITION_SECURITY);
-
- if (streq(c->parameter, "selinux"))
- return mac_selinux_use() == !c->negate;
- if (streq(c->parameter, "smack"))
- return mac_smack_use() == !c->negate;
- if (streq(c->parameter, "apparmor"))
- return mac_apparmor_use() == !c->negate;
- if (streq(c->parameter, "audit"))
- return use_audit() == !c->negate;
- if (streq(c->parameter, "ima"))
- return use_ima() == !c->negate;
-
- return c->negate;
-}
-
-static int condition_test_capability(Condition *c) {
- _cleanup_fclose_ FILE *f = NULL;
- cap_value_t value;
- char line[LINE_MAX];
- unsigned long long capabilities = -1;
-
- assert(c);
- assert(c->parameter);
- assert(c->type == CONDITION_CAPABILITY);
-
- /* If it's an invalid capability, we don't have it */
-
- if (cap_from_name(c->parameter, &value) < 0)
- return -EINVAL;
-
- /* If it's a valid capability we default to assume
- * that we have it */
-
- f = fopen("/proc/self/status", "re");
- if (!f)
- return -errno;
-
- while (fgets(line, sizeof(line), f)) {
- truncate_nl(line);
-
- if (startswith(line, "CapBnd:")) {
- (void) sscanf(line+7, "%llx", &capabilities);
- break;
- }
- }
-
- return !!(capabilities & (1ULL << value)) == !c->negate;
-}
-
-static bool condition_test_needs_update(Condition *c) {
- const char *p;
- struct stat usr, other;
-
- assert(c);
- assert(c->parameter);
- assert(c->type == CONDITION_NEEDS_UPDATE);
-
- /* If the file system is read-only we shouldn't suggest an update */
- if (path_is_read_only_fs(c->parameter) > 0)
- return c->negate;
-
- /* Any other failure means we should allow the condition to be true,
- * so that we rather invoke too many update tools then too
- * few. */
-
- if (!path_is_absolute(c->parameter))
- return !c->negate;
-
- p = strappenda(c->parameter, "/.updated");
- if (lstat(p, &other) < 0)
- return !c->negate;
-
- if (lstat("/usr/", &usr) < 0)
- return !c->negate;
-
- return (usr.st_mtim.tv_sec > other.st_mtim.tv_sec ||
- (usr.st_mtim.tv_sec == other.st_mtim.tv_sec && usr.st_mtim.tv_nsec > other.st_mtim.tv_nsec)) == !c->negate;
-}
-
-static bool condition_test_first_boot(Condition *c) {
- int r;
-
- assert(c);
- assert(c->parameter);
- assert(c->type == CONDITION_FIRST_BOOT);
-
- r = parse_boolean(c->parameter);
- if (r < 0)
- return r;
-
- return ((access("/run/systemd/first-boot", F_OK) >= 0) == !!r) == !c->negate;
-}
-
-static int condition_test(Condition *c) {
- assert(c);
-
- switch(c->type) {
-
- case CONDITION_PATH_EXISTS:
- return (access(c->parameter, F_OK) >= 0) == !c->negate;
-
- case CONDITION_PATH_EXISTS_GLOB:
- return (glob_exists(c->parameter) > 0) == !c->negate;
-
- case CONDITION_PATH_IS_DIRECTORY: {
- struct stat st;
-
- if (stat(c->parameter, &st) < 0)
- return c->negate;
- return S_ISDIR(st.st_mode) == !c->negate;
- }
-
- case CONDITION_PATH_IS_SYMBOLIC_LINK: {
- struct stat st;
-
- if (lstat(c->parameter, &st) < 0)
- return c->negate;
- return S_ISLNK(st.st_mode) == !c->negate;
- }
-
- case CONDITION_PATH_IS_MOUNT_POINT:
- return (path_is_mount_point(c->parameter, true) > 0) == !c->negate;
-
- case CONDITION_PATH_IS_READ_WRITE:
- return (path_is_read_only_fs(c->parameter) > 0) == c->negate;
-
- case CONDITION_DIRECTORY_NOT_EMPTY: {
- int k;
-
- k = dir_is_empty(c->parameter);
- return !(k == -ENOENT || k > 0) == !c->negate;
- }
-
- case CONDITION_FILE_NOT_EMPTY: {
- struct stat st;
-
- if (stat(c->parameter, &st) < 0)
- return c->negate;
-
- return (S_ISREG(st.st_mode) && st.st_size > 0) == !c->negate;
- }
-
- case CONDITION_FILE_IS_EXECUTABLE: {
- struct stat st;
-
- if (stat(c->parameter, &st) < 0)
- return c->negate;
-
- return (S_ISREG(st.st_mode) && (st.st_mode & 0111)) == !c->negate;
- }
-
- case CONDITION_KERNEL_COMMAND_LINE:
- return condition_test_kernel_command_line(c);
-
- case CONDITION_VIRTUALIZATION:
- return condition_test_virtualization(c);
-
- case CONDITION_SECURITY:
- return condition_test_security(c);
-
- case CONDITION_CAPABILITY:
- return condition_test_capability(c);
-
- case CONDITION_HOST:
- return condition_test_host(c);
-
- case CONDITION_AC_POWER:
- return condition_test_ac_power(c);
-
- case CONDITION_ARCHITECTURE:
- return condition_test_architecture(c);
-
- case CONDITION_NEEDS_UPDATE:
- return condition_test_needs_update(c);
-
- case CONDITION_FIRST_BOOT:
- return condition_test_first_boot(c);
-
- case CONDITION_NULL:
- return !c->negate;
-
- default:
- assert_not_reached("Invalid condition type.");
- }
-}
bool condition_test_list(const char *unit, Condition *first) {
Condition *c;
diff --git a/src/shared/condition-util.c b/src/shared/condition-util.c
index 33752c8..ab889e3 100644
--- a/src/shared/condition-util.c
+++ b/src/shared/condition-util.c
@@ -26,7 +26,7 @@
#include <sys/statvfs.h>
#include <fnmatch.h>
-#include "systemd/sd-id128.h"
+#include "sd-id128.h"
#include "util.h"
#include "condition-util.h"
#include "virt.h"
@@ -34,9 +34,16 @@
#include "fileio.h"
#include "unit.h"
#include "architecture.h"
+#include "virt.h"
+#include "smack-util.h"
+#include "apparmor-util.h"
+#include "ima-util.h"
+#include "selinux-util.h"
+#include "audit.h"
Condition* condition_new(ConditionType type, const char *parameter, bool trigger, bool negate) {
Condition *c;
+ int r;
assert(type < _CONDITION_TYPE_MAX);
@@ -48,12 +55,10 @@ Condition* condition_new(ConditionType type, const char *parameter, bool trigger
c->trigger = trigger;
c->negate = negate;
- if (parameter) {
- c->parameter = strdup(parameter);
- if (!c->parameter) {
- free(c);
- return NULL;
- }
+ r = free_and_strdup(&c->parameter, parameter);
+ if (r < 0) {
+ free(c);
+ return NULL;
}
return c;
@@ -210,6 +215,227 @@ int condition_test_ac_power(Condition *c) {
return ((on_ac_power() != 0) == !!r) == !c->negate;
}
+static int condition_test_security(Condition *c) {
+ assert(c);
+ assert(c->parameter);
+ assert(c->type == CONDITION_SECURITY);
+
+ if (streq(c->parameter, "selinux"))
+ return mac_selinux_use() == !c->negate;
+ if (streq(c->parameter, "smack"))
+ return mac_smack_use() == !c->negate;
+ if (streq(c->parameter, "apparmor"))
+ return mac_apparmor_use() == !c->negate;
+ if (streq(c->parameter, "audit"))
+ return use_audit() == !c->negate;
+ if (streq(c->parameter, "ima"))
+ return use_ima() == !c->negate;
+
+ return c->negate;
+}
+
+static int condition_test_capability(Condition *c) {
+ _cleanup_fclose_ FILE *f = NULL;
+ cap_value_t value;
+ char line[LINE_MAX];
+ unsigned long long capabilities = -1;
+
+ assert(c);
+ assert(c->parameter);
+ assert(c->type == CONDITION_CAPABILITY);
+
+ /* If it's an invalid capability, we don't have it */
+
+ if (cap_from_name(c->parameter, &value) < 0)
+ return -EINVAL;
+
+ /* If it's a valid capability we default to assume
+ * that we have it */
+
+ f = fopen("/proc/self/status", "re");
+ if (!f)
+ return -errno;
+
+ while (fgets(line, sizeof(line), f)) {
+ truncate_nl(line);
+
+ if (startswith(line, "CapBnd:")) {
+ (void) sscanf(line+7, "%llx", &capabilities);
+ break;
+ }
+ }
+
+ return !!(capabilities & (1ULL << value)) == !c->negate;
+}
+
+static int condition_test_needs_update(Condition *c) {
+ const char *p;
+ struct stat usr, other;
+
+ assert(c);
+ assert(c->parameter);
+ assert(c->type == CONDITION_NEEDS_UPDATE);
+
+ /* If the file system is read-only we shouldn't suggest an update */
+ if (path_is_read_only_fs(c->parameter) > 0)
+ return c->negate;
+
+ /* Any other failure means we should allow the condition to be true,
+ * so that we rather invoke too many update tools then too
+ * few. */
+
+ if (!path_is_absolute(c->parameter))
+ return !c->negate;
+
+ p = strappenda(c->parameter, "/.updated");
+ if (lstat(p, &other) < 0)
+ return !c->negate;
+
+ if (lstat("/usr/", &usr) < 0)
+ return !c->negate;
+
+ return (usr.st_mtim.tv_sec > other.st_mtim.tv_sec ||
+ (usr.st_mtim.tv_sec == other.st_mtim.tv_sec && usr.st_mtim.tv_nsec > other.st_mtim.tv_nsec)) == !c->negate;
+}
+
+static int condition_test_first_boot(Condition *c) {
+ int r;
+
+ assert(c);
+ assert(c->parameter);
+ assert(c->type == CONDITION_FIRST_BOOT);
+
+ r = parse_boolean(c->parameter);
+ if (r < 0)
+ return r;
+
+ return ((access("/run/systemd/first-boot", F_OK) >= 0) == !!r) == !c->negate;
+}
+
+static int condition_test_path_exists(Condition *c) {
+ assert(c);
+ assert(c->parameter);
+ assert(c->type == CONDITION_PATH_EXISTS);
+
+ return (access(c->parameter, F_OK) >= 0) == !c->negate;
+}
+
+static int condition_test_path_exists_glob(Condition *c) {
+ assert(c);
+ assert(c->parameter);
+ assert(c->type == CONDITION_PATH_EXISTS_GLOB);
+
+ return (glob_exists(c->parameter) > 0) == !c->negate;
+}
+
+static int condition_test_path_is_directory(Condition *c) {
+ assert(c);
+ assert(c->parameter);
+ assert(c->type == CONDITION_PATH_IS_DIRECTORY);
+
+ return (is_dir(c->parameter, true) > 0) == !c->negate;
+}
+
+static int condition_test_path_is_symbolic_link(Condition *c) {
+ assert(c);
+ assert(c->parameter);
+ assert(c->type == CONDITION_PATH_IS_SYMBOLIC_LINK);
+
+ return (is_symlink(c->parameter) > 0) == !c->negate;
+}
+
+static int condition_test_path_is_mount_point(Condition *c) {
+ assert(c);
+ assert(c->parameter);
+ assert(c->type == CONDITION_PATH_IS_MOUNT_POINT);
+
+ return (path_is_mount_point(c->parameter, true) > 0) == !c->negate;
+}
+
+static int condition_test_path_is_read_write(Condition *c) {
+ assert(c);
+ assert(c->parameter);
+ assert(c->type == CONDITION_PATH_IS_READ_WRITE);
+
+ return (path_is_read_only_fs(c->parameter) > 0) == c->negate;
+}
+
+static int condition_test_directory_not_empty(Condition *c) {
+ int r;
+
+ assert(c);
+ assert(c->parameter);
+ assert(c->type == CONDITION_DIRECTORY_NOT_EMPTY);
+
+ r = dir_is_empty(c->parameter);
+ return !(r == -ENOENT || r > 0) == !c->negate;
+}
+
+static int condition_test_file_not_empty(Condition *c) {
+ struct stat st;
+
+ assert(c);
+ assert(c->parameter);
+ assert(c->type == CONDITION_FILE_NOT_EMPTY);
+
+ return (stat(c->parameter, &st) >= 0 &&
+ S_ISREG(st.st_mode) &&
+ st.st_size > 0) == !c->negate;
+}
+
+static int condition_test_file_is_executable(Condition *c) {
+ struct stat st;
+
+ assert(c);
+ assert(c->parameter);
+ assert(c->type == CONDITION_FILE_IS_EXECUTABLE);
+
+ return (stat(c->parameter, &st) >= 0 &&
+ S_ISREG(st.st_mode) &&
+ (st.st_mode & 0111)) == !c->negate;
+}
+
+static int condition_test_null(Condition *c) {
+ assert(c);
+ assert(c->parameter);
+ assert(c->type == CONDITION_NULL);
+
+ /* Note that during parsing we already evaluate the string and
+ * store it in c->negate */
+ return !c->negate;
+}
+
+int condition_test(Condition *c) {
+
+ static int (*const condition_tests[_CONDITION_TYPE_MAX])(Condition *c) = {
+ [CONDITION_PATH_EXISTS] = condition_test_path_exists,
+ [CONDITION_PATH_EXISTS_GLOB] = condition_test_path_exists_glob,
+ [CONDITION_PATH_IS_DIRECTORY] = condition_test_path_is_directory,
+ [CONDITION_PATH_IS_SYMBOLIC_LINK] = condition_test_path_is_symbolic_link,
+ [CONDITION_PATH_IS_MOUNT_POINT] = condition_test_path_is_mount_point,
+ [CONDITION_PATH_IS_READ_WRITE] = condition_test_path_is_read_write,
+ [CONDITION_DIRECTORY_NOT_EMPTY] = condition_test_directory_not_empty,
+ [CONDITION_FILE_NOT_EMPTY] = condition_test_file_not_empty,
+ [CONDITION_FILE_IS_EXECUTABLE] = condition_test_file_is_executable,
+ [CONDITION_KERNEL_COMMAND_LINE] = condition_test_kernel_command_line,
+ [CONDITION_VIRTUALIZATION] = condition_test_virtualization,
+ [CONDITION_SECURITY] = condition_test_security,
+ [CONDITION_CAPABILITY] = condition_test_capability,
+ [CONDITION_HOST] = condition_test_host,
+ [CONDITION_AC_POWER] = condition_test_ac_power,
+ [CONDITION_ARCHITECTURE] = condition_test_architecture,
+ [CONDITION_NEEDS_UPDATE] = condition_test_needs_update,
+ [CONDITION_FIRST_BOOT] = condition_test_first_boot,
+ [CONDITION_NULL] = condition_test_null,
+ };
+
+ assert(c);
+ assert(c->type >= 0);
+ assert(c->type < _CONDITION_TYPE_MAX);
+
+ return condition_tests[c->type](c);
+}
+
void condition_dump(Condition *c, FILE *f, const char *prefix) {
assert(c);
assert(f);
diff --git a/src/shared/condition-util.h b/src/shared/condition-util.h
index fbb8150..deeb6b4 100644
--- a/src/shared/condition-util.h
+++ b/src/shared/condition-util.h
@@ -83,6 +83,8 @@ int condition_test_architecture(Condition *c);
int condition_test_host(Condition *c);
int condition_test_ac_power(Condition *c);
+int condition_test(Condition *c);
+
void condition_dump(Condition *c, FILE *f, const char *prefix);
void condition_dump_list(Condition *c, FILE *f, const char *prefix);
diff --git a/src/shared/util.c b/src/shared/util.c
index d33f349..39ce46a 100644
--- a/src/shared/util.c
+++ b/src/shared/util.c
@@ -6987,14 +6987,14 @@ int is_symlink(const char *path) {
int is_dir(const char* path, bool follow) {
struct stat st;
+ int r;
- if (follow) {
- if (stat(path, &st) < 0)
- return -errno;
- } else {
- if (lstat(path, &st) < 0)
- return -errno;
- }
+ if (follow)
+ r = stat(path, &st);
+ else
+ r = lstat(path, &st);
+ if (r < 0)
+ return -errno;
return !!S_ISDIR(st.st_mode);
}
diff --git a/src/test/test-condition-util.c b/src/test/test-condition-util.c
index 7a247fb..4f9ae8a 100644
--- a/src/test/test-condition-util.c
+++ b/src/test/test-condition-util.c
@@ -22,21 +22,37 @@
#include "util.h"
#include "log.h"
#include "architecture.h"
-#include "systemd/sd-id128.h"
+#include "sd-id128.h"
+
+static void test_condition_test_path_exists(void) {
+ Condition *condition;
+
+ condition = condition_new(CONDITION_PATH_EXISTS, "/bin/sh", false, false);
+ assert_se(condition_test(condition));
+ condition_free(condition);
+
+ condition = condition_new(CONDITION_PATH_EXISTS, "/thiscertainlywontexist", false, false);
+ assert_se(!condition_test(condition));
+ condition_free(condition);
+
+ condition = condition_new(CONDITION_PATH_EXISTS, "/thiscertainlywontexist", false, true);
+ assert_se(condition_test(condition));
+ condition_free(condition);
+}
static void test_condition_test_ac_power(void) {
Condition *condition;
condition = condition_new(CONDITION_AC_POWER, "true", false, false);
- assert_se(condition_test_ac_power(condition) == on_ac_power());
+ assert_se(condition_test(condition) == on_ac_power());
condition_free(condition);
condition = condition_new(CONDITION_AC_POWER, "false", false, false);
- assert_se(condition_test_ac_power(condition) != on_ac_power());
+ assert_se(condition_test(condition) != on_ac_power());
condition_free(condition);
condition = condition_new(CONDITION_AC_POWER, "false", false, true);
- assert_se(condition_test_ac_power(condition) == on_ac_power());
+ assert_se(condition_test(condition) == on_ac_power());
condition_free(condition);
}
@@ -52,22 +68,22 @@ static void test_condition_test_host(void) {
assert_se(sd_id128_to_string(id, sid));
condition = condition_new(CONDITION_HOST, sid, false, false);
- assert_se(condition_test_host(condition));
+ assert_se(condition_test(condition));
condition_free(condition);
condition = condition_new(CONDITION_HOST, "garbage value jjjjjjjjjjjjjj", false, false);
- assert_se(!condition_test_host(condition));
+ assert_se(!condition_test(condition));
condition_free(condition);
condition = condition_new(CONDITION_HOST, sid, false, true);
- assert_se(!condition_test_host(condition));
+ assert_se(!condition_test(condition));
condition_free(condition);
hostname = gethostname_malloc();
assert_se(hostname);
condition = condition_new(CONDITION_HOST, hostname, false, false);
- assert_se(condition_test_host(condition));
+ assert_se(condition_test(condition));
condition_free(condition);
}
@@ -83,15 +99,15 @@ static void test_condition_test_architecture(void) {
assert_se(sa);
condition = condition_new(CONDITION_ARCHITECTURE, sa, false, false);
- assert_se(condition_test_architecture(condition));
+ assert_se(condition_test(condition));
condition_free(condition);
condition = condition_new(CONDITION_ARCHITECTURE, "garbage value", false, false);
- assert_se(condition_test_architecture(condition) < 0);
+ assert_se(condition_test(condition) < 0);
condition_free(condition);
condition = condition_new(CONDITION_ARCHITECTURE, sa, false, true);
- assert_se(!condition_test_architecture(condition));
+ assert_se(!condition_test(condition));
condition_free(condition);
}
@@ -99,11 +115,11 @@ static void test_condition_test_kernel_command_line(void) {
Condition *condition;
condition = condition_new(CONDITION_KERNEL_COMMAND_LINE, "thisreallyshouldntbeonthekernelcommandline", false, false);
- assert_se(!condition_test_kernel_command_line(condition));
+ assert_se(!condition_test(condition));
condition_free(condition);
condition = condition_new(CONDITION_KERNEL_COMMAND_LINE, "andthis=neither", false, false);
- assert_se(!condition_test_kernel_command_line(condition));
+ assert_se(!condition_test(condition));
condition_free(condition);
}
@@ -111,6 +127,7 @@ int main(int argc, char *argv[]) {
log_parse_environment();
log_open();
+ test_condition_test_path_exists();
test_condition_test_ac_power();
test_condition_test_host();
test_condition_test_architecture();
commit 592fd144ae313855f48d0ca52a103013b41e5d59
Author: Lennart Poettering <lennart at poettering.net>
Date: Thu Nov 6 00:49:44 2014 +0100
condition: properly allow passing back errors from condition checks
diff --git a/src/core/condition.c b/src/core/condition.c
index 8e2e311..32135ec 100644
--- a/src/core/condition.c
+++ b/src/core/condition.c
@@ -40,7 +40,7 @@
#include "selinux-util.h"
#include "audit.h"
-static bool condition_test_security(Condition *c) {
+static int condition_test_security(Condition *c) {
assert(c);
assert(c->parameter);
assert(c->type == CONDITION_SECURITY);
@@ -59,7 +59,7 @@ static bool condition_test_security(Condition *c) {
return c->negate;
}
-static bool condition_test_capability(Condition *c) {
+static int condition_test_capability(Condition *c) {
_cleanup_fclose_ FILE *f = NULL;
cap_value_t value;
char line[LINE_MAX];
@@ -72,14 +72,14 @@ static bool condition_test_capability(Condition *c) {
/* If it's an invalid capability, we don't have it */
if (cap_from_name(c->parameter, &value) < 0)
- return c->negate;
+ return -EINVAL;
/* If it's a valid capability we default to assume
* that we have it */
f = fopen("/proc/self/status", "re");
if (!f)
- return !c->negate;
+ return -errno;
while (fgets(line, sizeof(line), f)) {
truncate_nl(line);
@@ -132,12 +132,12 @@ static bool condition_test_first_boot(Condition *c) {
r = parse_boolean(c->parameter);
if (r < 0)
- return c->negate;
+ return r;
return ((access("/run/systemd/first-boot", F_OK) >= 0) == !!r) == !c->negate;
}
-static bool condition_test(Condition *c) {
+static int condition_test(Condition *c) {
assert(c);
switch(c->type) {
@@ -242,25 +242,35 @@ bool condition_test_list(const char *unit, Condition *first) {
* 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 (unit)
+ int r;
+
+ r = condition_test(c);
+ if (r < 0)
+ log_warning_unit(unit,
+ "Couldn't determine result for %s=%s%s%s for %s, assuming failed: %s",
+ condition_type_to_string(c->type),
+ c->trigger ? "|" : "",
+ c->negate ? "!" : "",
+ c->parameter,
+ unit,
+ strerror(-r));
+ else
log_debug_unit(unit,
"%s=%s%s%s %s for %s.",
condition_type_to_string(c->type),
c->trigger ? "|" : "",
c->negate ? "!" : "",
c->parameter,
- b ? "succeeded" : "failed",
+ r > 0 ? "succeeded" : "failed",
unit);
- c->state = b ? 1 : -1;
- if (!c->trigger && !b)
+ c->state = r > 0 ? CONDITION_STATE_SUCCEEDED : CONDITION_STATE_FAILED;
+
+ if (!c->trigger && r <= 0)
return false;
if (c->trigger && triggered <= 0)
- triggered = b;
+ triggered = r > 0;
}
return triggered != 0;
diff --git a/src/shared/architecture.c b/src/shared/architecture.c
index dc45f35..34c5a53 100644
--- a/src/shared/architecture.c
+++ b/src/shared/architecture.c
@@ -23,7 +23,7 @@
#include "architecture.h"
-Architecture uname_architecture(void) {
+int uname_architecture(void) {
/* Return a sanitized enum identifying the architecture we are
* running on. This is based on uname(), and the user may
@@ -41,7 +41,7 @@ Architecture uname_architecture(void) {
static const struct {
const char *machine;
- Architecture arch;
+ int arch;
} arch_map[] = {
#if defined(__x86_64__) || defined(__i386__)
{ "x86_64", ARCHITECTURE_X86_64 },
@@ -121,7 +121,7 @@ Architecture uname_architecture(void) {
#endif
};
- static Architecture cached = _ARCHITECTURE_INVALID;
+ static int cached = _ARCHITECTURE_INVALID;
struct utsname u;
unsigned i;
@@ -168,4 +168,4 @@ static const char *const architecture_table[_ARCHITECTURE_MAX] = {
[ARCHITECTURE_CRIS] = "cris",
};
-DEFINE_STRING_TABLE_LOOKUP(architecture, Architecture);
+DEFINE_STRING_TABLE_LOOKUP(architecture, int);
diff --git a/src/shared/architecture.h b/src/shared/architecture.h
index 353d49b..f1fef23 100644
--- a/src/shared/architecture.h
+++ b/src/shared/architecture.h
@@ -30,7 +30,7 @@
* focus on general family, and distuignish word width and
* endianness. */
-typedef enum Architecture {
+enum {
ARCHITECTURE_X86 = 0,
ARCHITECTURE_X86_64,
ARCHITECTURE_PPC,
@@ -60,9 +60,9 @@ typedef enum Architecture {
ARCHITECTURE_CRIS,
_ARCHITECTURE_MAX,
_ARCHITECTURE_INVALID = -1
-} Architecture;
+};
-Architecture uname_architecture(void);
+int uname_architecture(void);
/*
* LIB_ARCH_TUPLE should resolve to the local library path
@@ -188,5 +188,5 @@ Architecture uname_architecture(void);
#error "Please register your architecture here!"
#endif
-const char *architecture_to_string(Architecture a) _const_;
-Architecture architecture_from_string(const char *s) _pure_;
+const char *architecture_to_string(int a) _const_;
+int architecture_from_string(const char *s) _pure_;
diff --git a/src/shared/condition-util.c b/src/shared/condition-util.c
index 026b6a8..33752c8 100644
--- a/src/shared/condition-util.c
+++ b/src/shared/condition-util.c
@@ -73,7 +73,7 @@ void condition_free_list(Condition *first) {
condition_free(c);
}
-bool condition_test_kernel_command_line(Condition *c) {
+int condition_test_kernel_command_line(Condition *c) {
_cleanup_free_ char *line = NULL;
const char *p;
bool equal;
@@ -85,8 +85,8 @@ bool condition_test_kernel_command_line(Condition *c) {
r = proc_cmdline(&line);
if (r < 0)
- log_warning("Failed to read /proc/cmdline, ignoring: %s", strerror(-r));
- if (r <= 0)
+ return r;
+ if (r == 0)
return c->negate;
equal = !!strchr(c->parameter, '=');
@@ -97,7 +97,9 @@ bool condition_test_kernel_command_line(Condition *c) {
bool found;
r = unquote_first_word(&p, &word);
- if (r <= 0)
+ if (r < 0)
+ return r;
+ if (r == 0)
return c->negate;
if (equal)
@@ -116,7 +118,7 @@ bool condition_test_kernel_command_line(Condition *c) {
return c->negate;
}
-bool condition_test_virtualization(Condition *c) {
+int condition_test_virtualization(Condition *c) {
int b, v;
const char *id;
@@ -125,10 +127,8 @@ bool condition_test_virtualization(Condition *c) {
assert(c->type == CONDITION_VIRTUALIZATION);
v = detect_virtualization(&id);
- if (v < 0) {
- log_warning("Failed to detect virtualization, ignoring: %s", strerror(-v));
- return c->negate;
- }
+ if (v < 0)
+ return v;
/* First, compare with yes/no */
b = parse_boolean(c->parameter);
@@ -150,8 +150,8 @@ bool condition_test_virtualization(Condition *c) {
return (v > 0 && streq(c->parameter, id)) == !c->negate;
}
-bool condition_test_architecture(Condition *c) {
- Architecture a, b;
+int condition_test_architecture(Condition *c) {
+ int a, b;
assert(c);
assert(c->parameter);
@@ -159,20 +159,19 @@ bool condition_test_architecture(Condition *c) {
a = uname_architecture();
if (a < 0)
- return c->negate;
+ return a;
if (streq(c->parameter, "native"))
b = native_architecture();
else
b = architecture_from_string(c->parameter);
-
if (b < 0)
- return c->negate;
+ return b;
return (a == b) == !c->negate;
}
-bool condition_test_host(Condition *c) {
+int condition_test_host(Condition *c) {
_cleanup_free_ char *h = NULL;
sd_id128_t x, y;
int r;
@@ -185,19 +184,19 @@ bool condition_test_host(Condition *c) {
r = sd_id128_get_machine(&y);
if (r < 0)
- return c->negate;
+ return r;
return sd_id128_equal(x, y) == !c->negate;
}
h = gethostname_malloc();
if (!h)
- return c->negate;
+ return -ENOMEM;
return (fnmatch(c->parameter, h, FNM_CASEFOLD) == 0) == !c->negate;
}
-bool condition_test_ac_power(Condition *c) {
+int condition_test_ac_power(Condition *c) {
int r;
assert(c);
@@ -206,7 +205,7 @@ bool condition_test_ac_power(Condition *c) {
r = parse_boolean(c->parameter);
if (r < 0)
- return !c->negate;
+ return r;
return ((on_ac_power() != 0) == !!r) == !c->negate;
}
@@ -225,7 +224,7 @@ void condition_dump(Condition *c, FILE *f, const char *prefix) {
c->trigger ? "|" : "",
c->negate ? "!" : "",
c->parameter,
- c->state < 0 ? "failed" : c->state > 0 ? "succeeded" : "untested");
+ CONDITION_STATE_IS_FAILED(c->state) ? "failed" : CONDITION_STATE_IS_SUCCEEDED(c->state) ? "succeeded" : "untested");
}
void condition_dump_list(Condition *first, FILE *f, const char *prefix) {
diff --git a/src/shared/condition-util.h b/src/shared/condition-util.h
index 047fdbf..fbb8150 100644
--- a/src/shared/condition-util.h
+++ b/src/shared/condition-util.h
@@ -51,6 +51,16 @@ typedef enum ConditionType {
_CONDITION_TYPE_INVALID = -1
} ConditionType;
+#define CONDITION_STATE_IS_SUCCEEDED(state) ((state) > 0)
+#define CONDITION_STATE_IS_UNKNOWN(state) ((state) == 0)
+#define CONDITION_STATE_IS_FAILED(state) ((state) < 0)
+
+enum {
+ CONDITION_STATE_SUCCEEDED = -1,
+ CONDITION_STATE_UNKNOWN = 0,
+ CONDITION_STATE_FAILED = 1
+};
+
typedef struct Condition {
ConditionType type;
@@ -58,7 +68,6 @@ typedef struct Condition {
bool negate:1;
char *parameter;
-
int state;
LIST_FIELDS(struct Condition, conditions);
@@ -68,11 +77,11 @@ Condition* condition_new(ConditionType type, const char *parameter, bool trigger
void condition_free(Condition *c);
void condition_free_list(Condition *c);
-bool condition_test_kernel_command_line(Condition *c);
-bool condition_test_virtualization(Condition *c);
-bool condition_test_architecture(Condition *c);
-bool condition_test_host(Condition *c);
-bool condition_test_ac_power(Condition *c);
+int condition_test_kernel_command_line(Condition *c);
+int condition_test_virtualization(Condition *c);
+int condition_test_architecture(Condition *c);
+int condition_test_host(Condition *c);
+int condition_test_ac_power(Condition *c);
void condition_dump(Condition *c, FILE *f, const char *prefix);
void condition_dump_list(Condition *c, FILE *f, const char *prefix);
diff --git a/src/test/test-architecture.c b/src/test/test-architecture.c
index 24217ad..30bdec4 100644
--- a/src/test/test-architecture.c
+++ b/src/test/test-architecture.c
@@ -25,9 +25,8 @@
#include "log.h"
int main(int argc, char *argv[]) {
- Architecture a;
- int v;
const char *id = NULL;
+ int a, v;
v = detect_virtualization(&id);
if (v == -EPERM || v == -EACCES)
diff --git a/src/test/test-condition-util.c b/src/test/test-condition-util.c
index 1c79244..7a247fb 100644
--- a/src/test/test-condition-util.c
+++ b/src/test/test-condition-util.c
@@ -73,8 +73,8 @@ static void test_condition_test_host(void) {
static void test_condition_test_architecture(void) {
Condition *condition;
- Architecture a;
const char *sa;
+ int a;
a = uname_architecture();
assert_se(a >= 0);
@@ -87,7 +87,7 @@ static void test_condition_test_architecture(void) {
condition_free(condition);
condition = condition_new(CONDITION_ARCHITECTURE, "garbage value", false, false);
- assert_se(!condition_test_architecture(condition));
+ assert_se(condition_test_architecture(condition) < 0);
condition_free(condition);
condition = condition_new(CONDITION_ARCHITECTURE, sa, false, true);
More information about the systemd-commits
mailing list