chiark / gitweb /
core: add new ConditionArchitecture() that checks the architecture returned by uname...
authorLennart Poettering <lennart@poettering.net>
Fri, 21 Feb 2014 01:06:04 +0000 (02:06 +0100)
committerLennart Poettering <lennart@poettering.net>
Fri, 21 Feb 2014 01:43:14 +0000 (02:43 +0100)
Makefile.am
man/systemd.unit.xml
src/core/condition.c
src/core/load-fragment-gperf.gperf.m4
src/shared/architecture.c [new file with mode: 0644]
src/shared/architecture.h [new file with mode: 0644]
src/shared/condition-util.c
src/shared/condition-util.h
src/test/test-architecture.c [new file with mode: 0644]

index ac90c18..85d51b4 100644 (file)
@@ -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
 
index 2a965f5..2b59b1b 100644 (file)
                         </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>
                                 <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
                                 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
                                 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
                                 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
                                 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
index 658e8d6..1448fa1 100644 (file)
@@ -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;
 
index 1c2c142..e9995bf 100644 (file)
@@ -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 (file)
index 0000000..1dc5fa5
--- /dev/null
@@ -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 (file)
index 0000000..fcfc45a
--- /dev/null
@@ -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_;
index d31c4bf..4aea3ca 100644 (file)
@@ -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"
 };
 
index 85d4d5b..63d945e 100644 (file)
@@ -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 (file)
index 0000000..b586c0d
--- /dev/null
@@ -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;
+}