diff options
Diffstat (limited to 'src')
-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 |
7 files changed, 347 insertions, 1 deletions
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; +} |