[systemd-commits] 4 commits - src/libsystemd-bus src/rc-local-generator src/systemd src/timedate

Lennart Poettering lennart at kemper.freedesktop.org
Tue Oct 29 19:35:18 CET 2013


 src/libsystemd-bus/bus-message.c            |  351 ++++++++++++++++++----------
 src/libsystemd-bus/bus-message.h            |    2 
 src/libsystemd-bus/busctl.c                 |    2 
 src/libsystemd-bus/test-bus-kernel.c        |    4 
 src/libsystemd-bus/test-bus-marshal.c       |   48 +++
 src/libsystemd-bus/test-bus-objects.c       |   10 
 src/libsystemd-bus/test-bus-zero-copy.c     |    4 
 src/rc-local-generator/rc-local-generator.c |   43 +--
 src/systemd/sd-bus.h                        |    8 
 src/timedate/timedated.c                    |   10 
 10 files changed, 313 insertions(+), 169 deletions(-)

New commits:
commit 7b1132f60d2a447c31556c23ea90ea31447ac557
Author: Lennart Poettering <lennart at poettering.net>
Date:   Tue Oct 29 19:34:11 2013 +0100

    rc-local: use access(X_OK) to check if files are executable
    
    ... and other modernizations.

diff --git a/src/rc-local-generator/rc-local-generator.c b/src/rc-local-generator/rc-local-generator.c
index 9265501..01ff470 100644
--- a/src/rc-local-generator/rc-local-generator.c
+++ b/src/rc-local-generator/rc-local-generator.c
@@ -39,45 +39,32 @@
 const char *arg_dest = "/tmp";
 
 static int add_symlink(const char *service, const char *where) {
-        char *from = NULL, *to = NULL;
+        _cleanup_free_ char *from = NULL, *to = NULL;
         int r;
 
         assert(service);
+        assert(where);
 
-        asprintf(&from, SYSTEM_DATA_UNIT_PATH "/%s", service);
-        asprintf(&to, "%s/%s.wants/%s", arg_dest, where, service);
+        from = strjoin(SYSTEM_DATA_UNIT_PATH, "/", service, NULL);
+        if (!from)
+                return log_oom();
 
-        if (!from || !to) {
-                r = log_oom();
-                goto finish;
-        }
+        to = strjoin(arg_dest, "/", where, ".wants/", service, NULL);
+        if (!to)
+                return log_oom();
 
         mkdir_parents_label(to, 0755);
 
         r = symlink(from, to);
         if (r < 0) {
                 if (errno == EEXIST)
-                        r = 0;
-                else {
-                        log_error("Failed to create symlink %s: %m", to);
-                        r = -errno;
-                }
-        }
-
-finish:
-        free(from);
-        free(to);
-
-        return r;
-}
+                        return 0;
 
-static bool file_is_executable(const char *f) {
-        struct stat st;
-
-        if (stat(f, &st) < 0)
-                return false;
+                log_error("Failed to create symlink %s: %m", to);
+                return -errno;
+        }
 
-        return S_ISREG(st.st_mode) && (st.st_mode & 0111);
+        return 1;
 }
 
 int main(int argc, char *argv[]) {
@@ -97,14 +84,14 @@ int main(int argc, char *argv[]) {
 
         umask(0022);
 
-        if (file_is_executable(RC_LOCAL_SCRIPT_PATH_START)) {
+        if (access(RC_LOCAL_SCRIPT_PATH_START, X_OK) >= 0) {
                 log_debug("Automatically adding rc-local.service.");
 
                 if (add_symlink("rc-local.service", "multi-user.target") < 0)
                         r = EXIT_FAILURE;
         }
 
-        if (file_is_executable(RC_LOCAL_SCRIPT_PATH_STOP)) {
+        if (access(RC_LOCAL_SCRIPT_PATH_STOP, X_OK) >= 0) {
                 log_debug("Automatically adding halt-local.service.");
 
                 if (add_symlink("halt-local.service", "final.target") < 0)

commit 88e262b667df1cd9873c45f0062ae79735f41ae6
Author: Lennart Poettering <lennart at poettering.net>
Date:   Tue Oct 29 19:31:41 2013 +0100

    timedate: handle more nicely if something or somebody keeps open /dev/rtc and thus blocks out everybody else
    
    chrony is appears to keep the RTC open continuously these days which is
    a bad idea, and /dev/rtc is a single-user device, which is a bad idea
    too. Together both bad ideas mean that nobody else can access the RTC
    anymore. That's something to fix, but in the meantime we should handle
    this more gracefully.

diff --git a/src/timedate/timedated.c b/src/timedate/timedated.c
index 809c80b..3d450ca 100644
--- a/src/timedate/timedated.c
+++ b/src/timedate/timedated.c
@@ -467,12 +467,14 @@ static int property_get_rtc_time(
 
         zero(tm);
         r = hwclock_get_time(&tm);
-        if (r < 0) {
+        if (r == -EBUSY) {
+                log_warning("/dev/rtc is busy, is somebody keeping it open continously? That's not a good idea... Returning a bogus RTC timestamp.");
+                t = 0;
+        } else if (r < 0) {
                 sd_bus_error_set_errnof(error, -r, "Failed to read RTC: %s", strerror(-r));
                 return r;
-        }
-
-        t = (usec_t) mktime(&tm) * USEC_PER_SEC;
+        } else
+                t = (usec_t) mktime(&tm) * USEC_PER_SEC;
 
         r = sd_bus_message_append(reply, "t", t);
         if (r < 0)

commit 29f8d1f21ab5341361adcc2533fcda24a7fcf490
Author: Lennart Poettering <lennart at poettering.net>
Date:   Tue Oct 29 19:31:25 2013 +0100

    bus: add a macro to simplify reading of UUIDs

diff --git a/src/systemd/sd-bus.h b/src/systemd/sd-bus.h
index a98887d..aa8caee 100644
--- a/src/systemd/sd-bus.h
+++ b/src/systemd/sd-bus.h
@@ -255,6 +255,12 @@ int sd_bus_error_has_name(const sd_bus_error *e, const char *name);
                 (x).bytes[8],  (x).bytes[9],  (x).bytes[10], (x).bytes[11], \
                 (x).bytes[12], (x).bytes[13], (x).bytes[14], (x).bytes[15]
 
+#define SD_BUS_MESSAGE_READ_ID128(x) 16,                                \
+                &(x).bytes[0],  &(x).bytes[1],  &(x).bytes[2],  &(x).bytes[3], \
+                &(x).bytes[4],  &(x).bytes[5],  &(x).bytes[6],  &(x).bytes[7], \
+                &(x).bytes[8],  &(x).bytes[9],  &(x).bytes[10], &(x).bytes[11], \
+                &(x).bytes[12], &(x).bytes[13], &(x).bytes[14], &(x).bytes[15]
+
 #ifdef __cplusplus
 }
 #endif

commit c430fee6ffda0e3736e4e2b617bef0a4c0882849
Author: Lennart Poettering <lennart at poettering.net>
Date:   Tue Oct 29 19:30:55 2013 +0100

    bus: add new sd_bus_message_verify_type() and sd_bus_message_copy() API calls

diff --git a/src/libsystemd-bus/bus-message.c b/src/libsystemd-bus/bus-message.c
index b0d4dd2..0d565dd 100644
--- a/src/libsystemd-bus/bus-message.c
+++ b/src/libsystemd-bus/bus-message.c
@@ -3103,10 +3103,8 @@ int sd_bus_message_peek_type(sd_bus_message *m, char *type, const char **content
         struct bus_container *c;
         int r;
 
-        if (!m)
-                return -EINVAL;
-        if (!m->sealed)
-                return -EPERM;
+        assert_return(m, -EINVAL);
+        assert_return(m->sealed, -EPERM);
 
         c = message_get_container(m);
 
@@ -4018,7 +4016,7 @@ int sd_bus_message_set_destination(sd_bus_message *m, const char *destination) {
         return message_append_field_string(m, SD_BUS_MESSAGE_HEADER_DESTINATION, SD_BUS_TYPE_STRING, destination, &m->destination);
 }
 
-int bus_message_dump(sd_bus_message *m) {
+int bus_message_dump(sd_bus_message *m, FILE *f, bool with_header) {
         const char *u = NULL, *uu = NULL, *s = NULL;
         char **cmdline = NULL;
         unsigned level = 1;
@@ -4028,102 +4026,108 @@ int bus_message_dump(sd_bus_message *m) {
 
         assert(m);
 
-        printf("Message %p\n"
-               "\tn_ref=%u\n"
-               "\tendian=%c\n"
-               "\ttype=%i\n"
-               "\tflags=%u\n"
-               "\tversion=%u\n"
-               "\tserial=%u\n"
-               "\tfields_size=%u\n"
-               "\tbody_size=%u\n"
-               "\tpath=%s\n"
-               "\tinterface=%s\n"
-               "\tmember=%s\n"
-               "\tdestination=%s\n"
-               "\tsender=%s\n"
-               "\tsignature=%s\n"
-               "\treply_serial=%u\n"
-               "\terror.name=%s\n"
-               "\terror.message=%s\n"
-               "\tsealed=%s\n"
-               "\tn_body_parts=%u\n",
-               m,
-               m->n_ref,
-               m->header->endian,
-               m->header->type,
-               m->header->flags,
-               m->header->version,
-               BUS_MESSAGE_SERIAL(m),
-               BUS_MESSAGE_FIELDS_SIZE(m),
-               BUS_MESSAGE_BODY_SIZE(m),
-               strna(m->path),
-               strna(m->interface),
-               strna(m->member),
-               strna(m->destination),
-               strna(m->sender),
-               strna(m->root_container.signature),
-               m->reply_serial,
-               strna(m->error.name),
-               strna(m->error.message),
-               yes_no(m->sealed),
-               m->n_body_parts);
-
-        if (m->pid != 0)
-                printf("\tpid=%lu\n", (unsigned long) m->pid);
-        if (m->tid != 0)
-                printf("\ttid=%lu\n", (unsigned long) m->tid);
-        if (m->uid_valid)
-                printf("\tuid=%lu\n", (unsigned long) m->uid);
-        if (m->gid_valid)
-                printf("\tgid=%lu\n", (unsigned long) m->gid);
-        if (m->pid_starttime != 0)
-                printf("\tpid_starttime=%llu\n", (unsigned long long) m->pid_starttime);
-        if (m->monotonic != 0)
-                printf("\tmonotonic=%llu\n", (unsigned long long) m->monotonic);
-        if (m->realtime != 0)
-                printf("\trealtime=%llu\n", (unsigned long long) m->realtime);
-        if (m->exe)
-                printf("\texe=[%s]\n", m->exe);
-        if (m->comm)
-                printf("\tcomm=[%s]\n", m->comm);
-        if (m->tid_comm)
-                printf("\ttid_comm=[%s]\n", m->tid_comm);
-        if (m->label)
-                printf("\tlabel=[%s]\n", m->label);
-        if (m->cgroup)
-                printf("\tcgroup=[%s]\n", m->cgroup);
-
-        sd_bus_message_get_unit(m, &u);
-        if (u)
-                printf("\tunit=[%s]\n", u);
-        sd_bus_message_get_user_unit(m, &uu);
-        if (uu)
-                printf("\tuser_unit=[%s]\n", uu);
-        sd_bus_message_get_session(m, &s);
-        if (s)
-                printf("\tsession=[%s]\n", s);
-        if (sd_bus_message_get_owner_uid(m, &owner) >= 0)
-                printf("\towner_uid=%lu\n", (unsigned long) owner);
-        if (sd_bus_message_get_audit_loginuid(m, &audit_loginuid) >= 0)
-                printf("\taudit_loginuid=%lu\n", (unsigned long) audit_loginuid);
-        if (sd_bus_message_get_audit_sessionid(m, &audit_sessionid) >= 0)
-                printf("\taudit_sessionid=%lu\n", (unsigned long) audit_sessionid);
-
-        printf("\tCAP_KILL=%i\n", sd_bus_message_has_effective_cap(m, 5));
-
-        if (sd_bus_message_get_cmdline(m, &cmdline) >= 0) {
-                char **c;
-
-                fputs("\tcmdline=[", stdout);
-                STRV_FOREACH(c, cmdline) {
-                        if (c != cmdline)
-                                putchar(' ');
-
-                        fputs(*c, stdout);
-                }
+        if (!f)
+                f = stdout;
+
+        if (with_header) {
+                fprintf(f,
+                        "Message %p\n"
+                        "\tn_ref=%u\n"
+                        "\tendian=%c\n"
+                        "\ttype=%i\n"
+                        "\tflags=%u\n"
+                        "\tversion=%u\n"
+                        "\tserial=%u\n"
+                        "\tfields_size=%u\n"
+                        "\tbody_size=%u\n"
+                        "\tpath=%s\n"
+                        "\tinterface=%s\n"
+                        "\tmember=%s\n"
+                        "\tdestination=%s\n"
+                        "\tsender=%s\n"
+                        "\tsignature=%s\n"
+                        "\treply_serial=%u\n"
+                        "\terror.name=%s\n"
+                        "\terror.message=%s\n"
+                        "\tsealed=%s\n"
+                        "\tn_body_parts=%u\n",
+                        m,
+                        m->n_ref,
+                        m->header->endian,
+                        m->header->type,
+                        m->header->flags,
+                        m->header->version,
+                        BUS_MESSAGE_SERIAL(m),
+                        BUS_MESSAGE_FIELDS_SIZE(m),
+                        BUS_MESSAGE_BODY_SIZE(m),
+                        strna(m->path),
+                        strna(m->interface),
+                        strna(m->member),
+                        strna(m->destination),
+                        strna(m->sender),
+                        strna(m->root_container.signature),
+                        m->reply_serial,
+                        strna(m->error.name),
+                        strna(m->error.message),
+                        yes_no(m->sealed),
+                        m->n_body_parts);
+
+                if (m->pid != 0)
+                        fprintf(f, "\tpid=%lu\n", (unsigned long) m->pid);
+                if (m->tid != 0)
+                        fprintf(f, "\ttid=%lu\n", (unsigned long) m->tid);
+                if (m->uid_valid)
+                        fprintf(f, "\tuid=%lu\n", (unsigned long) m->uid);
+                if (m->gid_valid)
+                        fprintf(f, "\tgid=%lu\n", (unsigned long) m->gid);
+                if (m->pid_starttime != 0)
+                        fprintf(f, "\tpid_starttime=%llu\n", (unsigned long long) m->pid_starttime);
+                if (m->monotonic != 0)
+                        fprintf(f, "\tmonotonic=%llu\n", (unsigned long long) m->monotonic);
+                if (m->realtime != 0)
+                        fprintf(f, "\trealtime=%llu\n", (unsigned long long) m->realtime);
+                if (m->exe)
+                        fprintf(f, "\texe=[%s]\n", m->exe);
+                if (m->comm)
+                        fprintf(f, "\tcomm=[%s]\n", m->comm);
+                if (m->tid_comm)
+                        fprintf(f, "\ttid_comm=[%s]\n", m->tid_comm);
+                if (m->label)
+                        fprintf(f, "\tlabel=[%s]\n", m->label);
+                if (m->cgroup)
+                        fprintf(f, "\tcgroup=[%s]\n", m->cgroup);
+
+                sd_bus_message_get_unit(m, &u);
+                if (u)
+                        fprintf(f, "\tunit=[%s]\n", u);
+                sd_bus_message_get_user_unit(m, &uu);
+                if (uu)
+                        fprintf(f, "\tuser_unit=[%s]\n", uu);
+                sd_bus_message_get_session(m, &s);
+                if (s)
+                        fprintf(f, "\tsession=[%s]\n", s);
+                if (sd_bus_message_get_owner_uid(m, &owner) >= 0)
+                        fprintf(f, "\towner_uid=%lu\n", (unsigned long) owner);
+                if (sd_bus_message_get_audit_loginuid(m, &audit_loginuid) >= 0)
+                        fprintf(f, "\taudit_loginuid=%lu\n", (unsigned long) audit_loginuid);
+                if (sd_bus_message_get_audit_sessionid(m, &audit_sessionid) >= 0)
+                        fprintf(f, "\taudit_sessionid=%lu\n", (unsigned long) audit_sessionid);
+
+                fprintf(f, "\tCAP_KILL=%i\n", sd_bus_message_has_effective_cap(m, 5));
+
+                if (sd_bus_message_get_cmdline(m, &cmdline) >= 0) {
+                        char **c;
+
+                        fputs("\tcmdline=[", f);
+                        STRV_FOREACH(c, cmdline) {
+                                if (c != cmdline)
+                                        fputc(' ', f);
+
+                                fputs(*c, f);
+                        }
 
-                fputs("]\n", stdout);
+                        fputs("]\n", f);
+                }
         }
 
         r = sd_bus_message_rewind(m, true);
@@ -4132,7 +4136,7 @@ int bus_message_dump(sd_bus_message *m) {
                 return r;
         }
 
-        printf("BEGIN_MESSAGE \"%s\" {\n", strempty(m->root_container.signature));
+        fprintf(f, "BEGIN_MESSAGE \"%s\" {\n", strempty(m->root_container.signature));
 
         for(;;) {
                 _cleanup_free_ char *prefix = NULL;
@@ -4173,13 +4177,13 @@ int bus_message_dump(sd_bus_message *m) {
                                 return log_oom();
 
                         if (type == SD_BUS_TYPE_ARRAY)
-                                printf("%s} END_ARRAY \n", prefix);
+                                fprintf(f, "%s} END_ARRAY \n", prefix);
                         else if (type == SD_BUS_TYPE_VARIANT)
-                                printf("%s} END_VARIANT\n", prefix);
+                                fprintf(f, "%s} END_VARIANT\n", prefix);
                         else if (type == SD_BUS_TYPE_STRUCT)
-                                printf("%s} END_STRUCT\n", prefix);
+                                fprintf(f, "%s} END_STRUCT\n", prefix);
                         else if (type == SD_BUS_TYPE_DICT_ENTRY)
-                                printf("%s} END_DICT_ENTRY\n", prefix);
+                                fprintf(f, "%s} END_DICT_ENTRY\n", prefix);
 
                         continue;
                 }
@@ -4196,13 +4200,13 @@ int bus_message_dump(sd_bus_message *m) {
                         }
 
                         if (type == SD_BUS_TYPE_ARRAY)
-                                printf("%sBEGIN_ARRAY \"%s\" {\n", prefix, contents);
+                                fprintf(f, "%sBEGIN_ARRAY \"%s\" {\n", prefix, contents);
                         else if (type == SD_BUS_TYPE_VARIANT)
-                                printf("%sBEGIN_VARIANT \"%s\" {\n", prefix, contents);
+                                fprintf(f, "%sBEGIN_VARIANT \"%s\" {\n", prefix, contents);
                         else if (type == SD_BUS_TYPE_STRUCT)
-                                printf("%sBEGIN_STRUCT \"%s\" {\n", prefix, contents);
+                                fprintf(f, "%sBEGIN_STRUCT \"%s\" {\n", prefix, contents);
                         else if (type == SD_BUS_TYPE_DICT_ENTRY)
-                                printf("%sBEGIN_DICT_ENTRY \"%s\" {\n", prefix, contents);
+                                fprintf(f, "%sBEGIN_DICT_ENTRY \"%s\" {\n", prefix, contents);
 
                         level ++;
 
@@ -4215,58 +4219,60 @@ int bus_message_dump(sd_bus_message *m) {
                         return r;
                 }
 
+                assert(r > 0);
+
                 switch (type) {
 
                 case SD_BUS_TYPE_BYTE:
-                        printf("%sBYTE: %u\n", prefix, basic.u8);
+                        fprintf(f, "%sBYTE: %u\n", prefix, basic.u8);
                         break;
 
                 case SD_BUS_TYPE_BOOLEAN:
-                        printf("%sBOOLEAN: %s\n", prefix, yes_no(basic.i));
+                        fprintf(f, "%sBOOLEAN: %s\n", prefix, yes_no(basic.i));
                         break;
 
                 case SD_BUS_TYPE_INT16:
-                        printf("%sINT16: %i\n", prefix, basic.s16);
+                        fprintf(f, "%sINT16: %i\n", prefix, basic.s16);
                         break;
 
                 case SD_BUS_TYPE_UINT16:
-                        printf("%sUINT16: %u\n", prefix, basic.u16);
+                        fprintf(f, "%sUINT16: %u\n", prefix, basic.u16);
                         break;
 
                 case SD_BUS_TYPE_INT32:
-                        printf("%sINT32: %i\n", prefix, basic.s32);
+                        fprintf(f, "%sINT32: %i\n", prefix, basic.s32);
                         break;
 
                 case SD_BUS_TYPE_UINT32:
-                        printf("%sUINT32: %u\n", prefix, basic.u32);
+                        fprintf(f, "%sUINT32: %u\n", prefix, basic.u32);
                         break;
 
                 case SD_BUS_TYPE_INT64:
-                        printf("%sINT64: %lli\n", prefix, (long long) basic.s64);
+                        fprintf(f, "%sINT64: %lli\n", prefix, (long long) basic.s64);
                         break;
 
                 case SD_BUS_TYPE_UINT64:
-                        printf("%sUINT64: %llu\n", prefix, (unsigned long long) basic.u64);
+                        fprintf(f, "%sUINT64: %llu\n", prefix, (unsigned long long) basic.u64);
                         break;
 
                 case SD_BUS_TYPE_DOUBLE:
-                        printf("%sDOUBLE: %g\n", prefix, basic.d64);
+                        fprintf(f, "%sDOUBLE: %g\n", prefix, basic.d64);
                         break;
 
                 case SD_BUS_TYPE_STRING:
-                        printf("%sSTRING: \"%s\"\n", prefix, basic.string);
+                        fprintf(f, "%sSTRING: \"%s\"\n", prefix, basic.string);
                         break;
 
                 case SD_BUS_TYPE_OBJECT_PATH:
-                        printf("%sOBJECT_PATH: \"%s\"\n", prefix, basic.string);
+                        fprintf(f, "%sOBJECT_PATH: \"%s\"\n", prefix, basic.string);
                         break;
 
                 case SD_BUS_TYPE_SIGNATURE:
-                        printf("%sSIGNATURE: \"%s\"\n", prefix, basic.string);
+                        fprintf(f, "%sSIGNATURE: \"%s\"\n", prefix, basic.string);
                         break;
 
                 case SD_BUS_TYPE_UNIX_FD:
-                        printf("%sUNIX_FD: %i\n", prefix, basic.i);
+                        fprintf(f, "%sUNIX_FD: %i\n", prefix, basic.i);
                         break;
 
                 default:
@@ -4274,7 +4280,7 @@ int bus_message_dump(sd_bus_message *m) {
                 }
         }
 
-        printf("} END_MESSAGE\n");
+        fprintf(f, "} END_MESSAGE\n");
         return 0;
 }
 
@@ -4420,3 +4426,102 @@ const char* sd_bus_message_get_signature(sd_bus_message *m, int complete) {
         c = complete ? &m->root_container : message_get_container(m);
         return c->signature ?: "";
 }
+
+int sd_bus_message_copy(sd_bus_message *m, sd_bus_message *source, int all) {
+        bool done_something = false;
+        int r;
+
+        do {
+                const char *contents;
+                char type;
+                union {
+                        uint8_t u8;
+                        uint16_t u16;
+                        int16_t s16;
+                        uint32_t u32;
+                        int32_t s32;
+                        uint64_t u64;
+                        int64_t s64;
+                        double d64;
+                        const char *string;
+                        int i;
+                } basic;
+
+                r = sd_bus_message_peek_type(source, &type, &contents);
+                if (r < 0)
+                        return r;
+                if (r == 0)
+                        break;
+
+                done_something = true;
+
+                if (bus_type_is_container(type) > 0) {
+
+                        r = sd_bus_message_enter_container(source, type, contents);
+                        if (r < 0)
+                                return r;
+
+                        r = sd_bus_message_open_container(m, type, contents);
+                        if (r < 0)
+                                return r;
+
+                        r = sd_bus_message_copy(m, source, true);
+                        if (r < 0)
+                                return r;
+
+                        r = sd_bus_message_close_container(m);
+                        if (r < 0)
+                                return r;
+
+                        r = sd_bus_message_exit_container(source);
+                        if (r < 0)
+                                return r;
+
+                        continue;
+                }
+
+                r = sd_bus_message_read_basic(source, type, &basic);
+                if (r < 0)
+                        return r;
+
+                assert(r > 0);
+
+                if (type == SD_BUS_TYPE_OBJECT_PATH ||
+                    type == SD_BUS_TYPE_SIGNATURE ||
+                    type == SD_BUS_TYPE_STRING)
+                        r = sd_bus_message_append_basic(m, type, basic.string);
+                else
+                        r = sd_bus_message_append_basic(m, type, &basic);
+
+                if (r < 0)
+                        return r;
+
+        } while (all);
+
+        return done_something;
+}
+
+int sd_bus_message_verify_type(sd_bus_message *m, char type, const char *contents) {
+        const char *c;
+        char t;
+        int r;
+
+        assert_return(m, -EINVAL);
+        assert_return(m->sealed, -EPERM);
+        assert_return(!type || bus_type_is_valid(type), -EINVAL);
+        assert_return(!contents || signature_is_valid(contents, true), -EINVAL);
+        assert_return(type || contents, -EINVAL);
+        assert_return(!contents || !type || bus_type_is_container(type), -EINVAL);
+
+        r = sd_bus_message_peek_type(m, &t, &c);
+        if (r <= 0)
+                return r;
+
+        if (type != 0 && type != t)
+                return 0;
+
+        if (contents && !streq_ptr(contents, c))
+                return 0;
+
+        return 1;
+}
diff --git a/src/libsystemd-bus/bus-message.h b/src/libsystemd-bus/bus-message.h
index c79ff1b..d0f11d8 100644
--- a/src/libsystemd-bus/bus-message.h
+++ b/src/libsystemd-bus/bus-message.h
@@ -190,7 +190,7 @@ static inline void* BUS_MESSAGE_FIELDS(sd_bus_message *m) {
 }
 
 int bus_message_seal(sd_bus_message *m, uint64_t serial);
-int bus_message_dump(sd_bus_message *m);
+int bus_message_dump(sd_bus_message *m, FILE *f, bool with_header);
 int bus_message_get_blob(sd_bus_message *m, void **buffer, size_t *sz);
 int bus_message_read_strv_extend(sd_bus_message *m, char ***l);
 
diff --git a/src/libsystemd-bus/busctl.c b/src/libsystemd-bus/busctl.c
index b15b41a..cb7d258 100644
--- a/src/libsystemd-bus/busctl.c
+++ b/src/libsystemd-bus/busctl.c
@@ -158,7 +158,7 @@ static int monitor(sd_bus *bus, char *argv[]) {
                 }
 
                 if (m) {
-                        bus_message_dump(m);
+                        bus_message_dump(m, stdout, true);
                         continue;
                 }
 
diff --git a/src/libsystemd-bus/test-bus-kernel.c b/src/libsystemd-bus/test-bus-kernel.c
index 075903c..e498801 100644
--- a/src/libsystemd-bus/test-bus-kernel.c
+++ b/src/libsystemd-bus/test-bus-kernel.c
@@ -103,7 +103,7 @@ int main(int argc, char *argv[]) {
         assert_se(r > 0);
         assert_se(m);
 
-        bus_message_dump(m);
+        bus_message_dump(m, stdout, true);
         assert_se(sd_bus_message_rewind(m, true) >= 0);
 
         r = sd_bus_message_read(m, "s", &the_string);
@@ -142,7 +142,7 @@ int main(int argc, char *argv[]) {
                 assert_se(r > 0);
                 assert_se(m);
 
-                bus_message_dump(m);
+                bus_message_dump(m, stdout, true);
                 assert_se(sd_bus_message_rewind(m, true) >= 0);
 
                 if (sd_bus_message_is_method_call(m, "an.inter.face", "AMethod")) {
diff --git a/src/libsystemd-bus/test-bus-marshal.c b/src/libsystemd-bus/test-bus-marshal.c
index 1e2caa0..baa269c 100644
--- a/src/libsystemd-bus/test-bus-marshal.c
+++ b/src/libsystemd-bus/test-bus-marshal.c
@@ -37,7 +37,7 @@
 #include "bus-util.h"
 
 int main(int argc, char *argv[]) {
-        _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
+        _cleanup_bus_message_unref_ sd_bus_message *m = NULL, *copy = NULL;
         int r, boolean;
         const char *x, *y, *z, *a, *b, *c, *d;
         uint8_t u, v;
@@ -46,6 +46,9 @@ int main(int argc, char *argv[]) {
         char *h;
         const int32_t integer_array[] = { -1, -2, 0, 1, 2 }, *return_array;
         char *s;
+        _cleanup_free_ char *first = NULL, *second = NULL, *third = NULL;
+        _cleanup_fclose_ FILE *ms = NULL;
+        size_t first_size = 0, second_size = 0, third_size = 0;
 
         r = sd_bus_message_new_method_call(NULL, "foobar.waldo", "/", "foobar.waldo", "Piep", &m);
         assert_se(r >= 0);
@@ -90,7 +93,12 @@ int main(int argc, char *argv[]) {
         r = bus_message_seal(m, 4711);
         assert_se(r >= 0);
 
-        bus_message_dump(m);
+        bus_message_dump(m, stdout, true);
+
+        ms = open_memstream(&first, &first_size);
+        bus_message_dump(m, ms, false);
+        fflush(ms);
+        assert_se(!ferror(ms));
 
         r = bus_message_get_blob(m, &buffer, &sz);
         assert_se(r >= 0);
@@ -136,7 +144,15 @@ int main(int argc, char *argv[]) {
         r = bus_message_from_malloc(buffer, sz, NULL, 0, NULL, NULL, &m);
         assert_se(r >= 0);
 
-        bus_message_dump(m);
+        bus_message_dump(m, stdout, true);
+
+        fclose(ms);
+        ms = open_memstream(&second, &second_size);
+        bus_message_dump(m, ms, false);
+        fflush(ms);
+        assert_se(!ferror(ms));
+        assert_se(first_size == second_size);
+        assert_se(memcmp(first, second, first_size) == 0);
 
         assert_se(sd_bus_message_rewind(m, true) >= 0);
 
@@ -173,6 +189,8 @@ int main(int argc, char *argv[]) {
         assert_se(streq(c, "ccc"));
         assert_se(streq(d, "3"));
 
+        assert_se(sd_bus_message_verify_type(m, 'a', "s") > 0);
+
         r = sd_bus_message_read(m, "as", 2, &x, &y);
         assert_se(r > 0);
         assert_se(streq(x, "foobar"));
@@ -190,5 +208,29 @@ int main(int argc, char *argv[]) {
         r = sd_bus_message_peek_type(m, NULL, NULL);
         assert_se(r == 0);
 
+        r = sd_bus_message_new_method_call(NULL, "foobar.waldo", "/", "foobar.waldo", "Piep", &copy);
+        assert_se(r >= 0);
+
+        r = sd_bus_message_rewind(m, true);
+        assert_se(r >= 0);
+
+        r = sd_bus_message_copy(copy, m, true);
+        assert_se(r >= 0);
+
+        r = bus_message_seal(copy, 4712);
+        assert_se(r >= 0);
+
+        fclose(ms);
+        ms = open_memstream(&third, &third_size);
+        bus_message_dump(copy, ms, false);
+        fflush(ms);
+        assert_se(!ferror(ms));
+
+        printf("<%.*s>", (int) first_size, first);
+        printf("<%.*s>", (int) third_size, third);
+
+        assert_se(first_size == third_size);
+        assert_se(memcmp(first, third, third_size) == 0);
+
         return 0;
 }
diff --git a/src/libsystemd-bus/test-bus-objects.c b/src/libsystemd-bus/test-bus-objects.c
index 8758404..e7b9321 100644
--- a/src/libsystemd-bus/test-bus-objects.c
+++ b/src/libsystemd-bus/test-bus-objects.c
@@ -366,7 +366,7 @@ static int client(struct context *c) {
         r = sd_bus_call_method(bus, "org.freedesktop.systemd.test", "/foo", "org.freedesktop.DBus.Properties", "GetAll", &error, &reply, "s", "");
         assert_se(r >= 0);
 
-        bus_message_dump(reply);
+        bus_message_dump(reply, stdout, true);
 
         sd_bus_message_unref(reply);
         reply = NULL;
@@ -384,7 +384,7 @@ static int client(struct context *c) {
         r = sd_bus_call_method(bus, "org.freedesktop.systemd.test", "/value", "org.freedesktop.DBus.ObjectManager", "GetManagedObjects", &error, &reply, "");
         assert_se(r >= 0);
 
-        bus_message_dump(reply);
+        bus_message_dump(reply, stdout, true);
 
         sd_bus_message_unref(reply);
         reply = NULL;
@@ -396,7 +396,7 @@ static int client(struct context *c) {
         assert_se(r > 0);
 
         assert_se(sd_bus_message_is_signal(reply, "org.freedesktop.DBus.Properties", "PropertiesChanged"));
-        bus_message_dump(reply);
+        bus_message_dump(reply, stdout, true);
 
         sd_bus_message_unref(reply);
         reply = NULL;
@@ -408,7 +408,7 @@ static int client(struct context *c) {
         assert_se(r > 0);
 
         assert_se(sd_bus_message_is_signal(reply, "org.freedesktop.DBus.ObjectManager", "InterfacesAdded"));
-        bus_message_dump(reply);
+        bus_message_dump(reply, stdout, true);
 
         sd_bus_message_unref(reply);
         reply = NULL;
@@ -420,7 +420,7 @@ static int client(struct context *c) {
         assert_se(r > 0);
 
         assert_se(sd_bus_message_is_signal(reply, "org.freedesktop.DBus.ObjectManager", "InterfacesRemoved"));
-        bus_message_dump(reply);
+        bus_message_dump(reply, stdout, true);
 
         sd_bus_message_unref(reply);
         reply = NULL;
diff --git a/src/libsystemd-bus/test-bus-zero-copy.c b/src/libsystemd-bus/test-bus-zero-copy.c
index db3906e..0c07a33 100644
--- a/src/libsystemd-bus/test-bus-zero-copy.c
+++ b/src/libsystemd-bus/test-bus-zero-copy.c
@@ -130,7 +130,7 @@ int main(int argc, char *argv[]) {
         r = bus_message_seal(m, 55);
         assert_se(r >= 0);
 
-        bus_message_dump(m);
+        bus_message_dump(m, stdout, true);
 
         r = sd_bus_send(b, m, NULL);
         assert_se(r >= 0);
@@ -140,7 +140,7 @@ int main(int argc, char *argv[]) {
         r = sd_bus_process(a, &m);
         assert_se(r > 0);
 
-        bus_message_dump(m);
+        bus_message_dump(m, stdout, true);
         sd_bus_message_rewind(m, true);
 
         r = sd_bus_message_enter_container(m, 'r', "aysay");
diff --git a/src/systemd/sd-bus.h b/src/systemd/sd-bus.h
index c36ea5a..a98887d 100644
--- a/src/systemd/sd-bus.h
+++ b/src/systemd/sd-bus.h
@@ -190,6 +190,7 @@ int sd_bus_message_append_string_memfd(sd_bus_message *m, sd_memfd* memfd);
 int sd_bus_message_append_strv(sd_bus_message *m, char **l);
 int sd_bus_message_open_container(sd_bus_message *m, char type, const char *contents);
 int sd_bus_message_close_container(sd_bus_message *m);
+int sd_bus_message_copy(sd_bus_message *m, sd_bus_message *source, int all);
 
 int sd_bus_message_read(sd_bus_message *m, const char *types, ...);
 int sd_bus_message_read_basic(sd_bus_message *m, char type, void *p);
@@ -197,6 +198,7 @@ int sd_bus_message_read_array(sd_bus_message *m, char type, const void **ptr, si
 int sd_bus_message_enter_container(sd_bus_message *m, char type, const char *contents);
 int sd_bus_message_exit_container(sd_bus_message *m);
 int sd_bus_message_peek_type(sd_bus_message *m, char *type, const char **contents);
+int sd_bus_message_verify_type(sd_bus_message *m, char type, const char *contents);
 int sd_bus_message_rewind(sd_bus_message *m, int complete);
 
 /* Convenience calls */



More information about the systemd-commits mailing list