• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

systemd / systemd / 14766779411

30 Apr 2025 04:55PM UTC coverage: 72.225% (-0.06%) from 72.282%
14766779411

push

github

web-flow
wait-online: handle varlink connection errors while waiting for DNS (#37283)

Currently, if systemd-networkd-wait-online is started with --dns, and
systemd-resolved is not running, it will exit with an error right away.
Similarly, if systemd-resolved is restarted while waiting for DNS
configuration, systemd-networkd-wait-online will not attempt to
re-connect, and will potentially never see subsequent DNS
configurations.

Improve this by adding socket units for the systemd-resolved varlink
servers, and re-establish the connection in systemd-networkd-wait-online
when we receive `SD_VARLINK_ERROR_DISCONNECTED`.

8 of 16 new or added lines in 2 files covered. (50.0%)

5825 existing lines in 217 files now uncovered.

297168 of 411450 relevant lines covered (72.22%)

695892.62 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

93.88
/src/core/unit-printf.c
1
/* SPDX-License-Identifier: LGPL-2.1-or-later */
2

3
#include "sd-path.h"
4

5
#include "alloc-util.h"
6
#include "cgroup-util.h"
7
#include "format-util.h"
8
#include "macro.h"
9
#include "manager.h"
10
#include "specifier.h"
11
#include "string-util.h"
12
#include "strv.h"
13
#include "unit.h"
14
#include "unit-name.h"
15
#include "unit-printf.h"
16
#include "user-util.h"
17

18
static int specifier_prefix_and_instance(char specifier, const void *data, const char *root, const void *userdata, char **ret) {
153✔
19
        const Unit *u = ASSERT_PTR(userdata);
153✔
20

21
        return unit_name_to_prefix_and_instance(u->id, ret);
153✔
22
}
23

24
static int specifier_prefix(char specifier, const void *data, const char *root, const void *userdata, char **ret) {
3✔
25
        const Unit *u = ASSERT_PTR(userdata);
3✔
26

27
        return unit_name_to_prefix(u->id, ret);
3✔
28
}
29

30
static int specifier_prefix_unescaped(char specifier, const void *data, const char *root, const void *userdata, char **ret) {
3✔
31
        _cleanup_free_ char *p = NULL;
3✔
32
        const Unit *u = ASSERT_PTR(userdata);
3✔
33
        int r;
3✔
34

35
        r = unit_name_to_prefix(u->id, &p);
3✔
36
        if (r < 0)
3✔
37
                return r;
38

39
        return unit_name_unescape(p, ret);
3✔
40
}
41

42
static int specifier_instance_unescaped(char specifier, const void *data, const char *root, const void *userdata, char **ret) {
561✔
43
        const Unit *u = ASSERT_PTR(userdata);
561✔
44

45
        return unit_name_unescape(strempty(u->instance), ret);
563✔
46
}
47

48
static int specifier_last_component(char specifier, const void *data, const char *root, const void *userdata, char **ret) {
133✔
49
        const Unit *u = ASSERT_PTR(userdata);
133✔
50
        _cleanup_free_ char *prefix = NULL;
133✔
51
        char *dash;
133✔
52
        int r;
133✔
53

54
        r = unit_name_to_prefix(u->id, &prefix);
133✔
55
        if (r < 0)
133✔
56
                return r;
57

58
        dash = strrchr(prefix, '-');
133✔
59
        if (dash)
133✔
60
                return specifier_string(specifier, dash + 1, root, userdata, ret);
129✔
61

62
        *ret = TAKE_PTR(prefix);
4✔
63
        return 0;
4✔
64
}
65

66
static int specifier_last_component_unescaped(char specifier, const void *data, const char *root, const void *userdata, char **ret) {
3✔
67
        _cleanup_free_ char *p = NULL;
3✔
68
        int r;
3✔
69

70
        r = specifier_last_component(specifier, data, root, userdata, &p);
3✔
71
        if (r < 0)
3✔
72
                return r;
73

74
        return unit_name_unescape(p, ret);
3✔
75
}
76

77
static int specifier_filename(char specifier, const void *data, const char *root, const void *userdata, char **ret) {
3,438✔
78
        const Unit *u = ASSERT_PTR(userdata);
3,438✔
79

80
        if (u->instance)
3,438✔
81
                return unit_name_path_unescape(u->instance, ret);
3,436✔
82
        else
83
                return unit_name_to_path(u->id, ret);
2✔
84
}
85

86
static void bad_specifier(const Unit *u, char specifier) {
9✔
87
        log_unit_warning(u, "Specifier '%%%c' used in unit configuration, which is deprecated. Please update your unit file, as it does not work as intended.", specifier);
9✔
88
}
9✔
89

90
static int specifier_cgroup(char specifier, const void *data, const char *root, const void *userdata, char **ret) {
3✔
91
        const Unit *u = ASSERT_PTR(userdata);
3✔
92
        CGroupRuntime *crt = unit_get_cgroup_runtime(u);
3✔
93

94
        bad_specifier(u, specifier);
3✔
95

96
        if (crt && crt->cgroup_path)
3✔
UNCOV
97
                return strdup_to(ret, crt->cgroup_path);
×
98

99
        return unit_default_cgroup_path(u, ret);
3✔
100
}
101

102
static int specifier_cgroup_root(char specifier, const void *data, const char *root, const void *userdata, char **ret) {
3✔
103
        const Unit *u = ASSERT_PTR(userdata);
3✔
104

105
        bad_specifier(u, specifier);
3✔
106

107
        return strdup_to(ret, u->manager->cgroup_root);
3✔
108
}
109

110
static int specifier_cgroup_slice(char specifier, const void *data, const char *root, const void *userdata, char **ret) {
3✔
111
        const Unit *u = ASSERT_PTR(userdata), *slice;
3✔
112

113
        bad_specifier(u, specifier);
3✔
114

115
        slice = UNIT_GET_SLICE(u);
3✔
116
        if (slice) {
3✔
117
                CGroupRuntime *crt = unit_get_cgroup_runtime(slice);
2✔
118

119
                if (crt && crt->cgroup_path)
2✔
UNCOV
120
                        return strdup_to(ret, crt->cgroup_path);
×
121

122
                return unit_default_cgroup_path(slice, ret);
2✔
123
        }
124

125
        return strdup_to(ret, u->manager->cgroup_root);
1✔
126
}
127

128
static int specifier_special_directory(char specifier, const void *data, const char *root, const void *userdata, char **ret) {
2,135✔
129
        const Unit *u = ASSERT_PTR(userdata);
2,135✔
130

131
        return strdup_to(ret, u->manager->prefix[PTR_TO_UINT(data)]);
2,135✔
132
}
133

134
static int specifier_credentials_dir(char specifier, const void *data, const char *root, const void *userdata, char **ret) {
3✔
135
        const Unit *u = ASSERT_PTR(userdata);
3✔
136
        char *d;
3✔
137

138
        assert(ret);
3✔
139

140
        d = strjoin(u->manager->prefix[EXEC_DIRECTORY_RUNTIME], "/credentials/", u->id);
3✔
141
        if (!d)
3✔
142
                return -ENOMEM;
143

144
        *ret = d;
3✔
145
        return 0;
3✔
146
}
147

148
static int specifier_shared_data_dir(char specifier, const void *data, const char *root, const void *userdata, char **ret) {
×
UNCOV
149
        const Unit *u = ASSERT_PTR(userdata);
×
150

UNCOV
151
        assert(ret);
×
152

UNCOV
153
        return sd_path_lookup(MANAGER_IS_SYSTEM(u->manager) ? SD_PATH_SYSTEM_SHARED : SD_PATH_USER_SHARED, NULL, ret);
×
154
}
155

156
int unit_name_printf(const Unit *u, const char* format, char **ret) {
87,268✔
157
        /*
158
         * This will use the passed string as format string and replace the following specifiers (which should all be
159
         * safe for inclusion in unit names):
160
         *
161
         * %n: the full id of the unit                 (foo-aaa@bar.waldo)
162
         * %N: the id of the unit without the suffix   (foo-aaa@bar)
163
         * %p: the prefix                              (foo-aaa)
164
         * %i: the instance                            (bar)
165
         * %j: the last component of the prefix        (aaa)
166
         */
167

168
        const Specifier table[] = {
87,268✔
169
                { 'i', specifier_string,              u->instance },
87,268✔
170
                { 'j', specifier_last_component,      NULL },
171
                { 'n', specifier_string,              u->id },
87,268✔
172
                { 'N', specifier_prefix_and_instance, NULL },
173
                { 'p', specifier_prefix,              NULL },
174

175
                COMMON_SYSTEM_SPECIFIERS,
176

177
                COMMON_CREDS_SPECIFIERS(u->manager->runtime_scope),
87,268✔
178
                {}
179
        };
180

181
        assert(u);
87,268✔
182
        assert(format);
87,268✔
183
        assert(ret);
87,268✔
184

185
        return specifier_printf(format, UNIT_NAME_MAX, table, NULL, u, ret);
87,268✔
186
}
187

188
int unit_full_printf_full(const Unit *u, const char *format, size_t max_length, char **ret) {
151,201✔
189
        /* This is similar to unit_name_printf() but also supports unescaping. Also, adds a couple of
190
         * additional codes (which are likely not suitable for unescaped inclusion in unit names):
191
         *
192
         * %f: the unescaped instance if set, otherwise the id unescaped as path
193
         *
194
         * %c: cgroup path of unit (deprecated)
195
         * %r: where units in this slice are placed in the cgroup tree (deprecated)
196
         * %R: the root of this systemd's instance tree (deprecated)
197
         *
198
         * %C: the cache directory root (e.g. /var/cache or $XDG_CACHE_HOME)
199
         * %d: the credentials directory ($CREDENTIALS_DIRECTORY)
200
         * %D: the shared data root (e.g. /usr/share or $XDG_DATA_HOME)
201
         * %E: the configuration directory root (e.g. /etc or $XDG_CONFIG_HOME)
202
         * %L: the log directory root (e.g. /var/log or $XDG_STATE_HOME/log)
203
         * %S: the state directory root (e.g. /var/lib or $XDG_STATE_HOME)
204
         * %t: the runtime directory root (e.g. /run or $XDG_RUNTIME_DIR)
205
         *
206
         * %h: the homedir of the running user
207
         * %s: the shell of the running user
208
         *
209
         * NOTICE: When you add new entries here, please be careful: specifiers which depend on settings of
210
         * the unit file itself are broken by design, as they would resolve differently depending on whether
211
         * they are used before or after the relevant configuration setting. Hence: don't add them.
212
         */
213

214
        assert(u);
151,201✔
215
        assert(format);
151,201✔
216
        assert(ret);
151,201✔
217

218
        const Specifier table[] = {
151,201✔
219
                { 'i', specifier_string,                   u->instance },
151,201✔
220
                { 'I', specifier_instance_unescaped,       NULL },
221
                { 'j', specifier_last_component,           NULL },
222
                { 'J', specifier_last_component_unescaped, NULL },
223
                { 'n', specifier_string,                   u->id },
151,201✔
224
                { 'N', specifier_prefix_and_instance,      NULL },
225
                { 'p', specifier_prefix,                   NULL },
226
                { 'P', specifier_prefix_unescaped,         NULL },
227

228
                { 'f', specifier_filename,                 NULL },
229
                { 'y', specifier_real_path,                u->fragment_path },
151,201✔
230
                { 'Y', specifier_real_directory,           u->fragment_path },
151,201✔
231

232
                { 'c', specifier_cgroup,                   NULL },  /* deprecated, see 1b89b0c499cd4bf0ff389caab4ecaae6e75f9d4e */
233
                { 'r', specifier_cgroup_slice,             NULL },  /* deprecated, see 1b89b0c499cd4bf0ff389caab4ecaae6e75f9d4e */
234
                { 'R', specifier_cgroup_root,              NULL },  /* deprecated, see 1b89b0c499cd4bf0ff389caab4ecaae6e75f9d4e */
235

236
                { 'C', specifier_special_directory,        UINT_TO_PTR(EXEC_DIRECTORY_CACHE) },
237
                { 'd', specifier_credentials_dir,          NULL },
238
                { 'D', specifier_shared_data_dir,          NULL },
239
                { 'E', specifier_special_directory,        UINT_TO_PTR(EXEC_DIRECTORY_CONFIGURATION) },
240
                { 'L', specifier_special_directory,        UINT_TO_PTR(EXEC_DIRECTORY_LOGS) },
241
                { 'S', specifier_special_directory,        UINT_TO_PTR(EXEC_DIRECTORY_STATE) },
242
                { 't', specifier_special_directory,        UINT_TO_PTR(EXEC_DIRECTORY_RUNTIME) },
243

244
                { 'h', specifier_user_home,                NULL },
245
                { 's', specifier_user_shell,               NULL },
246

247
                COMMON_SYSTEM_SPECIFIERS,
248

249
                COMMON_CREDS_SPECIFIERS(u->manager->runtime_scope),
151,201✔
250

251
                COMMON_TMP_SPECIFIERS,
252
                {}
253
        };
254

255
        return specifier_printf(format, max_length, table, NULL, u, ret);
151,201✔
256
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc