예제 #1
0
static int operation_done(sd_event_source *s, const siginfo_t *si, void *userdata) {
        _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
        Operation *o = userdata;
        int r;

        assert(o);
        assert(si);

        log_debug("Operating " PID_FMT " is now complete with code=%s status=%i",
                  o->pid,
                  sigchld_code_to_string(si->si_code), si->si_status);

        o->pid = 0;

        if (si->si_code != CLD_EXITED) {
                r = sd_bus_error_setf(&error, SD_BUS_ERROR_FAILED, "Child died abnormally.");
                goto fail;
        }

        if (si->si_status == EXIT_SUCCESS)
                r = 0;
        else if (read(o->errno_fd, &r, sizeof(r)) != sizeof(r)) { /* Try to acquire error code for failed operation */
                r = sd_bus_error_setf(&error, SD_BUS_ERROR_FAILED, "Child failed.");
                goto fail;
        }

        if (o->done) {
                /* A completion routine is set for this operation, call it. */
                r = o->done(o, r, &error);
                if (r < 0) {
                        if (!sd_bus_error_is_set(&error))
                                sd_bus_error_set_errno(&error, r);

                        goto fail;
                }

        } else {
                /* The default operation when done is to simply return an error on failure or an empty success
                 * message on success. */
                if (r < 0) {
                        sd_bus_error_set_errno(&error, r);
                        goto fail;
                }

                r = sd_bus_reply_method_return(o->message, NULL);
                if (r < 0)
                        log_error_errno(r, "Failed to reply to message: %m");
        }

        operation_free(o);
        return 0;

fail:
        r = sd_bus_reply_method_error(o->message, &error);
        if (r < 0)
                log_error_errno(r, "Failed to reply to message: %m");

        operation_free(o);
        return 0;
}
예제 #2
0
int bus_machine_method_get_addresses(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
        _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
        _cleanup_close_pair_ int pair[2] = { -1, -1 };
        _cleanup_free_ char *us = NULL, *them = NULL;
        _cleanup_close_ int netns_fd = -1;
        Machine *m = userdata;
        const char *p;
        siginfo_t si;
        pid_t child;
        int r;

        assert(bus);
        assert(message);
        assert(m);

        r = readlink_malloc("/proc/self/ns/net", &us);
        if (r < 0)
                return sd_bus_error_set_errno(error, r);

        p = procfs_file_alloca(m->leader, "ns/net");
        r = readlink_malloc(p, &them);
        if (r < 0)
                return sd_bus_error_set_errno(error, r);

        if (streq(us, them))
                return sd_bus_error_setf(error, BUS_ERROR_NO_PRIVATE_NETWORKING, "Machine %s does not use private networking", m->name);

        r = namespace_open(m->leader, NULL, NULL, &netns_fd, NULL);
        if (r < 0)
                return sd_bus_error_set_errno(error, r);

        if (socketpair(AF_UNIX, SOCK_SEQPACKET, 0, pair) < 0)
                return sd_bus_error_set_errno(error, -errno);

        child = fork();
        if (child < 0)
                return sd_bus_error_set_errno(error, -errno);

        if (child == 0) {
                _cleanup_free_ struct local_address *addresses = NULL;
                struct local_address *a;
                int i, n;

                pair[0] = safe_close(pair[0]);

                r = namespace_enter(-1, -1, netns_fd, -1);
                if (r < 0)
                        _exit(EXIT_FAILURE);

                n = local_addresses(NULL, 0, &addresses);
                if (n < 0)
                        _exit(EXIT_FAILURE);

                for (a = addresses, i = 0; i < n; a++, i++) {
                        struct iovec iov[2] = {
                                { .iov_base = &a->family, .iov_len = sizeof(a->family) },
                                { .iov_base = &a->address, .iov_len = FAMILY_ADDRESS_SIZE(a->family) },
                        };
예제 #3
0
int bus_name_has_owner(sd_bus *c, const char *name, sd_bus_error *error) {
        _cleanup_bus_message_unref_ sd_bus_message *rep = NULL;
        int r, has_owner = 0;

        assert(c);
        assert(name);

        r = sd_bus_call_method(c,
                               "org.freedesktop.DBus",
                               "/org/freedesktop/dbus",
                               "org.freedesktop.DBus",
                               "NameHasOwner",
                               error,
                               &rep,
                               "s",
                               name);
        if (r < 0)
                return r;

        r = sd_bus_message_read_basic(rep, 'b', &has_owner);
        if (r < 0)
                return sd_bus_error_set_errno(error, r);

        return has_owner;
}
예제 #4
0
_public_ int sd_bus_reply_method_errno(
                sd_bus_message *call,
                int error,
                const sd_bus_error *p) {

        _cleanup_bus_error_free_ sd_bus_error berror = SD_BUS_ERROR_NULL;

        assert_return(call, -EINVAL);
        assert_return(call->sealed, -EPERM);
        assert_return(call->header->type == SD_BUS_MESSAGE_METHOD_CALL, -EINVAL);
        assert_return(call->bus, -EINVAL);
        assert_return(!bus_pid_changed(call->bus), -ECHILD);

        if (!BUS_IS_OPEN(call->bus->state))
                return -ENOTCONN;

        if (call->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED)
                return 0;

        if (sd_bus_error_is_set(p))
                return sd_bus_reply_method_error(call, p);

        sd_bus_error_set_errno(&berror, error);

        return sd_bus_reply_method_error(call, &berror);
}
예제 #5
0
_public_ int sd_bus_set_property(
                sd_bus *bus,
                const char *destination,
                const char *path,
                const char *interface,
                const char *member,
                sd_bus_error *error,
                const char *type, ...) {

        _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
        va_list ap;
        int r;

        bus_assert_return(bus, -EINVAL, error);
        bus_assert_return(isempty(interface) || interface_name_is_valid(interface), -EINVAL, error);
        bus_assert_return(member_name_is_valid(member), -EINVAL, error);
        bus_assert_return(signature_is_single(type, false), -EINVAL, error);
        bus_assert_return(!bus_pid_changed(bus), -ECHILD, error);

        if (!BUS_IS_OPEN(bus->state)) {
                r = -ENOTCONN;
                goto fail;
        }

        r = sd_bus_message_new_method_call(bus, &m, destination, path, "org.freedesktop.DBus.Properties", "Set");
        if (r < 0)
                goto fail;

        r = sd_bus_message_append(m, "ss", strempty(interface), member);
        if (r < 0)
                goto fail;

        r = sd_bus_message_open_container(m, 'v', type);
        if (r < 0)
                goto fail;

        va_start(ap, type);
        r = sd_bus_message_appendv(m, type, ap);
        va_end(ap);
        if (r < 0)
                goto fail;

        r = sd_bus_message_close_container(m);
        if (r < 0)
                goto fail;

        return sd_bus_call(bus, m, 0, error, NULL);

fail:
        return sd_bus_error_set_errno(error, r);
}
예제 #6
0
_public_ int sd_bus_get_property_string(
                sd_bus *bus,
                const char *destination,
                const char *path,
                const char *interface,
                const char *member,
                sd_bus_error *error,
                char **ret) {

        _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
        const char *s;
        char *n;
        int r;

        bus_assert_return(bus, -EINVAL, error);
        bus_assert_return(isempty(interface) || interface_name_is_valid(interface), -EINVAL, error);
        bus_assert_return(member_name_is_valid(member), -EINVAL, error);
        bus_assert_return(ret, -EINVAL, error);
        bus_assert_return(!bus_pid_changed(bus), -ECHILD, error);

        if (!BUS_IS_OPEN(bus->state)) {
                r = -ENOTCONN;
                goto fail;
        }

        r = sd_bus_call_method(bus, destination, path, "org.freedesktop.DBus.Properties", "Get", error, &reply, "ss", strempty(interface), member);
        if (r < 0)
                return r;

        r = sd_bus_message_enter_container(reply, 'v', "s");
        if (r < 0)
                goto fail;

        r = sd_bus_message_read_basic(reply, 's', &s);
        if (r < 0)
                goto fail;

        n = strdup(s);
        if (!n) {
                r = -ENOMEM;
                goto fail;
        }

        *ret = n;
        return 0;

fail:
        return sd_bus_error_set_errno(error, r);
}
예제 #7
0
_public_ int sd_bus_get_property_trivial(
                sd_bus *bus,
                const char *destination,
                const char *path,
                const char *interface,
                const char *member,
                sd_bus_error *error,
                char type, void *ptr) {

        _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
        int r;

        bus_assert_return(bus, -EINVAL, error);
        bus_assert_return(isempty(interface) || interface_name_is_valid(interface), -EINVAL, error);
        bus_assert_return(member_name_is_valid(member), -EINVAL, error);
        bus_assert_return(bus_type_is_trivial(type), -EINVAL, error);
        bus_assert_return(ptr, -EINVAL, error);
        bus_assert_return(!bus_pid_changed(bus), -ECHILD, error);

        if (!BUS_IS_OPEN(bus->state)) {
                r = -ENOTCONN;
                goto fail;
        }

        r = sd_bus_call_method(bus, destination, path, "org.freedesktop.DBus.Properties", "Get", error, &reply, "ss", strempty(interface), member);
        if (r < 0)
                return r;

        r = sd_bus_message_enter_container(reply, 'v', CHAR_TO_STR(type));
        if (r < 0)
                goto fail;

        r = sd_bus_message_read_basic(reply, type, ptr);
        if (r < 0)
                goto fail;

        return 0;

fail:
        return sd_bus_error_set_errno(error, r);
}
예제 #8
0
_public_ int sd_bus_get_property(
                sd_bus *bus,
                const char *destination,
                const char *path,
                const char *interface,
                const char *member,
                sd_bus_error *error,
                sd_bus_message **reply,
                const char *type) {

        sd_bus_message *rep = NULL;
        int r;

        bus_assert_return(bus, -EINVAL, error);
        bus_assert_return(isempty(interface) || interface_name_is_valid(interface), -EINVAL, error);
        bus_assert_return(member_name_is_valid(member), -EINVAL, error);
        bus_assert_return(reply, -EINVAL, error);
        bus_assert_return(signature_is_single(type, false), -EINVAL, error);
        bus_assert_return(!bus_pid_changed(bus), -ECHILD, error);

        if (!BUS_IS_OPEN(bus->state)) {
                r = -ENOTCONN;
                goto fail;
        }

        r = sd_bus_call_method(bus, destination, path, "org.freedesktop.DBus.Properties", "Get", error, &rep, "ss", strempty(interface), member);
        if (r < 0)
                return r;

        r = sd_bus_message_enter_container(rep, 'v', type);
        if (r < 0) {
                sd_bus_message_unref(rep);
                goto fail;
        }

        *reply = rep;
        return 0;

fail:
        return sd_bus_error_set_errno(error, r);
}
예제 #9
0
_public_ int sd_bus_call_method(
                sd_bus *bus,
                const char *destination,
                const char *path,
                const char *interface,
                const char *member,
                sd_bus_error *error,
                sd_bus_message **reply,
                const char *types, ...) {

        _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
        int r;

        bus_assert_return(bus, -EINVAL, error);
        bus_assert_return(!bus_pid_changed(bus), -ECHILD, error);

        if (!BUS_IS_OPEN(bus->state)) {
                r = -ENOTCONN;
                goto fail;
        }

        r = sd_bus_message_new_method_call(bus, &m, destination, path, interface, member);
        if (r < 0)
                goto fail;

        if (!isempty(types)) {
                va_list ap;

                va_start(ap, types);
                r = sd_bus_message_appendv(m, types, ap);
                va_end(ap);
                if (r < 0)
                        goto fail;
        }

        return sd_bus_call(bus, m, 0, error, reply);

fail:
        return sd_bus_error_set_errno(error, r);
}
예제 #10
0
int main(int argc, char *argv[]) {

    _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL, second = SD_BUS_ERROR_NULL;
    const sd_bus_error const_error = SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_FILE_EXISTS, "const error");
    const sd_bus_error temporarily_const_error = {
        .name = SD_BUS_ERROR_ACCESS_DENIED,
        .message = "oh! no",
        ._need_free = -1
    };

    assert_se(!sd_bus_error_is_set(&error));
    assert_se(sd_bus_error_set(&error, SD_BUS_ERROR_NOT_SUPPORTED, "xxx") == -ENOTSUP);
    assert_se(streq(error.name, SD_BUS_ERROR_NOT_SUPPORTED));
    assert_se(streq(error.message, "xxx"));
    assert_se(sd_bus_error_has_name(&error, SD_BUS_ERROR_NOT_SUPPORTED));
    assert_se(sd_bus_error_get_errno(&error) == ENOTSUP);
    assert_se(sd_bus_error_is_set(&error));
    sd_bus_error_free(&error);

    assert_se(!sd_bus_error_is_set(&error));
    assert_se(sd_bus_error_setf(&error, SD_BUS_ERROR_FILE_NOT_FOUND, "yyy %i", -1) == -ENOENT);
    assert_se(streq(error.name, SD_BUS_ERROR_FILE_NOT_FOUND));
    assert_se(streq(error.message, "yyy -1"));
    assert_se(sd_bus_error_has_name(&error, SD_BUS_ERROR_FILE_NOT_FOUND));
    assert_se(sd_bus_error_get_errno(&error) == ENOENT);
    assert_se(sd_bus_error_is_set(&error));

    assert_se(!sd_bus_error_is_set(&second));
    assert_se(second._need_free == 0);
    assert_se(error._need_free > 0);
    assert_se(sd_bus_error_copy(&second, &error) == -ENOENT);
    assert_se(second._need_free > 0);
    assert_se(streq(error.name, second.name));
    assert_se(streq(error.message, second.message));
    assert_se(sd_bus_error_get_errno(&second) == ENOENT);
    assert_se(sd_bus_error_has_name(&second, SD_BUS_ERROR_FILE_NOT_FOUND));
    assert_se(sd_bus_error_is_set(&second));

    sd_bus_error_free(&error);
    sd_bus_error_free(&second);

    assert_se(!sd_bus_error_is_set(&second));
    assert_se(const_error._need_free == 0);
    assert_se(sd_bus_error_copy(&second, &const_error) == -EEXIST);
    assert_se(second._need_free == 0);
    assert_se(streq(const_error.name, second.name));
    assert_se(streq(const_error.message, second.message));
    assert_se(sd_bus_error_get_errno(&second) == EEXIST);
    assert_se(sd_bus_error_has_name(&second, SD_BUS_ERROR_FILE_EXISTS));
    assert_se(sd_bus_error_is_set(&second));
    sd_bus_error_free(&second);

    assert_se(!sd_bus_error_is_set(&second));
    assert_se(temporarily_const_error._need_free < 0);
    assert_se(sd_bus_error_copy(&second, &temporarily_const_error) == -EACCES);
    assert_se(second._need_free > 0);
    assert_se(streq(temporarily_const_error.name, second.name));
    assert_se(streq(temporarily_const_error.message, second.message));
    assert_se(sd_bus_error_get_errno(&second) == EACCES);
    assert_se(sd_bus_error_has_name(&second, SD_BUS_ERROR_ACCESS_DENIED));
    assert_se(sd_bus_error_is_set(&second));

    assert_se(!sd_bus_error_is_set(&error));
    assert_se(sd_bus_error_set_const(&error, "System.Error.EUCLEAN", "Hallo") == -EUCLEAN);
    assert_se(streq(error.name, "System.Error.EUCLEAN"));
    assert_se(streq(error.message, "Hallo"));
    assert_se(sd_bus_error_has_name(&error, "System.Error.EUCLEAN"));
    assert_se(sd_bus_error_get_errno(&error) == EUCLEAN);
    assert_se(sd_bus_error_is_set(&error));
    sd_bus_error_free(&error);

    assert_se(!sd_bus_error_is_set(&error));
    assert_se(sd_bus_error_set_errno(&error, EBUSY) == -EBUSY);
    assert_se(streq(error.name, "System.Error.EBUSY"));
    assert_se(streq(error.message, strerror(EBUSY)));
    assert_se(sd_bus_error_has_name(&error, "System.Error.EBUSY"));
    assert_se(sd_bus_error_get_errno(&error) == EBUSY);
    assert_se(sd_bus_error_is_set(&error));
    sd_bus_error_free(&error);

    assert_se(!sd_bus_error_is_set(&error));
    assert_se(sd_bus_error_set_errnof(&error, EIO, "Waldi %c", 'X') == -EIO);
    assert_se(streq(error.name, SD_BUS_ERROR_IO_ERROR));
    assert_se(streq(error.message, "Waldi X"));
    assert_se(sd_bus_error_has_name(&error, SD_BUS_ERROR_IO_ERROR));
    assert_se(sd_bus_error_get_errno(&error) == EIO);
    assert_se(sd_bus_error_is_set(&error));

    return 0;
}
예제 #11
0
static void test_error(void) {
        _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL, second = SD_BUS_ERROR_NULL;
        const sd_bus_error const_error = SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_FILE_EXISTS, "const error");
        const sd_bus_error temporarily_const_error = {
                .name = SD_BUS_ERROR_ACCESS_DENIED,
                .message = "oh! no",
                ._need_free = -1
        };

        assert_se(!sd_bus_error_is_set(&error));
        assert_se(sd_bus_error_set(&error, SD_BUS_ERROR_NOT_SUPPORTED, "xxx") == -EOPNOTSUPP);
        assert_se(streq(error.name, SD_BUS_ERROR_NOT_SUPPORTED));
        assert_se(streq(error.message, "xxx"));
        assert_se(sd_bus_error_has_name(&error, SD_BUS_ERROR_NOT_SUPPORTED));
        assert_se(sd_bus_error_get_errno(&error) == EOPNOTSUPP);
        assert_se(sd_bus_error_is_set(&error));
        sd_bus_error_free(&error);

        assert_se(!sd_bus_error_is_set(&error));
        assert_se(sd_bus_error_setf(&error, SD_BUS_ERROR_FILE_NOT_FOUND, "yyy %i", -1) == -ENOENT);
        assert_se(streq(error.name, SD_BUS_ERROR_FILE_NOT_FOUND));
        assert_se(streq(error.message, "yyy -1"));
        assert_se(sd_bus_error_has_name(&error, SD_BUS_ERROR_FILE_NOT_FOUND));
        assert_se(sd_bus_error_get_errno(&error) == ENOENT);
        assert_se(sd_bus_error_is_set(&error));

        assert_se(!sd_bus_error_is_set(&second));
        assert_se(second._need_free == 0);
        assert_se(error._need_free > 0);
        assert_se(sd_bus_error_copy(&second, &error) == -ENOENT);
        assert_se(second._need_free > 0);
        assert_se(streq(error.name, second.name));
        assert_se(streq(error.message, second.message));
        assert_se(sd_bus_error_get_errno(&second) == ENOENT);
        assert_se(sd_bus_error_has_name(&second, SD_BUS_ERROR_FILE_NOT_FOUND));
        assert_se(sd_bus_error_is_set(&second));

        sd_bus_error_free(&error);
        sd_bus_error_free(&second);

        assert_se(!sd_bus_error_is_set(&second));
        assert_se(const_error._need_free == 0);
        assert_se(sd_bus_error_copy(&second, &const_error) == -EEXIST);
        assert_se(second._need_free == 0);
        assert_se(streq(const_error.name, second.name));
        assert_se(streq(const_error.message, second.message));
        assert_se(sd_bus_error_get_errno(&second) == EEXIST);
        assert_se(sd_bus_error_has_name(&second, SD_BUS_ERROR_FILE_EXISTS));
        assert_se(sd_bus_error_is_set(&second));
        sd_bus_error_free(&second);

        assert_se(!sd_bus_error_is_set(&second));
        assert_se(temporarily_const_error._need_free < 0);
        assert_se(sd_bus_error_copy(&second, &temporarily_const_error) == -EACCES);
        assert_se(second._need_free > 0);
        assert_se(streq(temporarily_const_error.name, second.name));
        assert_se(streq(temporarily_const_error.message, second.message));
        assert_se(sd_bus_error_get_errno(&second) == EACCES);
        assert_se(sd_bus_error_has_name(&second, SD_BUS_ERROR_ACCESS_DENIED));
        assert_se(sd_bus_error_is_set(&second));

        assert_se(!sd_bus_error_is_set(&error));
        assert_se(sd_bus_error_set_const(&error, "System.Error.EUCLEAN", "Hallo") == -EUCLEAN);
        assert_se(streq(error.name, "System.Error.EUCLEAN"));
        assert_se(streq(error.message, "Hallo"));
        assert_se(sd_bus_error_has_name(&error, "System.Error.EUCLEAN"));
        assert_se(sd_bus_error_get_errno(&error) == EUCLEAN);
        assert_se(sd_bus_error_is_set(&error));
        sd_bus_error_free(&error);

        assert_se(!sd_bus_error_is_set(&error));
        assert_se(sd_bus_error_set_errno(&error, EBUSY) == -EBUSY);
        assert_se(streq(error.name, "System.Error.EBUSY"));
        assert_se(streq(error.message, strerror(EBUSY)));
        assert_se(sd_bus_error_has_name(&error, "System.Error.EBUSY"));
        assert_se(sd_bus_error_get_errno(&error) == EBUSY);
        assert_se(sd_bus_error_is_set(&error));
        sd_bus_error_free(&error);

        assert_se(!sd_bus_error_is_set(&error));
        assert_se(sd_bus_error_set_errnof(&error, EIO, "Waldi %c", 'X') == -EIO);
        assert_se(streq(error.name, SD_BUS_ERROR_IO_ERROR));
        assert_se(streq(error.message, "Waldi X"));
        assert_se(sd_bus_error_has_name(&error, SD_BUS_ERROR_IO_ERROR));
        assert_se(sd_bus_error_get_errno(&error) == EIO);
        assert_se(sd_bus_error_is_set(&error));
}

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_error_map *m;

        printf("----- errno mappings ------\n");
        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");
}

static void test_errno_mapping_standard(void) {
        assert_se(sd_bus_error_set(NULL, "System.Error.EUCLEAN", NULL) == -EUCLEAN);
        assert_se(sd_bus_error_set(NULL, "System.Error.EBUSY", NULL) == -EBUSY);
        assert_se(sd_bus_error_set(NULL, "System.Error.EINVAL", NULL) == -EINVAL);
        assert_se(sd_bus_error_set(NULL, "System.Error.WHATSIT", NULL) == -EIO);
}