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

systemd / systemd / 14630481637

23 Apr 2025 07:04PM UTC coverage: 72.178% (-0.002%) from 72.18%
14630481637

push

github

DaanDeMeyer
mkosi: Run clangd within the tools tree instead of the build container

Running within the build sandbox has a number of disadvantages:
- We have a separate clangd cache for each distribution/release combo
- It requires to build the full image before clangd can be used
- It breaks every time the image becomes out of date and requires a
  rebuild
- We can't look at system headers as we don't have the knowledge to map
  them from inside the build sandbox to the corresponding path on the host

Instead, let's have mkosi.clangd run clangd within the tools tree. We
already require building systemd for both the host and the target anyway,
and all the dependencies to build systemd are installed in the tools tree
already for that, as well as clangd since it's installed together with the
other clang tooling we install in the tools tree. Unlike the previous approach,
this approach only requires the mkosi tools tree to be built upfront, which has
a much higher chance of not invalidating its cache. We can also trivially map
system header lookups from within the sandbox to the path within mkosi.tools
on the host so that starts working as well.

297054 of 411557 relevant lines covered (72.18%)

686269.58 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 "alloc-util.h"
4
#include "cgroup-util.h"
5
#include "format-util.h"
6
#include "macro.h"
7
#include "manager.h"
8
#include "sd-path.h"
9
#include "specifier.h"
10
#include "string-util.h"
11
#include "strv.h"
12
#include "unit-name.h"
13
#include "unit-printf.h"
14
#include "unit.h"
15
#include "user-util.h"
16

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

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

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

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

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

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

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

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

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

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

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

57
        dash = strrchr(prefix, '-');
132✔
58
        if (dash)
132✔
59
                return specifier_string(specifier, dash + 1, root, userdata, ret);
128✔
60

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

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

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

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

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

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

85
static void bad_specifier(const Unit *u, char specifier) {
9✔
86
        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✔
87
}
9✔
88

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

93
        bad_specifier(u, specifier);
3✔
94

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

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

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

104
        bad_specifier(u, specifier);
3✔
105

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

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

112
        bad_specifier(u, specifier);
3✔
113

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

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

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

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

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

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

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

137
        assert(ret);
3✔
138

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

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

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

150
        assert(ret);
×
151

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

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

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

174
                COMMON_SYSTEM_SPECIFIERS,
175

176
                COMMON_CREDS_SPECIFIERS(u->manager->runtime_scope),
85,538✔
177
                {}
178
        };
179

180
        assert(u);
85,538✔
181
        assert(format);
85,538✔
182
        assert(ret);
85,538✔
183

184
        return specifier_printf(format, UNIT_NAME_MAX, table, NULL, u, ret);
85,538✔
185
}
186

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

213
        assert(u);
150,186✔
214
        assert(format);
150,186✔
215
        assert(ret);
150,186✔
216

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

227
                { 'f', specifier_filename,                 NULL },
228
                { 'y', specifier_real_path,                u->fragment_path },
150,186✔
229
                { 'Y', specifier_real_directory,           u->fragment_path },
150,186✔
230

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

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

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

246
                COMMON_SYSTEM_SPECIFIERS,
247

248
                COMMON_CREDS_SPECIFIERS(u->manager->runtime_scope),
150,186✔
249

250
                COMMON_TMP_SPECIFIERS,
251
                {}
252
        };
253

254
        return specifier_printf(format, max_length, table, NULL, u, ret);
150,186✔
255
}
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