diff options
author | Tom Gundersen <teg@jklm.no> | 2014-02-20 19:26:54 +0100 |
---|---|---|
committer | Tom Gundersen <teg@jklm.no> | 2014-02-20 20:14:33 +0100 |
commit | b77c08e06b67d5b1dd8aaf67b732e93851d8ae43 (patch) | |
tree | 02ef68efc40638eb2c0c58ada6de66d5b87eec4e | |
parent | afc50ea84e40d6a3f27ad5bfb5161e2d9b431275 (diff) |
condition: split out most of condition handling into libsystemd-shard
The parts that require linknig to libcap, libselinux and friends stays in libsystemd-core.
-rw-r--r-- | Makefile.am | 4 | ||||
-rw-r--r-- | src/core/condition.c | 208 | ||||
-rw-r--r-- | src/core/condition.h | 48 | ||||
-rw-r--r-- | src/shared/condition-util.c | 243 | ||||
-rw-r--r-- | src/shared/condition-util.h | 77 |
5 files changed, 324 insertions, 256 deletions
diff --git a/Makefile.am b/Makefile.am index 03a65bf084..ee7dd2d6cf 100644 --- a/Makefile.am +++ b/Makefile.am @@ -766,7 +766,9 @@ libsystemd_shared_la_SOURCES = \ src/shared/audit.c \ src/shared/audit.h \ src/shared/xml.c \ - src/shared/xml.h + src/shared/xml.h \ + src/shared/condition-util.c \ + src/shared/condition-util.h nodist_libsystemd_shared_la_SOURCES = \ src/shared/errno-from-name.h \ diff --git a/src/core/condition.c b/src/core/condition.c index 35de996f88..658e8d6a4c 100644 --- a/src/core/condition.c +++ b/src/core/condition.c @@ -39,126 +39,6 @@ #include "ima-util.h" #include "selinux-util.h" -Condition* condition_new(ConditionType type, const char *parameter, bool trigger, bool negate) { - Condition *c; - - assert(type < _CONDITION_TYPE_MAX); - - c = new0(Condition, 1); - if (!c) - return NULL; - - c->type = type; - c->trigger = trigger; - c->negate = negate; - - if (parameter) { - c->parameter = strdup(parameter); - if (!c->parameter) { - 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 bool condition_test_kernel_command_line(Condition *c) { - char *line, *w, *state, *word = NULL; - bool equal; - int r; - size_t l, pl; - bool found = false; - - assert(c); - assert(c->parameter); - assert(c->type == CONDITION_KERNEL_COMMAND_LINE); - - r = proc_cmdline(&line); - if (r < 0) - log_warning("Failed to read /proc/cmdline, ignoring: %s", strerror(-r)); - if (r <= 0) - return c->negate; - - equal = !!strchr(c->parameter, '='); - pl = strlen(c->parameter); - - FOREACH_WORD_QUOTED(w, l, line, state) { - - free(word); - word = strndup(w, l); - if (!word) - break; - - if (equal) { - if (streq(word, c->parameter)) { - found = true; - break; - } - } else { - if (startswith(word, c->parameter) && (word[pl] == '=' || word[pl] == 0)) { - found = true; - break; - } - } - - } - - free(word); - free(line); - - return found == !c->negate; -} - -static bool condition_test_virtualization(Condition *c) { - int b; - Virtualization v; - const char *id; - - assert(c); - assert(c->parameter); - 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; - } - - /* First, compare with yes/no */ - b = parse_boolean(c->parameter); - - if (v > 0 && b > 0) - return !c->negate; - - if (v == 0 && b == 0) - return !c->negate; - - /* Then, compare categorization */ - if (v == VIRTUALIZATION_VM && streq(c->parameter, "vm")) - return !c->negate; - - if (v == VIRTUALIZATION_CONTAINER && streq(c->parameter, "container")) - return !c->negate; - - /* Finally compare id */ - return (v > 0 && streq(c->parameter, id)) == !c->negate; -} - static bool condition_test_security(Condition *c) { assert(c); assert(c->parameter); @@ -211,49 +91,6 @@ static bool condition_test_capability(Condition *c) { return !!(capabilities & (1ULL << value)) == !c->negate; } -static bool condition_test_host(Condition *c) { - sd_id128_t x, y; - char *h; - int r; - bool b; - - 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 c->negate; - - return sd_id128_equal(x, y); - } - - h = gethostname_malloc(); - if (!h) - return c->negate; - - b = fnmatch(c->parameter, h, FNM_CASEFOLD) == 0; - free(h); - - return b == !c->negate; -} - -static bool 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 !c->negate; - - return ((on_ac_power() != 0) == !!r) == !c->negate; -} - static bool condition_test(Condition *c) { assert(c); @@ -373,48 +210,3 @@ bool condition_test_list(const char *unit, Condition *first) { return triggered != 0; } - -void condition_dump(Condition *c, FILE *f, const char *prefix) { - assert(c); - assert(f); - - if (!prefix) - prefix = ""; - - fprintf(f, - "%s\t%s: %s%s%s %s\n", - prefix, - condition_type_to_string(c->type), - c->trigger ? "|" : "", - c->negate ? "!" : "", - c->parameter, - c->state < 0 ? "failed" : c->state > 0 ? "succeeded" : "untested"); -} - -void condition_dump_list(Condition *first, FILE *f, const char *prefix) { - Condition *c; - - LIST_FOREACH(conditions, c, first) - condition_dump(c, f, prefix); -} - -static const char* const condition_type_table[_CONDITION_TYPE_MAX] = { - [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_KERNEL_COMMAND_LINE] = "ConditionKernelCommandLine", - [CONDITION_VIRTUALIZATION] = "ConditionVirtualization", - [CONDITION_SECURITY] = "ConditionSecurity", - [CONDITION_CAPABILITY] = "ConditionCapability", - [CONDITION_HOST] = "ConditionHost", - [CONDITION_AC_POWER] = "ConditionACPower", - [CONDITION_NULL] = "ConditionNull" -}; - -DEFINE_STRING_TABLE_LOOKUP(condition_type, ConditionType); diff --git a/src/core/condition.h b/src/core/condition.h index 1813b735a5..6dd77bb658 100644 --- a/src/core/condition.h +++ b/src/core/condition.h @@ -21,52 +21,6 @@ along with systemd; If not, see <http://www.gnu.org/licenses/>. ***/ -#include <stdbool.h> - -#include "list.h" - -typedef enum ConditionType { - 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_KERNEL_COMMAND_LINE, - CONDITION_VIRTUALIZATION, - CONDITION_SECURITY, - CONDITION_CAPABILITY, - CONDITION_HOST, - CONDITION_AC_POWER, - CONDITION_NULL, - _CONDITION_TYPE_MAX, - _CONDITION_TYPE_INVALID = -1 -} ConditionType; - -typedef struct Condition { - ConditionType type; - - bool trigger:1; - bool negate:1; - - char *parameter; - - int state; - - 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); +#include "condition-util.h" bool condition_test_list(const char *unit, Condition *c); - -void condition_dump(Condition *c, FILE *f, const char *prefix); -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_; diff --git a/src/shared/condition-util.c b/src/shared/condition-util.c new file mode 100644 index 0000000000..d31c4bf5b1 --- /dev/null +++ b/src/shared/condition-util.c @@ -0,0 +1,243 @@ +/*-*- 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 <systemd/sd-id128.h> +#include "util.h" +#include "condition-util.h" +#include "virt.h" +#include "path-util.h" +#include "fileio.h" +#include "unit.h" + +Condition* condition_new(ConditionType type, const char *parameter, bool trigger, bool negate) { + Condition *c; + + assert(type < _CONDITION_TYPE_MAX); + + c = new0(Condition, 1); + if (!c) + return NULL; + + c->type = type; + c->trigger = trigger; + c->negate = negate; + + if (parameter) { + c->parameter = strdup(parameter); + if (!c->parameter) { + 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); +} + +bool condition_test_kernel_command_line(Condition *c) { + char *line, *w, *state, *word = NULL; + bool equal; + int r; + size_t l, pl; + bool found = false; + + assert(c); + assert(c->parameter); + assert(c->type == CONDITION_KERNEL_COMMAND_LINE); + + r = proc_cmdline(&line); + if (r < 0) + log_warning("Failed to read /proc/cmdline, ignoring: %s", strerror(-r)); + if (r <= 0) + return c->negate; + + equal = !!strchr(c->parameter, '='); + pl = strlen(c->parameter); + + FOREACH_WORD_QUOTED(w, l, line, state) { + + free(word); + word = strndup(w, l); + if (!word) + break; + + if (equal) { + if (streq(word, c->parameter)) { + found = true; + break; + } + } else { + if (startswith(word, c->parameter) && (word[pl] == '=' || word[pl] == 0)) { + found = true; + break; + } + } + + } + + free(word); + free(line); + + return found == !c->negate; +} + +bool condition_test_virtualization(Condition *c) { + int b; + Virtualization v; + const char *id; + + assert(c); + assert(c->parameter); + 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; + } + + /* First, compare with yes/no */ + b = parse_boolean(c->parameter); + + if (v > 0 && b > 0) + return !c->negate; + + if (v == 0 && b == 0) + return !c->negate; + + /* Then, compare categorization */ + if (v == VIRTUALIZATION_VM && streq(c->parameter, "vm")) + return !c->negate; + + if (v == VIRTUALIZATION_CONTAINER && streq(c->parameter, "container")) + return !c->negate; + + /* Finally compare id */ + return (v > 0 && streq(c->parameter, id)) == !c->negate; +} + +bool condition_test_host(Condition *c) { + sd_id128_t x, y; + char *h; + int r; + bool b; + + 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 c->negate; + + return sd_id128_equal(x, y); + } + + h = gethostname_malloc(); + if (!h) + return c->negate; + + b = fnmatch(c->parameter, h, FNM_CASEFOLD) == 0; + free(h); + + return b == !c->negate; +} + +bool 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 !c->negate; + + return ((on_ac_power() != 0) == !!r) == !c->negate; +} + +void condition_dump(Condition *c, FILE *f, const char *prefix) { + assert(c); + assert(f); + + if (!prefix) + prefix = ""; + + fprintf(f, + "%s\t%s: %s%s%s %s\n", + prefix, + condition_type_to_string(c->type), + c->trigger ? "|" : "", + c->negate ? "!" : "", + c->parameter, + c->state < 0 ? "failed" : c->state > 0 ? "succeeded" : "untested"); +} + +void condition_dump_list(Condition *first, FILE *f, const char *prefix) { + Condition *c; + + LIST_FOREACH(conditions, c, first) + condition_dump(c, f, prefix); +} + +static const char* const condition_type_table[_CONDITION_TYPE_MAX] = { + [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_KERNEL_COMMAND_LINE] = "ConditionKernelCommandLine", + [CONDITION_VIRTUALIZATION] = "ConditionVirtualization", + [CONDITION_SECURITY] = "ConditionSecurity", + [CONDITION_CAPABILITY] = "ConditionCapability", + [CONDITION_HOST] = "ConditionHost", + [CONDITION_AC_POWER] = "ConditionACPower", + [CONDITION_NULL] = "ConditionNull" +}; + +DEFINE_STRING_TABLE_LOOKUP(condition_type, ConditionType); diff --git a/src/shared/condition-util.h b/src/shared/condition-util.h new file mode 100644 index 0000000000..85d4d5bbfc --- /dev/null +++ b/src/shared/condition-util.h @@ -0,0 +1,77 @@ +/*-*- 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_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_KERNEL_COMMAND_LINE, + CONDITION_VIRTUALIZATION, + CONDITION_SECURITY, + CONDITION_CAPABILITY, + CONDITION_HOST, + CONDITION_AC_POWER, + CONDITION_NULL, + _CONDITION_TYPE_MAX, + _CONDITION_TYPE_INVALID = -1 +} ConditionType; + +typedef struct Condition { + ConditionType type; + + bool trigger:1; + bool negate:1; + + char *parameter; + + int state; + + 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); + +bool condition_test_kernel_command_line(Condition *c); +bool condition_test_virtualization(Condition *c); +bool condition_test_host(Condition *c); +bool 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); + +const char* condition_type_to_string(ConditionType t) _const_; +int condition_type_from_string(const char *s) _pure_; |