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

systemd / systemd / 14630481637

23 Apr 2025 07:04PM UTC coverage: 72.178% (-0.002%) from 72.18%
14630481637

push

github

DaanDeMeyer
mkosi: Run clangd within the tools tree instead of the build container

Running within the build sandbox has a number of disadvantages:
- We have a separate clangd cache for each distribution/release combo
- It requires to build the full image before clangd can be used
- It breaks every time the image becomes out of date and requires a
  rebuild
- We can't look at system headers as we don't have the knowledge to map
  them from inside the build sandbox to the corresponding path on the host

Instead, let's have mkosi.clangd run clangd within the tools tree. We
already require building systemd for both the host and the target anyway,
and all the dependencies to build systemd are installed in the tools tree
already for that, as well as clangd since it's installed together with the
other clang tooling we install in the tools tree. Unlike the previous approach,
this approach only requires the mkosi tools tree to be built upfront, which has
a much higher chance of not invalidating its cache. We can also trivially map
system header lookups from within the sandbox to the path within mkosi.tools
on the host so that starts working as well.

297054 of 411557 relevant lines covered (72.18%)

686269.58 hits per line

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

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

3
#include <ctype.h>
4
#include <errno.h>
5
#include <fcntl.h>
6
#include <limits.h>
7
#include <stdarg.h>
8
#include <stdint.h>
9
#include <stdio_ext.h>
10
#include <stdlib.h>
11
#include <sys/stat.h>
12
#include <sys/types.h>
13
#include <unistd.h>
14

15
#include "alloc-util.h"
16
#include "chase.h"
17
#include "extract-word.h"
18
#include "fd-util.h"
19
#include "fileio.h"
20
#include "fs-util.h"
21
#include "hexdecoct.h"
22
#include "label.h"
23
#include "log.h"
24
#include "macro.h"
25
#include "mkdir.h"
26
#include "nulstr-util.h"
27
#include "parse-util.h"
28
#include "path-util.h"
29
#include "socket-util.h"
30
#include "stdio-util.h"
31
#include "string-util.h"
32
#include "sync-util.h"
33
#include "terminal-util.h"
34
#include "tmpfile-util.h"
35

36
/* The maximum size of the file we'll read in one go in read_full_file() (64M). */
37
#define READ_FULL_BYTES_MAX (64U * U64_MB - UINT64_C(1))
38
/* Used when a size is specified for read_full_file() with READ_FULL_FILE_UNBASE64 or _UNHEX */
39
#define READ_FULL_FILE_ENCODED_STRING_AMPLIFICATION_BOUNDARY 3
40

41
/* The maximum size of virtual files (i.e. procfs, sysfs, and other virtual "API" files) we'll read in one go
42
 * in read_virtual_file(). Note that this limit is different (and much lower) than the READ_FULL_BYTES_MAX
43
 * limit. This reflects the fact that we use different strategies for reading virtual and regular files:
44
 * virtual files we generally have to read in a single read() syscall since the kernel doesn't support
45
 * continuation read()s for them. Thankfully they are somewhat size constrained. Thus we can allocate the
46
 * full potential buffer in advance. Regular files OTOH can be much larger, and there we grow the allocations
47
 * exponentially in a loop. We use a size limit of 4M-2 because 4M-1 is the maximum buffer that /proc/sys/
48
 * allows us to read() (larger reads will fail with ENOMEM), and we want to read one extra byte so that we
49
 * can detect EOFs. */
50
#define READ_VIRTUAL_BYTES_MAX (4U * U64_MB - UINT64_C(2))
51

52
int fdopen_unlocked(int fd, const char *options, FILE **ret) {
345,562✔
53
        assert(ret);
345,562✔
54

55
        FILE *f = fdopen(fd, options);
345,562✔
56
        if (!f)
345,562✔
57
                return -errno;
×
58

59
        (void) __fsetlocking(f, FSETLOCKING_BYCALLER);
345,562✔
60

61
        *ret = f;
345,562✔
62
        return 0;
345,562✔
63
}
64

65
int take_fdopen_unlocked(int *fd, const char *options, FILE **ret) {
345,562✔
66
        int r;
345,562✔
67

68
        assert(fd);
345,562✔
69

70
        r = fdopen_unlocked(*fd, options, ret);
345,562✔
71
        if (r < 0)
345,562✔
72
                return r;
73

74
        *fd = -EBADF;
345,562✔
75

76
        return 0;
345,562✔
77
}
78

79
FILE* take_fdopen(int *fd, const char *options) {
38,462✔
80
        assert(fd);
38,462✔
81

82
        FILE *f = fdopen(*fd, options);
38,462✔
83
        if (!f)
38,462✔
84
                return NULL;
85

86
        *fd = -EBADF;
38,462✔
87

88
        return f;
38,462✔
89
}
90

91
DIR* take_fdopendir(int *dfd) {
226,305✔
92
        assert(dfd);
226,305✔
93

94
        DIR *d = fdopendir(*dfd);
226,305✔
95
        if (!d)
226,305✔
96
                return NULL;
97

98
        *dfd = -EBADF;
226,305✔
99

100
        return d;
226,305✔
101
}
102

103
FILE* open_memstream_unlocked(char **ptr, size_t *sizeloc) {
475,590✔
104
        FILE *f = open_memstream(ptr, sizeloc);
475,590✔
105
        if (!f)
475,590✔
106
                return NULL;
107

108
        (void) __fsetlocking(f, FSETLOCKING_BYCALLER);
475,590✔
109

110
        return f;
475,590✔
111
}
112

113
FILE* fmemopen_unlocked(void *buf, size_t size, const char *mode) {
103✔
114
        FILE *f = fmemopen(buf, size, mode);
103✔
115
        if (!f)
103✔
116
                return NULL;
117

118
        (void) __fsetlocking(f, FSETLOCKING_BYCALLER);
103✔
119

120
        return f;
103✔
121
}
122

123
int write_string_stream_full(
149,742✔
124
                FILE *f,
125
                const char *line,
126
                WriteStringFileFlags flags,
127
                const struct timespec *ts) {
128

129
        bool needs_nl;
149,742✔
130
        int r, fd = -EBADF;
149,742✔
131

132
        assert(f);
149,742✔
133
        assert(line);
149,742✔
134

135
        if (ferror(f))
149,742✔
136
                return -EIO;
137

138
        if (ts) {
149,742✔
139
                /* If we shall set the timestamp we need the fd. But fmemopen() streams generally don't have
140
                 * an fd. Let's fail early in that case. */
141
                fd = fileno(f);
2✔
142
                if (fd < 0)
2✔
143
                        return -EBADF;
144
        }
145

146
        if (flags & WRITE_STRING_FILE_SUPPRESS_REDUNDANT_VIRTUAL) {
149,742✔
147
                _cleanup_free_ char *t = NULL;
8,122✔
148

149
                /* If value to be written is same as that of the existing value, then suppress the write. */
150

151
                if (fd < 0) {
8,122✔
152
                        fd = fileno(f);
8,122✔
153
                        if (fd < 0)
8,122✔
154
                                return -EBADF;
155
                }
156

157
                /* Read an additional byte to detect cases where the prefix matches but the rest
158
                 * doesn't. Also, 0 returned by read_virtual_file_fd() means the read was truncated and
159
                 * it won't be equal to the new value. */
160
                if (read_virtual_file_fd(fd, strlen(line)+1, &t, NULL) > 0 &&
16,198✔
161
                    streq_skip_trailing_chars(line, t, NEWLINE)) {
8,076✔
162
                        log_debug("No change in value '%s', suppressing write", line);
5,911✔
163
                        return 0;
5,911✔
164
                }
165

166
                if (lseek(fd, 0, SEEK_SET) < 0)
2,211✔
167
                        return -errno;
×
168
        }
169

170
        needs_nl = !(flags & WRITE_STRING_FILE_AVOID_NEWLINE) && !endswith(line, "\n");
143,831✔
171

172
        if (needs_nl && (flags & WRITE_STRING_FILE_DISABLE_BUFFER)) {
43,744✔
173
                /* If STDIO buffering was disabled, then let's append the newline character to the string
174
                 * itself, so that the write goes out in one go, instead of two */
175

176
                line = strjoina(line, "\n");
213,495✔
177
                needs_nl = false;
42,699✔
178
        }
179

180
        if (fputs(line, f) == EOF)
143,831✔
181
                return -errno;
22✔
182

183
        if (needs_nl)
143,809✔
184
                if (fputc('\n', f) == EOF)
1,044✔
185
                        return -errno;
×
186

187
        if (flags & WRITE_STRING_FILE_SYNC)
143,809✔
188
                r = fflush_sync_and_check(f);
1,708✔
189
        else
190
                r = fflush_and_check(f);
142,101✔
191
        if (r < 0)
143,809✔
192
                return r;
193

194
        if (ts) {
143,797✔
195
                const struct timespec twice[2] = {*ts, *ts};
2✔
196

197
                assert(fd >= 0);
2✔
198
                if (futimens(fd, twice) < 0)
2✔
199
                        return -errno;
×
200
        }
201

202
        return 0;
203
}
204

205
static mode_t write_string_file_flags_to_mode(WriteStringFileFlags flags) {
74,850✔
206

207
        /* We support three different modes, that are the ones that really make sense for text files like this:
208
         *
209
         *     → 0600 (i.e. root-only)
210
         *     → 0444 (i.e. read-only)
211
         *     → 0644 (i.e. writable for root, readable for everyone else)
212
         */
213

214
        return FLAGS_SET(flags, WRITE_STRING_FILE_MODE_0600) ? 0600 :
74,850✔
215
                FLAGS_SET(flags, WRITE_STRING_FILE_MODE_0444) ? 0444 : 0644;
74,640✔
216
}
217

218
static int write_string_file_atomic_at(
2,439✔
219
                int dir_fd,
220
                const char *fn,
221
                const char *line,
222
                WriteStringFileFlags flags,
223
                const struct timespec *ts) {
224

225
        _cleanup_fclose_ FILE *f = NULL;
2,439✔
226
        _cleanup_free_ char *p = NULL;
2,439✔
227
        int r;
2,439✔
228

229
        assert(fn);
2,439✔
230
        assert(line);
2,439✔
231

232
        /* Note that we'd really like to use O_TMPFILE here, but can't really, since we want replacement
233
         * semantics here, and O_TMPFILE can't offer that. i.e. rename() replaces but linkat() doesn't. */
234

235
        mode_t mode = write_string_file_flags_to_mode(flags);
2,439✔
236

237
        bool call_label_ops_post = false;
2,439✔
238
        if (FLAGS_SET(flags, WRITE_STRING_FILE_LABEL)) {
2,439✔
239
                r = label_ops_pre(dir_fd, fn, mode);
157✔
240
                if (r < 0)
157✔
241
                        return r;
242

243
                call_label_ops_post = true;
244
        }
245

246
        r = fopen_temporary_at(dir_fd, fn, &f, &p);
2,439✔
247
        if (call_label_ops_post)
2,439✔
248
                /* If fopen_temporary_at() failed in the above, propagate the error code, and ignore failures
249
                 * in label_ops_post(). */
250
                RET_GATHER(r, label_ops_post(f ? fileno(f) : dir_fd, f ? NULL : fn, /* created= */ !!f));
314✔
251
        if (r < 0)
2,439✔
252
                goto fail;
1✔
253

254
        r = write_string_stream_full(f, line, flags, ts);
2,438✔
255
        if (r < 0)
2,438✔
256
                goto fail;
×
257

258
        r = fchmod_umask(fileno(f), mode);
2,438✔
259
        if (r < 0)
2,438✔
260
                goto fail;
×
261

262
        r = RET_NERRNO(renameat(dir_fd, p, dir_fd, fn));
2,438✔
263
        if (r < 0)
×
264
                goto fail;
×
265

266
        if (FLAGS_SET(flags, WRITE_STRING_FILE_SYNC)) {
2,438✔
267
                /* Sync the rename, too */
268
                r = fsync_directory_of_file(fileno(f));
1,708✔
269
                if (r < 0)
1,708✔
270
                        return r;
×
271
        }
272

273
        return 0;
274

275
fail:
1✔
276
        if (f)
1✔
277
                (void) unlinkat(dir_fd, p, 0);
×
278
        return r;
279
}
280

281
int write_string_file_full(
133,809✔
282
                int dir_fd,
283
                const char *fn,
284
                const char *line,
285
                WriteStringFileFlags flags,
286
                const struct timespec *ts,
287
                const char *label_fn) {
288

289
        bool made_file = false;
133,809✔
290
        _cleanup_fclose_ FILE *f = NULL;
133,809✔
291
        _cleanup_close_ int fd = -EBADF;
133,809✔
292
        int r;
133,809✔
293

294
        assert(dir_fd == AT_FDCWD || dir_fd >= 0);
133,809✔
295
        assert(line);
133,809✔
296

297
        /* We don't know how to verify whether the file contents was already on-disk. */
298
        assert(!((flags & WRITE_STRING_FILE_VERIFY_ON_FAILURE) && (flags & WRITE_STRING_FILE_SYNC)));
133,809✔
299

300
        if (flags & WRITE_STRING_FILE_MKDIR_0755) {
133,809✔
301
                assert(fn);
222✔
302

303
                r = mkdirat_parents(dir_fd, fn, 0755);
222✔
304
                if (r < 0)
222✔
305
                        return r;
306
        }
307

308
        if (flags & WRITE_STRING_FILE_ATOMIC) {
133,809✔
309
                assert(fn);
2,439✔
310
                assert(flags & WRITE_STRING_FILE_CREATE);
2,439✔
311

312
                r = write_string_file_atomic_at(dir_fd, fn, line, flags, ts);
2,439✔
313
                if (r < 0)
2,439✔
314
                        goto fail;
1✔
315

316
                return r;
317
        }
318

319
        /* We manually build our own version of fopen(..., "we") that works without O_CREAT and with O_NOFOLLOW if needed. */
320
        if (isempty(fn))
131,370✔
321
                r = fd = fd_reopen(
58,959✔
322
                                ASSERT_FD(dir_fd), O_CLOEXEC | O_NOCTTY |
58,959✔
323
                                (FLAGS_SET(flags, WRITE_STRING_FILE_TRUNCATE) ? O_TRUNC : 0) |
58,959✔
324
                                (FLAGS_SET(flags, WRITE_STRING_FILE_SUPPRESS_REDUNDANT_VIRTUAL) ? O_RDWR : O_WRONLY));
58,959✔
325
        else {
326
                mode_t mode = write_string_file_flags_to_mode(flags);
72,411✔
327
                bool call_label_ops_post = false;
72,411✔
328

329
                if (FLAGS_SET(flags, WRITE_STRING_FILE_LABEL|WRITE_STRING_FILE_CREATE)) {
72,411✔
330
                        r = label_ops_pre(dir_fd, label_fn ?: fn, mode);
359✔
331
                        if (r < 0)
359✔
332
                                goto fail;
×
333

334
                        call_label_ops_post = true;
335
                }
336

337
                r = fd = openat_report_new(
72,411✔
338
                                dir_fd, fn, O_CLOEXEC | O_NOCTTY |
72,411✔
339
                                (FLAGS_SET(flags, WRITE_STRING_FILE_NOFOLLOW) ? O_NOFOLLOW : 0) |
72,411✔
340
                                (FLAGS_SET(flags, WRITE_STRING_FILE_CREATE) ? O_CREAT : 0) |
72,411✔
341
                                (FLAGS_SET(flags, WRITE_STRING_FILE_TRUNCATE) ? O_TRUNC : 0) |
72,411✔
342
                                (FLAGS_SET(flags, WRITE_STRING_FILE_SUPPRESS_REDUNDANT_VIRTUAL) ? O_RDWR : O_WRONLY),
72,411✔
343
                                mode,
344
                                &made_file);
345
                if (call_label_ops_post)
72,411✔
346
                        /* If openat_report_new() failed in the above, propagate the error code, and ignore
347
                         * failures in label_ops_post(). */
348
                        RET_GATHER(r, label_ops_post(fd >= 0 ? fd : dir_fd, fd >= 0 ? NULL : fn, made_file));
1,077✔
349
        }
350
        if (r < 0)
131,370✔
351
                goto fail;
1,571✔
352

353
        r = take_fdopen_unlocked(&fd, "w", &f);
129,799✔
354
        if (r < 0)
129,799✔
355
                goto fail;
×
356

357
        if (flags & WRITE_STRING_FILE_DISABLE_BUFFER)
129,799✔
358
                setvbuf(f, NULL, _IONBF, 0);
128,780✔
359

360
        r = write_string_stream_full(f, line, flags, ts);
129,799✔
361
        if (r < 0)
129,799✔
362
                goto fail;
27✔
363

364
        return 0;
365

366
fail:
1,599✔
367
        if (made_file)
1,599✔
368
                (void) unlinkat(dir_fd, fn, 0);
×
369

370
        if (!(flags & WRITE_STRING_FILE_VERIFY_ON_FAILURE))
1,599✔
371
                return r;
372

373
        f = safe_fclose(f);
1,569✔
374
        fd = safe_close(fd);
1,569✔
375

376
        /* OK, the operation failed, but let's see if the right contents in place already. If so, eat up the
377
         * error. */
378
        if (verify_file_at(dir_fd, fn, line, !(flags & WRITE_STRING_FILE_AVOID_NEWLINE) || (flags & WRITE_STRING_FILE_VERIFY_IGNORE_NEWLINE)) > 0)
1,569✔
379
                return 0;
454✔
380

381
        return r;
382
}
383

384
int write_string_filef(
228✔
385
                const char *fn,
386
                WriteStringFileFlags flags,
387
                const char *format, ...) {
388

389
        _cleanup_free_ char *p = NULL;
228✔
390
        va_list ap;
228✔
391
        int r;
228✔
392

393
        va_start(ap, format);
228✔
394
        r = vasprintf(&p, format, ap);
228✔
395
        va_end(ap);
228✔
396

397
        if (r < 0)
228✔
398
                return -ENOMEM;
399

400
        return write_string_file(fn, p, flags);
228✔
401
}
402

403
int write_base64_file_at(
7✔
404
                int dir_fd,
405
                const char *fn,
406
                const struct iovec *data,
407
                WriteStringFileFlags flags) {
408

409
        _cleanup_free_ char *encoded = NULL;
7✔
410
        ssize_t n;
7✔
411

412
        n = base64mem_full(data ? data->iov_base : NULL, data ? data->iov_len : 0, 79, &encoded);
7✔
413
        if (n < 0)
7✔
414
                return n;
×
415

416
        return write_string_file_at(dir_fd, fn, encoded, flags);
7✔
417
}
418

419
int read_one_line_file_at(int dir_fd, const char *filename, char **ret) {
153,276✔
420
        _cleanup_fclose_ FILE *f = NULL;
153,276✔
421
        int r;
153,276✔
422

423
        assert(dir_fd >= 0 || dir_fd == AT_FDCWD);
153,276✔
424
        assert(filename);
153,276✔
425
        assert(ret);
153,276✔
426

427
        r = fopen_unlocked_at(dir_fd, filename, "re", 0, &f);
153,276✔
428
        if (r < 0)
153,276✔
429
                return r;
430

431
        return read_line(f, LONG_LINE_MAX, ret);
153,276✔
432
}
433

434
int verify_file_at(int dir_fd, const char *fn, const char *blob, bool accept_extra_nl) {
1,569✔
435
        _cleanup_fclose_ FILE *f = NULL;
1,569✔
436
        _cleanup_free_ char *buf = NULL;
1,569✔
437
        size_t l, k;
1,569✔
438
        int r;
1,569✔
439

440
        assert(blob);
1,569✔
441

442
        l = strlen(blob);
1,569✔
443

444
        if (accept_extra_nl && endswith(blob, "\n"))
1,569✔
445
                accept_extra_nl = false;
1✔
446

447
        buf = malloc(l + accept_extra_nl + 1);
1,569✔
448
        if (!buf)
1,569✔
449
                return -ENOMEM;
450

451
        r = fopen_unlocked_at(dir_fd, strempty(fn), "re", 0, &f);
1,569✔
452
        if (r < 0)
1,569✔
453
                return r;
454

455
        /* We try to read one byte more than we need, so that we know whether we hit eof */
456
        errno = 0;
866✔
457
        k = fread(buf, 1, l + accept_extra_nl + 1, f);
866✔
458
        if (ferror(f))
866✔
459
                return errno_or_else(EIO);
×
460

461
        if (k != l && k != l + accept_extra_nl)
866✔
462
                return 0;
463
        if (memcmp(buf, blob, l) != 0)
727✔
464
                return 0;
465
        if (k > l && buf[l] != '\n')
454✔
466
                return 0;
×
467

468
        return 1;
469
}
470

471
int read_virtual_file_at(
830,990✔
472
                int dir_fd,
473
                const char *filename,
474
                size_t max_size,
475
                char **ret_contents,
476
                size_t *ret_size) {
477

478
        _cleanup_free_ char *buf = NULL;
830,990✔
479
        size_t n, size;
830,990✔
480
        int n_retries;
830,990✔
481
        bool truncated = false;
830,990✔
482

483
        /* Virtual filesystems such as sysfs or procfs use kernfs, and kernfs can work with two sorts of
484
         * virtual files. One sort uses "seq_file", and the results of the first read are buffered for the
485
         * second read. The other sort uses "raw" reads which always go direct to the device. In the latter
486
         * case, the content of the virtual file must be retrieved with a single read otherwise a second read
487
         * might get the new value instead of finding EOF immediately. That's the reason why the usage of
488
         * fread(3) is prohibited in this case as it always performs a second call to read(2) looking for
489
         * EOF. See issue #13585.
490
         *
491
         * max_size specifies a limit on the bytes read. If max_size is SIZE_MAX, the full file is read. If
492
         * the full file is too large to read, an error is returned. For other values of max_size, *partial
493
         * contents* may be returned. (Though the read is still done using one syscall.) Returns 0 on
494
         * partial success, 1 if untruncated contents were read.
495
         *
496
         * Rule: for kernfs files using "seq_file" → use regular read_full_file_at()
497
         *       for kernfs files using "raw" → use read_virtual_file_at()
498
         */
499

500
        assert(dir_fd >= 0 || dir_fd == AT_FDCWD);
830,990✔
501
        assert(max_size <= READ_VIRTUAL_BYTES_MAX || max_size == SIZE_MAX);
830,990✔
502

503
        _cleanup_close_ int fd = -EBADF;
830,990✔
504
        if (isempty(filename))
830,990✔
505
                fd = fd_reopen(ASSERT_FD(dir_fd), O_RDONLY | O_NOCTTY | O_CLOEXEC);
623,021✔
506
        else
507
                fd = RET_NERRNO(openat(dir_fd, filename, O_RDONLY | O_NOCTTY | O_CLOEXEC));
207,969✔
508
        if (fd < 0)
830,990✔
509
                return fd;
510

511
        /* Limit the number of attempts to read the number of bytes returned by fstat(). */
512
        n_retries = 3;
513

514
        for (;;) {
773,109✔
515
                struct stat st;
773,108✔
516

517
                if (fstat(fd, &st) < 0)
773,108✔
518
                        return -errno;
1,141✔
519

520
                if (!S_ISREG(st.st_mode))
773,108✔
521
                        return -EBADF;
522

523
                /* Be prepared for files from /proc which generally report a file size of 0. */
524
                assert_cc(READ_VIRTUAL_BYTES_MAX < SSIZE_MAX);
773,108✔
525
                if (st.st_size > 0 && n_retries > 1) {
773,108✔
526
                        /* Let's use the file size if we have more than 1 attempt left. On the last attempt
527
                         * we'll ignore the file size */
528

529
                        if (st.st_size > SSIZE_MAX) { /* Avoid overflow with 32-bit size_t and 64-bit off_t. */
568,219✔
530

531
                                if (max_size == SIZE_MAX)
532
                                        return -EFBIG;
533

534
                                size = max_size;
535
                        } else {
536
                                size = MIN((size_t) st.st_size, max_size);
568,219✔
537

538
                                if (size > READ_VIRTUAL_BYTES_MAX)
568,219✔
539
                                        return -EFBIG;
540
                        }
541

542
                        n_retries--;
568,219✔
543
                } else if (n_retries > 1) {
204,889✔
544
                        /* Files in /proc are generally smaller than the page size so let's start with
545
                         * a page size buffer from malloc and only use the max buffer on the final try. */
546
                        size = MIN3(page_size() - 1, READ_VIRTUAL_BYTES_MAX, max_size);
204,888✔
547
                        n_retries = 1;
204,888✔
548
                } else {
549
                        size = MIN(READ_VIRTUAL_BYTES_MAX, max_size);
1✔
550
                        n_retries = 0;
1✔
551
                }
552

553
                buf = malloc(size + 1);
773,108✔
554
                if (!buf)
773,108✔
555
                        return -ENOMEM;
556

557
                /* Use a bigger allocation if we got it anyway, but not more than the limit. */
558
                size = MIN3(MALLOC_SIZEOF_SAFE(buf) - 1, max_size, READ_VIRTUAL_BYTES_MAX);
773,108✔
559

560
                for (;;) {
773,108✔
561
                        ssize_t k;
773,108✔
562

563
                        /* Read one more byte so we can detect whether the content of the
564
                         * file has already changed or the guessed size for files from /proc
565
                         * wasn't large enough . */
566
                        k = read(fd, buf, size + 1);
773,108✔
567
                        if (k >= 0) {
773,108✔
568
                                n = k;
771,967✔
569
                                break;
771,967✔
570
                        }
571

572
                        if (errno != EINTR)
1,141✔
573
                                return -errno;
1,141✔
574
                }
575

576
                /* Consider a short read as EOF */
577
                if (n <= size)
771,967✔
578
                        break;
579

580
                /* If a maximum size is specified and we already read more we know the file is larger, and
581
                 * can handle this as truncation case. Note that if the size of what we read equals the
582
                 * maximum size then this doesn't mean truncation, the file might or might not end on that
583
                 * byte. We need to rerun the loop in that case, with a larger buffer size, so that we read
584
                 * at least one more byte to be able to distinguish EOF from truncation. */
585
                if (max_size != SIZE_MAX && n > max_size) {
35,616✔
586
                        n = size; /* Make sure we never use more than what we sized the buffer for (so that
587
                                   * we have one free byte in it for the trailing NUL we add below). */
588
                        truncated = true;
589
                        break;
590
                }
591

592
                /* We have no further attempts left? Then the file is apparently larger than our limits. Give up. */
593
                if (n_retries <= 0)
1✔
594
                        return -EFBIG;
595

596
                /* Hmm... either we read too few bytes from /proc or less likely the content of the file
597
                 * might have been changed (and is now bigger) while we were processing, let's try again
598
                 * either with the new file size. */
599

600
                if (lseek(fd, 0, SEEK_SET) < 0)
1✔
601
                        return -errno;
×
602

603
                buf = mfree(buf);
1✔
604
        }
605

606
        if (ret_contents) {
771,966✔
607

608
                /* Safety check: if the caller doesn't want to know the size of what we just read it will
609
                 * rely on the trailing NUL byte. But if there's an embedded NUL byte, then we should refuse
610
                 * operation as otherwise there'd be ambiguity about what we just read. */
611
                if (!ret_size && memchr(buf, 0, n))
736,461✔
612
                        return -EBADMSG;
613

614
                if (n < size) {
736,461✔
615
                        char *p;
728,810✔
616

617
                        /* Return rest of the buffer to libc */
618
                        p = realloc(buf, n + 1);
728,810✔
619
                        if (!p)
728,810✔
620
                                return -ENOMEM;
621
                        buf = p;
728,810✔
622
                }
623

624
                buf[n] = 0;
736,461✔
625
                *ret_contents = TAKE_PTR(buf);
736,461✔
626
        }
627

628
        if (ret_size)
771,966✔
629
                *ret_size = n;
581,359✔
630

631
        return !truncated;
771,966✔
632
}
633

634
int read_full_stream_full(
457,988✔
635
                FILE *f,
636
                const char *filename,
637
                uint64_t offset,
638
                size_t size,
639
                ReadFullFileFlags flags,
640
                char **ret_contents,
641
                size_t *ret_size) {
642

643
        _cleanup_free_ char *buf = NULL;
457,988✔
644
        size_t n, n_next = 0, l, expected_decoded_size = size;
457,988✔
645
        int fd, r;
457,988✔
646

647
        assert(f);
457,988✔
648
        assert(ret_contents);
457,988✔
649
        assert(!FLAGS_SET(flags, READ_FULL_FILE_UNBASE64 | READ_FULL_FILE_UNHEX));
457,988✔
650
        assert(size != SIZE_MAX || !FLAGS_SET(flags, READ_FULL_FILE_FAIL_WHEN_LARGER));
457,988✔
651

652
        if (offset != UINT64_MAX && offset > LONG_MAX) /* fseek() can only deal with "long" offsets */
457,988✔
653
                return -ERANGE;
654

655
        if ((flags & (READ_FULL_FILE_UNBASE64 | READ_FULL_FILE_UNHEX)) != 0) {
457,988✔
656
                if (size <= SIZE_MAX / READ_FULL_FILE_ENCODED_STRING_AMPLIFICATION_BOUNDARY)
34✔
657
                        size *= READ_FULL_FILE_ENCODED_STRING_AMPLIFICATION_BOUNDARY;
32✔
658
                else
659
                        size = SIZE_MAX;
660
        }
661

662
        fd = fileno(f);
457,988✔
663
        if (fd >= 0) { /* If the FILE* object is backed by an fd (as opposed to memory or such, see
457,988✔
664
                        * fmemopen()), let's optimize our buffering */
665
                struct stat st;
457,898✔
666

667
                if (fstat(fd, &st) < 0)
457,898✔
668
                        return -errno;
×
669

670
                if (S_ISREG(st.st_mode)) {
457,898✔
671

672
                        /* Try to start with the right file size if we shall read the file in full. Note
673
                         * that we increase the size to read here by one, so that the first read attempt
674
                         * already makes us notice the EOF. If the reported size of the file is zero, we
675
                         * avoid this logic however, since quite likely it might be a virtual file in procfs
676
                         * that all report a zero file size. */
677

678
                        if (st.st_size > 0 &&
457,486✔
679
                            (size == SIZE_MAX || FLAGS_SET(flags, READ_FULL_FILE_FAIL_WHEN_LARGER))) {
1,243✔
680

681
                                uint64_t rsize =
1,304,589✔
682
                                        LESS_BY((uint64_t) st.st_size, offset == UINT64_MAX ? 0 : offset);
869,720✔
683

684
                                if (rsize < SIZE_MAX) /* overflow check */
434,863✔
685
                                        n_next = rsize + 1;
434,863✔
686
                        }
687

688
                        if (flags & READ_FULL_FILE_WARN_WORLD_READABLE)
457,486✔
689
                                (void) warn_file_is_world_accessible(filename, &st, NULL, 0);
130✔
690
                }
691
        }
692

693
        /* If we don't know how much to read, figure it out now. If we shall read a part of the file, then
694
         * allocate the requested size. If we shall load the full file start with LINE_MAX. Note that if
695
         * READ_FULL_FILE_FAIL_WHEN_LARGER we consider the specified size a safety limit, and thus also start
696
         * with LINE_MAX, under assumption the file is most likely much shorter. */
697
        if (n_next == 0)
457,898✔
698
                n_next = size != SIZE_MAX && !FLAGS_SET(flags, READ_FULL_FILE_FAIL_WHEN_LARGER) ? size : LINE_MAX;
23,125✔
699

700
        /* Never read more than we need to determine that our own limit is hit */
701
        if (n_next > READ_FULL_BYTES_MAX)
435,052✔
702
                n_next = READ_FULL_BYTES_MAX + 1;
×
703

704
        if (offset != UINT64_MAX && fseek(f, offset, SEEK_SET) < 0)
457,988✔
705
                return -errno;
×
706

707
        n = l = 0;
708
        for (;;) {
458,272✔
709
                char *t;
458,130✔
710
                size_t k;
458,130✔
711

712
                /* If we shall fail when reading overly large data, then read exactly one byte more than the
713
                 * specified size at max, since that'll tell us if there's anymore data beyond the limit. */
714
                if (FLAGS_SET(flags, READ_FULL_FILE_FAIL_WHEN_LARGER) && n_next > size)
458,130✔
715
                        n_next = size + 1;
8✔
716

717
                if (flags & READ_FULL_FILE_SECURE) {
458,130✔
718
                        t = malloc(n_next + 1);
1,445✔
719
                        if (!t) {
1,445✔
720
                                r = -ENOMEM;
×
721
                                goto finalize;
×
722
                        }
723
                        memcpy_safe(t, buf, n);
1,445✔
724
                        explicit_bzero_safe(buf, n);
1,445✔
725
                        free(buf);
1,445✔
726
                } else {
727
                        t = realloc(buf, n_next + 1);
456,685✔
728
                        if (!t)
456,685✔
729
                                return -ENOMEM;
730
                }
731

732
                buf = t;
458,130✔
733
                /* Unless a size has been explicitly specified, try to read as much as fits into the memory
734
                 * we allocated (minus 1, to leave one byte for the safety NUL byte) */
735
                n = size == SIZE_MAX ? MALLOC_SIZEOF_SAFE(buf) - 1 : n_next;
458,130✔
736

737
                errno = 0;
458,130✔
738
                k = fread(buf + l, 1, n - l, f);
458,130✔
739

740
                assert(k <= n - l);
458,130✔
741
                l += k;
458,130✔
742

743
                if (ferror(f)) {
458,130✔
744
                        r = errno_or_else(EIO);
2✔
745
                        goto finalize;
2✔
746
                }
747
                if (feof(f))
458,128✔
748
                        break;
749

750
                if (size != SIZE_MAX && !FLAGS_SET(flags, READ_FULL_FILE_FAIL_WHEN_LARGER)) { /* If we got asked to read some specific size, we already sized the buffer right, hence leave */
238✔
751
                        assert(l == size);
90✔
752
                        break;
753
                }
754

755
                assert(k > 0); /* we can't have read zero bytes because that would have been EOF */
148✔
756

757
                if (FLAGS_SET(flags, READ_FULL_FILE_FAIL_WHEN_LARGER) && l > size) {
148✔
758
                        r = -E2BIG;
6✔
759
                        goto finalize;
6✔
760
                }
761

762
                if (n >= READ_FULL_BYTES_MAX) {
142✔
763
                        r = -E2BIG;
×
764
                        goto finalize;
×
765
                }
766

767
                n_next = MIN(n * 2, READ_FULL_BYTES_MAX);
142✔
768
        }
769

770
        if (flags & (READ_FULL_FILE_UNBASE64 | READ_FULL_FILE_UNHEX)) {
457,980✔
771
                _cleanup_free_ void *decoded = NULL;
32✔
772
                size_t decoded_size;
32✔
773

774
                buf[l++] = 0;
32✔
775
                if (flags & READ_FULL_FILE_UNBASE64)
32✔
776
                        r = unbase64mem_full(buf, l, flags & READ_FULL_FILE_SECURE, &decoded, &decoded_size);
30✔
777
                else
778
                        r = unhexmem_full(buf, l, flags & READ_FULL_FILE_SECURE, &decoded, &decoded_size);
2✔
779
                if (r < 0)
32✔
780
                        goto finalize;
×
781

782
                if (flags & READ_FULL_FILE_SECURE)
32✔
783
                        explicit_bzero_safe(buf, n);
14✔
784
                free_and_replace(buf, decoded);
32✔
785
                n = l = decoded_size;
32✔
786

787
                if (FLAGS_SET(flags, READ_FULL_FILE_FAIL_WHEN_LARGER) && l > expected_decoded_size) {
32✔
788
                        r = -E2BIG;
×
789
                        goto finalize;
×
790
                }
791
        }
792

793
        if (!ret_size) {
457,980✔
794
                /* Safety check: if the caller doesn't want to know the size of what we just read it will rely on the
795
                 * trailing NUL byte. But if there's an embedded NUL byte, then we should refuse operation as otherwise
796
                 * there'd be ambiguity about what we just read. */
797

798
                if (memchr(buf, 0, l)) {
324,487✔
799
                        r = -EBADMSG;
2✔
800
                        goto finalize;
2✔
801
                }
802
        }
803

804
        buf[l] = 0;
457,978✔
805
        *ret_contents = TAKE_PTR(buf);
457,978✔
806

807
        if (ret_size)
457,978✔
808
                *ret_size = l;
133,493✔
809

810
        return 0;
811

812
finalize:
10✔
813
        if (flags & READ_FULL_FILE_SECURE)
10✔
814
                explicit_bzero_safe(buf, n);
3✔
815

816
        return r;
817
}
818

819
int read_full_file_full(
646,091✔
820
                int dir_fd,
821
                const char *filename,
822
                uint64_t offset,
823
                size_t size,
824
                ReadFullFileFlags flags,
825
                const char *bind_name,
826
                char **ret_contents,
827
                size_t *ret_size) {
828

829
        _cleanup_fclose_ FILE *f = NULL;
646,091✔
830
        XfopenFlags xflags = XFOPEN_UNLOCKED;
646,091✔
831
        int r;
646,091✔
832

833
        assert(filename);
646,091✔
834
        assert(ret_contents);
646,091✔
835

836
        if (FLAGS_SET(flags, READ_FULL_FILE_CONNECT_SOCKET) && /* If this is enabled, let's try to connect to it */
646,091✔
837
            offset == UINT64_MAX)                              /* Seeking is not supported on AF_UNIX sockets */
838
                xflags |= XFOPEN_SOCKET;
185✔
839

840
        r = xfopenat_full(dir_fd, filename, "re", 0, xflags, bind_name, &f);
646,091✔
841
        if (r < 0)
646,091✔
842
                return r;
843

844
        return read_full_stream_full(f, filename, offset, size, flags, ret_contents, ret_size);
443,434✔
845
}
846

847
int script_get_shebang_interpreter(const char *path, char **ret) {
8✔
848
        _cleanup_fclose_ FILE *f = NULL;
8✔
849
        int r;
8✔
850

851
        assert(path);
8✔
852

853
        f = fopen(path, "re");
8✔
854
        if (!f)
8✔
855
                return -errno;
1✔
856

857
        char c;
7✔
858
        r = safe_fgetc(f, &c);
7✔
859
        if (r < 0)
7✔
860
                return r;
861
        if (r == 0)
7✔
862
                return -EBADMSG;
863
        if (c != '#')
7✔
864
                return -EMEDIUMTYPE;
865
        r = safe_fgetc(f, &c);
2✔
866
        if (r < 0)
2✔
867
                return r;
868
        if (r == 0)
2✔
869
                return -EBADMSG;
870
        if (c != '!')
2✔
871
                return -EMEDIUMTYPE;
872

873
        _cleanup_free_ char *line = NULL;
2✔
874
        r = read_line(f, LONG_LINE_MAX, &line);
2✔
875
        if (r < 0)
2✔
876
                return r;
877

878
        _cleanup_free_ char *p = NULL;
2✔
879
        const char *s = line;
2✔
880

881
        r = extract_first_word(&s, &p, /* separators = */ NULL, /* flags = */ 0);
2✔
882
        if (r < 0)
2✔
883
                return r;
884
        if (r == 0)
2✔
885
                return -ENOEXEC;
886

887
        if (ret)
2✔
888
                *ret = TAKE_PTR(p);
2✔
889
        return 0;
890
}
891

892
/**
893
 * Retrieve one field from a file like /proc/self/status.  pattern
894
 * should not include whitespace or the delimiter (':'). pattern matches only
895
 * the beginning of a line. Whitespace before ':' is skipped. Whitespace and
896
 * zeros after the ':' will be skipped. field must be freed afterwards.
897
 * terminator specifies the terminating characters of the field value (not
898
 * included in the value).
899
 */
900
int get_proc_field(const char *filename, const char *pattern, const char *terminator, char **field) {
27,151✔
901
        _cleanup_free_ char *status = NULL;
27,151✔
902
        char *t, *f;
27,151✔
903
        int r;
27,151✔
904

905
        assert(terminator);
27,151✔
906
        assert(filename);
27,151✔
907
        assert(pattern);
27,151✔
908
        assert(field);
27,151✔
909

910
        r = read_full_virtual_file(filename, &status, NULL);
27,151✔
911
        if (r < 0)
27,151✔
912
                return r;
913

914
        t = status;
27,139✔
915

916
        do {
27,139✔
917
                bool pattern_ok;
27,139✔
918

919
                do {
27,139✔
920
                        t = strstr(t, pattern);
27,139✔
921
                        if (!t)
27,139✔
922
                                return -ENOENT;
923

924
                        /* Check that pattern occurs in beginning of line. */
925
                        pattern_ok = (t == status || t[-1] == '\n');
27,138✔
926

927
                        t += strlen(pattern);
27,138✔
928

929
                } while (!pattern_ok);
27,138✔
930

931
                t += strspn(t, " \t");
27,138✔
932
                if (!*t)
27,138✔
933
                        return -ENOENT;
934

935
        } while (*t != ':');
27,138✔
936

937
        t++;
27,138✔
938

939
        if (*t) {
27,138✔
940
                t += strspn(t, " \t");
27,138✔
941

942
                /* Also skip zeros, because when this is used for
943
                 * capabilities, we don't want the zeros. This way the
944
                 * same capability set always maps to the same string,
945
                 * irrespective of the total capability set size. For
946
                 * other numbers it shouldn't matter. */
947
                t += strspn(t, "0");
27,138✔
948
                /* Back off one char if there's nothing but whitespace
949
                   and zeros */
950
                if (!*t || isspace(*t))
27,138✔
951
                        t--;
8,463✔
952
        }
953

954
        f = strdupcspn(t, terminator);
27,138✔
955
        if (!f)
27,138✔
956
                return -ENOMEM;
957

958
        *field = f;
27,138✔
959
        return 0;
27,138✔
960
}
961

962
DIR* xopendirat(int dir_fd, const char *name, int flags) {
190,028✔
963
        _cleanup_close_ int fd = -EBADF;
190,028✔
964

965
        assert(dir_fd >= 0 || dir_fd == AT_FDCWD);
190,028✔
966
        assert(name);
190,028✔
967
        assert(!(flags & (O_CREAT|O_TMPFILE)));
190,028✔
968

969
        if (dir_fd == AT_FDCWD && flags == 0)
190,028✔
970
                return opendir(name);
×
971

972
        fd = openat(dir_fd, name, O_NONBLOCK|O_DIRECTORY|O_CLOEXEC|flags);
190,028✔
973
        if (fd < 0)
190,028✔
974
                return NULL;
975

976
        return take_fdopendir(&fd);
189,530✔
977
}
978

979
int fopen_mode_to_flags(const char *mode) {
78,462✔
980
        const char *p;
78,462✔
981
        int flags;
78,462✔
982

983
        assert(mode);
78,462✔
984

985
        if ((p = startswith(mode, "r+")))
78,462✔
986
                flags = O_RDWR;
987
        else if ((p = startswith(mode, "r")))
78,461✔
988
                flags = O_RDONLY;
989
        else if ((p = startswith(mode, "w+")))
×
990
                flags = O_RDWR|O_CREAT|O_TRUNC;
991
        else if ((p = startswith(mode, "w")))
×
992
                flags = O_WRONLY|O_CREAT|O_TRUNC;
993
        else if ((p = startswith(mode, "a+")))
×
994
                flags = O_RDWR|O_CREAT|O_APPEND;
995
        else if ((p = startswith(mode, "a")))
×
996
                flags = O_WRONLY|O_CREAT|O_APPEND;
997
        else
998
                return -EINVAL;
999

1000
        for (; *p != 0; p++) {
153,338✔
1001

1002
                switch (*p) {
74,876✔
1003

1004
                case 'e':
74,876✔
1005
                        flags |= O_CLOEXEC;
74,876✔
1006
                        break;
74,876✔
1007

1008
                case 'x':
×
1009
                        flags |= O_EXCL;
×
1010
                        break;
×
1011

1012
                case 'm':
1013
                        /* ignore this here, fdopen() might care later though */
1014
                        break;
1015

1016
                case 'c': /* not sure what to do about this one */
1017
                default:
1018
                        return -EINVAL;
1019
                }
1020
        }
1021

1022
        return flags;
1023
}
1024

1025
static int xfopenat_regular(int dir_fd, const char *path, const char *mode, int open_flags, FILE **ret) {
852,102✔
1026
        FILE *f;
852,102✔
1027

1028
        /* A combination of fopen() with openat() */
1029

1030
        assert(dir_fd >= 0 || dir_fd == AT_FDCWD);
852,102✔
1031
        assert(path);
852,102✔
1032
        assert(mode);
852,102✔
1033
        assert(ret);
852,102✔
1034

1035
        if (dir_fd == AT_FDCWD && open_flags == 0)
852,102✔
1036
                f = fopen(path, mode);
851,276✔
1037
        else {
1038
                _cleanup_close_ int fd = -EBADF;
826✔
1039
                int mode_flags;
826✔
1040

1041
                mode_flags = fopen_mode_to_flags(mode);
826✔
1042
                if (mode_flags < 0)
826✔
1043
                        return mode_flags;
1044

1045
                fd = openat(dir_fd, path, mode_flags | open_flags);
826✔
1046
                if (fd < 0)
826✔
1047
                        return -errno;
272✔
1048

1049
                f = take_fdopen(&fd, mode);
554✔
1050
        }
1051
        if (!f)
851,830✔
1052
                return -errno;
232,300✔
1053

1054
        *ret = f;
619,530✔
1055
        return 0;
619,530✔
1056
}
1057

1058
static int xfopenat_unix_socket(int dir_fd, const char *path, const char *bind_name, FILE **ret) {
1✔
1059
        _cleanup_close_ int sk = -EBADF;
1✔
1060
        FILE *f;
1✔
1061
        int r;
1✔
1062

1063
        assert(dir_fd >= 0 || dir_fd == AT_FDCWD);
1✔
1064
        assert(path);
1✔
1065
        assert(ret);
1✔
1066

1067
        sk = socket(AF_UNIX, SOCK_STREAM|SOCK_CLOEXEC, 0);
1✔
1068
        if (sk < 0)
1✔
1069
                return -errno;
×
1070

1071
        if (bind_name) {
1✔
1072
                /* If the caller specified a socket name to bind to, do so before connecting. This is
1073
                 * useful to communicate some minor, short meta-information token from the client to
1074
                 * the server. */
1075
                union sockaddr_union bsa;
1✔
1076

1077
                r = sockaddr_un_set_path(&bsa.un, bind_name);
1✔
1078
                if (r < 0)
1✔
1079
                        return r;
×
1080

1081
                if (bind(sk, &bsa.sa, r) < 0)
1✔
1082
                        return -errno;
×
1083
        }
1084

1085
        r = connect_unix_path(sk, dir_fd, path);
1✔
1086
        if (r < 0)
1✔
1087
                return r;
1088

1089
        if (shutdown(sk, SHUT_WR) < 0)
1✔
1090
                return -errno;
×
1091

1092
        f = take_fdopen(&sk, "r");
1✔
1093
        if (!f)
1✔
1094
                return -errno;
×
1095

1096
        *ret = f;
1✔
1097
        return 0;
1✔
1098
}
1099

1100
int xfopenat_full(
852,102✔
1101
                int dir_fd,
1102
                const char *path,
1103
                const char *mode,
1104
                int open_flags,
1105
                XfopenFlags flags,
1106
                const char *bind_name,
1107
                FILE **ret) {
1108

1109
        FILE *f = NULL;  /* avoid false maybe-uninitialized warning */
852,102✔
1110
        int r;
852,102✔
1111

1112
        assert(dir_fd >= 0 || dir_fd == AT_FDCWD);
852,102✔
1113
        assert(path);
852,102✔
1114
        assert(mode);
852,102✔
1115
        assert(ret);
852,102✔
1116

1117
        r = xfopenat_regular(dir_fd, path, mode, open_flags, &f);
852,102✔
1118
        if (r == -ENXIO && FLAGS_SET(flags, XFOPEN_SOCKET)) {
852,102✔
1119
                /* ENXIO is what Linux returns if we open a node that is an AF_UNIX socket */
1120
                r = xfopenat_unix_socket(dir_fd, path, bind_name, &f);
1✔
1121
                if (IN_SET(r, -ENOTSOCK, -EINVAL))
1✔
1122
                        return -ENXIO; /* propagate original error if this is not a socket after all */
852,102✔
1123
        }
1124
        if (r < 0)
852,102✔
1125
                return r;
1126

1127
        if (FLAGS_SET(flags, XFOPEN_UNLOCKED))
619,531✔
1128
                (void) __fsetlocking(f, FSETLOCKING_BYCALLER);
619,299✔
1129

1130
        *ret = f;
619,531✔
1131
        return 0;
619,531✔
1132
}
1133

1134
int fdopen_independent(int fd, const char *mode, FILE **ret) {
10,930✔
1135
        _cleanup_close_ int copy_fd = -EBADF;
10,930✔
1136
        _cleanup_fclose_ FILE *f = NULL;
10,930✔
1137
        int mode_flags;
10,930✔
1138

1139
        assert(fd >= 0);
10,930✔
1140
        assert(mode);
10,930✔
1141
        assert(ret);
10,930✔
1142

1143
        /* A combination of fdopen() + fd_reopen(). i.e. reopens the inode the specified fd points to and
1144
         * returns a FILE* for it */
1145

1146
        mode_flags = fopen_mode_to_flags(mode);
10,930✔
1147
        if (mode_flags < 0)
10,930✔
1148
                return mode_flags;
1149

1150
        /* Flags returned by fopen_mode_to_flags might contain O_CREAT, but it doesn't make sense for fd_reopen
1151
         * since we're working on an existing fd anyway. Let's drop it here to avoid triggering assertion. */
1152
        copy_fd = fd_reopen(fd, mode_flags & ~O_CREAT);
10,930✔
1153
        if (copy_fd < 0)
10,930✔
1154
                return copy_fd;
1155

1156
        f = take_fdopen(&copy_fd, mode);
10,930✔
1157
        if (!f)
10,930✔
1158
                return -errno;
×
1159

1160
        *ret = TAKE_PTR(f);
10,930✔
1161
        return 0;
10,930✔
1162
}
1163

1164
static int search_and_open_internal(
21,523✔
1165
                const char *path,
1166
                int mode,            /* if ret_fd is NULL this is an [FRWX]_OK mode for access(), otherwise an open mode for open() */
1167
                const char *root,
1168
                char **search,
1169
                int *ret_fd,
1170
                char **ret_path) {
1171

1172
        int r;
21,523✔
1173

1174
        assert(!ret_fd || !FLAGS_SET(mode, O_CREAT)); /* We don't support O_CREAT for this */
21,523✔
1175
        assert(path);
21,523✔
1176

1177
        if (path_is_absolute(path)) {
21,523✔
1178
                _cleanup_close_ int fd = -EBADF;
×
1179

1180
                if (ret_fd)
5,364✔
1181
                        /* We only specify 0777 here to appease static analyzers, it's never used since we
1182
                         * don't support O_CREAT here */
1183
                        r = fd = RET_NERRNO(open(path, mode, 0777));
5,362✔
1184
                else
1185
                        r = RET_NERRNO(access(path, mode));
2✔
1186
                if (r < 0)
124✔
1187
                        return r;
1188

1189
                if (ret_path) {
5,240✔
1190
                        r = path_simplify_alloc(path, ret_path);
5,240✔
1191
                        if (r < 0)
5,240✔
1192
                                return r;
1193
                }
1194

1195
                if (ret_fd)
5,240✔
1196
                        *ret_fd = TAKE_FD(fd);
5,239✔
1197

1198
                return 0;
5,240✔
1199
        }
1200

1201
        if (!path_strv_resolve_uniq(search, root))
16,159✔
1202
                return -ENOMEM;
1203

1204
        STRV_FOREACH(i, search) {
88,724✔
1205
                _cleanup_close_ int fd = -EBADF;
94,088✔
1206
                _cleanup_free_ char *p = NULL;
74,138✔
1207

1208
                p = path_join(root, *i, path);
74,138✔
1209
                if (!p)
74,138✔
1210
                        return -ENOMEM;
1211

1212
                if (ret_fd)
74,138✔
1213
                        /* as above, 0777 is static analyzer appeasement */
1214
                        r = fd = RET_NERRNO(open(p, mode, 0777));
73,820✔
1215
                else
1216
                        r = RET_NERRNO(access(p, F_OK));
318✔
1217
                if (r >= 0) {
72,565✔
1218
                        if (ret_path)
1,573✔
1219
                                *ret_path = path_simplify(TAKE_PTR(p));
1,573✔
1220

1221
                        if (ret_fd)
1,573✔
1222
                                *ret_fd = TAKE_FD(fd);
1,566✔
1223

1224
                        return 0;
1,573✔
1225
                }
1226
                if (r != -ENOENT)
72,565✔
1227
                        return r;
1228
        }
1229

1230
        return -ENOENT;
1231
}
1232

1233
int search_and_open(
21,523✔
1234
                const char *path,
1235
                int mode,
1236
                const char *root,
1237
                char **search,
1238
                int *ret_fd,
1239
                char **ret_path) {
1240

1241
        _cleanup_strv_free_ char **copy = NULL;
21,523✔
1242

1243
        assert(path);
21,523✔
1244

1245
        copy = strv_copy((char**) search);
21,523✔
1246
        if (!copy)
21,523✔
1247
                return -ENOMEM;
1248

1249
        return search_and_open_internal(path, mode, root, copy, ret_fd, ret_path);
21,523✔
1250
}
1251

1252
static int search_and_fopen_internal(
21,518✔
1253
                const char *path,
1254
                const char *mode,
1255
                const char *root,
1256
                char **search,
1257
                FILE **ret_file,
1258
                char **ret_path) {
1259

1260
        _cleanup_free_ char *found_path = NULL;
21,518✔
1261
        _cleanup_close_ int fd = -EBADF;
21,518✔
1262
        int r;
21,518✔
1263

1264
        assert(path);
21,518✔
1265
        assert(mode || !ret_file);
21,518✔
1266

1267
        r = search_and_open(
43,139✔
1268
                        path,
1269
                        mode ? fopen_mode_to_flags(mode) : 0,
21,367✔
1270
                        root,
1271
                        search,
1272
                        ret_file ? &fd : NULL,
1273
                        ret_path ? &found_path : NULL);
1274
        if (r < 0)
21,518✔
1275
                return r;
1276

1277
        if (ret_file) {
6,808✔
1278
                FILE *f = take_fdopen(&fd, mode);
6,805✔
1279
                if (!f)
6,805✔
1280
                        return -errno;
×
1281

1282
                *ret_file = f;
6,805✔
1283
        }
1284

1285
        if (ret_path)
6,808✔
1286
                *ret_path = TAKE_PTR(found_path);
6,808✔
1287

1288
        return 0;
1289
}
1290

1291
int search_and_fopen(
5,369✔
1292
                const char *path,
1293
                const char *mode,
1294
                const char *root,
1295
                const char **search,
1296
                FILE **ret_file,
1297
                char **ret_path) {
1298

1299
        _cleanup_strv_free_ char **copy = NULL;
5,369✔
1300

1301
        assert(path);
5,369✔
1302
        assert(mode || !ret_file);
5,369✔
1303

1304
        copy = strv_copy((char**) search);
5,369✔
1305
        if (!copy)
5,369✔
1306
                return -ENOMEM;
1307

1308
        return search_and_fopen_internal(path, mode, root, copy, ret_file, ret_path);
5,369✔
1309
}
1310

1311
int search_and_fopen_nulstr(
16,149✔
1312
                const char *path,
1313
                const char *mode,
1314
                const char *root,
1315
                const char *search,
1316
                FILE **ret_file,
1317
                char **ret_path) {
1318

1319
        _cleanup_strv_free_ char **l = NULL;
16,149✔
1320

1321
        assert(path);
16,149✔
1322
        assert(mode || !ret_file);
16,149✔
1323

1324
        l = strv_split_nulstr(search);
16,149✔
1325
        if (!l)
16,149✔
1326
                return -ENOMEM;
1327

1328
        return search_and_fopen_internal(path, mode, root, l, ret_file, ret_path);
16,149✔
1329
}
1330

1331
int fflush_and_check(FILE *f) {
785,513✔
1332
        assert(f);
785,513✔
1333

1334
        errno = 0;
785,513✔
1335
        fflush(f);
785,513✔
1336

1337
        if (ferror(f))
785,513✔
1338
                return errno_or_else(EIO);
24✔
1339

1340
        return 0;
1341
}
1342

1343
int fflush_sync_and_check(FILE *f) {
2,144✔
1344
        int r, fd;
2,144✔
1345

1346
        assert(f);
2,144✔
1347

1348
        r = fflush_and_check(f);
2,144✔
1349
        if (r < 0)
2,144✔
1350
                return r;
1351

1352
        /* Not all file streams have an fd associated (think: fmemopen()), let's handle this gracefully and
1353
         * assume that in that case we need no explicit syncing */
1354
        fd = fileno(f);
2,144✔
1355
        if (fd < 0)
2,144✔
1356
                return 0;
1357

1358
        r = fsync_full(fd);
2,144✔
1359
        if (r < 0)
2,144✔
1360
                return r;
×
1361

1362
        return 0;
1363
}
1364

1365
int write_timestamp_file_atomic(const char *fn, usec_t n) {
133✔
1366
        char ln[DECIMAL_STR_MAX(n)+2];
133✔
1367

1368
        /* Creates a "timestamp" file, that contains nothing but a
1369
         * usec_t timestamp, formatted in ASCII. */
1370

1371
        if (!timestamp_is_set(n))
133✔
1372
                return -ERANGE;
133✔
1373

1374
        xsprintf(ln, USEC_FMT "\n", n);
133✔
1375

1376
        return write_string_file(fn, ln, WRITE_STRING_FILE_CREATE|WRITE_STRING_FILE_ATOMIC);
133✔
1377
}
1378

1379
int read_timestamp_file(const char *fn, usec_t *ret) {
24✔
1380
        _cleanup_free_ char *ln = NULL;
24✔
1381
        uint64_t t;
24✔
1382
        int r;
24✔
1383

1384
        r = read_one_line_file(fn, &ln);
24✔
1385
        if (r < 0)
24✔
1386
                return r;
1387

1388
        r = safe_atou64(ln, &t);
×
1389
        if (r < 0)
×
1390
                return r;
1391

1392
        if (!timestamp_is_set(t))
×
1393
                return -ERANGE;
1394

1395
        *ret = (usec_t) t;
×
1396
        return 0;
×
1397
}
1398

1399
int fputs_with_separator(FILE *f, const char *s, const char *separator, bool *space) {
3,146✔
1400
        assert(s);
3,146✔
1401
        assert(space);
3,146✔
1402

1403
        /* Outputs the specified string with fputs(), but optionally prefixes it with a separator.
1404
         * The *space parameter when specified shall initially point to a boolean variable initialized
1405
         * to false. It is set to true after the first invocation. This call is supposed to be use in loops,
1406
         * where a separator shall be inserted between each element, but not before the first one. */
1407

1408
        if (!f)
3,146✔
1409
                f = stdout;
×
1410

1411
        if (!separator)
3,146✔
1412
                separator = " ";
1,454✔
1413

1414
        if (*space)
3,146✔
1415
                if (fputs(separator, f) < 0)
1,378✔
1416
                        return -EIO;
1417

1418
        *space = true;
3,146✔
1419

1420
        if (fputs(s, f) < 0)
3,146✔
1421
                return -EIO;
×
1422

1423
        return 0;
1424
}
1425

1426
int fputs_with_newline(FILE *f, const char *s) {
769✔
1427

1428
        /* This is like fputs() but outputs a trailing newline char, but only if the string isn't empty
1429
         * and doesn't end in a newline already. Returns 0 in case we didn't append a newline, > 0 otherwise. */
1430

1431
        if (isempty(s))
769✔
1432
                return 0;
1433

1434
        if (!f)
769✔
1435
                f = stdout;
×
1436

1437
        if (fputs(s, f) < 0)
769✔
1438
                return -EIO;
1439

1440
        if (endswith(s, "\n"))
769✔
1441
                return 0;
1442

1443
        if (fputc('\n', f) < 0)
624✔
1444
                return -EIO;
×
1445

1446
        return 1;
1447
}
1448

1449
/* A bitmask of the EOL markers we know */
1450
typedef enum EndOfLineMarker {
1451
        EOL_NONE     = 0,
1452
        EOL_ZERO     = 1 << 0,  /* \0 (aka NUL) */
1453
        EOL_TEN      = 1 << 1,  /* \n (aka NL, aka LF)  */
1454
        EOL_THIRTEEN = 1 << 2,  /* \r (aka CR)  */
1455
} EndOfLineMarker;
1456

1457
static EndOfLineMarker categorize_eol(char c, ReadLineFlags flags) {
198,160,953✔
1458

1459
        if (!FLAGS_SET(flags, READ_LINE_ONLY_NUL)) {
198,160,953✔
1460
                if (c == '\n')
197,472,639✔
1461
                        return EOL_TEN;
1462
                if (c == '\r')
191,098,543✔
1463
                        return EOL_THIRTEEN;
1464
        }
1465

1466
        if (c == '\0')
191,786,841✔
1467
                return EOL_ZERO;
21,673✔
1468

1469
        return EOL_NONE;
1470
}
1471

1472
DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(FILE*, funlockfile, NULL);
5,961,158✔
1473

1474
int read_line_full(FILE *f, size_t limit, ReadLineFlags flags, char **ret) {
5,961,177✔
1475
        _cleanup_free_ char *buffer = NULL;
5,961,177✔
1476
        size_t n = 0, count = 0;
5,961,177✔
1477
        int r;
5,961,177✔
1478

1479
        assert(f);
5,961,177✔
1480

1481
        /* Something like a bounded version of getline().
1482
         *
1483
         * Considers EOF, \n, \r and \0 end of line delimiters (or combinations of these), and does not include these
1484
         * delimiters in the string returned. Specifically, recognizes the following combinations of markers as line
1485
         * endings:
1486
         *
1487
         *     • \n        (UNIX)
1488
         *     • \r        (old MacOS)
1489
         *     • \0        (C strings)
1490
         *     • \n\0
1491
         *     • \r\0
1492
         *     • \r\n      (Windows)
1493
         *     • \n\r
1494
         *     • \r\n\0
1495
         *     • \n\r\0
1496
         *
1497
         * Returns the number of bytes read from the files (i.e. including delimiters — this hence usually differs from
1498
         * the number of characters in the returned string). When EOF is hit, 0 is returned.
1499
         *
1500
         * The input parameter limit is the maximum numbers of characters in the returned string, i.e. excluding
1501
         * delimiters. If the limit is hit we fail and return -ENOBUFS.
1502
         *
1503
         * If a line shall be skipped ret may be initialized as NULL. */
1504

1505
        if (ret) {
5,961,177✔
1506
                if (!GREEDY_REALLOC(buffer, 1))
5,961,146✔
1507
                        return -ENOMEM;
1508
        }
1509

1510
        {
1511
                _unused_ _cleanup_(funlockfilep) FILE *flocked = f;
×
1512
                EndOfLineMarker previous_eol = EOL_NONE;
5,961,177✔
1513
                flockfile(f);
5,961,177✔
1514

1515
                for (;;) {
198,615,903✔
1516
                        EndOfLineMarker eol;
198,615,903✔
1517
                        char c;
198,615,903✔
1518

1519
                        if (n >= limit)
198,615,903✔
1520
                                return -ENOBUFS;
19✔
1521

1522
                        if (count >= INT_MAX) /* We couldn't return the counter anymore as "int", hence refuse this */
198,615,897✔
1523
                                return -ENOBUFS;
1524

1525
                        r = safe_fgetc(f, &c);
198,615,897✔
1526
                        if (r < 0)
198,615,897✔
1527
                                return r;
1528
                        if (r == 0) /* EOF is definitely EOL */
198,615,884✔
1529
                                break;
1530

1531
                        eol = categorize_eol(c, flags);
198,160,953✔
1532

1533
                        if (FLAGS_SET(previous_eol, EOL_ZERO) ||
198,160,953✔
1534
                            (eol == EOL_NONE && previous_eol != EOL_NONE) ||
198,142,120✔
1535
                            (eol != EOL_NONE && (previous_eol & eol) != 0)) {
6,395,779✔
1536
                                /* Previous char was a NUL? This is not an EOL, but the previous char was? This type of
1537
                                 * EOL marker has been seen right before?  In either of these three cases we are
1538
                                 * done. But first, let's put this character back in the queue. (Note that we have to
1539
                                 * cast this to (unsigned char) here as ungetc() expects a positive 'int', and if we
1540
                                 * are on an architecture where 'char' equals 'signed char' we need to ensure we don't
1541
                                 * pass a negative value here. That said, to complicate things further ungetc() is
1542
                                 * actually happy with most negative characters and implicitly casts them back to
1543
                                 * positive ones as needed, except for \xff (aka -1, aka EOF), which it refuses. What a
1544
                                 * godawful API!) */
1545
                                assert_se(ungetc((unsigned char) c, f) != EOF);
5,506,227✔
1546
                                break;
1547
                        }
1548

1549
                        count++;
192,654,726✔
1550

1551
                        if (eol != EOL_NONE) {
186,830,054✔
1552
                                /* If we are on a tty, we can't shouldn't wait for more input, because that
1553
                                 * generally means waiting for the user, interactively. In the case of a TTY
1554
                                 * we expect only \n as the single EOL marker, so we are in the lucky
1555
                                 * position that there is no need to wait. We check this condition last, to
1556
                                 * avoid isatty() check if not necessary. */
1557

1558
                                if ((flags & (READ_LINE_IS_A_TTY|READ_LINE_NOT_A_TTY)) == 0) {
5,824,672✔
1559
                                        int fd;
5,114,052✔
1560

1561
                                        fd = fileno(f);
5,114,052✔
1562
                                        if (fd < 0) /* Maybe an fmemopen() stream? Handle this gracefully,
5,114,052✔
1563
                                                     * and don't call isatty() on an invalid fd */
1564
                                                flags |= READ_LINE_NOT_A_TTY;
28✔
1565
                                        else
1566
                                                flags |= isatty_safe(fd) ? READ_LINE_IS_A_TTY : READ_LINE_NOT_A_TTY;
10,228,048✔
1567
                                }
1568
                                if (FLAGS_SET(flags, READ_LINE_IS_A_TTY))
5,824,672✔
1569
                                        break;
1570
                        }
1571

1572
                        if (eol != EOL_NONE) {
192,654,726✔
1573
                                previous_eol |= eol;
5,824,672✔
1574
                                continue;
5,824,672✔
1575
                        }
1576

1577
                        if (ret) {
186,830,054✔
1578
                                if (!GREEDY_REALLOC(buffer, n + 2))
186,829,954✔
1579
                                        return -ENOMEM;
1580

1581
                                buffer[n] = c;
186,829,954✔
1582
                        }
1583

1584
                        n++;
186,830,054✔
1585
                }
1586
        }
1587

1588
        if (ret) {
5,961,158✔
1589
                buffer[n] = 0;
5,961,127✔
1590

1591
                *ret = TAKE_PTR(buffer);
5,961,127✔
1592
        }
1593

1594
        return (int) count;
5,961,158✔
1595
}
1596

1597
int read_stripped_line(FILE *f, size_t limit, char **ret) {
2,626,128✔
1598
        _cleanup_free_ char *s = NULL;
2,626,128✔
1599
        int r, k;
2,626,128✔
1600

1601
        assert(f);
2,626,128✔
1602

1603
        r = read_line(f, limit, ret ? &s : NULL);
2,626,128✔
1604
        if (r < 0)
2,626,128✔
1605
                return r;
1606

1607
        if (ret) {
2,626,128✔
1608
                const char *p = strstrip(s);
2,626,128✔
1609
                if (p == s)
2,626,128✔
1610
                        *ret = TAKE_PTR(s);
2,626,125✔
1611
                else {
1612
                        k = strdup_to(ret, p);
3✔
1613
                        if (k < 0)
3✔
1614
                                return k;
1615
                }
1616
        }
1617

1618
        return r > 0;          /* Return 1 if something was read. */
2,626,128✔
1619
}
1620

1621
int safe_fgetc(FILE *f, char *ret) {
198,622,493✔
1622
        int k;
198,622,493✔
1623

1624
        assert(f);
198,622,493✔
1625

1626
        /* A safer version of plain fgetc(): let's propagate the error that happened while reading as such, and
1627
         * separate the EOF condition from the byte read, to avoid those confusion signed/unsigned issues fgetc()
1628
         * has. */
1629

1630
        errno = 0;
198,622,493✔
1631
        k = fgetc(f);
198,622,493✔
1632
        if (k == EOF) {
198,622,493✔
1633
                if (ferror(f))
455,034✔
1634
                        return errno_or_else(EIO);
26✔
1635

1636
                if (ret)
455,021✔
1637
                        *ret = 0;
454,947✔
1638

1639
                return 0;
455,021✔
1640
        }
1641

1642
        if (ret)
198,167,459✔
1643
                *ret = k;
198,167,459✔
1644

1645
        return 1;
1646
}
1647

1648
int warn_file_is_world_accessible(const char *filename, struct stat *st, const char *unit, unsigned line) {
152✔
1649
        struct stat _st;
152✔
1650

1651
        if (!filename)
152✔
1652
                return 0;
152✔
1653

1654
        if (!st) {
152✔
1655
                if (stat(filename, &_st) < 0)
22✔
1656
                        return -errno;
×
1657
                st = &_st;
1658
        }
1659

1660
        if ((st->st_mode & S_IRWXO) == 0)
152✔
1661
                return 0;
1662

1663
        if (unit)
35✔
1664
                log_syntax(unit, LOG_WARNING, filename, line, 0,
×
1665
                           "%s has %04o mode that is too permissive, please adjust the ownership and access mode.",
1666
                           filename, st->st_mode & 07777);
1667
        else
1668
                log_warning("%s has %04o mode that is too permissive, please adjust the ownership and access mode.",
35✔
1669
                            filename, st->st_mode & 07777);
1670
        return 0;
1671
}
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