• 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

99.42
/src/basic/escape.c
1
/* SPDX-License-Identifier: LGPL-2.1-or-later */
2

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

6
#include "alloc-util.h"
7
#include "escape.h"
8
#include "hexdecoct.h"
9
#include "string-util.h"
10
#include "strv.h"
11
#include "utf8.h"
12

13
int cescape_char(char c, char *buf) {
931,051✔
14
        char *buf_old = buf;
931,051✔
15

16
        /* Needs space for 4 characters in the buffer */
17

18
        switch (c) {
931,051✔
19

20
                case '\a':
7✔
21
                        *(buf++) = '\\';
7✔
22
                        *(buf++) = 'a';
7✔
23
                        break;
7✔
24
                case '\b':
9✔
25
                        *(buf++) = '\\';
9✔
26
                        *(buf++) = 'b';
9✔
27
                        break;
9✔
28
                case '\f':
7✔
29
                        *(buf++) = '\\';
7✔
30
                        *(buf++) = 'f';
7✔
31
                        break;
7✔
32
                case '\n':
261✔
33
                        *(buf++) = '\\';
261✔
34
                        *(buf++) = 'n';
261✔
35
                        break;
261✔
36
                case '\r':
4✔
37
                        *(buf++) = '\\';
4✔
38
                        *(buf++) = 'r';
4✔
39
                        break;
4✔
40
                case '\t':
45✔
41
                        *(buf++) = '\\';
45✔
42
                        *(buf++) = 't';
45✔
43
                        break;
45✔
44
                case '\v':
2✔
45
                        *(buf++) = '\\';
2✔
46
                        *(buf++) = 'v';
2✔
47
                        break;
2✔
48
                case '\\':
611✔
49
                        *(buf++) = '\\';
611✔
50
                        *(buf++) = '\\';
611✔
51
                        break;
611✔
52
                case '"':
2,322✔
53
                        *(buf++) = '\\';
2,322✔
54
                        *(buf++) = '"';
2,322✔
55
                        break;
2,322✔
56
                case '\'':
19✔
57
                        *(buf++) = '\\';
19✔
58
                        *(buf++) = '\'';
19✔
59
                        break;
19✔
60

61
                default:
927,764✔
62
                        /* For special chars we prefer octal over
63
                         * hexadecimal encoding, simply because glib's
64
                         * g_strescape() does the same */
65
                        if ((c < ' ') || (c >= 127)) {
927,764✔
66
                                *(buf++) = '\\';
13,823✔
67
                                *(buf++) = octchar((unsigned char) c >> 6);
13,823✔
68
                                *(buf++) = octchar((unsigned char) c >> 3);
13,823✔
69
                                *(buf++) = octchar((unsigned char) c);
13,823✔
70
                        } else
71
                                *(buf++) = c;
913,941✔
72
                        break;
73
        }
74

75
        return buf - buf_old;
931,051✔
76
}
77

78
char* cescape_length(const char *s, size_t n) {
17,677✔
79
        const char *f;
17,677✔
80
        char *r, *t;
17,677✔
81

82
        /* Does C style string escaping. May be reversed with cunescape(). */
83

84
        assert(s || n == 0);
17,677✔
85

86
        if (n == SIZE_MAX)
17,677✔
87
                n = strlen(s);
8,067✔
88

89
        if (n > (SIZE_MAX - 1) / 4)
17,677✔
90
                return NULL;
91

92
        r = new(char, n*4 + 1);
17,677✔
93
        if (!r)
17,677✔
94
                return NULL;
95

96
        for (f = s, t = r; f < s + n; f++)
485,803✔
97
                t += cescape_char(*f, t);
468,126✔
98

99
        *t = 0;
17,677✔
100

101
        return r;
17,677✔
102
}
103

104
int cunescape_one(const char *p, size_t length, char32_t *ret, bool *eight_bit, bool accept_nul) {
6,683✔
105
        int r = 1;
6,683✔
106

107
        assert(p);
6,683✔
108
        assert(ret);
6,683✔
109

110
        /* Unescapes C style. Returns the unescaped character in ret.
111
         * Sets *eight_bit to true if the escaped sequence either fits in
112
         * one byte in UTF-8 or is a non-unicode literal byte and should
113
         * instead be copied directly.
114
         */
115

116
        if (length != SIZE_MAX && length < 1)
6,683✔
117
                return -EINVAL;
118

119
        switch (p[0]) {
6,683✔
120

121
        case 'a':
4✔
122
                *ret = '\a';
4✔
123
                break;
4✔
124
        case 'b':
8✔
125
                *ret = '\b';
8✔
126
                break;
8✔
127
        case 'f':
3✔
128
                *ret = '\f';
3✔
129
                break;
3✔
130
        case 'n':
22✔
131
                *ret = '\n';
22✔
132
                break;
22✔
133
        case 'r':
4✔
134
                *ret = '\r';
4✔
135
                break;
4✔
136
        case 't':
6✔
137
                *ret = '\t';
6✔
138
                break;
6✔
139
        case 'v':
3✔
140
                *ret = '\v';
3✔
141
                break;
3✔
142
        case '\\':
15✔
143
                *ret = '\\';
15✔
144
                break;
15✔
145
        case '"':
5✔
146
                *ret = '"';
5✔
147
                break;
5✔
148
        case '\'':
1✔
149
                *ret = '\'';
1✔
150
                break;
1✔
151

152
        case 's':
3✔
153
                /* This is an extension of the XDG syntax files */
154
                *ret = ' ';
3✔
155
                break;
3✔
156

157
        case 'x': {
6,527✔
158
                /* hexadecimal encoding */
159
                int a, b;
6,527✔
160

161
                if (length != SIZE_MAX && length < 3)
6,527✔
162
                        return -EINVAL;
163

164
                a = unhexchar(p[1]);
6,523✔
165
                if (a < 0)
6,523✔
166
                        return -EINVAL;
167

168
                b = unhexchar(p[2]);
6,521✔
169
                if (b < 0)
6,521✔
170
                        return -EINVAL;
171

172
                /* Don't allow NUL bytes */
173
                if (a == 0 && b == 0 && !accept_nul)
6,521✔
174
                        return -EINVAL;
175

176
                *ret = (a << 4U) | b;
6,520✔
177
                *eight_bit = true;
6,520✔
178
                r = 3;
6,520✔
179
                break;
6,520✔
180
        }
181

182
        case 'u': {
19✔
183
                /* C++11 style 16-bit unicode */
184

185
                int a[4];
19✔
186
                size_t i;
19✔
187
                uint32_t c;
19✔
188

189
                if (length != SIZE_MAX && length < 5)
19✔
190
                        return -EINVAL;
1✔
191

192
                for (i = 0; i < 4; i++) {
95✔
193
                        a[i] = unhexchar(p[1 + i]);
76✔
194
                        if (a[i] < 0)
76✔
195
                                return a[i];
196
                }
197

198
                c = ((uint32_t) a[0] << 12U) | ((uint32_t) a[1] << 8U) | ((uint32_t) a[2] << 4U) | (uint32_t) a[3];
19✔
199

200
                /* Don't allow 0 chars */
201
                if (c == 0 && !accept_nul)
19✔
202
                        return -EINVAL;
203

204
                *ret = c;
18✔
205
                r = 5;
18✔
206
                break;
18✔
207
        }
208

209
        case 'U': {
10✔
210
                /* C++11 style 32-bit unicode */
211

212
                int a[8];
10✔
213
                size_t i;
10✔
214
                char32_t c;
10✔
215

216
                if (length != SIZE_MAX && length < 9)
10✔
UNCOV
217
                        return -EINVAL;
×
218

219
                for (i = 0; i < 8; i++) {
90✔
220
                        a[i] = unhexchar(p[1 + i]);
80✔
221
                        if (a[i] < 0)
80✔
222
                                return a[i];
223
                }
224

225
                c = ((uint32_t) a[0] << 28U) | ((uint32_t) a[1] << 24U) | ((uint32_t) a[2] << 20U) | ((uint32_t) a[3] << 16U) |
10✔
226
                    ((uint32_t) a[4] << 12U) | ((uint32_t) a[5] <<  8U) | ((uint32_t) a[6] <<  4U) |  (uint32_t) a[7];
10✔
227

228
                /* Don't allow 0 chars */
229
                if (c == 0 && !accept_nul)
10✔
230
                        return -EINVAL;
231

232
                /* Don't allow invalid code points */
233
                if (!unichar_is_valid(c))
10✔
234
                        return -EINVAL;
235

236
                *ret = c;
10✔
237
                r = 9;
10✔
238
                break;
10✔
239
        }
240

241
        case '0':
20✔
242
        case '1':
243
        case '2':
244
        case '3':
245
        case '4':
246
        case '5':
247
        case '6':
248
        case '7': {
249
                /* octal encoding */
250
                int a, b, c;
20✔
251
                char32_t m;
20✔
252

253
                if (length != SIZE_MAX && length < 3)
20✔
254
                        return -EINVAL;
255

256
                a = unoctchar(p[0]);
16✔
257
                if (a < 0)
16✔
258
                        return -EINVAL;
259

260
                b = unoctchar(p[1]);
16✔
261
                if (b < 0)
16✔
262
                        return -EINVAL;
263

264
                c = unoctchar(p[2]);
16✔
265
                if (c < 0)
16✔
266
                        return -EINVAL;
267

268
                /* don't allow NUL bytes */
269
                if (a == 0 && b == 0 && c == 0 && !accept_nul)
16✔
270
                        return -EINVAL;
271

272
                /* Don't allow bytes above 255 */
273
                m = ((uint32_t) a << 6U) | ((uint32_t) b << 3U) | (uint32_t) c;
14✔
274
                if (m > 255)
14✔
275
                        return -EINVAL;
276

277
                *ret = m;
14✔
278
                *eight_bit = true;
14✔
279
                r = 3;
14✔
280
                break;
14✔
281
        }
282

283
        default:
284
                return -EINVAL;
285
        }
286

287
        return r;
288
}
289

290
ssize_t cunescape_length_with_prefix(const char *s, size_t length, const char *prefix, UnescapeFlags flags, char **ret) {
102,277✔
291
        _cleanup_free_ char *ans = NULL;
102,277✔
292
        char *t;
102,277✔
293
        const char *f;
102,277✔
294
        size_t pl;
102,277✔
295
        int r;
102,277✔
296

297
        assert(s);
102,277✔
298
        assert(ret);
102,277✔
299

300
        /* Undoes C style string escaping, and optionally prefixes it. */
301

302
        if (length == SIZE_MAX)
102,277✔
303
                length = strlen(s);
97,944✔
304

305
        pl = strlen_ptr(prefix);
102,277✔
306

307
        ans = new(char, pl+length+1);
102,277✔
308
        if (!ans)
102,277✔
309
                return -ENOMEM;
310

311
        if (prefix)
102,277✔
312
                memcpy(ans, prefix, pl);
4,297✔
313

314
        for (f = s, t = ans + pl; f < s + length; f++) {
2,593,380✔
315
                size_t remaining;
2,491,112✔
316
                bool eight_bit = false;
2,491,112✔
317
                char32_t u;
2,491,112✔
318

319
                remaining = s + length - f;
2,491,112✔
320
                assert(remaining > 0);
2,491,112✔
321

322
                if (*f != '\\') {
2,491,112✔
323
                        /* A literal, copy verbatim */
324
                        *(t++) = *f;
2,484,504✔
325
                        continue;
2,484,511✔
326
                }
327

328
                if (remaining == 1) {
6,608✔
329
                        if (flags & UNESCAPE_RELAX) {
3✔
330
                                /* A trailing backslash, copy verbatim */
331
                                *(t++) = *f;
1✔
332
                                continue;
1✔
333
                        }
334

335
                        return -EINVAL;
9✔
336
                }
337

338
                r = cunescape_one(f + 1, remaining - 1, &u, &eight_bit, flags & UNESCAPE_ACCEPT_NUL);
6,605✔
339
                if (r < 0) {
6,605✔
340
                        if (flags & UNESCAPE_RELAX) {
13✔
341
                                /* Invalid escape code, let's take it literal then */
342
                                *(t++) = '\\';
6✔
343
                                continue;
6✔
344
                        }
345

346
                        return r;
7✔
347
                }
348

349
                f += r;
6,592✔
350
                if (eight_bit)
6,592✔
351
                        /* One byte? Set directly as specified */
352
                        *(t++) = u;
6,521✔
353
                else
354
                        /* Otherwise encode as multi-byte UTF-8 */
355
                        t += utf8_encode_unichar(t, u);
71✔
356
        }
357

358
        *t = 0;
102,268✔
359

360
        assert(t >= ans); /* Let static analyzers know that the answer is non-negative. */
102,268✔
361
        *ret = TAKE_PTR(ans);
102,268✔
362
        return t - *ret;
102,268✔
363
}
364

365
char* xescape_full(const char *s, const char *bad, size_t console_width, XEscapeFlags flags) {
61,896✔
366
        char *ans, *t, *prev, *prev2;
61,896✔
367
        const char *f;
61,896✔
368

369
        assert(s);
61,896✔
370

371
        /* Escapes all chars in bad, in addition to \ and all special chars, in \xFF style escaping. May be
372
         * reversed with cunescape(). If XESCAPE_8_BIT is specified, characters >= 127 are let through
373
         * unchanged. This corresponds to non-ASCII printable characters in pre-unicode encodings.
374
         *
375
         * If console_width is reached, or XESCAPE_FORCE_ELLIPSIS is set, output is truncated and "..." is
376
         * appended. */
377

378
        if (console_width == 0)
61,896✔
379
                return strdup("");
4✔
380

381
        ans = new(char, MIN(strlen(s), console_width) * 4 + 1);
61,892✔
382
        if (!ans)
61,892✔
383
                return NULL;
384

385
        memset(ans, '_', MIN(strlen(s), console_width) * 4);
61,892✔
386
        ans[MIN(strlen(s), console_width) * 4] = 0;
61,892✔
387

388
        bool force_ellipsis = FLAGS_SET(flags, XESCAPE_FORCE_ELLIPSIS);
61,892✔
389

390
        for (f = s, t = prev = prev2 = ans; ; f++) {
61,892✔
391
                char *tmp_t = t;
5,045,576✔
392

393
                if (!*f) {
5,045,576✔
394
                        if (force_ellipsis)
61,688✔
395
                                break;
396

397
                        *t = 0;
61,675✔
398
                        return ans;
61,675✔
399
                }
400

401
                if ((unsigned char) *f < ' ' ||
4,983,888✔
402
                    (!FLAGS_SET(flags, XESCAPE_8_BIT) && (unsigned char) *f >= 127) ||
4,982,761✔
403
                    *f == '\\' || (bad && strchr(bad, *f))) {
4,982,428✔
404
                        if ((size_t) (t - ans) + 4 + 3 * force_ellipsis > console_width)
3,894✔
405
                                break;
406

407
                        *(t++) = '\\';
3,710✔
408
                        *(t++) = 'x';
3,710✔
409
                        *(t++) = hexchar(*f >> 4);
3,710✔
410
                        *(t++) = hexchar(*f);
3,710✔
411
                } else {
412
                        if ((size_t) (t - ans) + 1 + 3 * force_ellipsis > console_width)
4,979,994✔
413
                                break;
414

415
                        *(t++) = *f;
4,979,974✔
416
                }
417

418
                /* We might need to go back two cycles to fit three dots, so remember two positions */
419
                prev2 = prev;
4,983,684✔
420
                prev = tmp_t;
4,983,684✔
421
        }
422

423
        /* We can just write where we want, since chars are one-byte */
424
        size_t c = MIN(console_width, 3u); /* If the console is too narrow, write fewer dots */
217✔
425
        size_t off;
217✔
426
        if (console_width - c >= (size_t) (t - ans))
217✔
427
                off = (size_t) (t - ans);
428
        else if (console_width - c >= (size_t) (prev - ans))
76✔
429
                off = (size_t) (prev - ans);
430
        else if (console_width - c >= (size_t) (prev2 - ans))
10✔
431
                off = (size_t) (prev2 - ans);
432
        else
433
                off = console_width - c;
1✔
434
        assert(off <= (size_t) (t - ans));
217✔
435

436
        memcpy(ans + off, "...", c);
217✔
437
        ans[off + c] = '\0';
217✔
438
        return ans;
217✔
439
}
440

441
char* escape_non_printable_full(const char *str, size_t console_width, XEscapeFlags flags) {
413✔
442
        if (FLAGS_SET(flags, XESCAPE_8_BIT))
413✔
UNCOV
443
                return xescape_full(str, /* bad= */ NULL, console_width, flags);
×
444
        else
445
                return utf8_escape_non_printable_full(str,
413✔
446
                                                      console_width,
447
                                                      FLAGS_SET(flags, XESCAPE_FORCE_ELLIPSIS));
413✔
448
}
449

450
char* octescape(const char *s, size_t len) {
80✔
451
        char *buf, *t;
80✔
452

453
        /* Escapes \ and " chars, in \nnn style escaping. */
454

455
        assert(s || len == 0);
80✔
456

457
        if (len == SIZE_MAX)
80✔
458
                len = strlen(s);
27✔
459

460
        if (len > (SIZE_MAX - 1) / 4)
80✔
461
                return NULL;
462

463
        t = buf = new(char, len * 4 + 1);
80✔
464
        if (!buf)
80✔
465
                return NULL;
466

467
        for (size_t i = 0; i < len; i++) {
908✔
468
                uint8_t u = (uint8_t) s[i];
828✔
469

470
                if (u < ' ' || u >= 127 || IN_SET(u, '\\', '"')) {
828✔
471
                        *(t++) = '\\';
5✔
472
                        *(t++) = '0' + (u >> 6);
5✔
473
                        *(t++) = '0' + ((u >> 3) & 7);
5✔
474
                        *(t++) = '0' + (u & 7);
5✔
475
                } else
476
                        *(t++) = u;
823✔
477
        }
478

479
        *t = 0;
80✔
480
        return buf;
80✔
481
}
482

483
char* decescape(const char *s, size_t len, const char *bad) {
8✔
484
        char *buf, *t;
8✔
485

486
        /* Escapes all chars in bad, in addition to \ and " chars, in \nnn decimal style escaping. */
487

488
        assert(s || len == 0);
8✔
489

490
        if (len == SIZE_MAX)
8✔
491
                len = strlen(s);
6✔
492

493
        if (len > (SIZE_MAX - 1) / 4)
8✔
494
                return NULL;
495

496
        t = buf = new(char, len * 4 + 1);
8✔
497
        if (!buf)
8✔
498
                return NULL;
499

500
        for (size_t i = 0; i < len; i++) {
47✔
501
                uint8_t u = (uint8_t) s[i];
39✔
502

503
                if (u < ' ' || u >= 127 || IN_SET(u, '\\', '"') || strchr(bad, u)) {
39✔
504
                        *(t++) = '\\';
20✔
505
                        *(t++) = '0' + (u / 100);
20✔
506
                        *(t++) = '0' + ((u / 10) % 10);
20✔
507
                        *(t++) = '0' + (u % 10);
20✔
508
                } else
509
                        *(t++) = u;
19✔
510
        }
511

512
        *t = 0;
8✔
513
        return buf;
8✔
514
}
515

516
static char* strcpy_backslash_escaped(char *t, const char *s, const char *bad) {
4,860✔
517
        assert(bad);
4,860✔
518
        assert(t);
4,860✔
519
        assert(s);
4,860✔
520

521
        while (*s) {
195,659✔
522
                int l = utf8_encoded_valid_unichar(s, SIZE_MAX);
190,799✔
523

524
                if (char_is_cc(*s) || l < 0)
190,799✔
525
                        t += cescape_char(*(s++), t);
258✔
526
                else if (l == 1) {
190,541✔
527
                        if (*s == '\\' || strchr(bad, *s))
190,537✔
528
                                *(t++) = '\\';
2,202✔
529
                        *(t++) = *(s++);
190,537✔
530
                } else {
531
                        t = mempcpy(t, s, l);
4✔
532
                        s += l;
4✔
533
                }
534
        }
535

536
        return t;
4,860✔
537
}
538

539
char* shell_escape(const char *s, const char *bad) {
1,433✔
540
        char *buf, *t;
1,433✔
541

542
        buf = new(char, strlen(s)*4+1);
1,433✔
543
        if (!buf)
1,433✔
544
                return NULL;
545

546
        t = strcpy_backslash_escaped(buf, s, bad);
1,433✔
547
        *t = 0;
1,433✔
548

549
        return buf;
1,433✔
550
}
551

552
char* shell_maybe_quote(const char *s, ShellEscapeFlags flags) {
69,628✔
553
        const char *p;
69,628✔
554
        char *buf, *t;
69,628✔
555

556
        assert(s);
69,628✔
557

558
        /* Encloses a string in quotes if necessary to make it OK as a shell string. */
559

560
        if (FLAGS_SET(flags, SHELL_ESCAPE_EMPTY) && isempty(s))
69,628✔
561
                return strdup("\"\""); /* We don't use $'' here in the POSIX mode. "" is fine too. */
312✔
562

563
        for (p = s; *p; ) {
1,503,471✔
564
                int l = utf8_encoded_valid_unichar(p, SIZE_MAX);
1,437,582✔
565

566
                if (char_is_cc(*p) || l < 0 ||
1,437,582✔
567
                    strchr(WHITESPACE SHELL_NEED_QUOTES, *p))
1,437,555✔
568
                        break;
569

570
                p += l;
1,434,155✔
571
        }
572

573
        if (!*p)
69,316✔
574
                return strdup(s);
65,889✔
575

576
        buf = new(char, FLAGS_SET(flags, SHELL_ESCAPE_POSIX) + 1 + strlen(s)*4 + 1 + 1);
6,786✔
577
        if (!buf)
3,427✔
578
                return NULL;
579

580
        t = buf;
3,427✔
581
        if (FLAGS_SET(flags, SHELL_ESCAPE_POSIX)) {
3,427✔
582
                *(t++) = '$';
68✔
583
                *(t++) = '\'';
68✔
584
        } else
585
                *(t++) = '"';
3,359✔
586

587
        t = mempcpy(t, s, p - s);
3,427✔
588

589
        t = strcpy_backslash_escaped(t, p,
6,786✔
590
                                     FLAGS_SET(flags, SHELL_ESCAPE_POSIX) ? SHELL_NEED_ESCAPE_POSIX : SHELL_NEED_ESCAPE);
591

592
        if (FLAGS_SET(flags, SHELL_ESCAPE_POSIX))
3,427✔
593
                *(t++) = '\'';
68✔
594
        else
595
                *(t++) = '"';
3,359✔
596
        *t = 0;
3,427✔
597

598
        return str_realloc(buf);
3,427✔
599
}
600

601
char* quote_command_line(char **argv, ShellEscapeFlags flags) {
21,720✔
602
        _cleanup_free_ char *result = NULL;
21,720✔
603

604
        assert(argv);
21,720✔
605

606
        STRV_FOREACH(a, argv) {
90,602✔
607
                _cleanup_free_ char *t = NULL;
68,882✔
608

609
                t = shell_maybe_quote(*a, flags);
68,882✔
610
                if (!t)
68,882✔
611
                        return NULL;
612

613
                if (!strextend_with_separator(&result, " ", t))
68,882✔
614
                        return NULL;
615
        }
616

617
        return str_realloc(TAKE_PTR(result));
21,720✔
618
}
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