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

systemd / systemd / 14697484021

27 Apr 2025 11:31PM UTC coverage: 72.276% (+0.03%) from 72.251%
14697484021

push

github

yuwata
po: Translated using Weblate (Arabic)

Currently translated at 50.1% (129 of 257 strings)

Co-authored-by: joo es <johndevand@tutanota.com>
Translate-URL: https://translate.fedoraproject.org/projects/systemd/main/ar/
Translation: systemd/main

297189 of 411186 relevant lines covered (72.28%)

690098.6 hits per line

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

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

3
#include <fcntl.h>
4

5
#include "alloc-util.h"
6
#include "env-util.h"
7
#include "escape.h"
8
#include "fd-util.h"
9
#include "fileio.h"
10
#include "hexdecoct.h"
11
#include "memfd-util.h"
12
#include "missing_mman.h"
13
#include "missing_syscall.h"
14
#include "parse-util.h"
15
#include "process-util.h"
16
#include "serialize.h"
17
#include "strv.h"
18
#include "tmpfile-util.h"
19

20
int serialize_item(FILE *f, const char *key, const char *value) {
460,489✔
21
        assert(f);
460,489✔
22
        assert(key);
460,489✔
23

24
        if (!value)
460,489✔
25
                return 0;
26

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

32
        fputs(key, f);
403,801✔
33
        fputc('=', f);
403,801✔
34
        fputs(value, f);
403,801✔
35
        fputc('\n', f);
403,801✔
36

37
        return 1;
403,801✔
38
}
39

40
int serialize_item_escaped(FILE *f, const char *key, const char *value) {
38,666✔
41
        _cleanup_free_ char *c = NULL;
38,666✔
42

43
        assert(f);
38,666✔
44
        assert(key);
38,666✔
45

46
        if (!value)
38,666✔
47
                return 0;
48

49
        c = xescape(value, " ");
26,301✔
50
        if (!c)
26,301✔
51
                return log_oom();
×
52

53
        return serialize_item(f, key, c);
26,301✔
54
}
55

56
int serialize_item_format(FILE *f, const char *key, const char *format, ...) {
318,413✔
57
        _cleanup_free_ char *allocated = NULL;
318,413✔
58
        char buf[256]; /* Something reasonably short that fits nicely on any stack (i.e. is considerably less
318,413✔
59
                        * than LONG_LINE_MAX (1MiB!) */
60
        const char *b;
318,413✔
61
        va_list ap;
318,413✔
62
        int k;
318,413✔
63

64
        assert(f);
318,413✔
65
        assert(key);
318,413✔
66
        assert(format);
318,413✔
67

68
        /* First, let's try to format this into a stack buffer */
69
        va_start(ap, format);
318,413✔
70
        k = vsnprintf(buf, sizeof(buf), format, ap);
318,413✔
71
        va_end(ap);
318,413✔
72

73
        if (k < 0)
318,413✔
74
                return log_warning_errno(errno, "Failed to serialize item '%s', ignoring: %m", key);
×
75
        if (strlen(key) + 1 + k + 1 > LONG_LINE_MAX) /* See above */
318,413✔
76
                return log_warning_errno(SYNTHETIC_ERRNO(EINVAL), "Attempted to serialize overly long item '%s', refusing.", key);
×
77

78
        if ((size_t) k < sizeof(buf))
318,413✔
79
                b = buf; /* Yay, it fit! */
80
        else {
81
                /* So the string didn't fit in the short buffer above, but was not above our total limit,
82
                 * hence let's format it via dynamic memory */
83

84
                va_start(ap, format);
×
85
                k = vasprintf(&allocated, format, ap);
×
86
                va_end(ap);
×
87

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

91
                b = allocated;
×
92
        }
93

94
        fputs(key, f);
318,413✔
95
        fputc('=', f);
318,413✔
96
        fputs(b, f);
318,413✔
97
        fputc('\n', f);
318,413✔
98

99
        return 1;
100
}
101

102
int serialize_fd(FILE *f, FDSet *fds, const char *key, int fd) {
44,303✔
103
        int copy;
44,303✔
104

105
        assert(f);
44,303✔
106
        assert(fds);
44,303✔
107
        assert(key);
44,303✔
108

109
        if (fd < 0)
44,303✔
110
                return 0;
111

112
        copy = fdset_put_dup(fds, fd);
6,615✔
113
        if (copy < 0)
6,615✔
114
                return log_error_errno(copy, "Failed to add file descriptor to serialization set: %m");
×
115

116
        return serialize_item_format(f, key, "%i", copy);
6,615✔
117
}
118

119
int serialize_fd_many(FILE *f, FDSet *fds, const char *key, const int fd_array[], size_t n_fd_array) {
545✔
120
        _cleanup_free_ char *t = NULL;
545✔
121

122
        assert(f);
545✔
123

124
        if (n_fd_array == 0)
545✔
125
                return 0;
126

127
        assert(fd_array);
545✔
128

129
        for (size_t i = 0; i < n_fd_array; i++) {
1,454✔
130
                int copy;
909✔
131

132
                if (fd_array[i] < 0)
909✔
133
                        return -EBADF;
134

135
                copy = fdset_put_dup(fds, fd_array[i]);
909✔
136
                if (copy < 0)
909✔
137
                        return log_error_errno(copy, "Failed to add file descriptor to serialization set: %m");
×
138

139
                if (strextendf_with_separator(&t, " ", "%i", copy) < 0)
909✔
140
                        return log_oom();
×
141
        }
142

143
        return serialize_item(f, key, t);
545✔
144
}
145

146
int serialize_usec(FILE *f, const char *key, usec_t usec) {
21,649✔
147
        assert(f);
21,649✔
148
        assert(key);
21,649✔
149

150
        if (usec == USEC_INFINITY)
21,649✔
151
                return 0;
152

153
        return serialize_item_format(f, key, USEC_FMT, usec);
4,946✔
154
}
155

156
int serialize_dual_timestamp(FILE *f, const char *name, const dual_timestamp *t) {
140,857✔
157
        assert(f);
140,857✔
158
        assert(name);
140,857✔
159
        assert(t);
140,857✔
160

161
        if (!dual_timestamp_is_set(t))
140,857✔
162
                return 0;
163

164
        return serialize_item_format(f, name, USEC_FMT " " USEC_FMT, t->realtime, t->monotonic);
61,447✔
165
}
166

167
int serialize_strv(FILE *f, const char *key, char * const *l) {
40,842✔
168
        int ret = 0, r;
40,842✔
169

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

172
        assert(f);
40,842✔
173
        assert(key);
40,842✔
174

175
        STRV_FOREACH(i, l) {
65,718✔
176
                r = serialize_item_escaped(f, key, *i);
24,876✔
177
                if ((ret >= 0 && r < 0) ||
24,876✔
178
                    (ret == 0 && r > 0))
24,875✔
179
                        ret = r;
6,270✔
180
        }
181

182
        return ret;
40,842✔
183
}
184

185
int serialize_id128(FILE *f, const char *key, sd_id128_t id) {
17,980✔
186
        assert(f);
17,980✔
187
        assert(key);
17,980✔
188

189
        if (sd_id128_is_null(id))
17,980✔
190
                return 0;
8,151✔
191

192
        return serialize_item_format(f, key, SD_ID128_FORMAT_STR, SD_ID128_FORMAT_VAL(id));
9,829✔
193
}
194

195
int serialize_pidref(FILE *f, FDSet *fds, const char *key, PidRef *pidref) {
13,271✔
196
        int r;
13,271✔
197

198
        assert(f);
13,271✔
199
        assert(fds);
13,271✔
200

201
        if (!pidref_is_set(pidref))
13,271✔
202
                return 0;
203

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

210
        if (pidref->fd >= 0) {
797✔
211
                int copy = fdset_put_dup(fds, pidref->fd);
797✔
212
                if (copy < 0)
797✔
213
                        return log_error_errno(copy, "Failed to add file descriptor to serialization set: %m");
×
214

215
                r = serialize_item_format(f, key, "@%i:" PID_FMT, copy, pidref->pid);
797✔
216
                if (r < 0)
797✔
217
                        return r;
218
        }
219

220
        return serialize_item_format(f, key, PID_FMT, pidref->pid);
797✔
221
}
222

223
int serialize_ratelimit(FILE *f, const char *key, const RateLimit *rl) {
38,435✔
224
        assert(rl);
38,435✔
225

226
        return serialize_item_format(f, key,
76,870✔
227
                                     USEC_FMT " " USEC_FMT " %u %u",
228
                                     rl->begin,
38,435✔
229
                                     rl->interval,
38,435✔
230
                                     rl->num,
38,435✔
231
                                     rl->burst);
38,435✔
232
}
233

234
int serialize_item_hexmem(FILE *f, const char *key, const void *p, size_t l) {
2,199✔
235
        _cleanup_free_ char *encoded = NULL;
2,199✔
236
        int r;
2,199✔
237

238
        assert(f);
2,199✔
239
        assert(key);
2,199✔
240

241
        if (!p && l > 0)
2,199✔
242
                return -EINVAL;
243

244
        if (l == 0)
2,199✔
245
                return 0;
246

247
        encoded = hexmem(p, l);
1✔
248
        if (!encoded)
1✔
249
                return log_oom_debug();
×
250

251
        r = serialize_item(f, key, encoded);
1✔
252
        if (r < 0)
1✔
253
                return r;
×
254

255
        return 1;
256
}
257

258
int serialize_item_base64mem(FILE *f, const char *key, const void *p, size_t l) {
4,396✔
259
        _cleanup_free_ char *encoded = NULL;
4,396✔
260
        ssize_t len;
4,396✔
261
        int r;
4,396✔
262

263
        assert(f);
4,396✔
264
        assert(key);
4,396✔
265

266
        if (!p && l > 0)
4,396✔
267
                return -EINVAL;
268

269
        if (l == 0)
4,396✔
270
                return 0;
271

272
        len = base64mem(p, l, &encoded);
1✔
273
        if (len <= 0)
1✔
274
                return log_oom_debug();
×
275

276
        r = serialize_item(f, key, encoded);
1✔
277
        if (r < 0)
1✔
278
                return r;
×
279

280
        return 1;
281
}
282

283
int serialize_string_set(FILE *f, const char *key, const Set *s) {
4,396✔
284
        int r;
4,396✔
285

286
        assert(f);
4,396✔
287
        assert(key);
4,396✔
288

289
        if (set_isempty(s))
4,396✔
290
                return 0;
4,396✔
291

292
        /* Serialize as individual items, as each element might contain separators and escapes */
293

294
        const char *e;
1✔
295
        SET_FOREACH(e, s) {
3✔
296
                r = serialize_item(f, key, e);
2✔
297
                if (r < 0)
2✔
298
                        return r;
×
299
        }
300

301
        return 1;
1✔
302
}
303

304
int serialize_image_policy(FILE *f, const char *key, const ImagePolicy *p) {
6,591✔
305
        _cleanup_free_ char *policy = NULL;
6,591✔
306
        int r;
6,591✔
307

308
        assert(f);
6,591✔
309
        assert(key);
6,591✔
310

311
        if (!p)
6,591✔
312
                return 0;
313

314
        r = image_policy_to_string(p, /* simplify= */ false, &policy);
×
315
        if (r < 0)
×
316
                return r;
317

318
        r = serialize_item(f, key, policy);
×
319
        if (r < 0)
×
320
                return r;
×
321

322
        return 1;
323
}
324

325
int deserialize_read_line(FILE *f, char **ret) {
2,201,652✔
326
        _cleanup_free_ char *line = NULL;
2,201,652✔
327
        int r;
2,201,652✔
328

329
        assert(f);
2,201,652✔
330
        assert(ret);
2,201,652✔
331

332
        r = read_stripped_line(f, LONG_LINE_MAX, &line);
2,201,652✔
333
        if (r < 0)
2,201,652✔
334
                return log_error_errno(r, "Failed to read serialization line: %m");
×
335
        if (r == 0) { /* eof */
2,201,652✔
336
                *ret = NULL;
30✔
337
                return 0;
30✔
338
        }
339

340
        if (isempty(line)) { /* End marker */
2,201,622✔
341
                *ret = NULL;
71,392✔
342
                return 0;
71,392✔
343
        }
344

345
        *ret = TAKE_PTR(line);
2,130,230✔
346
        return 1;
2,130,230✔
347
}
348

349
int deserialize_fd(FDSet *fds, const char *value) {
41,331✔
350
        _cleanup_close_ int our_fd = -EBADF;
41,331✔
351
        int parsed_fd;
41,331✔
352

353
        assert(value);
41,331✔
354

355
        parsed_fd = parse_fd(value);
41,331✔
356
        if (parsed_fd < 0)
41,331✔
357
                return log_debug_errno(parsed_fd, "Failed to parse file descriptor serialization: %s", value);
×
358

359
        our_fd = fdset_remove(fds, parsed_fd); /* Take possession of the fd */
41,331✔
360
        if (our_fd < 0)
41,331✔
361
                return log_debug_errno(our_fd, "Failed to acquire fd from serialization fds: %m");
×
362

363
        return TAKE_FD(our_fd);
364
}
365

366
int deserialize_fd_many(FDSet *fds, const char *value, size_t n, int *ret) {
2,248✔
367
        int r, *fd_array = NULL;
2,248✔
368
        size_t m = 0;
2,248✔
369

370
        assert(value);
2,248✔
371

372
        fd_array = new(int, n);
2,248✔
373
        if (!fd_array)
2,248✔
374
                return -ENOMEM;
2,248✔
375

376
        CLEANUP_ARRAY(fd_array, m, close_many_and_free);
4,496✔
377

378
        for (;;) {
10,688✔
379
                _cleanup_free_ char *w = NULL;
4,220✔
380
                int fd;
6,468✔
381

382
                r = extract_first_word(&value, &w, NULL, 0);
6,468✔
383
                if (r < 0)
6,468✔
384
                        return r;
385
                if (r == 0) {
6,468✔
386
                        if (m < n) /* Too few */
2,248✔
387
                                return -EINVAL;
388

389
                        break;
2,248✔
390
                }
391

392
                if (m >= n) /* Too many */
4,220✔
393
                        return -EINVAL;
394

395
                fd = deserialize_fd(fds, w);
4,220✔
396
                if (fd < 0)
4,220✔
397
                        return fd;
398

399
                fd_array[m++] = fd;
4,220✔
400
        }
401

402
        memcpy(ret, fd_array, m * sizeof(int));
2,248✔
403
        fd_array = mfree(fd_array);
2,248✔
404

405
        return 0;
2,248✔
406
}
407

408
int deserialize_strv(const char *value, char ***l) {
90,914✔
409
        ssize_t unescaped_len;
90,914✔
410
        char *unescaped;
90,914✔
411

412
        assert(l);
90,914✔
413
        assert(value);
90,914✔
414

415
        unescaped_len = cunescape(value, 0, &unescaped);
90,914✔
416
        if (unescaped_len < 0)
90,914✔
417
                return unescaped_len;
×
418

419
        return strv_consume(l, unescaped);
90,914✔
420
}
421

422
int deserialize_usec(const char *value, usec_t *ret) {
15,754✔
423
        int r;
15,754✔
424

425
        assert(value);
15,754✔
426
        assert(ret);
15,754✔
427

428
        r = safe_atou64(value, ret);
15,754✔
429
        if (r < 0)
15,754✔
430
                return log_debug_errno(r, "Failed to parse usec value \"%s\": %m", value);
×
431

432
        return 0;
433
}
434

435
int deserialize_dual_timestamp(const char *value, dual_timestamp *ret) {
47,480✔
436
        uint64_t a, b;
47,480✔
437
        int r, pos;
47,480✔
438

439
        assert(value);
47,480✔
440
        assert(ret);
47,480✔
441

442
        pos = strspn(value, WHITESPACE);
47,480✔
443
        if (value[pos] == '-')
47,480✔
444
                return -EINVAL;
47,480✔
445
        pos += strspn(value + pos, DIGITS);
47,479✔
446
        pos += strspn(value + pos, WHITESPACE);
47,479✔
447
        if (value[pos] == '-')
47,479✔
448
                return -EINVAL;
449

450
        r = sscanf(value, "%" PRIu64 "%" PRIu64 "%n", &a, &b, &pos);
47,478✔
451
        if (r != 2)
47,478✔
452
                return log_debug_errno(SYNTHETIC_ERRNO(EINVAL),
1✔
453
                                       "Failed to parse dual timestamp value \"%s\".",
454
                                       value);
455

456
        if (value[pos] != '\0')
47,477✔
457
                /* trailing garbage */
458
                return -EINVAL;
459

460
        *ret = (dual_timestamp) {
47,476✔
461
                .realtime = a,
462
                .monotonic = b,
463
        };
464

465
        return 0;
47,476✔
466
}
467

468
int deserialize_environment(const char *value, char ***list) {
550✔
469
        _cleanup_free_ char *unescaped = NULL;
550✔
470
        ssize_t l;
550✔
471
        int r;
550✔
472

473
        assert(value);
550✔
474
        assert(list);
550✔
475

476
        /* Changes the *environment strv inline. */
477

478
        l = cunescape(value, 0, &unescaped);
550✔
479
        if (l < 0)
550✔
480
                return log_error_errno(l, "Failed to unescape: %m");
2✔
481

482
        r = strv_env_replace_consume(list, TAKE_PTR(unescaped));
548✔
483
        if (r < 0)
548✔
484
                return log_error_errno(r, "Failed to append environment variable: %m");
×
485

486
        return 0;
487
}
488

489
int deserialize_pidref(FDSet *fds, const char *value, PidRef *ret) {
658✔
490
        const char *e;
658✔
491
        int r;
658✔
492

493
        assert(value);
658✔
494
        assert(ret);
658✔
495

496
        e = startswith(value, "@");
658✔
497
        if (e) {
658✔
498
                _cleanup_free_ char *fdstr = NULL, *pidstr = NULL;
658✔
499
                _cleanup_close_ int fd = -EBADF;
658✔
500

501
                r = extract_many_words(&e, ":", /* flags = */ 0, &fdstr, &pidstr);
658✔
502
                if (r < 0)
658✔
503
                        return log_debug_errno(r, "Failed to deserialize pidref '%s': %m", e);
×
504
                if (r == 0)
658✔
505
                        return log_debug_errno(SYNTHETIC_ERRNO(EINVAL), "Cannot deserialize pidref from empty string.");
×
506

507
                assert(r <= 2);
658✔
508

509
                fd = deserialize_fd(fds, fdstr);
658✔
510
                if (fd < 0)
658✔
511
                        return fd;
512

513
                /* The serialization format changed after 255.4. In systemd <= 255.4 only pidfd is
514
                 * serialized, but that causes problems when reconstructing pidref (see serialize_pidref for
515
                 * details). After 255.4 the pid is serialized as well even if we have a pidfd, but we still
516
                 * need to support older format as we might be upgrading from a version that still uses the
517
                 * old format. */
518
                if (pidstr) {
658✔
519
                        pid_t pid;
658✔
520

521
                        r = parse_pid(pidstr, &pid);
658✔
522
                        if (r < 0)
658✔
523
                                return log_debug_errno(r, "Failed to parse PID: %s", pidstr);
×
524

525
                        *ret = (PidRef) {
658✔
526
                                .pid = pid,
527
                                .fd = TAKE_FD(fd),
658✔
528
                        };
529
                } else
530
                        r = pidref_set_pidfd_consume(ret, TAKE_FD(fd));
×
531
        } else {
532
                pid_t pid;
×
533

534
                r = parse_pid(value, &pid);
×
535
                if (r < 0)
×
536
                        return log_debug_errno(r, "Failed to parse PID: %s", value);
×
537

538
                r = pidref_set_pid(ret, pid);
×
539
        }
540
        if (r < 0)
658✔
541
                return log_debug_errno(r, "Failed to initialize pidref: %m");
×
542

543
        return 0;
544
}
545

546
void deserialize_ratelimit(RateLimit *rl, const char *name, const char *value) {
29,778✔
547
        usec_t begin, interval;
29,778✔
548
        unsigned num, burst;
29,778✔
549

550
        assert(rl);
29,778✔
551
        assert(name);
29,778✔
552
        assert(value);
29,778✔
553

554
        if (sscanf(value, USEC_FMT " " USEC_FMT " %u %u", &begin, &interval, &num, &burst) != 4)
29,778✔
555
                return log_notice("Failed to parse %s, ignoring: %s", name, value);
×
556

557
        /* Preserve the counter only if the configuration didn't change. */
558
        rl->num = (interval == rl->interval && burst == rl->burst) ? num : 0;
29,778✔
559
        rl->begin = begin;
29,778✔
560
}
561

562
int open_serialization_fd(const char *ident) {
4,272✔
563
        assert(ident);
4,272✔
564

565
        int fd = memfd_new_full(ident, MFD_ALLOW_SEALING);
4,272✔
566
        if (fd < 0)
4,272✔
567
                return fd;
568

569
        log_debug("Serializing %s to memfd.", ident);
4,272✔
570
        return fd;
571
}
572

573
int open_serialization_file(const char *ident, FILE **ret) {
2,327✔
574
        _cleanup_fclose_ FILE *f = NULL;
2,327✔
575
        _cleanup_close_ int fd;
2,327✔
576

577
        assert(ret);
2,327✔
578

579
        fd = open_serialization_fd(ident);
2,327✔
580
        if (fd < 0)
2,327✔
581
                return fd;
582

583
        f = take_fdopen(&fd, "w+");
2,327✔
584
        if (!f)
2,327✔
585
                return -errno;
×
586

587
        *ret = TAKE_PTR(f);
2,327✔
588
        return 0;
2,327✔
589
}
590

591
int finish_serialization_fd(int fd) {
1,945✔
592
        assert(fd >= 0);
1,945✔
593

594
        if (lseek(fd, 0, SEEK_SET) < 0)
1,945✔
595
                return -errno;
×
596

597
        return memfd_set_sealed(fd);
1,945✔
598
}
599

600
int finish_serialization_file(FILE *f) {
2,327✔
601
        int r;
2,327✔
602

603
        assert(f);
2,327✔
604

605
        r = fflush_and_check(f);
2,327✔
606
        if (r < 0)
2,327✔
607
                return r;
608

609
        if (fseeko(f, 0, SEEK_SET) < 0)
2,327✔
610
                return -errno;
×
611

612
        int fd = fileno(f);
2,327✔
613
        if (fd < 0)
2,327✔
614
                return -EBADF;
615

616
        return memfd_set_sealed(fd);
2,327✔
617
}
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