From 134e56dcc53970a20a858283650bb92cd5da1d17 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 6 Nov 2014 14:19:05 +0100 Subject: 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. --- .gitignore | 2 +- Makefile.am | 12 +- src/core/unit.h | 2 +- src/libsystemd-network/network-internal.c | 2 +- src/libsystemd-network/network-internal.h | 2 +- src/network/networkd-netdev.h | 1 - src/network/networkd.h | 2 +- src/shared/condition-util.c | 529 ------------------------------ src/shared/condition-util.h | 96 ------ src/shared/condition.c | 529 ++++++++++++++++++++++++++++++ src/shared/condition.h | 96 ++++++ src/test/test-condition-util.c | 194 ----------- src/test/test-condition.c | 194 +++++++++++ src/test/test-tables.c | 2 +- src/udev/net/link-config.h | 5 +- 15 files changed, 833 insertions(+), 835 deletions(-) delete mode 100644 src/shared/condition-util.c delete mode 100644 src/shared/condition-util.h create mode 100644 src/shared/condition.c create mode 100644 src/shared/condition.h delete mode 100644 src/test/test-condition-util.c create mode 100644 src/test/test-condition.c diff --git a/.gitignore b/.gitignore index 6649d19fc7..4c66564c4d 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 a10c306ceb..461ffa944d 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 b5a224b3d4..8b24272245 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 f3141f75dc..6f16050cdc 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 49387d03cf..c64db2e79d 100644 --- a/src/libsystemd-network/network-internal.h +++ b/src/libsystemd-network/network-internal.h @@ -26,7 +26,7 @@ #include #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 e9a8a169db..a6fad2dbc4 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 d4e79ab2f3..19a661e131 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 5db20a7085..0000000000 --- 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 . -***/ - -#include -#include -#include -#include -#include -#include - -#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 28d1d94ff4..0000000000 --- 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 . -***/ - -#include -#include - -#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 0000000000..08bebeee73 --- /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 . +***/ + +#include +#include +#include +#include +#include +#include + +#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 0000000000..28d1d94ff4 --- /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 . +***/ + +#include +#include + +#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 b69e62bfd3..0000000000 --- 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 . -***/ - -#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 0000000000..349c6470c3 --- /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 . +***/ + +#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 d0a621c775..97d5609adf 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 5f3d4ad142..844ea98629 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; -- cgit v1.2.3-54-g00ecf