summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLennart Poettering <lennart@poettering.net>2014-02-21 02:06:04 +0100
committerLennart Poettering <lennart@poettering.net>2014-02-21 02:43:14 +0100
commit099524d7b0df690e3361ffc3fe3c6aed0558b4fc (patch)
tree9983d7ff3452ce44a2a8150e124d01e998f8dbd9
parenta03c5fd2d86c4e3f758a5ca0d98638e5c8bd8d8d (diff)
core: add new ConditionArchitecture() that checks the architecture returned by uname()'s machine field.
-rw-r--r--Makefile.am11
-rw-r--r--man/systemd.unit.xml255
-rw-r--r--src/core/condition.c3
-rw-r--r--src/core/load-fragment-gperf.gperf.m41
-rw-r--r--src/shared/architecture.c159
-rw-r--r--src/shared/architecture.h105
-rw-r--r--src/shared/condition-util.c26
-rw-r--r--src/shared/condition-util.h2
-rw-r--r--src/test/test-architecture.c52
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;
+}