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

systemd / systemd / 15263807472

26 May 2025 08:53PM UTC coverage: 72.046% (-0.002%) from 72.048%
15263807472

push

github

yuwata
src/core/manager.c: log preset activity on first boot

This gives us a little more information about what units were enabled
or disabled on that first boot and will be useful for OS developers
tracking down the source of unit state.

An example with this enabled looks like:

```
NET: Registered PF_VSOCK protocol family
systemd[1]: Applying preset policy.
systemd[1]: Unit /etc/systemd/system/dnsmasq.service is masked, ignoring.
systemd[1]: Unit /etc/systemd/system/systemd-repart.service is masked, ignoring.
systemd[1]: Removed '/etc/systemd/system/sockets.target.wants/systemd-resolved-monitor.socket'.
systemd[1]: Removed '/etc/systemd/system/sockets.target.wants/systemd-resolved-varlink.socket'.
systemd[1]: Created symlink '/etc/systemd/system/multi-user.target.wants/var-mnt-workdir.mount' → '/etc/systemd/system/var-mnt-workdir.mount'.
systemd[1]: Created symlink '/etc/systemd/system/multi-user.target.wants/var-mnt-workdir\x2dtmp.mount' → '/etc/systemd/system/var-mnt-workdir\x2dtmp.mount'.
systemd[1]: Created symlink '/etc/systemd/system/afterburn-sshkeys.target.requires/afterburn-sshkeys@core.service' → '/usr/lib/systemd/system/afterburn-sshkeys@.service'.
systemd[1]: Created symlink '/etc/systemd/system/sockets.target.wants/systemd-resolved-varlink.socket' → '/usr/lib/systemd/system/systemd-resolved-varlink.socket'.
systemd[1]: Created symlink '/etc/systemd/system/sockets.target.wants/systemd-resolved-monitor.socket' → '/usr/lib/systemd/system/systemd-resolved-monitor.socket'.
systemd[1]: Populated /etc with preset unit settings.
```

Considering it only happens on first boot and not on every boot I think
the extra information is worth the extra verbosity in the logs just for
that boot.

5 of 6 new or added lines in 1 file covered. (83.33%)

5463 existing lines in 165 files now uncovered.

299151 of 415222 relevant lines covered (72.05%)

702386.45 hits per line

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

92.23
/src/basic/tmpfile-util.c
1
/* SPDX-License-Identifier: LGPL-2.1-or-later */
2

3
#include <stdlib.h>
4
#include <unistd.h>
5

6
#include "alloc-util.h"
7
#include "errno-util.h"
8
#include "fd-util.h"
9
#include "fileio.h"
10
#include "fs-util.h"
11
#include "log.h"
12
#include "path-util.h"
13
#include "random-util.h"
14
#include "string-util.h"
15
#include "sync-util.h"
16
#include "tmpfile-util.h"
17
#include "umask-util.h"
18

19
static int fopen_temporary_internal(int dir_fd, const char *path, FILE **ret_file) {
159,820✔
20
        _cleanup_fclose_ FILE *f = NULL;
159,820✔
21
        _cleanup_close_ int fd = -EBADF;
159,820✔
22
        int r;
159,820✔
23

24
        assert(dir_fd >= 0 || dir_fd == AT_FDCWD);
159,820✔
25
        assert(path);
159,820✔
26

27
        fd = openat(dir_fd, path, O_CLOEXEC|O_NOCTTY|O_RDWR|O_CREAT|O_EXCL, 0600);
159,820✔
28
        if (fd < 0)
159,820✔
29
                return -errno;
1✔
30

31
        /* This assumes that returned FILE object is short-lived and used within the same single-threaded
32
         * context and never shared externally, hence locking is not necessary. */
33

34
        r = take_fdopen_unlocked(&fd, "w", &f);
159,819✔
35
        if (r < 0) {
159,819✔
UNCOV
36
                (void) unlinkat(dir_fd, path, 0);
×
UNCOV
37
                return r;
×
38
        }
39

40
        if (ret_file)
159,819✔
41
                *ret_file = TAKE_PTR(f);
159,819✔
42

43
        return 0;
44
}
45

46
int fopen_temporary_at(int dir_fd, const char *path, FILE **ret_file, char **ret_path) {
159,818✔
47
        _cleanup_free_ char *t = NULL;
159,818✔
48
        int r;
159,818✔
49

50
        assert(dir_fd >= 0 || dir_fd == AT_FDCWD);
159,818✔
51
        assert(path);
159,818✔
52

53
        r = tempfn_random(path, NULL, &t);
159,818✔
54
        if (r < 0)
159,818✔
55
                return r;
56

57
        r = fopen_temporary_internal(dir_fd, t, ret_file);
159,818✔
58
        if (r < 0)
159,818✔
59
                return r;
60

61
        if (ret_path)
159,817✔
62
                *ret_path = TAKE_PTR(t);
159,817✔
63

64
        return 0;
65
}
66

67
int fopen_temporary_child_at(int dir_fd, const char *path, FILE **ret_file, char **ret_path) {
2✔
68
        _cleanup_free_ char *t = NULL;
2✔
69
        int r;
2✔
70

71
        assert(dir_fd >= 0 || dir_fd == AT_FDCWD);
2✔
72

73
        if (!path) {
2✔
74
                r = tmp_dir(&path);
1✔
75
                if (r < 0)
1✔
76
                        return r;
77
        }
78

79
        r = tempfn_random_child(path, NULL, &t);
2✔
80
        if (r < 0)
2✔
81
                return r;
82

83
        r = fopen_temporary_internal(dir_fd, t, ret_file);
2✔
84
        if (r < 0)
2✔
85
                return r;
86

87
        if (ret_path)
2✔
88
                *ret_path = TAKE_PTR(t);
2✔
89

90
        return 0;
91
}
92

93
/* This is much like mkostemp() but is subject to umask(). */
94
int mkostemp_safe(char *pattern) {
155✔
95
        assert(pattern);
155✔
96
        BLOCK_WITH_UMASK(0077);
155✔
97
        return RET_NERRNO(mkostemp(pattern, O_CLOEXEC));
155✔
98
}
99

100
int fmkostemp_safe(char *pattern, const char *mode, FILE **ret_f) {
44✔
101
        _cleanup_close_ int fd = -EBADF;
44✔
102
        FILE *f;
44✔
103

104
        fd = mkostemp_safe(pattern);
44✔
105
        if (fd < 0)
44✔
106
                return fd;
107

108
        f = take_fdopen(&fd, mode);
44✔
109
        if (!f)
44✔
UNCOV
110
                return -errno;
×
111

112
        *ret_f = f;
44✔
113
        return 0;
44✔
114
}
115

116
void unlink_tempfilep(char (*p)[]) {
121✔
117
        assert(p);
121✔
118

119
        /* If the file is created with mkstemp(), it will (almost always) change the suffix.
120
         * Treat this as a sign that the file was successfully created. We ignore both the rare case
121
         * where the original suffix is used and unlink failures. */
122

123
        if (!endswith(*p, ".XXXXXX"))
121✔
124
                (void) unlink(*p);
119✔
125
}
121✔
126

127
static int tempfn_build(const char *p, const char *pre, const char *post, bool child, char **ret) {
322,806✔
128
        _cleanup_free_ char *d = NULL, *fn = NULL, *nf = NULL, *result = NULL;
322,806✔
129
        size_t len_pre, len_post, len_add;
322,806✔
130
        int r;
322,806✔
131

132
        assert(p);
322,806✔
133
        assert(ret);
322,806✔
134

135
        /*
136
         * Turns this:
137
         *         /foo/bar/waldo
138
         *
139
         * Into this :
140
         *         /foo/bar/waldo/.#<pre><post> (child == true)
141
         *         /foo/bar/.#<pre>waldo<post> (child == false)
142
         */
143

144
        if (pre && strchr(pre, '/'))
322,806✔
145
                return -EINVAL;
146

147
        if (post && strchr(post, '/'))
322,803✔
148
                return -EINVAL;
149

150
        len_pre = strlen_ptr(pre);
322,803✔
151
        len_post = strlen_ptr(post);
322,803✔
152
        /* NAME_MAX is counted *without* the trailing NUL byte. */
153
        if (len_pre > NAME_MAX - STRLEN(".#") ||
322,803✔
154
            len_post > NAME_MAX - STRLEN(".#") - len_pre)
322,803✔
155
                return -EINVAL;
156

157
        len_add = len_pre + len_post + STRLEN(".#");
322,803✔
158

159
        if (child) {
322,803✔
160
                d = strdup(p);
1,970✔
161
                if (!d)
1,970✔
162
                        return -ENOMEM;
163
        } else {
164
                r = path_extract_directory(p, &d);
320,833✔
165
                if (r < 0 && r != -EDESTADDRREQ) /* EDESTADDRREQ → No directory specified, just a filename */
320,833✔
166
                        return r;
167

168
                r = path_extract_filename(p, &fn);
320,825✔
169
                if (r < 0)
320,825✔
170
                        return r;
171

172
                if (strlen(fn) > NAME_MAX - len_add)
320,825✔
173
                        /* We cannot simply prepend and append strings to the filename. Let's truncate the filename. */
174
                        fn[NAME_MAX - len_add] = '\0';
4✔
175
        }
176

177
        nf = strjoin(".#", strempty(pre), strempty(fn), strempty(post));
645,476✔
178
        if (!nf)
322,795✔
179
                return -ENOMEM;
180

181
        if (d) {
322,795✔
182
                if (!path_extend(&d, nf))
322,257✔
183
                        return -ENOMEM;
184

185
                result = path_simplify(TAKE_PTR(d));
322,257✔
186
        } else
187
                result = TAKE_PTR(nf);
188

189
        if (!path_is_valid(result)) /* New path is not valid? (Maybe because too long?) Refuse. */
322,795✔
190
                return -EINVAL;
191

192
        *ret = TAKE_PTR(result);
322,792✔
193
        return 0;
322,792✔
194
}
195

196
int tempfn_xxxxxx(const char *p, const char *extra, char **ret) {
27✔
197
        /*
198
         * Turns this:
199
         *         /foo/bar/waldo
200
         *
201
         * Into this:
202
         *         /foo/bar/.#<extra>waldoXXXXXX
203
         */
204

205
        return tempfn_build(p, extra, "XXXXXX", /* child = */ false, ret);
27✔
206
}
207

208
int tempfn_random(const char *p, const char *extra, char **ret) {
320,808✔
209
        _cleanup_free_ char *s = NULL;
320,808✔
210

211
        assert(p);
320,808✔
212
        assert(ret);
320,808✔
213

214
        /*
215
         * Turns this:
216
         *         /foo/bar/waldo
217
         *
218
         * Into this:
219
         *         /foo/bar/.#<extra>waldobaa2a261115984a9
220
         */
221

222
        if (asprintf(&s, "%016" PRIx64, random_u64()) < 0)
320,808✔
223
                return -ENOMEM;
224

225
        return tempfn_build(p, extra, s, /* child = */ false, ret);
320,808✔
226
}
227

228
int tempfn_random_child(const char *p, const char *extra, char **ret) {
1,971✔
229
        _cleanup_free_ char *s = NULL;
1,971✔
230
        int r;
1,971✔
231

232
        assert(ret);
1,971✔
233

234
        /* Turns this:
235
         *         /foo/bar/waldo
236
         * Into this:
237
         *         /foo/bar/waldo/.#<extra>3c2b6219aa75d7d0
238
         */
239

240
        if (!p) {
1,971✔
241
                r = tmp_dir(&p);
15✔
242
                if (r < 0)
15✔
243
                        return r;
244
        }
245

246
        if (asprintf(&s, "%016" PRIx64, random_u64()) < 0)
1,971✔
247
                return -ENOMEM;
248

249
        return tempfn_build(p, extra, s, /* child = */ true, ret);
1,971✔
250
}
251

252
int open_tmpfile_unlinkable(const char *directory, int flags) {
6,377✔
253
        char *p;
6,377✔
254
        int fd, r;
6,377✔
255

256
        if (!directory) {
6,377✔
257
                r = tmp_dir(&directory);
7✔
258
                if (r < 0)
7✔
259
                        return r;
260
        } else if (isempty(directory))
6,370✔
261
                return -EINVAL;
262

263
        /* Returns an unlinked temporary file that cannot be linked into the file system anymore */
264

265
        /* Try O_TMPFILE first, if it is supported */
266
        fd = open(directory, flags|O_TMPFILE|O_EXCL, S_IRUSR|S_IWUSR);
6,377✔
267
        if (fd >= 0)
6,377✔
268
                return fd;
269

270
        /* Fall back to unguessable name + unlinking */
UNCOV
271
        p = strjoina(directory, "/systemd-tmp-XXXXXX");
×
272

UNCOV
273
        fd = mkostemp_safe(p);
×
UNCOV
274
        if (fd < 0)
×
275
                return fd;
276

UNCOV
277
        (void) unlink(p);
×
278

UNCOV
279
        return fd;
×
280
}
281

282
int open_tmpfile_linkable_at(int dir_fd, const char *target, int flags, char **ret_path) {
6,953✔
283
        _cleanup_free_ char *tmp = NULL;
6,953✔
284
        int r, fd;
6,953✔
285

286
        assert(target);
6,953✔
287
        assert(ret_path);
6,953✔
288

289
        /* Don't allow O_EXCL, as that has a special meaning for O_TMPFILE */
290
        assert((flags & O_EXCL) == 0);
6,953✔
291

292
        /* Creates a temporary file, that shall be renamed to "target" later. If possible, this uses O_TMPFILE – in
293
         * which case "ret_path" will be returned as NULL. If not possible the temporary path name used is returned in
294
         * "ret_path". Use link_tmpfile() below to rename the result after writing the file in full. */
295

296
        fd = open_parent_at(dir_fd, target, O_TMPFILE|flags, 0640);
6,953✔
297
        if (fd >= 0) {
6,953✔
298
                *ret_path = NULL;
6,920✔
299
                return fd;
6,920✔
300
        }
301

302
        log_debug_errno(fd, "Failed to use O_TMPFILE for %s: %m", target);
33✔
303

304
        r = tempfn_random(target, NULL, &tmp);
33✔
305
        if (r < 0)
33✔
306
                return r;
307

308
        fd = openat(dir_fd, tmp, O_CREAT|O_EXCL|O_NOFOLLOW|O_NOCTTY|flags, 0640);
33✔
309
        if (fd < 0)
33✔
310
                return -errno;
17✔
311

312
        *ret_path = TAKE_PTR(tmp);
16✔
313

314
        return fd;
16✔
315
}
316

317
int fopen_tmpfile_linkable_at(int dir_fd, const char *target, int flags, char **ret_path, FILE **ret_file) {
4,248✔
318
        _cleanup_free_ char *path = NULL;
4,248✔
319
        _cleanup_fclose_ FILE *f = NULL;
4,248✔
320
        _cleanup_close_ int fd = -EBADF;
4,248✔
321

322
        assert(target);
4,248✔
323
        assert(ret_file);
4,248✔
324
        assert(ret_path);
4,248✔
325

326
        fd = open_tmpfile_linkable_at(dir_fd, target, flags, &path);
4,248✔
327
        if (fd < 0)
4,248✔
328
                return fd;
329

330
        f = take_fdopen(&fd, "w");
4,248✔
331
        if (!f)
4,248✔
332
                return -ENOMEM;
333

334
        *ret_path = TAKE_PTR(path);
4,248✔
335
        *ret_file = TAKE_PTR(f);
4,248✔
336
        return 0;
4,248✔
337
}
338

339
int link_tmpfile_at(int fd, int dir_fd, const char *path, const char *target, LinkTmpfileFlags flags) {
6,880✔
340
        int r;
6,880✔
341

342
        assert(fd >= 0);
6,880✔
343
        assert(dir_fd >= 0 || dir_fd == AT_FDCWD);
6,880✔
344
        assert(target);
6,880✔
345

346
        /* Moves a temporary file created with open_tmpfile() above into its final place. If "path" is NULL
347
         * an fd created with O_TMPFILE is assumed, and linkat() is used. Otherwise it is assumed O_TMPFILE
348
         * is not supported on the directory, and renameat2() is used instead. */
349

350
        if (FLAGS_SET(flags, LINK_TMPFILE_SYNC) && fsync(fd) < 0)
6,880✔
UNCOV
351
                return -errno;
×
352

353
        if (path) {
6,880✔
354
                if (FLAGS_SET(flags, LINK_TMPFILE_REPLACE))
16✔
UNCOV
355
                        r = RET_NERRNO(renameat(dir_fd, path, dir_fd, target));
×
356
                else
357
                        r = rename_noreplace(dir_fd, path, dir_fd, target);
16✔
358
        } else {
359
                if (FLAGS_SET(flags, LINK_TMPFILE_REPLACE))
6,864✔
360
                        r = linkat_replace(fd, /* oldpath= */ NULL, dir_fd, target);
5,988✔
361
                else
362
                        r = link_fd(fd, dir_fd, target);
876✔
363
        }
364
        if (r < 0)
6,880✔
365
                return r;
366

367
        if (FLAGS_SET(flags, LINK_TMPFILE_SYNC)) {
6,877✔
368
                r = fsync_full(fd);
1,385✔
369
                if (r < 0)
1,385✔
UNCOV
370
                        return r;
×
371
        }
372

373
        return 0;
374
}
375

376
int flink_tmpfile_at(FILE *f, int dir_fd, const char *path, const char *target, LinkTmpfileFlags flags) {
4,248✔
377
        int fd, r;
4,248✔
378

379
        assert(f);
4,248✔
380
        assert(target);
4,248✔
381

382
        fd = fileno(f);
4,248✔
383
        if (fd < 0) /* Not all FILE* objects encapsulate fds */
4,248✔
384
                return -EBADF;
385

386
        r = fflush_and_check(f);
4,248✔
387
        if (r < 0)
4,248✔
388
                return r;
389

390
        return link_tmpfile_at(fd, dir_fd, path, target, flags);
4,248✔
391
}
392

393
int mkdtemp_malloc(const char *template, char **ret) {
3,742✔
394
        _cleanup_free_ char *p = NULL;
7,484✔
395
        int r;
3,742✔
396

397
        assert(ret);
3,742✔
398

399
        if (template)
3,742✔
400
                p = strdup(template);
3,665✔
401
        else {
402
                const char *tmp;
77✔
403

404
                r = tmp_dir(&tmp);
77✔
405
                if (r < 0)
77✔
UNCOV
406
                        return r;
×
407

408
                p = path_join(tmp, "XXXXXX");
77✔
409
        }
410
        if (!p)
3,742✔
411
                return -ENOMEM;
412

413
        if (!mkdtemp(p))
3,742✔
UNCOV
414
                return -errno;
×
415

416
        *ret = TAKE_PTR(p);
3,742✔
417
        return 0;
3,742✔
418
}
419

420
int mkdtemp_open(const char *template, int flags, char **ret) {
36✔
421
        _cleanup_free_ char *p = NULL;
36✔
422
        int fd, r;
36✔
423

424
        r = mkdtemp_malloc(template, &p);
36✔
425
        if (r < 0)
36✔
426
                return r;
427

428
        fd = RET_NERRNO(open(p, O_DIRECTORY|O_CLOEXEC|flags));
36✔
UNCOV
429
        if (fd < 0) {
×
UNCOV
430
                (void) rmdir(p);
×
UNCOV
431
                return fd;
×
432
        }
433

434
        if (ret)
36✔
435
                *ret = TAKE_PTR(p);
36✔
436

437
        return fd;
438
}
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