sd-bus: rework ELF error mapping table magic
authorLennart Poettering <lennart@poettering.net>
Sat, 6 Dec 2014 01:39:15 +0000 (02:39 +0100)
committerLennart Poettering <lennart@poettering.net>
Mon, 8 Dec 2014 13:55:22 +0000 (14:55 +0100)
The ELF magic cannot work for consumers of our shard library, since they
are in a different module. Hence make all the ELF magic private, and
instead introduce a public function to register additional static
mapping table.

src/libsystemd/sd-bus/bus-error.c
src/libsystemd/sd-bus/bus-error.h
src/libsystemd/sd-bus/test-bus-error.c
src/shared/bus-errors.c
src/shared/bus-errors.h
src/shared/macro.h
src/systemd/sd-bus.h
src/timedate/timedated.c

index 47f90c2..157b8d8 100644 (file)
 #include "sd-bus.h"
 #include "bus-error.h"
 
-#define BUS_ERROR_OOM SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_NO_MEMORY, "Out of memory")
-#define BUS_ERROR_FAILED SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_FAILED, "Operation failed")
-
-SD_BUS_ERROR_MAPPING(sd_bus_standard) = {
-        {"org.freedesktop.DBus.Error.Failed",                           EACCES},
-        {"org.freedesktop.DBus.Error.NoMemory",                         ENOMEM},
-        {"org.freedesktop.DBus.Error.ServiceUnknown",                   EHOSTUNREACH},
-        {"org.freedesktop.DBus.Error.NameHasNoOwner",                   ENXIO},
-        {"org.freedesktop.DBus.Error.NoReply",                          ETIMEDOUT},
-        {"org.freedesktop.DBus.Error.IOError",                          EIO},
-        {"org.freedesktop.DBus.Error.BadAddress",                       EADDRNOTAVAIL},
-        {"org.freedesktop.DBus.Error.NotSupported",                     ENOTSUP},
-        {"org.freedesktop.DBus.Error.LimitsExceeded",                   ENOBUFS},
-        {"org.freedesktop.DBus.Error.AccessDenied",                     EACCES},
-        {"org.freedesktop.DBus.Error.AuthFailed",                       EACCES},
-        {"org.freedesktop.DBus.Error.InteractiveAuthorizationRequired", EACCES},
-        {"org.freedesktop.DBus.Error.NoServer",                         EHOSTDOWN},
-        {"org.freedesktop.DBus.Error.Timeout",                          ETIMEDOUT},
-        {"org.freedesktop.DBus.Error.NoNetwork",                        ENONET},
-        {"org.freedesktop.DBus.Error.AddressInUse",                     EADDRINUSE},
-        {"org.freedesktop.DBus.Error.Disconnected",                     ECONNRESET},
-        {"org.freedesktop.DBus.Error.InvalidArgs",                      EINVAL},
-        {"org.freedesktop.DBus.Error.FileNotFound",                     ENOENT},
-        {"org.freedesktop.DBus.Error.FileExists",                       EEXIST},
-        {"org.freedesktop.DBus.Error.UnknownMethod",                    EBADR},
-        {"org.freedesktop.DBus.Error.UnknownObject",                    EBADR},
-        {"org.freedesktop.DBus.Error.UnknownInterface",                 EBADR},
-        {"org.freedesktop.DBus.Error.UnknownProperty",                  EBADR},
-        {"org.freedesktop.DBus.Error.PropertyReadOnly",                 EROFS},
-        {"org.freedesktop.DBus.Error.UnixProcessIdUnknown",             ESRCH},
-        {"org.freedesktop.DBus.Error.InvalidSignature",                 EINVAL},
-        {"org.freedesktop.DBus.Error.InconsistentMessage",              EBADMSG},
-
-        {"org.freedesktop.DBus.Error.TimedOut",                         ETIMEDOUT},
-        {"org.freedesktop.DBus.Error.MatchRuleInvalid",                 EINVAL},
-        {"org.freedesktop.DBus.Error.InvalidFileContent",               EINVAL},
-        {"org.freedesktop.DBus.Error.MatchRuleNotFound",                ENOENT},
-        {"org.freedesktop.DBus.Error.SELinuxSecurityContextUnknown",    ESRCH},
-        {"org.freedesktop.DBus.Error.ObjectPathInUse",                  EBUSY},
+BUS_ERROR_MAP_ELF_REGISTER const sd_bus_error_map standard_errors[] = {
+        SD_BUS_ERROR_MAP("org.freedesktop.DBus.Error.Failed",                           EACCES),
+        SD_BUS_ERROR_MAP("org.freedesktop.DBus.Error.NoMemory",                         ENOMEM),
+        SD_BUS_ERROR_MAP("org.freedesktop.DBus.Error.ServiceUnknown",                   EHOSTUNREACH),
+        SD_BUS_ERROR_MAP("org.freedesktop.DBus.Error.NameHasNoOwner",                   ENXIO),
+        SD_BUS_ERROR_MAP("org.freedesktop.DBus.Error.NoReply",                          ETIMEDOUT),
+        SD_BUS_ERROR_MAP("org.freedesktop.DBus.Error.IOError",                          EIO),
+        SD_BUS_ERROR_MAP("org.freedesktop.DBus.Error.BadAddress",                       EADDRNOTAVAIL),
+        SD_BUS_ERROR_MAP("org.freedesktop.DBus.Error.NotSupported",                     ENOTSUP),
+        SD_BUS_ERROR_MAP("org.freedesktop.DBus.Error.LimitsExceeded",                   ENOBUFS),
+        SD_BUS_ERROR_MAP("org.freedesktop.DBus.Error.AccessDenied",                     EACCES),
+        SD_BUS_ERROR_MAP("org.freedesktop.DBus.Error.AuthFailed",                       EACCES),
+        SD_BUS_ERROR_MAP("org.freedesktop.DBus.Error.InteractiveAuthorizationRequired", EACCES),
+        SD_BUS_ERROR_MAP("org.freedesktop.DBus.Error.NoServer",                         EHOSTDOWN),
+        SD_BUS_ERROR_MAP("org.freedesktop.DBus.Error.Timeout",                          ETIMEDOUT),
+        SD_BUS_ERROR_MAP("org.freedesktop.DBus.Error.NoNetwork",                        ENONET),
+        SD_BUS_ERROR_MAP("org.freedesktop.DBus.Error.AddressInUse",                     EADDRINUSE),
+        SD_BUS_ERROR_MAP("org.freedesktop.DBus.Error.Disconnected",                     ECONNRESET),
+        SD_BUS_ERROR_MAP("org.freedesktop.DBus.Error.InvalidArgs",                      EINVAL),
+        SD_BUS_ERROR_MAP("org.freedesktop.DBus.Error.FileNotFound",                     ENOENT),
+        SD_BUS_ERROR_MAP("org.freedesktop.DBus.Error.FileExists",                       EEXIST),
+        SD_BUS_ERROR_MAP("org.freedesktop.DBus.Error.UnknownMethod",                    EBADR),
+        SD_BUS_ERROR_MAP("org.freedesktop.DBus.Error.UnknownObject",                    EBADR),
+        SD_BUS_ERROR_MAP("org.freedesktop.DBus.Error.UnknownInterface",                 EBADR),
+        SD_BUS_ERROR_MAP("org.freedesktop.DBus.Error.UnknownProperty",                  EBADR),
+        SD_BUS_ERROR_MAP("org.freedesktop.DBus.Error.PropertyReadOnly",                 EROFS),
+        SD_BUS_ERROR_MAP("org.freedesktop.DBus.Error.UnixProcessIdUnknown",             ESRCH),
+        SD_BUS_ERROR_MAP("org.freedesktop.DBus.Error.InvalidSignature",                 EINVAL),
+        SD_BUS_ERROR_MAP("org.freedesktop.DBus.Error.InconsistentMessage",              EBADMSG),
+        SD_BUS_ERROR_MAP("org.freedesktop.DBus.Error.TimedOut",                         ETIMEDOUT),
+        SD_BUS_ERROR_MAP("org.freedesktop.DBus.Error.MatchRuleInvalid",                 EINVAL),
+        SD_BUS_ERROR_MAP("org.freedesktop.DBus.Error.InvalidFileContent",               EINVAL),
+        SD_BUS_ERROR_MAP("org.freedesktop.DBus.Error.MatchRuleNotFound",                ENOENT),
+        SD_BUS_ERROR_MAP("org.freedesktop.DBus.Error.SELinuxSecurityContextUnknown",    ESRCH),
+        SD_BUS_ERROR_MAP("org.freedesktop.DBus.Error.ObjectPathInUse",                  EBUSY),
+        SD_BUS_ERROR_MAP_END
 };
 
-extern const sd_bus_name_error_mapping __start_sd_bus_errnomap[];
-extern const sd_bus_name_error_mapping __stop_sd_bus_errnomap[];
+/* GCC maps this magically to the beginning and end of the BUS_ERROR_MAP section */
+extern const sd_bus_error_map __start_BUS_ERROR_MAP[];
+extern const sd_bus_error_map __stop_BUS_ERROR_MAP[];
 
-static int bus_error_mapping_lookup(const char *name, size_t len) {
-        const sd_bus_name_error_mapping *m;
-
-        for (m = __start_sd_bus_errnomap; m < __stop_sd_bus_errnomap; m++)
-                if (m->name && strneq(m->name, name, len))
-                        return m->code;
-
-        return EIO;
-}
+/* Additional maps registered with sd_bus_error_add_map() are in this
+ * NULL terminated array */
+static const sd_bus_error_map **additional_error_maps = NULL;
 
 static int bus_error_name_to_errno(const char *name) {
+        const sd_bus_error_map **map, *m;
         const char *p;
         int r;
 
@@ -102,7 +95,39 @@ static int bus_error_name_to_errno(const char *name) {
                 return r;
         }
 
-        return bus_error_mapping_lookup(name, strlen(name));
+        if (additional_error_maps) {
+                for (map = additional_error_maps; *map; map++) {
+                        for (m = *map;; m++) {
+                                /* For additional error maps the end marker is actually the end marker */
+                                if (m->code == BUS_ERROR_MAP_END_MARKER)
+                                        break;
+
+                                if (streq(m->name, name))
+                                        return m->code;
+                        }
+                }
+        }
+
+        m = __start_BUS_ERROR_MAP;
+        while (m < __stop_BUS_ERROR_MAP) {
+                /* For magic ELF error maps, the end marker might
+                 * appear in the middle of things, since multiple maps
+                 * might appear in the same section. Hence, let's skip
+                 * over it, but realign the pointer to the netx 8byte
+                 * boundary, which is the selected alignment for the
+                 * arrays. */
+                if (m->code == BUS_ERROR_MAP_END_MARKER) {
+                        m = ALIGN8_PTR(m+1);
+                        continue;
+                }
+
+                if (streq(m->name, name))
+                        return m->code;
+
+                m++;
+        }
+
+        return EIO;
 }
 
 static sd_bus_error errno_to_bus_error_const(int error) {
@@ -552,3 +577,31 @@ const char *bus_error_message(const sd_bus_error *e, int error) {
 
         return strerror(error);
 }
+
+_public_ int sd_bus_error_add_map(const sd_bus_error_map *map) {
+        const sd_bus_error_map **maps = NULL;
+        unsigned n = 0;
+
+        assert_return(map, -EINVAL);
+
+        if (additional_error_maps) {
+                for (;; n++) {
+                        if (additional_error_maps[n] == NULL)
+                                break;
+
+                        if (additional_error_maps[n] == map)
+                                return 0;
+                }
+        }
+
+        maps = realloc_multiply(additional_error_maps, sizeof(struct sd_bus_error_map*), n + 2);
+        if (!maps)
+                return -ENOMEM;
+
+
+        maps[n] = map;
+        maps[n+1] = NULL;
+
+        additional_error_maps = maps;
+        return 1;
+}
index 1469486..5629715 100644 (file)
 #include "sd-bus.h"
 #include "macro.h"
 
-struct name_error_mapping {
-        const char* name;
-        int code;
-};
-typedef struct name_error_mapping name_error_mapping;
-
 bool bus_error_is_dirty(sd_bus_error *e);
 
 const char *bus_error_message(const sd_bus_error *e, int error);
 
 int bus_error_setfv(sd_bus_error *e, const char *name, const char *format, va_list ap) _printf_(3,0);
 int bus_error_set_errnofv(sd_bus_error *e, int error, const char *format, va_list ap) _printf_(3,0);
+
+#define BUS_ERROR_OOM SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_NO_MEMORY, "Out of memory")
+#define BUS_ERROR_FAILED SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_FAILED, "Operation failed")
+
+/*
+ * There are two ways to register error maps with the error translation
+ * logic: by using BUS_ERROR_MAP_ELF_REGISTER, which however only
+ * works when linked into the same ELF module, or via
+ * sd_bus_error_add_map() which is the official, external API, that
+ * works from any module.
+ *
+ * Note that BUS_ERROR_MAP_ELF_REGISTER has to be used as decorator in
+ * the bus error table, and BUS_ERROR_MAP_ELF_USE has to be used at
+ * least once per compilation unit (i.e. per library), to ensure that
+ * the error map is really added to the final binary.
+ */
+
+#define BUS_ERROR_MAP_ELF_REGISTER                                      \
+        __attribute__ ((__section__("BUS_ERROR_MAP")))                  \
+        __attribute__ ((__used__))                                      \
+        __attribute__ ((aligned(8)))
+
+#define BUS_ERROR_MAP_ELF_USE(errors)                                   \
+        extern const sd_bus_error_map errors[];                         \
+        __attribute__ ((used)) static const sd_bus_error_map * CONCATENATE(errors ## _copy_, __COUNTER__) = errors;
+
+/* We use something exotic as end marker, to ensure people build the
+ * maps using the macsd-ros. */
+#define BUS_ERROR_MAP_END_MARKER -'x'
+
+BUS_ERROR_MAP_ELF_USE(standard_errors);
index ae894e3..f72bcdb 100644 (file)
@@ -22,6 +22,8 @@
 #include "sd-bus.h"
 #include "bus-error.h"
 #include "bus-util.h"
+#include "errno-list.h"
+#include "bus-errors.h"
 
 static void test_error(void) {
         _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL, second = SD_BUS_ERROR_NULL;
@@ -111,15 +113,24 @@ static void test_error(void) {
         assert_se(sd_bus_error_is_set(&error));
 }
 
-extern const sd_bus_name_error_mapping __start_sd_bus_errnomap[];
-extern const sd_bus_name_error_mapping __stop_sd_bus_errnomap[];
+extern const sd_bus_error_map __start_BUS_ERROR_MAP[];
+extern const sd_bus_error_map __stop_BUS_ERROR_MAP[];
 
 static void dump_mapping_table(void) {
-        const sd_bus_name_error_mapping *m;
+        const sd_bus_error_map *m;
 
         printf("----- errno mappings ------\n");
-        for (m = __start_sd_bus_errnomap; m < __stop_sd_bus_errnomap; m++)
-                printf("%s -> %d\n", m->name, m->code);
+        m = __start_BUS_ERROR_MAP;
+        while (m < __stop_BUS_ERROR_MAP) {
+
+                if (m->code == BUS_ERROR_MAP_END_MARKER) {
+                        m = ALIGN8_PTR(m+1);
+                        continue;
+                }
+
+                printf("%s -> %i/%s\n", strna(m->name), m->code, strna(errno_to_name(m->code)));
+                m ++;
+        }
         printf("---------------------------\n");
 }
 
@@ -130,15 +141,54 @@ static void test_errno_mapping_standard(void) {
         assert_se(sd_bus_error_set(NULL, "System.Error.WHATSIT", NULL) == -EIO);
 }
 
-SD_BUS_ERROR_MAPPING(test) = {
-        {"org.freedesktop.custom-dbus-error", 5},
-        {"org.freedesktop.custom-dbus-error-2", 52},
+BUS_ERROR_MAP_ELF_REGISTER const sd_bus_error_map test_errors[] = {
+        SD_BUS_ERROR_MAP("org.freedesktop.custom-dbus-error", 5),
+        SD_BUS_ERROR_MAP("org.freedesktop.custom-dbus-error-2", 52),
+        SD_BUS_ERROR_MAP_END
+};
+
+BUS_ERROR_MAP_ELF_REGISTER const sd_bus_error_map test_errors2[] = {
+        SD_BUS_ERROR_MAP("org.freedesktop.custom-dbus-error-3", 33),
+        SD_BUS_ERROR_MAP("org.freedesktop.custom-dbus-error-4", 44),
+        SD_BUS_ERROR_MAP("org.freedesktop.custom-dbus-error-33", 333),
+        SD_BUS_ERROR_MAP_END
+};
+
+static const sd_bus_error_map test_errors3[] = {
+        SD_BUS_ERROR_MAP("org.freedesktop.custom-dbus-error-88", 888),
+        SD_BUS_ERROR_MAP("org.freedesktop.custom-dbus-error-99", 999),
+        SD_BUS_ERROR_MAP_END
+};
+
+static const sd_bus_error_map test_errors4[] = {
+        SD_BUS_ERROR_MAP("org.freedesktop.custom-dbus-error-77", 777),
+        SD_BUS_ERROR_MAP("org.freedesktop.custom-dbus-error-78", 778),
+        SD_BUS_ERROR_MAP_END
 };
 
 static void test_errno_mapping_custom(void) {
         assert_se(sd_bus_error_set(NULL, "org.freedesktop.custom-dbus-error", NULL) == -5);
         assert_se(sd_bus_error_set(NULL, "org.freedesktop.custom-dbus-error-2", NULL) == -52);
         assert_se(sd_bus_error_set(NULL, "org.freedesktop.custom-dbus-error-x", NULL) == -EIO);
+        assert_se(sd_bus_error_set(NULL, "org.freedesktop.custom-dbus-error-33", NULL) == -333);
+
+        assert_se(sd_bus_error_set(NULL, "org.freedesktop.custom-dbus-error-88", NULL) == -EIO);
+        assert_se(sd_bus_error_set(NULL, "org.freedesktop.custom-dbus-error-99", NULL) == -EIO);
+        assert_se(sd_bus_error_set(NULL, "org.freedesktop.custom-dbus-error-77", NULL) == -EIO);
+
+        assert_se(sd_bus_error_add_map(test_errors3) > 0);
+        assert_se(sd_bus_error_set(NULL, "org.freedesktop.custom-dbus-error-88", NULL) == -888);
+        assert_se(sd_bus_error_add_map(test_errors4) > 0);
+        assert_se(sd_bus_error_add_map(test_errors4) == 0);
+        assert_se(sd_bus_error_add_map(test_errors3) == 0);
+
+        assert_se(sd_bus_error_set(NULL, "org.freedesktop.custom-dbus-error-99", NULL) == -999);
+        assert_se(sd_bus_error_set(NULL, "org.freedesktop.custom-dbus-error-77", NULL) == -777);
+        assert_se(sd_bus_error_set(NULL, "org.freedesktop.custom-dbus-error-78", NULL) == -778);
+        assert_se(sd_bus_error_set(NULL, "org.freedesktop.custom-dbus-error-2", NULL) == -52);
+        assert_se(sd_bus_error_set(NULL, "org.freedesktop.custom-dbus-error-y", NULL) == -EIO);
+
+        assert_se(sd_bus_error_set(NULL, BUS_ERROR_NO_SUCH_UNIT, NULL) == -ENOENT);
 }
 
 int main(int argc, char *argv[]) {
index b6f65d2..c347545 100644 (file)
 #include <errno.h>
 
 #include "sd-bus.h"
+#include "bus-error.h"
 #include "bus-errors.h"
 
-SD_BUS_ERROR_MAPPING(systemd_shared) = {
-        {BUS_ERROR_NO_SUCH_UNIT,                 ENOENT},
-        {BUS_ERROR_NO_UNIT_FOR_PID,              ESRCH},
-        {BUS_ERROR_UNIT_EXISTS,                  EEXIST},
-        {BUS_ERROR_LOAD_FAILED,                  EIO},
-        {BUS_ERROR_JOB_FAILED,                   EREMOTEIO},
-        {BUS_ERROR_NO_SUCH_JOB,                  ENOENT},
-        {BUS_ERROR_NOT_SUBSCRIBED,               EINVAL},
-        {BUS_ERROR_ALREADY_SUBSCRIBED,           EINVAL},
-        {BUS_ERROR_ONLY_BY_DEPENDENCY,           EINVAL},
-        {BUS_ERROR_TRANSACTION_JOBS_CONFLICTING, EDEADLOCK},
-        {BUS_ERROR_TRANSACTION_ORDER_IS_CYCLIC,  EDEADLOCK},
-        {BUS_ERROR_TRANSACTION_IS_DESTRUCTIVE,   EDEADLOCK},
-        {BUS_ERROR_UNIT_MASKED,                  ENOSYS},
-        {BUS_ERROR_JOB_TYPE_NOT_APPLICABLE,      EBADR},
-        {BUS_ERROR_NO_ISOLATION,                 EPERM},
-        {BUS_ERROR_SHUTTING_DOWN,                ECANCELED},
-        {BUS_ERROR_SCOPE_NOT_RUNNING,            EHOSTDOWN},
+BUS_ERROR_MAP_ELF_REGISTER const sd_bus_error_map shared_errors[] = {
+        SD_BUS_ERROR_MAP(BUS_ERROR_NO_SUCH_UNIT,                 ENOENT),
+        SD_BUS_ERROR_MAP(BUS_ERROR_NO_UNIT_FOR_PID,              ESRCH),
+        SD_BUS_ERROR_MAP(BUS_ERROR_UNIT_EXISTS,                  EEXIST),
+        SD_BUS_ERROR_MAP(BUS_ERROR_LOAD_FAILED,                  EIO),
+        SD_BUS_ERROR_MAP(BUS_ERROR_JOB_FAILED,                   EREMOTEIO),
+        SD_BUS_ERROR_MAP(BUS_ERROR_NO_SUCH_JOB,                  ENOENT),
+        SD_BUS_ERROR_MAP(BUS_ERROR_NOT_SUBSCRIBED,               EINVAL),
+        SD_BUS_ERROR_MAP(BUS_ERROR_ALREADY_SUBSCRIBED,           EINVAL),
+        SD_BUS_ERROR_MAP(BUS_ERROR_ONLY_BY_DEPENDENCY,           EINVAL),
+        SD_BUS_ERROR_MAP(BUS_ERROR_TRANSACTION_JOBS_CONFLICTING, EDEADLOCK),
+        SD_BUS_ERROR_MAP(BUS_ERROR_TRANSACTION_ORDER_IS_CYCLIC,  EDEADLOCK),
+        SD_BUS_ERROR_MAP(BUS_ERROR_TRANSACTION_IS_DESTRUCTIVE,   EDEADLOCK),
+        SD_BUS_ERROR_MAP(BUS_ERROR_UNIT_MASKED,                  ENOSYS),
+        SD_BUS_ERROR_MAP(BUS_ERROR_JOB_TYPE_NOT_APPLICABLE,      EBADR),
+        SD_BUS_ERROR_MAP(BUS_ERROR_NO_ISOLATION,                 EPERM),
+        SD_BUS_ERROR_MAP(BUS_ERROR_SHUTTING_DOWN,                ECANCELED),
+        SD_BUS_ERROR_MAP(BUS_ERROR_SCOPE_NOT_RUNNING,            EHOSTDOWN),
 
-        {BUS_ERROR_NO_SUCH_MACHINE,              ENXIO},
-        {BUS_ERROR_NO_MACHINE_FOR_PID,           ENXIO},
-        {BUS_ERROR_MACHINE_EXISTS,               EEXIST},
-        {BUS_ERROR_NO_PRIVATE_NETWORKING,        ENOSYS},
+        SD_BUS_ERROR_MAP(BUS_ERROR_NO_SUCH_MACHINE,              ENXIO),
+        SD_BUS_ERROR_MAP(BUS_ERROR_NO_MACHINE_FOR_PID,           ENXIO),
+        SD_BUS_ERROR_MAP(BUS_ERROR_MACHINE_EXISTS,               EEXIST),
+        SD_BUS_ERROR_MAP(BUS_ERROR_NO_PRIVATE_NETWORKING,        ENOSYS),
 
-        {BUS_ERROR_NO_SUCH_SESSION,              ENXIO},
-        {BUS_ERROR_NO_SESSION_FOR_PID,           ENXIO},
-        {BUS_ERROR_NO_SUCH_USER,                 ENXIO},
-        {BUS_ERROR_NO_USER_FOR_PID,              ENXIO},
-        {BUS_ERROR_NO_SUCH_SEAT,                 ENXIO},
-        {BUS_ERROR_SESSION_NOT_ON_SEAT,          EINVAL},
-        {BUS_ERROR_NOT_IN_CONTROL,               EINVAL},
-        {BUS_ERROR_DEVICE_IS_TAKEN,              EINVAL},
-        {BUS_ERROR_DEVICE_NOT_TAKEN,             EINVAL},
-        {BUS_ERROR_OPERATION_IN_PROGRESS,        EINPROGRESS},
-        {BUS_ERROR_SLEEP_VERB_NOT_SUPPORTED,     ENOSYS},
+        SD_BUS_ERROR_MAP(BUS_ERROR_NO_SUCH_SESSION,              ENXIO),
+        SD_BUS_ERROR_MAP(BUS_ERROR_NO_SESSION_FOR_PID,           ENXIO),
+        SD_BUS_ERROR_MAP(BUS_ERROR_NO_SUCH_USER,                 ENXIO),
+        SD_BUS_ERROR_MAP(BUS_ERROR_NO_USER_FOR_PID,              ENXIO),
+        SD_BUS_ERROR_MAP(BUS_ERROR_NO_SUCH_SEAT,                 ENXIO),
+        SD_BUS_ERROR_MAP(BUS_ERROR_SESSION_NOT_ON_SEAT,          EINVAL),
+        SD_BUS_ERROR_MAP(BUS_ERROR_NOT_IN_CONTROL,               EINVAL),
+        SD_BUS_ERROR_MAP(BUS_ERROR_DEVICE_IS_TAKEN,              EINVAL),
+        SD_BUS_ERROR_MAP(BUS_ERROR_DEVICE_NOT_TAKEN,             EINVAL),
+        SD_BUS_ERROR_MAP(BUS_ERROR_OPERATION_IN_PROGRESS,        EINPROGRESS),
+        SD_BUS_ERROR_MAP(BUS_ERROR_SLEEP_VERB_NOT_SUPPORTED,     ENOSYS),
 
-        {BUS_ERROR_AUTOMATIC_TIME_SYNC_ENABLED,  EALREADY},
+        SD_BUS_ERROR_MAP(BUS_ERROR_AUTOMATIC_TIME_SYNC_ENABLED,  EALREADY),
 
-        {BUS_ERROR_NO_SUCH_PROCESS,              ESRCH},
+        SD_BUS_ERROR_MAP(BUS_ERROR_NO_SUCH_PROCESS,              ESRCH),
 
-        {BUS_ERROR_NO_NAME_SERVERS,              EIO},
-        {BUS_ERROR_INVALID_REPLY,                EINVAL},
-        {BUS_ERROR_NO_SUCH_RR,                   ENOENT},
-        {BUS_ERROR_NO_RESOURCES,                 ENOMEM},
-        {BUS_ERROR_CNAME_LOOP,                   EDEADLOCK},
-        {BUS_ERROR_ABORTED,                      ECANCELED},
+        SD_BUS_ERROR_MAP(BUS_ERROR_NO_NAME_SERVERS,              EIO),
+        SD_BUS_ERROR_MAP(BUS_ERROR_INVALID_REPLY,                EINVAL),
+        SD_BUS_ERROR_MAP(BUS_ERROR_NO_SUCH_RR,                   ENOENT),
+        SD_BUS_ERROR_MAP(BUS_ERROR_NO_RESOURCES,                 ENOMEM),
+        SD_BUS_ERROR_MAP(BUS_ERROR_CNAME_LOOP,                   EDEADLOCK),
+        SD_BUS_ERROR_MAP(BUS_ERROR_ABORTED,                      ECANCELED),
+
+        SD_BUS_ERROR_MAP_END
 };
index 1bf19c3..e842f85 100644 (file)
@@ -22,6 +22,7 @@
 ***/
 
 #include "sd-bus.h"
+#include "bus-error.h"
 
 #define BUS_ERROR_NO_SUCH_UNIT "org.freedesktop.systemd1.NoSuchUnit"
 #define BUS_ERROR_NO_UNIT_FOR_PID "org.freedesktop.systemd1.NoUnitForPID"
@@ -70,4 +71,4 @@
 #define BUS_ERROR_ABORTED "org.freedesktop.resolve1.Aborted"
 #define _BUS_ERROR_DNS "org.freedesktop.resolve1.DnsError."
 
-SD_BUS_ERROR_MAPPING_USE(systemd_shared);
+BUS_ERROR_MAP_ELF_USE(shared_errors);
index 9f5e455..548294e 100644 (file)
 #error "Wut? Pointers are neither 4 nor 8 bytes long?"
 #endif
 
-#define ALIGN_PTR(p) ((void*) ALIGN((unsigned long) p))
-#define ALIGN4_PTR(p) ((void*) ALIGN4((unsigned long) p))
-#define ALIGN8_PTR(p) ((void*) ALIGN8((unsigned long) p))
+#define ALIGN_PTR(p) ((void*) ALIGN((unsigned long) (p)))
+#define ALIGN4_PTR(p) ((void*) ALIGN4((unsigned long) (p)))
+#define ALIGN8_PTR(p) ((void*) ALIGN8((unsigned long) (p)))
 
 static inline size_t ALIGN_TO(size_t l, size_t ali) {
         return ((l + ali - 1) & ~(ali - 1));
 }
 
-#define ALIGN_TO_PTR(p, ali) ((void*) ALIGN_TO((unsigned long) p, ali))
+#define ALIGN_TO_PTR(p, ali) ((void*) ALIGN_TO((unsigned long) (p), (ali)))
 
 /* align to next higher power-of-2 (except for: 0 => 0, overflow => 0) */
 static inline unsigned long ALIGN_POWER2(unsigned long u) {
index 3ad3db5..f5fd37a 100644 (file)
@@ -46,6 +46,11 @@ typedef struct {
         int _need_free;
 } sd_bus_error;
 
+typedef struct {
+        const char* name;
+        int code;
+} sd_bus_error_map;
+
 /* Flags */
 
 enum {
@@ -356,32 +361,9 @@ int sd_bus_creds_get_description(sd_bus_creds *c, const char **name);
 
 /* Error structures */
 
-struct sd_bus_name_error_mapping {
-        const char* name;
-        int code;
-};
-typedef struct sd_bus_name_error_mapping sd_bus_name_error_mapping;
-
 #define SD_BUS_ERROR_MAKE_CONST(name, message) ((const sd_bus_error) {(name), (message), 0})
 #define SD_BUS_ERROR_NULL SD_BUS_ERROR_MAKE_CONST(NULL, NULL)
 
-#ifndef SD_BUS_ERROR_MAPPING
-#  define _SD_BUS_ERROR_XCONCAT(x, y) x ## y
-#  define _SD_BUS_ERROR_CONCAT(x, y) _SD_BUS_ERROR_XCONCAT(x, y)
-#  define SD_BUS_ERROR_MAPPING(name)                                    \
-        __attribute((__section__("sd_bus_errnomap")))                   \
-        __attribute((__used__))                                         \
-        const sd_bus_name_error_mapping _SD_BUS_ERROR_CONCAT(_sd_bus_errno_mapping_, name)[]
-#  define SD_BUS_ERROR_MAPPING_USE(name)                                \
-        extern                                                          \
-        const sd_bus_name_error_mapping _SD_BUS_ERROR_CONCAT(_sd_bus_errno_mapping_, name)[]; \
-        __attribute((__used__))                                         \
-        static const sd_bus_name_error_mapping*                         \
-        _SD_BUS_ERROR_CONCAT(sd_bus_name_error_mapping_ref, __COUNTER__) \
-        = _SD_BUS_ERROR_CONCAT(_sd_bus_errno_mapping_, name);
-#endif
-
-
 void sd_bus_error_free(sd_bus_error *e);
 int sd_bus_error_set(sd_bus_error *e, const char *name, const char *message);
 int sd_bus_error_setf(sd_bus_error *e, const char *name, const char *format, ...)  _sd_printf_(3, 4);
@@ -393,6 +375,19 @@ int sd_bus_error_copy(sd_bus_error *dest, const sd_bus_error *e);
 int sd_bus_error_is_set(const sd_bus_error *e);
 int sd_bus_error_has_name(const sd_bus_error *e, const char *name);
 
+#define SD_BUS_ERROR_MAP(_name, _code)          \
+        {                                       \
+                .name = _name,                  \
+                .code = _code,                  \
+        }
+#define SD_BUS_ERROR_MAP_END                    \
+        {                                       \
+                .name = NULL,                   \
+                .code = - 'x',                  \
+        }
+
+int sd_bus_error_add_map(const sd_bus_error_map *map);
+
 /* Auxiliary macros */
 
 #define SD_BUS_MESSAGE_APPEND_ID128(x) 16,                              \
index 24de210..08ddc52 100644 (file)
 #include "fileio-label.h"
 #include "label.h"
 #include "bus-util.h"
+#include "bus-error.h"
 #include "bus-errors.h"
 #include "event-util.h"
 
 #define NULL_ADJTIME_UTC "0.0 0 0\n0\nUTC\n"
 #define NULL_ADJTIME_LOCAL "0.0 0 0\n0\nLOCAL\n"
 
-SD_BUS_ERROR_MAPPING(timedated) = {
-        {"org.freedesktop.timedate1.NoNTPSupport", ENOTSUP},
+static BUS_ERROR_MAP_ELF_REGISTER const sd_bus_error_map timedated_errors[] = {
+        SD_BUS_ERROR_MAP("org.freedesktop.timedate1.NoNTPSupport", ENOTSUP),
+        SD_BUS_ERROR_MAP_END
 };
 
 typedef struct Context {