diff options
author | Lennart Poettering <lennart@poettering.net> | 2014-02-21 02:06:04 +0100 |
---|---|---|
committer | Lennart Poettering <lennart@poettering.net> | 2014-02-21 02:43:14 +0100 |
commit | 099524d7b0df690e3361ffc3fe3c6aed0558b4fc (patch) | |
tree | 9983d7ff3452ce44a2a8150e124d01e998f8dbd9 | |
parent | a03c5fd2d86c4e3f758a5ca0d98638e5c8bd8d8d (diff) |
core: add new ConditionArchitecture() that checks the architecture returned by uname()'s machine field.
-rw-r--r-- | Makefile.am | 11 | ||||
-rw-r--r-- | man/systemd.unit.xml | 255 | ||||
-rw-r--r-- | src/core/condition.c | 3 | ||||
-rw-r--r-- | src/core/load-fragment-gperf.gperf.m4 | 1 | ||||
-rw-r--r-- | src/shared/architecture.c | 159 | ||||
-rw-r--r-- | src/shared/architecture.h | 105 | ||||
-rw-r--r-- | src/shared/condition-util.c | 26 | ||||
-rw-r--r-- | src/shared/condition-util.h | 2 | ||||
-rw-r--r-- | src/test/test-architecture.c | 52 |
9 files changed, 505 insertions, 109 deletions
diff --git a/Makefile.am b/Makefile.am index ac90c1890c..85d51b4a96 100644 --- a/Makefile.am +++ b/Makefile.am @@ -674,6 +674,8 @@ libsystemd_shared_la_SOURCES = \ src/shared/util.h \ src/shared/virt.c \ src/shared/virt.h \ + src/shared/architecture.c \ + src/shared/architecture.h \ src/shared/efivars.c \ src/shared/efivars.h \ src/shared/path-util.c \ @@ -1150,7 +1152,8 @@ tests += \ test-list \ test-tables \ test-device-nodes \ - test-xml + test-xml \ + test-architecture EXTRA_DIST += \ test/sched_idle_bad.service \ @@ -1298,6 +1301,12 @@ test_time_SOURCES = \ test_time_LDADD = \ libsystemd-core.la +test_architecture_SOURCES = \ + src/test/test-architecture.c + +test_architecture_LDADD = \ + libsystemd-shared.la + test_log_SOURCES = \ src/test/test-log.c diff --git a/man/systemd.unit.xml b/man/systemd.unit.xml index 2a965f5a1c..2b59b1b841 100644 --- a/man/systemd.unit.xml +++ b/man/systemd.unit.xml @@ -879,6 +879,13 @@ </varlistentry> <varlistentry> + <term><varname>ConditionArchitecture=</varname></term> + <term><varname>ConditionVirtualization=</varname></term> + <term><varname>ConditionHost=</varname></term> + <term><varname>ConditionKernelCommandLine=</varname></term> + <term><varname>ConditionSecurity=</varname></term> + <term><varname>ConditionCapability=</varname></term> + <term><varname>ConditionACPower=</varname></term> <term><varname>ConditionPathExists=</varname></term> <term><varname>ConditionPathExistsGlob=</varname></term> <term><varname>ConditionPathIsDirectory=</varname></term> @@ -888,12 +895,6 @@ <term><varname>ConditionDirectoryNotEmpty=</varname></term> <term><varname>ConditionFileNotEmpty=</varname></term> <term><varname>ConditionFileIsExecutable=</varname></term> - <term><varname>ConditionKernelCommandLine=</varname></term> - <term><varname>ConditionVirtualization=</varname></term> - <term><varname>ConditionSecurity=</varname></term> - <term><varname>ConditionCapability=</varname></term> - <term><varname>ConditionHost=</varname></term> - <term><varname>ConditionACPower=</varname></term> <term><varname>ConditionNull=</varname></term> <listitem><para>Before starting a unit @@ -908,93 +909,46 @@ queued start job is to be executed.</para> - <para>With - <varname>ConditionPathExists=</varname> - a file existence condition is - checked before a unit is started. If - the specified absolute path name does - not exist, the condition will - fail. If the absolute path name passed - to - <varname>ConditionPathExists=</varname> - is prefixed with an exclamation mark - (<literal>!</literal>), the test is negated, and the unit - is only started if the path does not - exist.</para> - - <para><varname>ConditionPathExistsGlob=</varname> - is similar to - <varname>ConditionPathExists=</varname>, - but checks for the existence of at - least one file or directory matching - the specified globbing pattern.</para> - - <para><varname>ConditionPathIsDirectory=</varname> - is similar to - <varname>ConditionPathExists=</varname> - but verifies whether a certain path - exists and is a - directory.</para> - - <para><varname>ConditionPathIsSymbolicLink=</varname> - is similar to - <varname>ConditionPathExists=</varname> - but verifies whether a certain path - exists and is a symbolic - link.</para> - - <para><varname>ConditionPathIsMountPoint=</varname> - is similar to - <varname>ConditionPathExists=</varname> - but verifies whether a certain path - exists and is a mount - point.</para> - - <para><varname>ConditionPathIsReadWrite=</varname> - is similar to - <varname>ConditionPathExists=</varname> - but verifies whether the underlying - file system is readable and writable - (i.e. not mounted - read-only).</para> - - <para><varname>ConditionDirectoryNotEmpty=</varname> - is similar to - <varname>ConditionPathExists=</varname> - but verifies whether a certain path - exists and is a non-empty - directory.</para> - - <para><varname>ConditionFileNotEmpty=</varname> - is similar to - <varname>ConditionPathExists=</varname> - but verifies whether a certain path - exists and refers to a regular file - with a non-zero size.</para> - - <para><varname>ConditionFileIsExecutable=</varname> - is similar to - <varname>ConditionPathExists=</varname> - but verifies whether a certain path - exists, is a regular file and marked - executable.</para> - - <para>Similarly, - <varname>ConditionKernelCommandLine=</varname> - may be used to check whether a - specific kernel command line option is - set (or if prefixed with the - exclamation mark unset). The argument - must either be a single word, or an - assignment (i.e. two words, separated - <literal>=</literal>). In the former - case the kernel command line is - searched for the word appearing as is, - or as left hand side of an - assignment. In the latter case the - exact assignment is looked for with - right and left hand side - matching.</para> + <para><varname>ConditionArchitecture=</varname> + may be used to check whether the + system is running on a specific + architecture. Takes one of + <varname>x86</varname>, + <varname>x86-64</varname>, + <varname>ppc</varname>, + <varname>ppc64</varname>, + <varname>ia64</varname>, + <varname>parisc</varname>, + <varname>parisc64</varname>, + <varname>s390</varname>, + <varname>s390x</varname>, + <varname>sparc</varname>, + <varname>sparc64</varname>, + <varname>mips</varname>, + <varname>mips64</varname>, + <varname>alpha</varname>, + <varname>arm</varname>, + <varname>arm-be</varname>, + <varname>arm64</varname>, + <varname>arm64-be</varname>, + <varname>sh</varname>, + <varname>sh64</varname>, + <varname>m86k</varname> to test + against a specific architecture. The + architecture is determined from the + information returned by + <citerefentry><refentrytitle>uname</refentrytitle><manvolnum>2</manvolnum></citerefentry> + and is thus subject to + <citerefentry><refentrytitle>personality</refentrytitle><manvolnum>2</manvolnum></citerefentry>. Note + that a <varname>Personality=</varname> + setting in the same unit file has no + effect on this condition. A special + architecture name + <varname>native</varname> is mapped to + the architecture the system manager + itself is compiled for. The test may + be negated by prepending an + exclamation mark.</para> <para><varname>ConditionVirtualization=</varname> may be used to check whether the @@ -1028,6 +982,36 @@ test may be negated by prepending an exclamation mark.</para> + <para><varname>ConditionHost=</varname> + may be used to match against the + hostname or machine ID of the + host. This either takes a hostname + string (optionally with shell style + globs) which is tested against the + locally set hostname as returned by + <citerefentry><refentrytitle>gethostname</refentrytitle><manvolnum>2</manvolnum></citerefentry>, + or a machine ID formatted as string + (see + <citerefentry><refentrytitle>machine-id</refentrytitle><manvolnum>5</manvolnum></citerefentry>). + The test may be negated by prepending + an exclamation mark.</para> + + <para><varname>ConditionKernelCommandLine=</varname> + may be used to check whether a + specific kernel command line option is + set (or if prefixed with the + exclamation mark unset). The argument + must either be a single word, or an + assignment (i.e. two words, separated + <literal>=</literal>). In the former + case the kernel command line is + searched for the word appearing as is, + or as left hand side of an + assignment. In the latter case the + exact assignment is looked for with + right and left hand side + matching.</para> + <para><varname>ConditionSecurity=</varname> may be used to check whether the given security module is enabled on the @@ -1053,20 +1037,6 @@ possibly prefixed with an exclamation mark to negate the check.</para> - <para><varname>ConditionHost=</varname> - may be used to match against the - hostname or machine ID of the - host. This either takes a hostname - string (optionally with shell style - globs) which is tested against the - locally set hostname as returned by - <citerefentry><refentrytitle>gethostname</refentrytitle><manvolnum>2</manvolnum></citerefentry>, - or a machine ID formatted as string - (see - <citerefentry><refentrytitle>machine-id</refentrytitle><manvolnum>5</manvolnum></citerefentry>). - The test may be negated by prepending - an exclamation mark.</para> - <para><varname>ConditionACPower=</varname> may be used to check whether the system has AC power, or is exclusively @@ -1084,6 +1054,77 @@ all AC connectors are disconnected from a power source.</para> + <para>With + <varname>ConditionPathExists=</varname> + a file existence condition is + checked before a unit is started. If + the specified absolute path name does + not exist, the condition will + fail. If the absolute path name passed + to + <varname>ConditionPathExists=</varname> + is prefixed with an exclamation mark + (<literal>!</literal>), the test is negated, and the unit + is only started if the path does not + exist.</para> + + <para><varname>ConditionPathExistsGlob=</varname> + is similar to + <varname>ConditionPathExists=</varname>, + but checks for the existence of at + least one file or directory matching + the specified globbing pattern.</para> + + <para><varname>ConditionPathIsDirectory=</varname> + is similar to + <varname>ConditionPathExists=</varname> + but verifies whether a certain path + exists and is a + directory.</para> + + <para><varname>ConditionPathIsSymbolicLink=</varname> + is similar to + <varname>ConditionPathExists=</varname> + but verifies whether a certain path + exists and is a symbolic + link.</para> + + <para><varname>ConditionPathIsMountPoint=</varname> + is similar to + <varname>ConditionPathExists=</varname> + but verifies whether a certain path + exists and is a mount + point.</para> + + <para><varname>ConditionPathIsReadWrite=</varname> + is similar to + <varname>ConditionPathExists=</varname> + but verifies whether the underlying + file system is readable and writable + (i.e. not mounted + read-only).</para> + + <para><varname>ConditionDirectoryNotEmpty=</varname> + is similar to + <varname>ConditionPathExists=</varname> + but verifies whether a certain path + exists and is a non-empty + directory.</para> + + <para><varname>ConditionFileNotEmpty=</varname> + is similar to + <varname>ConditionPathExists=</varname> + but verifies whether a certain path + exists and refers to a regular file + with a non-zero size.</para> + + <para><varname>ConditionFileIsExecutable=</varname> + is similar to + <varname>ConditionPathExists=</varname> + but verifies whether a certain path + exists, is a regular file and marked + executable.</para> + <para>Finally, <varname>ConditionNull=</varname> may be used to add a constant condition diff --git a/src/core/condition.c b/src/core/condition.c index 658e8d6a4c..1448fa19dc 100644 --- a/src/core/condition.c +++ b/src/core/condition.c @@ -167,6 +167,9 @@ static bool condition_test(Condition *c) { case CONDITION_AC_POWER: return condition_test_ac_power(c); + case CONDITION_ARCHITECTURE: + return condition_test_architecture(c); + case CONDITION_NULL: return !c->negate; diff --git a/src/core/load-fragment-gperf.gperf.m4 b/src/core/load-fragment-gperf.gperf.m4 index 1c2c142eec..e9995bf0c7 100644 --- a/src/core/load-fragment-gperf.gperf.m4 +++ b/src/core/load-fragment-gperf.gperf.m4 @@ -153,6 +153,7 @@ Unit.ConditionDirectoryNotEmpty, config_parse_unit_condition_path, CONDITION_D 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.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 diff --git a/src/shared/architecture.c b/src/shared/architecture.c new file mode 100644 index 0000000000..1dc5fa5c0f --- /dev/null +++ b/src/shared/architecture.c @@ -0,0 +1,159 @@ +/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/ + +/*** + This file is part of systemd. + + Copyright 2014 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 <sys/utsname.h> + +#include "architecture.h" + +Architecture uname_architecture(void) { + + /* Return a sanitized enum identifying the architecture we are + * running on. This is based on uname(), and the user may + * hence control what this returns by using + * personality(). This puts the user in control on systems + * that can run binaries of multiple architectures. + * + * We do not translate the string returned by uname() + * 1:1. Instead we try to clean it up and break down the + * confusion on x86 and arm in particular. + * + * We do not try to distuingish CPUs not CPU features, but + * actual architectures, i.e. that have genuinely different + * code. */ + + static const struct { + const char *machine; + Architecture arch; + } arch_map[] = { +#if defined(__x86_64__) || defined(__i386__) + { "x86_64", ARCHITECTURE_X86_64 }, + { "i686", ARCHITECTURE_X86 }, + { "i586", ARCHITECTURE_X86 }, + { "i486", ARCHITECTURE_X86 }, + { "i386", ARCHITECTURE_X86 }, +#elif defined(__powerpc__) || defined(__powerpc64__) + { "ppc64", ARCHITECTURE_PPC64 }, + { "ppc", ARCHITECTURE_PPC }, +#elif defined(__ia64__) + { "ia64", ARCHITECTURE_IA64 }, +#elif defined(__hppa__) || defined(__hppa64__) + { "parisc64", ARCHITECTURE_PARISC64 }, + { "parisc", ARCHITECTURE_PARISC }, +#elif defined(__s390__) || defined(__s390x__) + { "s390x", ARCHITECTURE_S390X }, + { "s390", ARCHITECTURE_S390 }, +#elif defined(__sparc__) || defined(__sparc64__) + { "sparc64", ARCHITECTURE_SPARC64 }, + { "sparc", ARCHITECTURE_SPARC }, +#elif defined(__mips__) || defined(__mips64__) + { "mips64", ARCHITECTURE_MIPS64 }, + { "mips", ARCHITECTURE_MIPS }, +#elif defined(__alpha__) + { "alpha" , ARCHITECTURE_ALPHA }, +#elif defined(__arm__) || defined(__aarch64__) + { "aarch64", ARCHITECTURE_ARM64 }, + { "aarch64_be", ARCHITECTURE_ARM64_BE }, + { "armv4l", ARCHITECTURE_ARM }, + { "armv4b", ARCHITECTURE_ARM_BE }, + { "armv4tl", ARCHITECTURE_ARM }, + { "armv4tb", ARCHITECTURE_ARM_BE }, + { "armv5tl", ARCHITECTURE_ARM }, + { "armv5tb", ARCHITECTURE_ARM_BE }, + { "armv5tel", ARCHITECTURE_ARM }, + { "armv5teb" , ARCHITECTURE_ARM_BE }, + { "armv5tejl", ARCHITECTURE_ARM }, + { "armv5tejb", ARCHITECTURE_ARM_BE }, + { "armv6l", ARCHITECTURE_ARM }, + { "armv6b", ARCHITECTURE_ARM_BE }, + { "armv7l", ARCHITECTURE_ARM }, + { "armv7b", ARCHITECTURE_ARM_BE }, + { "armv7ml", ARCHITECTURE_ARM }, + { "armv7mb", ARCHITECTURE_ARM_BE }, + { "armv4l", ARCHITECTURE_ARM }, + { "armv4b", ARCHITECTURE_ARM_BE }, + { "armv4tl", ARCHITECTURE_ARM }, + { "armv4tb", ARCHITECTURE_ARM_BE }, + { "armv5tl", ARCHITECTURE_ARM }, + { "armv5tb", ARCHITECTURE_ARM_BE }, + { "armv5tel", ARCHITECTURE_ARM }, + { "armv5teb", ARCHITECTURE_ARM_BE }, + { "armv5tejl", ARCHITECTURE_ARM }, + { "armv5tejb", ARCHITECTURE_ARM_BE }, + { "armv6l", ARCHITECTURE_ARM }, + { "armv6b", ARCHITECTURE_ARM_BE }, + { "armv7l", ARCHITECTURE_ARM }, + { "armv7b", ARCHITECTURE_ARM_BE }, + { "armv7ml", ARCHITECTURE_ARM }, + { "armv7mb", ARCHITECTURE_ARM_BE }, + { "armv8l", ARCHITECTURE_ARM }, + { "armv8b", ARCHITECTURE_ARM_BE }, +#elif defined(__sh__) || defined(__sh64__) + { "sh64", ARCHITECTURE_SH64 }, + { "sh", ARCHITECTURE_SH }, +#elif defined(__m68k__) + { "m68k", ARCHITECTURE_M68K }, +#else +#error "Please register your architecture here!" +#endif + }; + + static Architecture cached = _ARCHITECTURE_INVALID; + struct utsname u; + unsigned i; + + if (cached != _ARCHITECTURE_INVALID) + return cached; + + assert_se(uname(&u) >= 0); + + for (i = 0; i < ELEMENTSOF(arch_map); i++) + if (streq(arch_map[i].machine, u.machine)) + return cached = arch_map[i].arch; + + assert_not_reached("Couldn't identify architecture. You need to patch systemd."); + return _ARCHITECTURE_INVALID; +} + +static const char *const architecture_table[_ARCHITECTURE_MAX] = { + [ARCHITECTURE_X86] = "x86", + [ARCHITECTURE_X86_64] = "x86-64", + [ARCHITECTURE_PPC] = "ppc", + [ARCHITECTURE_PPC64] = "ppc64", + [ARCHITECTURE_IA64] = "ia64", + [ARCHITECTURE_PARISC] = "parisc", + [ARCHITECTURE_PARISC64] = "parisc64", + [ARCHITECTURE_S390] = "s390", + [ARCHITECTURE_S390X] = "s390x", + [ARCHITECTURE_SPARC] = "sparc", + [ARCHITECTURE_SPARC64] = "sparc64", + [ARCHITECTURE_MIPS] = "mips", + [ARCHITECTURE_MIPS64] = "mips64", + [ARCHITECTURE_ALPHA] = "alpha", + [ARCHITECTURE_ARM] = "arm", + [ARCHITECTURE_ARM_BE] = "arm-be", + [ARCHITECTURE_ARM64] = "arm64", + [ARCHITECTURE_ARM64_BE] = "arm64-be", + [ARCHITECTURE_SH] = "sh", + [ARCHITECTURE_SH64] = "sh64", + [ARCHITECTURE_M68K] = "m68k", +}; + +DEFINE_STRING_TABLE_LOOKUP(architecture, Architecture); diff --git a/src/shared/architecture.h b/src/shared/architecture.h new file mode 100644 index 0000000000..fcfc45aa77 --- /dev/null +++ b/src/shared/architecture.h @@ -0,0 +1,105 @@ +/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/ + +#pragma once + +/*** + This file is part of systemd. + + Copyright 2014 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 "util.h" + +typedef enum Architecture { + ARCHITECTURE_X86 = 0, + ARCHITECTURE_X86_64, + ARCHITECTURE_PPC, + ARCHITECTURE_PPC64, + ARCHITECTURE_IA64, + ARCHITECTURE_PARISC, + ARCHITECTURE_PARISC64, + ARCHITECTURE_S390, + ARCHITECTURE_S390X, + ARCHITECTURE_SPARC, + ARCHITECTURE_SPARC64, + ARCHITECTURE_MIPS, + ARCHITECTURE_MIPS64, + ARCHITECTURE_ALPHA, + ARCHITECTURE_ARM, + ARCHITECTURE_ARM_BE, + ARCHITECTURE_ARM64, + ARCHITECTURE_ARM64_BE, + ARCHITECTURE_SH, + ARCHITECTURE_SH64, + ARCHITECTURE_M68K, + _ARCHITECTURE_MAX, + _ARCHITECTURE_INVALID = -1 +} Architecture; + +Architecture uname_architecture(void); + +#if defined(__x86_64__) +# define native_architecture() ARCHITECTURE_X86_64 +#elif defined(__i386__) +# define native_architecture() ARCHITECTURE_X86 +#elif defined(__powerpc64__) +# define native_architecture() ARCHITECTURE_PPC64 +#elif defined(__powerpc__) +# define native_architecture() ARCHITECTURE_PPC +#elif defined(__ia64__) +# define native_architecture() ARCHITECTURE_IA64 +#elif defined(__hppa64__) +# define native_architecture() ARCHITECTURE_PARISC64 +#elif defined(__hppa__) +# define native_architecture() ARCHITECTURE_PARISC +#elif defined(__s390x__) +# define native_architecture() ARCHITECTURE_S390X +#elif defined(__s390__) +# define native_architecture() ARCHITECTURE_S390 +#elif defined(__sparc64__) +# define native_architecture() ARCHITECTURE_SPARC64 +#elif defined(__sparc__) +# define native_architecture() ARCHITECTURE_SPARC +#elif defined(__mips64__) +# define native_architecture() ARCHITECTURE_MIPS64 +#elif defined(__mips__) +# define native_architecture() ARCHITECTURE_MIPS +#elif defined(__alpha__) +# define native_architecture() ARCHITECTURE_ALPHA +#elif defined(__aarch64__) +# ifdef defined(WORDS_BIGENDIAN) +# define native_architecture() ARCHITECTURE_ARM64_BE +# else +# define native_architecture() ARCHITECTURE_ARM64 +# endif +#elif defined(__arm__) +# ifdef defined(WORDS_BIGENDIAN) +# define native_architecture() ARCHITECTURE_ARM_BE +# else +# define native_architecture() ARCHITECTURE_ARM +# endif +#elif defined(__sh64__) +# define native_architecture() ARCHITECTURE_SH64 +#elif defined(__sh__) +# define native_architecture() ARCHITECTURE_SH +#elif defined(__m68k__) +# define native_architecture() ARCHITECTURE_M68K +#else +#error "Please register your architecture here!" +#endif + +const char *architecture_to_string(Architecture a) _const_; +Architecture architecture_from_string(const char *s) _pure_; diff --git a/src/shared/condition-util.c b/src/shared/condition-util.c index d31c4bf5b1..4aea3caf9d 100644 --- a/src/shared/condition-util.c +++ b/src/shared/condition-util.c @@ -33,6 +33,7 @@ #include "path-util.h" #include "fileio.h" #include "unit.h" +#include "architecture.h" Condition* condition_new(ConditionType type, const char *parameter, bool trigger, bool negate) { Condition *c; @@ -154,6 +155,28 @@ bool condition_test_virtualization(Condition *c) { return (v > 0 && streq(c->parameter, id)) == !c->negate; } +bool condition_test_architecture(Condition *c) { + Architecture a, b; + + assert(c); + assert(c->parameter); + assert(c->type == CONDITION_ARCHITECTURE); + + a = uname_architecture(); + if (a < 0) + return c->negate; + + if (streq(c->parameter, "native")) + b = native_architecture(); + else + b = architecture_from_string(c->parameter); + + if (b < 0) + return c->negate; + + return (a == b) == !c->negate; +} + bool condition_test_host(Condition *c) { sd_id128_t x, y; char *h; @@ -170,7 +193,7 @@ bool condition_test_host(Condition *c) { if (r < 0) return c->negate; - return sd_id128_equal(x, y); + return sd_id128_equal(x, y) == !c->negate; } h = gethostname_malloc(); @@ -237,6 +260,7 @@ static const char* const condition_type_table[_CONDITION_TYPE_MAX] = { [CONDITION_CAPABILITY] = "ConditionCapability", [CONDITION_HOST] = "ConditionHost", [CONDITION_AC_POWER] = "ConditionACPower", + [CONDITION_ARCHITECTURE] = "ConditionArchitecture", [CONDITION_NULL] = "ConditionNull" }; diff --git a/src/shared/condition-util.h b/src/shared/condition-util.h index 85d4d5bbfc..63d945efac 100644 --- a/src/shared/condition-util.h +++ b/src/shared/condition-util.h @@ -43,6 +43,7 @@ typedef enum ConditionType { CONDITION_CAPABILITY, CONDITION_HOST, CONDITION_AC_POWER, + CONDITION_ARCHITECTURE, CONDITION_NULL, _CONDITION_TYPE_MAX, _CONDITION_TYPE_INVALID = -1 @@ -67,6 +68,7 @@ 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); diff --git a/src/test/test-architecture.c b/src/test/test-architecture.c new file mode 100644 index 0000000000..b586c0da5d --- /dev/null +++ b/src/test/test-architecture.c @@ -0,0 +1,52 @@ +/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/ + +/*** + This file is part of systemd. + + Copyright 2014 Kay Sievers + + 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 "virt.h" +#include "architecture.h" +#include "util.h" +#include "log.h" + +int main(int argc, char *argv[]) { + Architecture a; + Virtualization v; + const char *id = NULL; + + v = detect_virtualization(&id); + if (v == -EPERM || v == -EACCES) + return EXIT_TEST_SKIP; + + assert_se(v >= 0); + + log_info("virtualization=%s id=%s", + v == VIRTUALIZATION_CONTAINER ? "container" : v == VIRTUALIZATION_VM ? "vm" : "n/a", + strna(id)); + + a = uname_architecture(); + assert_se(a >= 0); + + log_info("uname architecture=%s", architecture_to_string(a)); + + a = native_architecture(); + assert_se(a >= 0); + + log_info("native architecture=%s", architecture_to_string(a)); + return 0; +} |