Coverage Report

Created: 2026-01-17 06:15

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/dbus-broker/src/dbus/address.c
Line
Count
Source
1
/*
2
 * D-Bus Peer Addresses
3
 *
4
 * The D-Bus message broker requires peers to always address the destination of
5
 * their messages. Those addresses can come in different styles. The 'Address'
6
 * type implemented here parses or writes such addresses, hiding the details
7
 * behind a simple API.
8
 *
9
 * The 'Address' type is supposed to live on the stack. It can be initialized
10
 * either from one of the source addresses (a unique ID, a well-known name, ..)
11
 * or it can parse a user-supplied string.
12
 * The structure is open-coded and can be accesses directly. It consists of a
13
 * 'type' field that identifies the address type, and a union carrying the
14
 * parsed data.
15
 */
16
17
#include <c-stdaux.h>
18
#include <stdlib.h>
19
#include "dbus/address.h"
20
21
/**
22
 * address_init_from_id() - initialize ID address
23
 * @address:            address to operate on
24
 * @id:                 ID to use
25
 *
26
 * This initializes the address @address to be of type ADDRESS_TYPE_ID with ID
27
 * @id.
28
 */
29
0
void address_init_from_id(Address *address, uint64_t id) {
30
0
        *address = (Address)ADDRESS_INIT_ID(id);
31
0
}
32
33
/**
34
 * address_init_from_name() - initialize name address
35
 * @address:            address to operate on
36
 * @name:               name to use
37
 *
38
 * This initializes the address @address to be of type ADDRESS_TYPE_NAME with
39
 * name @name.
40
 *
41
 * Note that @name is *NOT* copied into @address. That is, the lifetime of
42
 * @address is bound to @name.
43
 */
44
0
void address_init_from_name(Address *address, const char *name) {
45
0
        *address = (Address)ADDRESS_INIT_NAME(name);
46
0
}
47
48
/**
49
 * address_from_string() - initialize address from string representation
50
 * @address:            address to operate on
51
 * @string:             string to use
52
 *
53
 * This initializes @address from the string representation of an address,
54
 * given as @string. On return, @address->type will contain the type of the
55
 * address that was given as @string. Note that this might be
56
 * ADDRESS_TYPE_OTHER, in case the parser couldn't detect the address type.
57
 *
58
 * Note that @string is *NOT* copied into @address, but might be referenced
59
 * from it. Hence, the lifetime of @address is bound to @string.
60
 *
61
 * This function does not fully validate the address! All it does is to detect
62
 * the type of address, but the address might still be invalid. In other words,
63
 * this function correctly assigns a type to all valid addresses. However, in
64
 * case of invalid addresses, it might give false positives. That is, for the
65
 * sake of distinguishing addresses, this is sufficient. However, for the sake
66
 * of data validation when creating/acquiring names, you need to further verify
67
 * the validity of the name.
68
 */
69
0
void address_from_string(Address *address, const char *string) {
70
0
        uint64_t id;
71
0
        char *end;
72
73
0
        address->type = ADDRESS_TYPE_OTHER;
74
75
0
        if (!string[0]) {
76
0
                return;
77
0
        } else if (string[0] == ':') {
78
0
                if (strncmp(string, ":1.", strlen(":1.")))
79
0
                        return;
80
81
0
                string += strlen(":1.");
82
0
                errno = 0;
83
0
                id = strtoull(string, &end, 10);
84
0
                if (end == string || *end || errno || id == ULLONG_MAX)
85
0
                        return;
86
87
0
                address->type = ADDRESS_TYPE_ID;
88
0
                address->id = id;
89
0
        } else {
90
0
                address->type = ADDRESS_TYPE_NAME;
91
0
                address->name = string;
92
0
        }
93
0
}
94
95
/**
96
 * address_to_string() - return string representation of an address
97
 * @address:            address to operate on
98
 *
99
 * This returns a pointer to the string representation of @address. Note that
100
 * the caller must make sure @address is a valid address. If @address is of
101
 * type ADDRESS_TYPE_OTHER, this will raise a fatal exception.
102
 *
103
 * Note that the address buffer is bound to @address. That is, whenever
104
 * @address is modified, the returned pointer will become invalid.
105
 *
106
 * Return: Pointer to string representation of @address.
107
 */
108
362
const char *address_to_string(Address *address) {
109
362
        int r;
110
111
362
        switch (address->type) {
112
362
        case ADDRESS_TYPE_ID:
113
362
                r = snprintf(address->buffer, sizeof(address->buffer), ":1.%"PRIu64, address->id);
114
362
                c_assert(r >= 0 && r < (ssize_t)sizeof(address->buffer));
115
362
                return address->buffer;
116
0
        case ADDRESS_TYPE_NAME:
117
0
                return address->name;
118
0
        default:
119
0
                c_assert(0);
120
0
                return ":<garbage>";
121
362
        }
122
362
}
123
124
/**
125
 * address_write() - write string representation of an address
126
 * @address:            address to operate on
127
 * @buffer:             buffer to write into
128
 * @n_buffer:           size of @buffer
129
 *
130
 * This is similar to address_to_string(), but rather than returning a pointer
131
 * to an internal buffer, it writes the address to a caller-supplied buffer.
132
 *
133
 * Note that the caller must provide a suitably sized buffer. If the buffer is
134
 * not big enough to hold the string representation, this will raise a fatal
135
 * exception.
136
 */
137
0
void address_write(Address *address, char *buffer, size_t n_buffer) {
138
0
        int r;
139
140
0
        switch (address->type) {
141
0
        case ADDRESS_TYPE_ID:
142
0
                r = snprintf(buffer, n_buffer, ":1.%"PRIu64, address->id);
143
0
                c_assert(r >= 0 && r < (ssize_t)n_buffer);
144
0
                break;
145
0
        case ADDRESS_TYPE_NAME:
146
0
                c_assert(n_buffer > strlen(address->name));
147
0
                strcpy(buffer, address->name);
148
0
                break;
149
0
        default:
150
0
                c_assert(0);
151
0
                strcpy(buffer, ":<garbage>");
152
0
                break;
153
0
        }
154
0
}