From: Lennart Poettering Date: Sat, 6 Dec 2014 01:39:15 +0000 (+0100) Subject: sd-bus: rework ELF error mapping table magic X-Git-Tag: v218~89 X-Git-Url: https://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?p=elogind.git;a=commitdiff_plain;h=5f86c1f4c43ee9caa120d130e9b89d3fd25124c0 sd-bus: rework ELF error mapping table magic 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. --- diff --git a/src/libsystemd/sd-bus/bus-error.c b/src/libsystemd/sd-bus/bus-error.c index 47f90c26f..157b8d890 100644 --- a/src/libsystemd/sd-bus/bus-error.c +++ b/src/libsystemd/sd-bus/bus-error.c @@ -32,61 +32,54 @@ #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; +} diff --git a/src/libsystemd/sd-bus/bus-error.h b/src/libsystemd/sd-bus/bus-error.h index 146948618..56297156a 100644 --- a/src/libsystemd/sd-bus/bus-error.h +++ b/src/libsystemd/sd-bus/bus-error.h @@ -26,15 +26,40 @@ #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); diff --git a/src/libsystemd/sd-bus/test-bus-error.c b/src/libsystemd/sd-bus/test-bus-error.c index ae894e39f..f72bcdb6b 100644 --- a/src/libsystemd/sd-bus/test-bus-error.c +++ b/src/libsystemd/sd-bus/test-bus-error.c @@ -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[]) { diff --git a/src/shared/bus-errors.c b/src/shared/bus-errors.c index b6f65d205..c347545c7 100644 --- a/src/shared/bus-errors.c +++ b/src/shared/bus-errors.c @@ -22,52 +22,55 @@ #include #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 }; diff --git a/src/shared/bus-errors.h b/src/shared/bus-errors.h index 1bf19c3f3..e842f850c 100644 --- a/src/shared/bus-errors.h +++ b/src/shared/bus-errors.h @@ -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); diff --git a/src/shared/macro.h b/src/shared/macro.h index 9f5e4552b..548294e47 100644 --- a/src/shared/macro.h +++ b/src/shared/macro.h @@ -95,15 +95,15 @@ #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) { diff --git a/src/systemd/sd-bus.h b/src/systemd/sd-bus.h index 3ad3db54e..f5fd37a66 100644 --- a/src/systemd/sd-bus.h +++ b/src/systemd/sd-bus.h @@ -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, \ diff --git a/src/timedate/timedated.c b/src/timedate/timedated.c index 24de21008..08ddc52ca 100644 --- a/src/timedate/timedated.c +++ b/src/timedate/timedated.c @@ -38,14 +38,16 @@ #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 {