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

systemd / systemd / 24165447443

08 Apr 2026 10:44PM UTC coverage: 72.303% (+0.1%) from 72.175%
24165447443

push

github

bluca
compress: write sparse files when decompressing to regular files

Core dumps are often very sparse, containing large zero-filled regions
whose actual disk usage can be significantly reduced by preserving
holes. Previously, decompress_stream() always wrote dense output,
expanding all zero regions into allocated disk blocks.

Each decompression backend (xz, lz4, zstd) now auto-detects whether the
output fd is suitable for sparse writes via a shared should_sparse()
helper. The check requires both S_ISREG (regular file) and !O_APPEND,
since O_APPEND causes write() to ignore the file position set by
lseek(), which would collapse the holes and corrupt the output. For
pipes, sockets, and append-mode files, dense writes are preserved via
loop_write_full() with USEC_INFINITY timeout, matching the original
behavior. After sparse decompression, finalize_sparse() sets the final
file size to account for any trailing holes.

This is transparent to callers — all public signatures are unchanged.
coredumpctl benefits automatically:
- coredumpctl debug: temp file in /var/tmp is now sparse
- coredumpctl dump -o file: output file is now sparse
- coredumpctl dump > file: redirected stdout is now sparse
- coredumpctl dump | ...: pipe output unchanged (dense)
- coredumpctl dump >> file: append mode, falls back to dense

Co-developed-by: Claude Opus 4.6 <noreply@anthropic.com>
Co-developed-by: Codex (GPT-5) <noreply@openai.com>

123 of 132 new or added lines in 2 files covered. (93.18%)

5704 existing lines in 82 files now uncovered.

319660 of 442111 relevant lines covered (72.3%)

1196031.58 hits per line

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

88.46
/src/shared/serialize.c
1
/* SPDX-License-Identifier: LGPL-2.1-or-later */
2

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

6
#include "sd-id128.h"
7

8
#include "alloc-util.h"
9
#include "env-util.h"
10
#include "escape.h"
11
#include "extract-word.h"
12
#include "fd-util.h"
13
#include "fdset.h"
14
#include "fileio.h"
15
#include "format-util.h"
16
#include "hexdecoct.h"
17
#include "image-policy.h"
18
#include "log.h"
19
#include "memfd-util.h"
20
#include "parse-util.h"
21
#include "pidref.h"
22
#include "ratelimit.h"
23
#include "serialize.h"
24
#include "set.h"
25
#include "string-util.h"
26
#include "strv.h"
27
#include "time-util.h"
28

29
int serialize_item(FILE *f, const char *key, const char *value) {
678,868✔
30
        assert(f);
678,868✔
31
        assert(key);
678,868✔
32

33
        if (!value)
678,868✔
34
                return 0;
35

36
        /* Make sure that anything we serialize we can also read back again with read_line() with a maximum line size
37
         * of LONG_LINE_MAX. This is a safety net only. All code calling us should filter this out earlier anyway. */
38
        if (strlen(key) + 1 + strlen(value) + 1 > LONG_LINE_MAX)
601,126✔
39
                return log_warning_errno(SYNTHETIC_ERRNO(EINVAL), "Attempted to serialize overly long item '%s', refusing.", key);
7✔
40

41
        fputs(key, f);
601,119✔
42
        fputc('=', f);
601,119✔
43
        fputs(value, f);
601,119✔
44
        fputc('\n', f);
601,119✔
45

46
        return 1;
601,119✔
47
}
48

49
int serialize_item_escaped(FILE *f, const char *key, const char *value) {
50,181✔
50
        _cleanup_free_ char *c = NULL;
50,181✔
51

52
        assert(f);
50,181✔
53
        assert(key);
50,181✔
54

55
        if (!value)
50,181✔
56
                return 0;
57

58
        c = xescape(value, " ");
30,895✔
59
        if (!c)
30,895✔
60
                return log_oom();
×
61

62
        return serialize_item(f, key, c);
30,895✔
63
}
64

65
int serialize_item_format(FILE *f, const char *key, const char *format, ...) {
437,916✔
66
        _cleanup_free_ char *allocated = NULL;
437,916✔
67
        char buf[256]; /* Something reasonably short that fits nicely on any stack (i.e. is considerably less
437,916✔
68
                        * than LONG_LINE_MAX (1MiB!) */
69
        const char *b;
437,916✔
70
        va_list ap;
437,916✔
71
        int k;
437,916✔
72

73
        assert(f);
437,916✔
74
        assert(key);
437,916✔
75
        assert(format);
437,916✔
76

77
        /* First, let's try to format this into a stack buffer */
78
        va_start(ap, format);
437,916✔
79
        k = vsnprintf(buf, sizeof(buf), format, ap);
437,916✔
80
        va_end(ap);
437,916✔
81

82
        if (k < 0)
437,916✔
83
                return log_warning_errno(errno, "Failed to serialize item '%s', ignoring: %m", key);
×
84
        if (strlen(key) + 1 + k + 1 > LONG_LINE_MAX) /* See above */
437,916✔
85
                return log_warning_errno(SYNTHETIC_ERRNO(EINVAL), "Attempted to serialize overly long item '%s', refusing.", key);
×
86

87
        if ((size_t) k < sizeof(buf))
437,916✔
88
                b = buf; /* Yay, it fit! */
89
        else {
90
                /* So the string didn't fit in the short buffer above, but was not above our total limit,
91
                 * hence let's format it via dynamic memory */
92

93
                va_start(ap, format);
×
94
                k = vasprintf(&allocated, format, ap);
×
95
                va_end(ap);
×
96

97
                if (k < 0)
×
98
                        return log_warning_errno(errno, "Failed to serialize item '%s', ignoring: %m", key);
×
99

100
                b = allocated;
×
101
        }
102

103
        fputs(key, f);
437,916✔
104
        fputc('=', f);
437,916✔
105
        fputs(b, f);
437,916✔
106
        fputc('\n', f);
437,916✔
107

108
        return 1;
109
}
110

111
int serialize_fd(FILE *f, FDSet *fds, const char *key, int fd) {
72,717✔
112
        int copy;
72,717✔
113

114
        assert(f);
72,717✔
115
        assert(fds);
72,717✔
116
        assert(key);
72,717✔
117

118
        if (fd < 0)
72,717✔
119
                return 0;
120

121
        copy = fdset_put_dup(fds, fd);
8,619✔
122
        if (copy < 0)
8,619✔
123
                return log_error_errno(copy, "Failed to add file descriptor to serialization set: %m");
×
124

125
        return serialize_item_format(f, key, "%i", copy);
8,619✔
126
}
127

128
int serialize_fd_many(FILE *f, FDSet *fds, const char *key, const int fd_array[], size_t n_fd_array) {
920✔
129
        _cleanup_free_ char *t = NULL;
920✔
130

131
        assert(f);
920✔
132

133
        if (n_fd_array == 0)
920✔
134
                return 0;
135

136
        assert(fd_array);
920✔
137

138
        for (size_t i = 0; i < n_fd_array; i++) {
2,476✔
139
                int copy;
1,556✔
140

141
                if (fd_array[i] < 0)
1,556✔
142
                        return -EBADF;
143

144
                copy = fdset_put_dup(fds, fd_array[i]);
1,556✔
145
                if (copy < 0)
1,556✔
146
                        return log_error_errno(copy, "Failed to add file descriptor to serialization set: %m");
×
147

148
                if (strextendf_with_separator(&t, " ", "%i", copy) < 0)
1,556✔
149
                        return log_oom();
×
150
        }
151

152
        return serialize_item(f, key, t);
920✔
153
}
154

155
int serialize_usec(FILE *f, const char *key, usec_t usec) {
29,374✔
156
        assert(f);
29,374✔
157
        assert(key);
29,374✔
158

159
        if (usec == USEC_INFINITY)
29,374✔
160
                return 0;
161

162
        return serialize_item_format(f, key, USEC_FMT, usec);
6,397✔
163
}
164

165
int serialize_dual_timestamp(FILE *f, const char *key, const dual_timestamp *t) {
232,371✔
166
        assert(f);
232,371✔
167
        assert(key);
232,371✔
168
        assert(t);
232,371✔
169

170
        if (!dual_timestamp_is_set(t))
232,371✔
171
                return 0;
172

173
        return serialize_item_format(f, key, USEC_FMT " " USEC_FMT, t->realtime, t->monotonic);
94,363✔
174
}
175

176
int serialize_strv(FILE *f, const char *key, char * const *l) {
48,252✔
177
        int ret = 0, r;
48,252✔
178

179
        /* Returns the first error, or positive if anything was serialized, 0 otherwise. */
180

181
        assert(f);
48,252✔
182
        assert(key);
48,252✔
183

184
        STRV_FOREACH(i, l) {
77,456✔
185
                r = serialize_item_escaped(f, key, *i);
29,204✔
186
                if ((ret >= 0 && r < 0) ||
29,204✔
187
                    (ret == 0 && r > 0))
29,203✔
188
                        ret = r;
7,963✔
189
        }
190

191
        return ret;
48,252✔
192
}
193

194
int serialize_id128(FILE *f, const char *key, sd_id128_t id) {
30,152✔
195
        assert(f);
30,152✔
196
        assert(key);
30,152✔
197

198
        if (sd_id128_is_null(id))
30,152✔
199
                return 0;
11,532✔
200

201
        return serialize_item_format(f, key, SD_ID128_FORMAT_STR, SD_ID128_FORMAT_VAL(id));
18,620✔
202
}
203

204
int serialize_pidref(FILE *f, FDSet *fds, const char *key, PidRef *pidref) {
20,530✔
205
        int r;
20,530✔
206

207
        assert(f);
20,530✔
208
        assert(fds);
20,530✔
209

210
        if (!pidref_is_set(pidref))
20,530✔
211
                return 0;
212

213
        /* We always serialize the pid separately, to keep downgrades mostly working (older versions will
214
         * deserialize the pid and silently fail to deserialize the pidfd). If we also have a pidfd, we
215
         * serialize both the pid and pidfd, so that we can construct the exact same pidref after
216
         * deserialization (this doesn't work with only the pidfd, as we can't retrieve the original pid
217
         * from the pidfd anymore if the process is reaped). */
218

219
        if (pidref->fd >= 0) {
1,268✔
220
                int copy = fdset_put_dup(fds, pidref->fd);
1,268✔
221
                if (copy < 0)
1,268✔
222
                        return log_error_errno(copy, "Failed to add file descriptor to serialization set: %m");
×
223

224
                r = serialize_item_format(f, key, "@%i:" PID_FMT, copy, pidref->pid);
1,268✔
225
                if (r < 0)
1,268✔
226
                        return r;
227
        }
228

229
        return serialize_item_format(f, key, PID_FMT, pidref->pid);
1,268✔
230
}
231

232
int serialize_ratelimit(FILE *f, const char *key, const RateLimit *rl) {
64,833✔
233
        assert(rl);
64,833✔
234

235
        return serialize_item_format(f, key,
129,666✔
236
                                     USEC_FMT " " USEC_FMT " %u %u",
237
                                     rl->begin,
64,833✔
238
                                     rl->interval,
64,833✔
239
                                     rl->num,
64,833✔
240
                                     rl->burst);
64,833✔
241
}
242

243
int serialize_item_hexmem(FILE *f, const char *key, const void *p, size_t l) {
2,698✔
244
        _cleanup_free_ char *encoded = NULL;
2,698✔
245
        int r;
2,698✔
246

247
        assert(f);
2,698✔
248
        assert(key);
2,698✔
249

250
        if (!p && l > 0)
2,698✔
251
                return -EINVAL;
252

253
        if (l == 0)
2,698✔
254
                return 0;
255

256
        encoded = hexmem(p, l);
1✔
257
        if (!encoded)
1✔
258
                return log_oom_debug();
×
259

260
        r = serialize_item(f, key, encoded);
1✔
261
        if (r < 0)
1✔
262
                return r;
×
263

264
        return 1;
265
}
266

267
int serialize_item_base64mem(FILE *f, const char *key, const void *p, size_t l) {
2,698✔
268
        _cleanup_free_ char *encoded = NULL;
2,698✔
269
        ssize_t len;
2,698✔
270
        int r;
2,698✔
271

272
        assert(f);
2,698✔
273
        assert(key);
2,698✔
274

275
        if (!p && l > 0)
2,698✔
276
                return -EINVAL;
277

278
        if (l == 0)
2,698✔
279
                return 0;
280

281
        len = base64mem(p, l, &encoded);
1✔
282
        if (len <= 0)
1✔
283
                return log_oom_debug();
×
284

285
        r = serialize_item(f, key, encoded);
1✔
286
        if (r < 0)
1✔
287
                return r;
×
288

289
        return 1;
290
}
291

292
int serialize_string_set(FILE *f, const char *key, const Set *s) {
5,394✔
293
        int r;
5,394✔
294

295
        assert(f);
5,394✔
296
        assert(key);
5,394✔
297

298
        if (set_isempty(s))
5,394✔
299
                return 0;
5,394✔
300

301
        /* Serialize as individual items, as each element might contain separators and escapes */
302

303
        const char *e;
1✔
304
        SET_FOREACH(e, s) {
3✔
305
                r = serialize_item(f, key, e);
2✔
306
                if (r < 0)
2✔
307
                        return r;
×
308
        }
309

310
        return 1;
1✔
311
}
312

313
int serialize_image_policy(FILE *f, const char *key, const ImagePolicy *p) {
8,088✔
314
        _cleanup_free_ char *policy = NULL;
8,088✔
315
        int r;
8,088✔
316

317
        assert(f);
8,088✔
318
        assert(key);
8,088✔
319

320
        if (!p)
8,088✔
321
                return 0;
322

323
        r = image_policy_to_string(p, /* simplify= */ false, &policy);
42✔
324
        if (r < 0)
42✔
325
                return r;
326

327
        r = serialize_item(f, key, policy);
42✔
328
        if (r < 0)
42✔
329
                return r;
×
330

331
        return 1;
332
}
333

334
int serialize_bool(FILE *f, const char *key, bool b) {
305,757✔
335
        return serialize_item(f, key, yes_no(b));
571,211✔
336
}
337

338
int serialize_bool_elide(FILE *f, const char *key, bool b) {
124,073✔
339
        return b ? serialize_item(f, key, yes_no(b)) : 0;
124,073✔
340
}
341

342
int deserialize_read_line(FILE *f, char **ret) {
2,101,277✔
343
        _cleanup_free_ char *line = NULL;
2,101,277✔
344
        int r;
2,101,277✔
345

346
        assert(f);
2,101,277✔
347
        assert(ret);
2,101,277✔
348

349
        r = read_stripped_line(f, LONG_LINE_MAX, &line);
2,101,277✔
350
        if (r < 0)
2,101,277✔
351
                return log_error_errno(r, "Failed to read serialization line: %m");
×
352
        if (r == 0) { /* eof */
2,101,277✔
353
                *ret = NULL;
32✔
354
                return 0;
32✔
355
        }
356

357
        if (isempty(line)) { /* End marker */
2,101,245✔
358
                *ret = NULL;
77,364✔
359
                return 0;
77,364✔
360
        }
361

362
        *ret = TAKE_PTR(line);
2,023,881✔
363
        return 1;
2,023,881✔
364
}
365

366
int deserialize_fd(FDSet *fds, const char *value) {
40,356✔
367
        _cleanup_close_ int our_fd = -EBADF;
40,356✔
368
        int parsed_fd;
40,356✔
369

370
        assert(value);
40,356✔
371

372
        parsed_fd = parse_fd(value);
40,356✔
373
        if (parsed_fd < 0)
40,356✔
374
                return log_debug_errno(parsed_fd, "Failed to parse file descriptor serialization: %s", value);
×
375

376
        our_fd = fdset_remove(fds, parsed_fd); /* Take possession of the fd */
40,356✔
377
        if (our_fd < 0)
40,356✔
378
                return log_debug_errno(our_fd, "Failed to acquire fd from serialization fds: %m");
×
379

380
        return TAKE_FD(our_fd);
381
}
382

383
int deserialize_fd_many(FDSet *fds, const char *value, size_t n, int *ret) {
2,165✔
384
        int r, *fd_array = NULL;
2,165✔
385
        size_t m = 0;
2,165✔
386

387
        assert(value);
2,165✔
388

389
        fd_array = new(int, n);
2,165✔
390
        if (!fd_array)
2,165✔
391
                return -ENOMEM;
2,165✔
392

393
        CLEANUP_ARRAY(fd_array, m, close_many_and_free);
4,330✔
394

395
        for (;;) {
12,397✔
396
                _cleanup_free_ char *w = NULL;
5,116✔
397
                int fd;
7,281✔
398

399
                r = extract_first_word(&value, &w, NULL, 0);
7,281✔
400
                if (r < 0)
7,281✔
401
                        return r;
402
                if (r == 0) {
7,281✔
403
                        if (m < n) /* Too few */
2,165✔
404
                                return -EINVAL;
405

406
                        break;
2,165✔
407
                }
408

409
                if (m >= n) /* Too many */
5,116✔
410
                        return -EINVAL;
411

412
                fd = deserialize_fd(fds, w);
5,116✔
413
                if (fd < 0)
5,116✔
414
                        return fd;
415

416
                fd_array[m++] = fd;
5,116✔
417
        }
418

419
        memcpy(ret, fd_array, m * sizeof(int));
2,165✔
420
        fd_array = mfree(fd_array);
2,165✔
421

422
        return 0;
2,165✔
423
}
424

425
int deserialize_strv(const char *value, char ***l) {
85,811✔
426
        ssize_t unescaped_len;
85,811✔
427
        char *unescaped;
85,811✔
428

429
        assert(l);
85,811✔
430
        assert(value);
85,811✔
431

432
        unescaped_len = cunescape(value, 0, &unescaped);
85,811✔
433
        if (unescaped_len < 0)
85,811✔
434
                return unescaped_len;
×
435

436
        return strv_consume(l, unescaped);
85,811✔
437
}
438

439
int deserialize_usec(const char *value, usec_t *ret) {
14,821✔
440
        int r;
14,821✔
441

442
        assert(value);
14,821✔
443
        assert(ret);
14,821✔
444

445
        r = safe_atou64(value, ret);
14,821✔
446
        if (r < 0)
14,821✔
447
                return log_debug_errno(r, "Failed to parse usec value \"%s\": %m", value);
×
448

449
        return 0;
450
}
451

452
int deserialize_dual_timestamp(const char *value, dual_timestamp *ret) {
76,871✔
453
        uint64_t a, b;
76,871✔
454
        int r, pos;
76,871✔
455

456
        assert(value);
76,871✔
457
        assert(ret);
76,871✔
458

459
        pos = strspn(value, WHITESPACE);
76,871✔
460
        if (value[pos] == '-')
76,871✔
461
                return -EINVAL;
76,871✔
462
        pos += strspn(value + pos, DIGITS);
76,870✔
463
        pos += strspn(value + pos, WHITESPACE);
76,870✔
464
        if (value[pos] == '-')
76,870✔
465
                return -EINVAL;
466

467
        r = sscanf(value, "%" PRIu64 "%" PRIu64 "%n", &a, &b, &pos);
76,869✔
468
        if (r != 2)
76,869✔
469
                return log_debug_errno(SYNTHETIC_ERRNO(EINVAL),
1✔
470
                                       "Failed to parse dual timestamp value \"%s\".",
471
                                       value);
472

473
        if (value[pos] != '\0')
76,868✔
474
                /* trailing garbage */
475
                return -EINVAL;
476

477
        *ret = (dual_timestamp) {
76,867✔
478
                .realtime = a,
479
                .monotonic = b,
480
        };
481

482
        return 0;
76,867✔
483
}
484

485
int deserialize_environment(const char *value, char ***list) {
656✔
486
        _cleanup_free_ char *unescaped = NULL;
656✔
487
        ssize_t l;
656✔
488
        int r;
656✔
489

490
        assert(value);
656✔
491
        assert(list);
656✔
492

493
        /* Changes the *environment strv inline. */
494

495
        l = cunescape(value, 0, &unescaped);
656✔
496
        if (l < 0)
656✔
497
                return log_error_errno(l, "Failed to unescape: %m");
2✔
498

499
        r = strv_env_replace_consume(list, TAKE_PTR(unescaped));
654✔
500
        if (r < 0)
654✔
501
                return log_error_errno(r, "Failed to append environment variable: %m");
×
502

503
        return 0;
504
}
505

506
int deserialize_pidref(FDSet *fds, const char *value, PidRef *ret) {
992✔
507
        const char *e;
992✔
508
        int r;
992✔
509

510
        assert(value);
992✔
511
        assert(ret);
992✔
512

513
        e = startswith(value, "@");
992✔
514
        if (e) {
992✔
515
                _cleanup_free_ char *fdstr = NULL, *pidstr = NULL;
992✔
516
                _cleanup_close_ int fd = -EBADF;
992✔
517

518
                r = extract_many_words(&e, ":", /* flags= */ 0, &fdstr, &pidstr);
992✔
519
                if (r < 0)
992✔
520
                        return log_debug_errno(r, "Failed to deserialize pidref '%s': %m", e);
×
521
                if (r == 0)
992✔
522
                        return log_debug_errno(SYNTHETIC_ERRNO(EINVAL), "Cannot deserialize pidref from empty string.");
×
523

524
                assert(r <= 2);
992✔
525

526
                fd = deserialize_fd(fds, fdstr);
992✔
527
                if (fd < 0)
992✔
528
                        return fd;
529

530
                /* The serialization format changed after 255.4. In systemd <= 255.4 only pidfd is
531
                 * serialized, but that causes problems when reconstructing pidref (see serialize_pidref for
532
                 * details). After 255.4 the pid is serialized as well even if we have a pidfd, but we still
533
                 * need to support older format as we might be upgrading from a version that still uses the
534
                 * old format. */
535
                if (pidstr) {
992✔
536
                        pid_t pid;
992✔
537

538
                        r = parse_pid(pidstr, &pid);
992✔
539
                        if (r < 0)
992✔
540
                                return log_debug_errno(r, "Failed to parse PID: %s", pidstr);
×
541

542
                        *ret = (PidRef) {
992✔
543
                                .pid = pid,
544
                                .fd = TAKE_FD(fd),
992✔
545
                        };
546
                } else
547
                        r = pidref_set_pidfd_consume(ret, TAKE_FD(fd));
×
548
        } else {
UNCOV
549
                pid_t pid;
×
550

UNCOV
551
                r = parse_pid(value, &pid);
×
UNCOV
552
                if (r < 0)
×
553
                        return log_debug_errno(r, "Failed to parse PID: %s", value);
×
554

UNCOV
555
                r = pidref_set_pid(ret, pid);
×
556
        }
557
        if (r < 0)
992✔
558
                return log_debug_errno(r, "Failed to initialize pidref: %m");
×
559

560
        return 0;
561
}
562

563
void deserialize_ratelimit(RateLimit *rl, const char *name, const char *value) {
53,511✔
564
        usec_t begin, interval;
53,511✔
565
        unsigned num, burst;
53,511✔
566

567
        assert(rl);
53,511✔
568
        assert(name);
53,511✔
569
        assert(value);
53,511✔
570

571
        if (sscanf(value, USEC_FMT " " USEC_FMT " %u %u", &begin, &interval, &num, &burst) != 4)
53,511✔
572
                return log_notice("Failed to parse %s, ignoring: %s", name, value);
×
573

574
        /* Preserve the counter only if the configuration didn't change. */
575
        rl->num = (interval == rl->interval && burst == rl->burst) ? num : 0;
53,511✔
576
        rl->begin = begin;
53,511✔
577
}
578

579
int open_serialization_fd(const char *ident) {
5,438✔
580
        assert(ident);
5,438✔
581

582
        int fd = memfd_new_full(ident, MFD_ALLOW_SEALING);
5,438✔
583
        if (fd < 0)
5,438✔
584
                return fd;
585

586
        log_debug("Serializing %s to memfd.", ident);
5,438✔
587
        return fd;
588
}
589

590
int open_serialization_file(const char *ident, FILE **ret) {
2,877✔
591
        _cleanup_fclose_ FILE *f = NULL;
2,877✔
592
        _cleanup_close_ int fd;
2,877✔
593

594
        assert(ret);
2,877✔
595

596
        fd = open_serialization_fd(ident);
2,877✔
597
        if (fd < 0)
2,877✔
598
                return fd;
599

600
        f = take_fdopen(&fd, "w+");
2,877✔
601
        if (!f)
2,877✔
602
                return -errno;
×
603

604
        *ret = TAKE_PTR(f);
2,877✔
605
        return 0;
2,877✔
606
}
607

608
int finish_serialization_fd(int fd) {
2,561✔
609
        assert(fd >= 0);
2,561✔
610

611
        if (lseek(fd, 0, SEEK_SET) < 0)
2,561✔
612
                return -errno;
×
613

614
        return memfd_set_sealed(fd);
2,561✔
615
}
616

617
int finish_serialization_file(FILE *f) {
2,877✔
618
        int r;
2,877✔
619

620
        assert(f);
2,877✔
621

622
        r = fflush_and_check(f);
2,877✔
623
        if (r < 0)
2,877✔
624
                return r;
625

626
        if (fseeko(f, 0, SEEK_SET) < 0)
2,877✔
627
                return -errno;
×
628

629
        int fd = fileno(f);
2,877✔
630
        if (fd < 0)
2,877✔
631
                return -EBADF;
632

633
        return memfd_set_sealed(fd);
2,877✔
634
}
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