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

systemd / systemd / 23367620641

20 Mar 2026 07:25PM UTC coverage: 72.606% (+0.3%) from 72.351%
23367620641

push

github

bluca
kmod-setup: load vsock_loopback alongside vsock

Loading vmw_vsock_virtio_transport early at boot causes vsock to be
resident before any application opens an AF_VSOCK socket. Because the
kernel skips autoloading when the vsock module is already present,
vsock_loopback never gets loaded automatically, and any subsequent
bind() to VMADDR_CID_LOCAL fails with EADDRNOTAVAIL.

Fix this by explicitly loading vsock_loopback on virtio or VMWare
machines via the new may_have_vsock_looopback() helper, wich covers both
vmw_vsock_virtio_transport and vmware_vsock_vmci_transport case.
vsock_loopback is the only module that registers a transport for
VMADDR_CID_LOCAL (CID 1) and has no hard dependency from any of the
vsock transport modules.

Fixes: #41100
Follow-up for 381c78db4

2 of 2 new or added lines in 1 file covered. (100.0%)

2634 existing lines in 55 files now uncovered.

316477 of 435881 relevant lines covered (72.61%)

1159615.85 hits per line

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

97.94
/src/basic/env-file.c
1
/* SPDX-License-Identifier: LGPL-2.1-or-later */
2

3
#include <sys/stat.h>
4
#include <unistd.h>
5

6
#include "alloc-util.h"
7
#include "env-file.h"
8
#include "env-util.h"
9
#include "escape.h"
10
#include "fd-util.h"
11
#include "fileio.h"
12
#include "fs-util.h"
13
#include "label.h"
14
#include "log.h"
15
#include "string-util.h"
16
#include "strv.h"
17
#include "tmpfile-util.h"
18
#include "utf8.h"
19

20
typedef int (*push_env_func_t)(
21
                const char *filename,
22
                unsigned line,
23
                const char *key,
24
                char *value,
25
                void *userdata);
26

27
static int parse_env_file_internal(
198,754✔
28
                FILE *f,
29
                const char *fname,
30
                push_env_func_t push,
31
                void *userdata) {
32

33
        size_t n_key = 0, n_value = 0, last_value_whitespace = SIZE_MAX, last_key_whitespace = SIZE_MAX;
198,754✔
34
        _cleanup_free_ char *contents = NULL, *key = NULL, *value = NULL;
198,754✔
35
        unsigned line = 1;
198,754✔
36
        int r;
198,754✔
37

38
        enum {
198,754✔
39
                PRE_KEY,
40
                KEY,
41
                PRE_VALUE,
42
                VALUE,
43
                VALUE_ESCAPE,
44
                SINGLE_QUOTE_VALUE,
45
                DOUBLE_QUOTE_VALUE,
46
                DOUBLE_QUOTE_VALUE_ESCAPE,
47
                COMMENT,
48
                COMMENT_ESCAPE
49
        } state = PRE_KEY;
198,754✔
50

51
        assert(f || fname);
198,754✔
52
        assert(push);
198,754✔
53

54
        if (f)
198,754✔
55
                r = read_full_stream(f, &contents, NULL);
11,947✔
56
        else
57
                r = read_full_file(fname, &contents, NULL);
186,807✔
58
        if (r < 0)
198,754✔
59
                return r;
60

61
        for (char *p = contents; *p; p++) {
70,088,452✔
62
                char c = *p;
69,893,670✔
63

64
                switch (state) {
69,893,670✔
65

66
                case PRE_KEY:
2,888,013✔
67
                        if (strchr(COMMENTS, c))
2,888,013✔
68
                                state = COMMENT;
69
                        else if (!strchr(WHITESPACE, c)) {
2,703,366✔
70
                                state = KEY;
2,696,419✔
71
                                last_key_whitespace = SIZE_MAX;
2,696,419✔
72

73
                                if (!GREEDY_REALLOC(key, n_key+2))
2,696,419✔
74
                                        return -ENOMEM;
75

76
                                key[n_key++] = c;
2,696,419✔
77
                        }
78
                        break;
79

80
                case KEY:
35,370,918✔
81
                        if (strchr(NEWLINE, c)) {
35,370,918✔
82
                                state = PRE_KEY;
25✔
83
                                line++;
25✔
84
                                n_key = 0;
25✔
85
                        } else if (c == '=') {
35,370,893✔
86
                                state = PRE_VALUE;
87
                                last_value_whitespace = SIZE_MAX;
88
                        } else {
89
                                if (!strchr(WHITESPACE, c))
32,674,499✔
90
                                        last_key_whitespace = SIZE_MAX;
91
                                else if (last_key_whitespace == SIZE_MAX)
86✔
92
                                         last_key_whitespace = n_key;
40✔
93

94
                                if (!GREEDY_REALLOC(key, n_key+2))
32,674,499✔
95
                                        return -ENOMEM;
96

97
                                key[n_key++] = c;
32,674,499✔
98
                        }
99

100
                        break;
101

102
                case PRE_VALUE:
2,918,142✔
103
                        if (strchr(NEWLINE, c)) {
2,918,142✔
104
                                state = PRE_KEY;
688,363✔
105
                                line++;
688,363✔
106
                                key[n_key] = 0;
688,363✔
107

108
                                if (value)
688,363✔
109
                                        value[n_value] = 0;
47,355✔
110

111
                                /* strip trailing whitespace from key */
112
                                if (last_key_whitespace != SIZE_MAX)
688,363✔
113
                                        key[last_key_whitespace] = 0;
6✔
114

115
                                r = push(fname, line, key, value, userdata);
688,363✔
116
                                if (r < 0)
688,363✔
117
                                        return r;
118

119
                                n_key = 0;
688,363✔
120
                                value = NULL;
688,363✔
121
                                n_value = 0;
688,363✔
122

123
                        } else if (c == '\'')
2,229,779✔
124
                                state = SINGLE_QUOTE_VALUE;
125
                        else if (c == '"')
2,229,769✔
126
                                state = DOUBLE_QUOTE_VALUE;
127
                        else if (c == '\\')
2,008,077✔
128
                                state = VALUE_ESCAPE;
129
                        else if (!strchr(WHITESPACE, c)) {
2,008,073✔
130
                                state = VALUE;
2,008,021✔
131

132
                                if (!GREEDY_REALLOC(value, n_value+2))
2,008,021✔
133
                                        return -ENOMEM;
134

135
                                value[n_value++] = c;
2,008,021✔
136
                        }
137

138
                        break;
139

140
                case VALUE:
19,259,878✔
141
                        if (strchr(NEWLINE, c)) {
19,259,878✔
142
                                state = PRE_KEY;
2,008,008✔
143
                                line++;
2,008,008✔
144

145
                                key[n_key] = 0;
2,008,008✔
146

147
                                if (value)
2,008,008✔
148
                                        value[n_value] = 0;
2,008,008✔
149

150
                                /* Chomp off trailing whitespace from value */
151
                                if (last_value_whitespace != SIZE_MAX)
2,008,008✔
152
                                        value[last_value_whitespace] = 0;
16✔
153

154
                                /* strip trailing whitespace from key */
155
                                if (last_key_whitespace != SIZE_MAX)
2,008,008✔
156
                                        key[last_key_whitespace] = 0;
6✔
157

158
                                r = push(fname, line, key, value, userdata);
2,008,008✔
159
                                if (r < 0)
2,008,008✔
160
                                        return r;
161

162
                                n_key = 0;
2,008,008✔
163
                                value = NULL;
2,008,008✔
164
                                n_value = 0;
2,008,008✔
165

166
                        } else if (c == '\\') {
17,251,870✔
167
                                state = VALUE_ESCAPE;
168
                                last_value_whitespace = SIZE_MAX;
169
                        } else {
170
                                if (!strchr(WHITESPACE, c))
17,251,848✔
171
                                        last_value_whitespace = SIZE_MAX;
172
                                else if (last_value_whitespace == SIZE_MAX)
18,382✔
173
                                        last_value_whitespace = n_value;
18,340✔
174

175
                                if (!GREEDY_REALLOC(value, n_value+2))
17,251,848✔
176
                                        return -ENOMEM;
177

178
                                value[n_value++] = c;
17,251,848✔
179
                        }
180

181
                        break;
182

183
                case VALUE_ESCAPE:
25✔
184
                        state = VALUE;
25✔
185

186
                        if (!strchr(NEWLINE, c)) {
25✔
187
                                /* Escaped newlines we eat up entirely */
188
                                if (!GREEDY_REALLOC(value, n_value+2))
16✔
189
                                        return -ENOMEM;
190

191
                                value[n_value++] = c;
16✔
192
                        }
193
                        break;
194

195
                case SINGLE_QUOTE_VALUE:
98✔
196
                        if (c == '\'')
98✔
197
                                state = PRE_VALUE;
198
                        else {
199
                                if (!GREEDY_REALLOC(value, n_value+2))
88✔
200
                                        return -ENOMEM;
201

202
                                value[n_value++] = c;
88✔
203
                        }
204

205
                        break;
206

207
                case DOUBLE_QUOTE_VALUE:
2,611,471✔
208
                        if (c == '"')
2,611,471✔
209
                                state = PRE_VALUE;
210
                        else if (c == '\\')
2,389,779✔
211
                                state = DOUBLE_QUOTE_VALUE_ESCAPE;
212
                        else {
213
                                if (!GREEDY_REALLOC(value, n_value+2))
2,389,747✔
214
                                        return -ENOMEM;
215

216
                                value[n_value++] = c;
2,389,747✔
217
                        }
218

219
                        break;
220

221
                case DOUBLE_QUOTE_VALUE_ESCAPE:
32✔
222
                        state = DOUBLE_QUOTE_VALUE;
32✔
223

224
                        if (strchr(SHELL_NEED_ESCAPE, c)) {
32✔
225
                                /* If this is a char that needs escaping, just unescape it. */
226
                                if (!GREEDY_REALLOC(value, n_value+2))
24✔
227
                                        return -ENOMEM;
228
                                value[n_value++] = c;
24✔
229
                        } else if (c != '\n') {
8✔
230
                                /* If other char than what needs escaping, keep the "\" in place, like the
231
                                 * real shell does. */
232
                                if (!GREEDY_REALLOC(value, n_value+3))
4✔
233
                                        return -ENOMEM;
234
                                value[n_value++] = '\\';
4✔
235
                                value[n_value++] = c;
4✔
236
                        }
237

238
                        /* Escaped newlines (aka "continuation lines") are eaten up entirely */
239
                        break;
240

241
                case COMMENT:
6,845,090✔
242
                        if (c == '\\')
6,845,090✔
243
                                state = COMMENT_ESCAPE;
244
                        else if (strchr(NEWLINE, c)) {
6,845,087✔
245
                                state = PRE_KEY;
184,644✔
246
                                line++;
184,644✔
247
                        }
248
                        break;
249

250
                case COMMENT_ESCAPE:
251
                        log_debug("The line which doesn't begin with \";\" or \"#\", but follows a comment" \
3✔
252
                                  " line trailing with escape is now treated as a non comment line since v254.");
253
                        if (strchr(NEWLINE, c)) {
3✔
254
                                state = PRE_KEY;
3✔
255
                                line++;
3✔
256
                        } else
257
                                state = COMMENT;
258
                        break;
259
                }
260
        }
261

262
        if (IN_SET(state,
194,782✔
263
                   PRE_VALUE,
264
                   VALUE,
265
                   VALUE_ESCAPE,
266
                   SINGLE_QUOTE_VALUE,
267
                   DOUBLE_QUOTE_VALUE,
268
                   DOUBLE_QUOTE_VALUE_ESCAPE)) {
269

270
                key[n_key] = 0;
23✔
271

272
                if (value)
23✔
273
                        value[n_value] = 0;
22✔
274

275
                if (state == VALUE)
23✔
276
                        if (last_value_whitespace != SIZE_MAX)
16✔
277
                                value[last_value_whitespace] = 0;
×
278

279
                /* strip trailing whitespace from key */
280
                if (last_key_whitespace != SIZE_MAX)
23✔
281
                        key[last_key_whitespace] = 0;
×
282

283
                r = push(fname, line, key, value, userdata);
23✔
284
                if (r < 0)
23✔
285
                        return r;
286

287
                value = NULL;
20✔
288
        }
289

290
        return 0;
291
}
292

293
static int check_utf8ness_and_warn(
2,696,381✔
294
                const char *filename, unsigned line,
295
                const char *key, char *value) {
296

297
        assert(key);
2,696,381✔
298

299
        if (!utf8_is_valid(key)) {
2,696,381✔
300
                _cleanup_free_ char *p = NULL;
1✔
301

302
                p = utf8_escape_invalid(key);
1✔
303
                return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
1✔
304
                                       "%s:%u: invalid UTF-8 in key '%s', ignoring.",
305
                                       strna(filename), line, p);
306
        }
307

308
        if (value && !utf8_is_valid(value)) {
4,751,761✔
309
                _cleanup_free_ char *p = NULL;
2✔
310

311
                p = utf8_escape_invalid(value);
2✔
312
                return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
2✔
313
                                       "%s:%u: invalid UTF-8 value for key %s: '%s', ignoring.",
314
                                       strna(filename), line, key, p);
315
        }
316

317
        return 0;
318
}
319

320
static int parse_env_file_push(
2,645,827✔
321
                const char *filename, unsigned line,
322
                const char *key, char *value,
323
                void *userdata) {
324

325
        const char *k;
2,645,827✔
326
        va_list aq, *ap = userdata;
2,645,827✔
327
        int r;
2,645,827✔
328

329
        assert(key);
2,645,827✔
330

331
        r = check_utf8ness_and_warn(filename, line, key, value);
2,645,827✔
332
        if (r < 0)
2,645,827✔
333
                return r;
2,645,827✔
334

335
        va_copy(aq, *ap);
2,645,827✔
336

337
        while ((k = va_arg(aq, const char *))) {
5,298,883✔
338
                char **v;
2,785,069✔
339

340
                v = va_arg(aq, char **);
2,785,069✔
341

342
                if (streq(key, k)) {
2,785,069✔
343
                        va_end(aq);
132,013✔
344
                        free_and_replace(*v, value);
132,013✔
345

346
                        return 1;
132,013✔
347
                }
348
        }
349

350
        va_end(aq);
2,513,814✔
351
        free(value);
2,513,814✔
352

353
        return 0;
2,513,814✔
354
}
355

356
int parse_env_filev(
186,344✔
357
                FILE *f,
358
                const char *fname,
359
                va_list ap) {
360

361
        int r;
186,344✔
362
        va_list aq;
186,344✔
363

364
        assert(f || fname);
186,344✔
365

366
        va_copy(aq, ap);
186,344✔
367
        r = parse_env_file_internal(f, fname, parse_env_file_push, &aq);
186,344✔
368
        va_end(aq);
186,344✔
369
        return r;
186,344✔
370
}
371

372
int parse_env_file_fdv(int fd, const char *fname, va_list ap) {
2,723✔
373
        _cleanup_fclose_ FILE *f = NULL;
2,723✔
374
        va_list aq;
2,723✔
375
        int r;
2,723✔
376

377
        assert(fd >= 0);
2,723✔
378

379
        r = fdopen_independent(fd, "re", &f);
2,723✔
380
        if (r < 0)
2,723✔
381
                return r;
382

383
        va_copy(aq, ap);
2,723✔
384
        r = parse_env_file_internal(f, fname, parse_env_file_push, &aq);
2,723✔
385
        va_end(aq);
2,723✔
386
        return r;
2,723✔
387
}
388

389
int parse_env_file_sentinel(
186,276✔
390
                FILE *f,
391
                const char *fname,
392
                ...) {
393

394
        va_list ap;
186,276✔
395
        int r;
186,276✔
396

397
        assert(f || fname);
186,276✔
398

399
        va_start(ap, fname);
186,276✔
400
        r = parse_env_filev(f, fname, ap);
186,276✔
401
        va_end(ap);
186,276✔
402

403
        return r;
186,276✔
404
}
405

406
int parse_env_file_fd_sentinel(
2,310✔
407
                int fd,
408
                const char *fname, /* only used for logging */
409
                ...) {
410

411
        va_list ap;
2,310✔
412
        int r;
2,310✔
413

414
        assert(fd >= 0);
2,310✔
415

416
        va_start(ap, fname);
2,310✔
417
        r = parse_env_file_fdv(fd, fname, ap);
2,310✔
418
        va_end(ap);
2,310✔
419

420
        return r;
2,310✔
421
}
422

423
int parse_env_datav(
68✔
424
                const char *data,
425
                size_t size,
426
                const char *fname, /* only used for logging */
427
                va_list ap) {
428

429
        assert(data);
68✔
430

431
        if (size == SIZE_MAX)
68✔
432
                size = strlen_ptr(data);
60✔
433

434
        _cleanup_fclose_ FILE *f = fmemopen_unlocked((void*) data, size, "r");
136✔
435
        if (!f)
68✔
436
                return -ENOMEM;
437

438
        return parse_env_filev(f, fname, ap);
68✔
439
}
440

441
int parse_env_data_sentinel(
68✔
442
                const char *data,
443
                size_t size,
444
                const char *fname, /* only used for logging */
445
                ...) {
446

447
        va_list ap;
68✔
448
        int r;
68✔
449

450
        va_start(ap, fname);
68✔
451
        r = parse_env_datav(data, size, fname, ap);
68✔
452
        va_end(ap);
68✔
453

454
        return r;
68✔
455
}
456

457
static int load_env_file_push(
561✔
458
                const char *filename, unsigned line,
459
                const char *key, char *value,
460
                void *userdata) {
461

462
        char ***m = userdata;
561✔
463
        char *p;
561✔
464
        int r;
561✔
465

466
        assert(key);
561✔
467

468
        r = check_utf8ness_and_warn(filename, line, key, value);
561✔
469
        if (r < 0)
561✔
470
                return r;
471

472
        p = strjoin(key, "=", value);
558✔
473
        if (!p)
558✔
474
                return -ENOMEM;
475

476
        r = strv_env_replace_consume(m, p);
558✔
477
        if (r < 0)
558✔
478
                return r;
479

480
        free(value);
558✔
481
        return 0;
558✔
482
}
483

484
int load_env_file(FILE *f, const char *fname, char ***ret) {
283✔
485
        _cleanup_strv_free_ char **m = NULL;
283✔
486
        int r;
283✔
487

488
        assert(f || fname);
283✔
489
        assert(ret);
283✔
490

491
        r = parse_env_file_internal(f, fname, load_env_file_push, &m);
283✔
492
        if (r < 0)
283✔
493
                return r;
494

495
        *ret = TAKE_PTR(m);
278✔
496
        return 0;
278✔
497
}
498

499
static int load_env_file_push_pairs(
49,993✔
500
                const char *filename, unsigned line,
501
                const char *key, char *value,
502
                void *userdata) {
503

504
        char ***m = ASSERT_PTR(userdata);
49,993✔
505
        int r;
49,993✔
506

507
        assert(key);
49,993✔
508

509
        r = check_utf8ness_and_warn(filename, line, key, value);
49,993✔
510
        if (r < 0)
49,993✔
511
                return r;
512

513
        /* Check if the key is present */
514
        for (char **t = *m; t && *t; t += 2)
287,959✔
515
                if (streq(t[0], key)) {
237,971✔
516
                        if (value)
5✔
517
                                return free_and_replace(t[1], value);
5✔
518
                        else
UNCOV
519
                                return free_and_strdup(t+1, "");
×
520
                }
521

522
        r = strv_extend(m, key);
49,988✔
523
        if (r < 0)
49,988✔
524
                return r;
525

526
        if (value)
49,988✔
527
                return strv_push(m, value);
49,985✔
528
        else
529
                return strv_extend(m, "");
3✔
530
}
531

532
int load_env_file_pairs(FILE *f, const char *fname, char ***ret) {
9,175✔
533
        _cleanup_strv_free_ char **m = NULL;
9,175✔
534
        int r;
9,175✔
535

536
        assert(f || fname);
9,175✔
537
        assert(ret);
9,175✔
538

539
        r = parse_env_file_internal(f, fname, load_env_file_push_pairs, &m);
9,175✔
540
        if (r < 0)
9,175✔
541
                return r;
542

543
        *ret = TAKE_PTR(m);
9,156✔
544
        return 0;
9,156✔
545
}
546

547
int load_env_file_pairs_fd(int fd, const char *fname, char ***ret) {
7,140✔
548
        _cleanup_fclose_ FILE *f = NULL;
7,140✔
549
        int r;
7,140✔
550

551
        assert(fd >= 0);
7,140✔
552

553
        r = fdopen_independent(fd, "re", &f);
7,140✔
554
        if (r < 0)
7,140✔
555
                return r;
556

557
        return load_env_file_pairs(f, fname, ret);
7,140✔
558
}
559

560
static int merge_env_file_push(
53✔
561
                const char *filename, unsigned line,
562
                const char *key, char *value,
563
                void *userdata) {
564

565
        char ***env = ASSERT_PTR(userdata);
53✔
566
        char *expanded_value;
53✔
567
        int r;
53✔
568

569
        assert(key);
53✔
570

571
        if (!value) {
53✔
572
                log_error("%s:%u: invalid syntax (around \"%s\"), ignoring.", strna(filename), line, key);
20✔
573
                return 0;
10✔
574
        }
575

576
        if (!env_name_is_valid(key)) {
43✔
577
                log_error("%s:%u: invalid variable name \"%s\", ignoring.", strna(filename), line, key);
6✔
578
                free(value);
3✔
579
                return 0;
3✔
580
        }
581

582
        r = replace_env(value,
40✔
583
                        *env,
584
                        REPLACE_ENV_USE_ENVIRONMENT|REPLACE_ENV_ALLOW_BRACELESS|REPLACE_ENV_ALLOW_EXTENDED,
585
                        &expanded_value);
586
        if (r < 0)
40✔
UNCOV
587
                return log_error_errno(r, "%s:%u: Failed to expand variable '%s': %m", strna(filename), line, value);
×
588

589
        free_and_replace(value, expanded_value);
40✔
590

591
        log_debug("%s:%u: setting %s=%s", filename, line, key, value);
40✔
592

593
        return load_env_file_push(filename, line, key, value, env);
40✔
594
}
595

596
int merge_env_file(
229✔
597
                char ***env,
598
                FILE *f,
599
                const char *fname) {
600

601
        assert(env);
229✔
602
        assert(f || fname);
229✔
603

604
        /* NOTE: this function supports braceful and braceless variable expansions,
605
         * plus "extended" substitutions, unlike other exported parsing functions.
606
         */
607

608
        return parse_env_file_internal(f, fname, merge_env_file_push, env);
229✔
609
}
610

611
static void env_file_fputs_escaped(FILE *f, const char *p) {
11,651✔
612
        assert(f);
11,651✔
613
        assert(p);
11,651✔
614

615
        flockfile(f);
11,651✔
616

617
        if (string_has_cc(p, NULL) || chars_intersect(p, WHITESPACE SHELL_NEED_QUOTES)) {
11,651✔
618
                fputc_unlocked('"', f);
18✔
619

620
                for (; *p; p++) {
249✔
621
                        if (strchr(SHELL_NEED_ESCAPE, *p))
231✔
622
                                fputc_unlocked('\\', f);
12✔
623

624
                        fputc_unlocked(*p, f);
462✔
625
                }
626

627
                fputc_unlocked('"', f);
18✔
628
        } else
629
                fputs_unlocked(p, f);
11,633✔
630

631
        funlockfile(f);
11,651✔
632
}
11,651✔
633

634
void env_file_fputs_assignment(FILE *f, const char *k, const char *v) {
26,959✔
635
        assert(f);
26,959✔
636
        assert(k);
26,959✔
637

638
        if (!v)
26,959✔
639
                return;
640

641
        fputs(k, f);
11,139✔
642
        env_file_fputs_escaped(f, v);
11,139✔
643
        fputc('\n', f);
11,139✔
644
}
645

646
static void write_env_var(FILE *f, const char *v) {
512✔
647
        const char *p;
512✔
648

649
        assert(f);
512✔
650
        assert(v);
512✔
651

652
        p = strchr(v, '=');
512✔
653
        if (!p) {
512✔
654
                /* Fallback */
UNCOV
655
                fputs_unlocked(v, f);
×
UNCOV
656
                fputc_unlocked('\n', f);
×
UNCOV
657
                return;
×
658
        }
659

660
        p++;
512✔
661
        fwrite_unlocked(v, 1, p-v, f);
512✔
662

663
        env_file_fputs_escaped(f, p);
512✔
664

665
        fputc_unlocked('\n', f);
512✔
666
}
667

668
int write_env_file(int dir_fd, const char *fname, char **headers, char **l, WriteEnvFileFlags flags) {
292✔
669
        _cleanup_fclose_ FILE *f = NULL;
292✔
670
        _cleanup_free_ char *p = NULL;
292✔
671
        int r;
292✔
672

673
        assert(dir_fd >= 0 || dir_fd == AT_FDCWD);
292✔
674
        assert(fname);
292✔
675

676
        bool call_label_ops_post = false;
292✔
677
        if (FLAGS_SET(flags, WRITE_ENV_FILE_LABEL)) {
292✔
678
                r = label_ops_pre(dir_fd, fname, S_IFREG);
281✔
679
                if (r < 0)
281✔
680
                        return r;
681

682
                call_label_ops_post = true;
683
        }
684

685
        r = fopen_tmpfile_linkable_at(dir_fd, fname, O_WRONLY|O_CLOEXEC, &p, &f);
292✔
686
        int k = call_label_ops_post ? label_ops_post(f ? fileno(f) : dir_fd, f ? NULL : fname, /* created= */ !!f) : 0;
573✔
687
        if (r < 0)
292✔
688
                return r;
689
        CLEANUP_TMPFILE_AT(dir_fd, p);
292✔
690
        if (k < 0)
292✔
691
                return k;
692

693
        r = fchmod_umask(fileno(f), 0644);
292✔
694
        if (r < 0)
292✔
695
                return r;
696

697
        STRV_FOREACH(i, headers) {
827✔
698
                assert(isempty(*i) || startswith(*i, "#"));
535✔
699
                fputs_unlocked(*i, f);
535✔
700
                fputc_unlocked('\n', f);
1,070✔
701
        }
702

703
        STRV_FOREACH(i, l)
804✔
704
                write_env_var(f, *i);
512✔
705

706
        r = flink_tmpfile_at(f, dir_fd, p, fname, LINK_TMPFILE_REPLACE|LINK_TMPFILE_SYNC);
292✔
707
        if (r < 0)
292✔
708
                return r;
709

710
        p = mfree(p); /* disarm CLEANUP_TMPFILE_AT() */
292✔
711

712
        return 0;
292✔
713
}
714

715
int write_vconsole_conf(int dir_fd, const char *fname, char **l) {
254✔
716
        char **headers = STRV_MAKE(
254✔
717
                "# Written by systemd-localed(8) or systemd-firstboot(1), read by systemd-localed",
718
                "# and systemd-vconsole-setup(8). Use localectl(1) to update this file.");
719

720
        return write_env_file(dir_fd, fname, headers, l, WRITE_ENV_FILE_LABEL);
254✔
721
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE TRIAL · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc