]>
Commit | Line | Data |
---|---|---|
53e1b683 | 1 | /* SPDX-License-Identifier: LGPL-2.1+ */ |
a5c32cff | 2 | |
8bdc9a90 | 3 | #include <ctype.h> |
11c3a366 TA |
4 | #include <errno.h> |
5 | #include <fcntl.h> | |
6 | #include <limits.h> | |
7 | #include <stdarg.h> | |
8 | #include <stdint.h> | |
35bbbf85 | 9 | #include <stdio_ext.h> |
11c3a366 | 10 | #include <stdlib.h> |
11c3a366 TA |
11 | #include <sys/stat.h> |
12 | #include <sys/types.h> | |
a5c32cff | 13 | #include <unistd.h> |
cda134ab | 14 | |
b5efdb8a | 15 | #include "alloc-util.h" |
3ffd4af2 LP |
16 | #include "fd-util.h" |
17 | #include "fileio.h" | |
f4f15635 | 18 | #include "fs-util.h" |
07d8c0eb | 19 | #include "hexdecoct.h" |
93cc7779 TA |
20 | #include "log.h" |
21 | #include "macro.h" | |
50ccd864 | 22 | #include "mkdir.h" |
33d52ab9 | 23 | #include "parse-util.h" |
0d39fa9c | 24 | #include "path-util.h" |
33d52ab9 | 25 | #include "stdio-util.h" |
07630cea | 26 | #include "string-util.h" |
e4de7287 | 27 | #include "tmpfile-util.h" |
a5c32cff | 28 | |
c2d11a63 VC |
29 | #define READ_FULL_BYTES_MAX (4U*1024U*1024U) |
30 | ||
fdeea3f4 ZJS |
31 | int fopen_unlocked(const char *path, const char *options, FILE **ret) { |
32 | assert(ret); | |
33 | ||
34 | FILE *f = fopen(path, options); | |
35 | if (!f) | |
36 | return -errno; | |
37 | ||
38 | (void) __fsetlocking(f, FSETLOCKING_BYCALLER); | |
39 | ||
40 | *ret = f; | |
41 | return 0; | |
42 | } | |
43 | ||
02e23d1a ZJS |
44 | int fdopen_unlocked(int fd, const char *options, FILE **ret) { |
45 | assert(ret); | |
46 | ||
47 | FILE *f = fdopen(fd, options); | |
48 | if (!f) | |
49 | return -errno; | |
50 | ||
51 | (void) __fsetlocking(f, FSETLOCKING_BYCALLER); | |
52 | ||
53 | *ret = f; | |
54 | return 0; | |
55 | } | |
56 | ||
2fe21124 ZJS |
57 | FILE* open_memstream_unlocked(char **ptr, size_t *sizeloc) { |
58 | FILE *f = open_memstream(ptr, sizeloc); | |
59 | if (!f) | |
60 | return NULL; | |
61 | ||
62 | (void) __fsetlocking(f, FSETLOCKING_BYCALLER); | |
63 | ||
64 | return f; | |
65 | } | |
66 | ||
673a1e6f ZJS |
67 | FILE* fmemopen_unlocked(void *buf, size_t size, const char *mode) { |
68 | FILE *f = fmemopen(buf, size, mode); | |
69 | if (!f) | |
70 | return NULL; | |
71 | ||
72 | (void) __fsetlocking(f, FSETLOCKING_BYCALLER); | |
73 | ||
74 | return f; | |
75 | } | |
76 | ||
b1837133 LP |
77 | int write_string_stream_ts( |
78 | FILE *f, | |
79 | const char *line, | |
80 | WriteStringFileFlags flags, | |
81 | struct timespec *ts) { | |
dacd6cee | 82 | |
91dc2bf7 | 83 | bool needs_nl; |
be83711c | 84 | int r; |
91dc2bf7 | 85 | |
717603e3 LP |
86 | assert(f); |
87 | assert(line); | |
88 | ||
ba8b8c9e MG |
89 | if (ferror(f)) |
90 | return -EIO; | |
91 | ||
91dc2bf7 LP |
92 | needs_nl = !(flags & WRITE_STRING_FILE_AVOID_NEWLINE) && !endswith(line, "\n"); |
93 | ||
94 | if (needs_nl && (flags & WRITE_STRING_FILE_DISABLE_BUFFER)) { | |
95 | /* If STDIO buffering was disabled, then let's append the newline character to the string itself, so | |
96 | * that the write goes out in one go, instead of two */ | |
97 | ||
98 | line = strjoina(line, "\n"); | |
99 | needs_nl = false; | |
100 | } | |
101 | ||
94d3b60f MG |
102 | if (fputs(line, f) == EOF) |
103 | return -errno; | |
104 | ||
91dc2bf7 | 105 | if (needs_nl) |
94d3b60f MG |
106 | if (fputc('\n', f) == EOF) |
107 | return -errno; | |
a5c32cff | 108 | |
be83711c CL |
109 | if (flags & WRITE_STRING_FILE_SYNC) |
110 | r = fflush_sync_and_check(f); | |
111 | else | |
112 | r = fflush_and_check(f); | |
113 | if (r < 0) | |
114 | return r; | |
115 | ||
39c38d77 ZJS |
116 | if (ts) { |
117 | struct timespec twice[2] = {*ts, *ts}; | |
118 | ||
119 | if (futimens(fileno(f), twice) < 0) | |
120 | return -errno; | |
121 | } | |
122 | ||
be83711c | 123 | return 0; |
a5c32cff HH |
124 | } |
125 | ||
2eabcc77 LP |
126 | static int write_string_file_atomic( |
127 | const char *fn, | |
128 | const char *line, | |
b1837133 | 129 | WriteStringFileFlags flags, |
2eabcc77 LP |
130 | struct timespec *ts) { |
131 | ||
a5c32cff HH |
132 | _cleanup_fclose_ FILE *f = NULL; |
133 | _cleanup_free_ char *p = NULL; | |
134 | int r; | |
135 | ||
136 | assert(fn); | |
137 | assert(line); | |
138 | ||
139 | r = fopen_temporary(fn, &f, &p); | |
140 | if (r < 0) | |
141 | return r; | |
142 | ||
0d39fa9c | 143 | (void) fchmod_umask(fileno(f), 0644); |
a5c32cff | 144 | |
b1837133 | 145 | r = write_string_stream_ts(f, line, flags, ts); |
9dd1b1e8 LP |
146 | if (r < 0) |
147 | goto fail; | |
148 | ||
149 | if (rename(p, fn) < 0) { | |
150 | r = -errno; | |
151 | goto fail; | |
a5c32cff HH |
152 | } |
153 | ||
9dd1b1e8 | 154 | return 0; |
a5c32cff | 155 | |
9dd1b1e8 LP |
156 | fail: |
157 | (void) unlink(p); | |
a5c32cff HH |
158 | return r; |
159 | } | |
160 | ||
b1837133 LP |
161 | int write_string_file_ts( |
162 | const char *fn, | |
163 | const char *line, | |
164 | WriteStringFileFlags flags, | |
165 | struct timespec *ts) { | |
166 | ||
4c1fc3e4 | 167 | _cleanup_fclose_ FILE *f = NULL; |
eb3da901 | 168 | int q, r; |
4c1fc3e4 DM |
169 | |
170 | assert(fn); | |
171 | assert(line); | |
172 | ||
265710c2 AJ |
173 | /* We don't know how to verify whether the file contents was already on-disk. */ |
174 | assert(!((flags & WRITE_STRING_FILE_VERIFY_ON_FAILURE) && (flags & WRITE_STRING_FILE_SYNC))); | |
0675e94a | 175 | |
50ccd864 LP |
176 | if (flags & WRITE_STRING_FILE_MKDIR_0755) { |
177 | r = mkdir_parents(fn, 0755); | |
178 | if (r < 0) | |
179 | return r; | |
180 | } | |
181 | ||
4c1fc3e4 DM |
182 | if (flags & WRITE_STRING_FILE_ATOMIC) { |
183 | assert(flags & WRITE_STRING_FILE_CREATE); | |
184 | ||
b1837133 | 185 | r = write_string_file_atomic(fn, line, flags, ts); |
eb3da901 LP |
186 | if (r < 0) |
187 | goto fail; | |
188 | ||
189 | return r; | |
39c38d77 | 190 | } else |
234519ae | 191 | assert(!ts); |
4c1fc3e4 DM |
192 | |
193 | if (flags & WRITE_STRING_FILE_CREATE) { | |
41f6e627 ZJS |
194 | r = fopen_unlocked(fn, "we", &f); |
195 | if (r < 0) | |
eb3da901 | 196 | goto fail; |
4c1fc3e4 DM |
197 | } else { |
198 | int fd; | |
199 | ||
200 | /* We manually build our own version of fopen(..., "we") that | |
201 | * works without O_CREAT */ | |
835d18ba | 202 | fd = open(fn, O_WRONLY|O_CLOEXEC|O_NOCTTY | ((flags & WRITE_STRING_FILE_NOFOLLOW) ? O_NOFOLLOW : 0)); |
eb3da901 LP |
203 | if (fd < 0) { |
204 | r = -errno; | |
205 | goto fail; | |
206 | } | |
4c1fc3e4 | 207 | |
02e23d1a ZJS |
208 | r = fdopen_unlocked(fd, "w", &f); |
209 | if (r < 0) { | |
4c1fc3e4 | 210 | safe_close(fd); |
eb3da901 | 211 | goto fail; |
4c1fc3e4 | 212 | } |
41f6e627 | 213 | } |
35bbbf85 | 214 | |
12ec9c30 TSH |
215 | if (flags & WRITE_STRING_FILE_DISABLE_BUFFER) |
216 | setvbuf(f, NULL, _IONBF, 0); | |
217 | ||
b1837133 | 218 | r = write_string_stream_ts(f, line, flags, ts); |
eb3da901 LP |
219 | if (r < 0) |
220 | goto fail; | |
221 | ||
222 | return 0; | |
223 | ||
224 | fail: | |
225 | if (!(flags & WRITE_STRING_FILE_VERIFY_ON_FAILURE)) | |
226 | return r; | |
227 | ||
228 | f = safe_fclose(f); | |
229 | ||
230 | /* OK, the operation failed, but let's see if the right | |
231 | * contents in place already. If so, eat up the error. */ | |
232 | ||
233 | q = verify_file(fn, line, !(flags & WRITE_STRING_FILE_AVOID_NEWLINE)); | |
234 | if (q <= 0) | |
235 | return r; | |
236 | ||
237 | return 0; | |
4c1fc3e4 DM |
238 | } |
239 | ||
3130fca5 LP |
240 | int write_string_filef( |
241 | const char *fn, | |
242 | WriteStringFileFlags flags, | |
243 | const char *format, ...) { | |
244 | ||
245 | _cleanup_free_ char *p = NULL; | |
246 | va_list ap; | |
247 | int r; | |
248 | ||
249 | va_start(ap, format); | |
250 | r = vasprintf(&p, format, ap); | |
251 | va_end(ap); | |
252 | ||
253 | if (r < 0) | |
254 | return -ENOMEM; | |
255 | ||
256 | return write_string_file(fn, p, flags); | |
257 | } | |
258 | ||
a5c32cff HH |
259 | int read_one_line_file(const char *fn, char **line) { |
260 | _cleanup_fclose_ FILE *f = NULL; | |
fdeea3f4 | 261 | int r; |
a5c32cff HH |
262 | |
263 | assert(fn); | |
264 | assert(line); | |
265 | ||
fdeea3f4 ZJS |
266 | r = fopen_unlocked(fn, "re", &f); |
267 | if (r < 0) | |
268 | return r; | |
35bbbf85 | 269 | |
d6062e3b | 270 | return read_line(f, LONG_LINE_MAX, line); |
a5c32cff HH |
271 | } |
272 | ||
eb3da901 LP |
273 | int verify_file(const char *fn, const char *blob, bool accept_extra_nl) { |
274 | _cleanup_fclose_ FILE *f = NULL; | |
275 | _cleanup_free_ char *buf = NULL; | |
276 | size_t l, k; | |
fdeea3f4 | 277 | int r; |
15dee3f0 | 278 | |
eb3da901 LP |
279 | assert(fn); |
280 | assert(blob); | |
281 | ||
282 | l = strlen(blob); | |
283 | ||
284 | if (accept_extra_nl && endswith(blob, "\n")) | |
285 | accept_extra_nl = false; | |
286 | ||
287 | buf = malloc(l + accept_extra_nl + 1); | |
288 | if (!buf) | |
289 | return -ENOMEM; | |
290 | ||
fdeea3f4 ZJS |
291 | r = fopen_unlocked(fn, "re", &f); |
292 | if (r < 0) | |
293 | return r; | |
35bbbf85 | 294 | |
eb3da901 LP |
295 | /* We try to read one byte more than we need, so that we know whether we hit eof */ |
296 | errno = 0; | |
297 | k = fread(buf, 1, l + accept_extra_nl + 1, f); | |
298 | if (ferror(f)) | |
66855de7 | 299 | return errno_or_else(EIO); |
eb3da901 LP |
300 | |
301 | if (k != l && k != l + accept_extra_nl) | |
302 | return 0; | |
303 | if (memcmp(buf, blob, l) != 0) | |
304 | return 0; | |
305 | if (k > l && buf[l] != '\n') | |
306 | return 0; | |
15dee3f0 | 307 | |
eb3da901 | 308 | return 1; |
15dee3f0 LP |
309 | } |
310 | ||
21b40f16 FB |
311 | int read_full_virtual_file(const char *filename, char **ret_contents, size_t *ret_size) { |
312 | _cleanup_free_ char *buf = NULL; | |
313 | _cleanup_close_ int fd = -1; | |
314 | struct stat st; | |
315 | size_t n, size; | |
316 | int n_retries; | |
317 | char *p; | |
318 | ||
319 | assert(ret_contents); | |
320 | ||
321 | /* Virtual filesystems such as sysfs or procfs use kernfs, and kernfs can work | |
322 | * with two sorts of virtual files. One sort uses "seq_file", and the results of | |
323 | * the first read are buffered for the second read. The other sort uses "raw" | |
324 | * reads which always go direct to the device. In the latter case, the content of | |
325 | * the virtual file must be retrieved with a single read otherwise a second read | |
326 | * might get the new value instead of finding EOF immediately. That's the reason | |
327 | * why the usage of fread(3) is prohibited in this case as it always performs a | |
328 | * second call to read(2) looking for EOF. See issue 13585. */ | |
329 | ||
330 | fd = open(filename, O_RDONLY|O_CLOEXEC); | |
331 | if (fd < 0) | |
332 | return -errno; | |
333 | ||
334 | /* Start size for files in /proc which usually report a file size of 0. */ | |
335 | size = LINE_MAX / 2; | |
336 | ||
337 | /* Limit the number of attempts to read the number of bytes returned by fstat(). */ | |
338 | n_retries = 3; | |
339 | ||
340 | for (;;) { | |
341 | if (n_retries <= 0) | |
342 | return -EIO; | |
343 | ||
344 | if (fstat(fd, &st) < 0) | |
345 | return -errno; | |
346 | ||
347 | if (!S_ISREG(st.st_mode)) | |
348 | return -EBADF; | |
349 | ||
350 | /* Be prepared for files from /proc which generally report a file size of 0. */ | |
351 | if (st.st_size > 0) { | |
352 | size = st.st_size; | |
353 | n_retries--; | |
354 | } else | |
355 | size = size * 2; | |
356 | ||
357 | if (size > READ_FULL_BYTES_MAX) | |
358 | return -E2BIG; | |
359 | ||
360 | p = realloc(buf, size + 1); | |
361 | if (!p) | |
362 | return -ENOMEM; | |
363 | buf = TAKE_PTR(p); | |
364 | ||
365 | for (;;) { | |
366 | ssize_t k; | |
367 | ||
368 | /* Read one more byte so we can detect whether the content of the | |
369 | * file has already changed or the guessed size for files from /proc | |
370 | * wasn't large enough . */ | |
371 | k = read(fd, buf, size + 1); | |
372 | if (k >= 0) { | |
373 | n = k; | |
374 | break; | |
375 | } | |
376 | ||
377 | if (errno != -EINTR) | |
378 | return -errno; | |
379 | } | |
380 | ||
381 | /* Consider a short read as EOF */ | |
382 | if (n <= size) | |
383 | break; | |
384 | ||
385 | /* Hmm... either we read too few bytes from /proc or less likely the content | |
386 | * of the file might have been changed (and is now bigger) while we were | |
387 | * processing, let's try again either with a bigger guessed size or the new | |
388 | * file size. */ | |
389 | ||
390 | if (lseek(fd, 0, SEEK_SET) < 0) | |
391 | return -errno; | |
392 | } | |
393 | ||
394 | if (n < size) { | |
395 | p = realloc(buf, n + 1); | |
396 | if (!p) | |
397 | return -ENOMEM; | |
398 | buf = TAKE_PTR(p); | |
399 | } | |
400 | ||
401 | if (!ret_size) { | |
402 | /* Safety check: if the caller doesn't want to know the size of what we | |
403 | * just read it will rely on the trailing NUL byte. But if there's an | |
404 | * embedded NUL byte, then we should refuse operation as otherwise | |
405 | * there'd be ambiguity about what we just read. */ | |
406 | ||
407 | if (memchr(buf, 0, n)) | |
408 | return -EBADMSG; | |
409 | } else | |
410 | *ret_size = n; | |
411 | ||
412 | buf[n] = 0; | |
413 | *ret_contents = TAKE_PTR(buf); | |
414 | ||
415 | return 0; | |
416 | } | |
417 | ||
15f8f026 | 418 | int read_full_stream_full( |
2d78717b | 419 | FILE *f, |
50caae7b | 420 | const char *filename, |
15f8f026 | 421 | ReadFullFileFlags flags, |
2d78717b LP |
422 | char **ret_contents, |
423 | size_t *ret_size) { | |
424 | ||
a5c32cff HH |
425 | _cleanup_free_ char *buf = NULL; |
426 | struct stat st; | |
15f8f026 YW |
427 | size_t n, n_next, l; |
428 | int fd, r; | |
a5c32cff | 429 | |
717603e3 | 430 | assert(f); |
2d78717b | 431 | assert(ret_contents); |
89aaf655 YW |
432 | assert(!FLAGS_SET(flags, READ_FULL_FILE_UNBASE64 | READ_FULL_FILE_UNHEX)); |
433 | assert(!(flags & (READ_FULL_FILE_UNBASE64 | READ_FULL_FILE_UNHEX)) || ret_size); | |
a5c32cff | 434 | |
15f8f026 | 435 | n_next = LINE_MAX; /* Start size */ |
a5c32cff | 436 | |
c4054ddf LP |
437 | fd = fileno(f); |
438 | if (fd >= 0) { /* If the FILE* object is backed by an fd (as opposed to memory or such, see fmemopen(), let's | |
439 | * optimize our buffering) */ | |
717603e3 | 440 | |
15f8f026 | 441 | if (fstat(fd, &st) < 0) |
c4054ddf LP |
442 | return -errno; |
443 | ||
444 | if (S_ISREG(st.st_mode)) { | |
717603e3 | 445 | |
c4054ddf LP |
446 | /* Safety check */ |
447 | if (st.st_size > READ_FULL_BYTES_MAX) | |
448 | return -E2BIG; | |
449 | ||
21b40f16 FB |
450 | /* Start with the right file size. Note that we increase the size |
451 | * to read here by one, so that the first read attempt already | |
452 | * makes us notice the EOF. */ | |
c4054ddf | 453 | if (st.st_size > 0) |
15f8f026 | 454 | n_next = st.st_size + 1; |
50caae7b YW |
455 | |
456 | if (flags & READ_FULL_FILE_SECURE) | |
457 | (void) warn_file_is_world_accessible(filename, &st, NULL, 0); | |
c4054ddf | 458 | } |
717603e3 | 459 | } |
a5c32cff | 460 | |
15f8f026 | 461 | n = l = 0; |
a5c32cff HH |
462 | for (;;) { |
463 | char *t; | |
464 | size_t k; | |
465 | ||
15f8f026 YW |
466 | if (flags & READ_FULL_FILE_SECURE) { |
467 | t = malloc(n_next + 1); | |
468 | if (!t) { | |
469 | r = -ENOMEM; | |
470 | goto finalize; | |
471 | } | |
472 | memcpy_safe(t, buf, n); | |
473 | explicit_bzero_safe(buf, n); | |
c424bed1 | 474 | buf = mfree(buf); |
15f8f026 YW |
475 | } else { |
476 | t = realloc(buf, n_next + 1); | |
477 | if (!t) | |
478 | return -ENOMEM; | |
479 | } | |
a5c32cff HH |
480 | |
481 | buf = t; | |
15f8f026 YW |
482 | n = n_next; |
483 | ||
5a89faf0 | 484 | errno = 0; |
a5c32cff | 485 | k = fread(buf + l, 1, n - l, f); |
c2d11a63 VC |
486 | if (k > 0) |
487 | l += k; | |
a5c32cff | 488 | |
15f8f026 | 489 | if (ferror(f)) { |
66855de7 | 490 | r = errno_or_else(EIO); |
15f8f026 YW |
491 | goto finalize; |
492 | } | |
a5c32cff | 493 | |
c2d11a63 | 494 | if (feof(f)) |
a5c32cff | 495 | break; |
a5c32cff | 496 | |
c2d11a63 VC |
497 | /* We aren't expecting fread() to return a short read outside |
498 | * of (error && eof), assert buffer is full and enlarge buffer. | |
499 | */ | |
500 | assert(l == n); | |
a5c32cff HH |
501 | |
502 | /* Safety check */ | |
15f8f026 YW |
503 | if (n >= READ_FULL_BYTES_MAX) { |
504 | r = -E2BIG; | |
505 | goto finalize; | |
506 | } | |
c2d11a63 | 507 | |
15f8f026 | 508 | n_next = MIN(n * 2, READ_FULL_BYTES_MAX); |
a5c32cff HH |
509 | } |
510 | ||
89aaf655 | 511 | if (flags & (READ_FULL_FILE_UNBASE64 | READ_FULL_FILE_UNHEX)) { |
07d8c0eb | 512 | buf[l++] = 0; |
89aaf655 YW |
513 | if (flags & READ_FULL_FILE_UNBASE64) |
514 | r = unbase64mem_full(buf, l, flags & READ_FULL_FILE_SECURE, (void **) ret_contents, ret_size); | |
515 | else | |
516 | r = unhexmem_full(buf, l, flags & READ_FULL_FILE_SECURE, (void **) ret_contents, ret_size); | |
07d8c0eb YW |
517 | goto finalize; |
518 | } | |
519 | ||
2d78717b LP |
520 | if (!ret_size) { |
521 | /* Safety check: if the caller doesn't want to know the size of what we just read it will rely on the | |
522 | * trailing NUL byte. But if there's an embedded NUL byte, then we should refuse operation as otherwise | |
523 | * there'd be ambiguity about what we just read. */ | |
524 | ||
15f8f026 YW |
525 | if (memchr(buf, 0, l)) { |
526 | r = -EBADMSG; | |
527 | goto finalize; | |
528 | } | |
2d78717b LP |
529 | } |
530 | ||
a5c32cff | 531 | buf[l] = 0; |
2d78717b | 532 | *ret_contents = TAKE_PTR(buf); |
a5c32cff | 533 | |
2d78717b LP |
534 | if (ret_size) |
535 | *ret_size = l; | |
a5c32cff HH |
536 | |
537 | return 0; | |
15f8f026 YW |
538 | |
539 | finalize: | |
540 | if (flags & READ_FULL_FILE_SECURE) | |
541 | explicit_bzero_safe(buf, n); | |
542 | ||
543 | return r; | |
a5c32cff HH |
544 | } |
545 | ||
15f8f026 | 546 | int read_full_file_full(const char *filename, ReadFullFileFlags flags, char **contents, size_t *size) { |
717603e3 | 547 | _cleanup_fclose_ FILE *f = NULL; |
fdeea3f4 | 548 | int r; |
717603e3 | 549 | |
15f8f026 | 550 | assert(filename); |
717603e3 LP |
551 | assert(contents); |
552 | ||
fdeea3f4 ZJS |
553 | r = fopen_unlocked(filename, "re", &f); |
554 | if (r < 0) | |
555 | return r; | |
35bbbf85 | 556 | |
50caae7b | 557 | return read_full_stream_full(f, filename, flags, contents, size); |
717603e3 LP |
558 | } |
559 | ||
68fee104 | 560 | int executable_is_script(const char *path, char **interpreter) { |
c8b32e11 | 561 | _cleanup_free_ char *line = NULL; |
99c61f6b | 562 | size_t len; |
68fee104 | 563 | char *ans; |
99c61f6b | 564 | int r; |
68fee104 ZJS |
565 | |
566 | assert(path); | |
567 | ||
568 | r = read_one_line_file(path, &line); | |
99c61f6b LP |
569 | if (r == -ENOBUFS) /* First line overly long? if so, then it's not a script */ |
570 | return 0; | |
68fee104 ZJS |
571 | if (r < 0) |
572 | return r; | |
573 | ||
574 | if (!startswith(line, "#!")) | |
575 | return 0; | |
576 | ||
577 | ans = strstrip(line + 2); | |
578 | len = strcspn(ans, " \t"); | |
579 | ||
580 | if (len == 0) | |
581 | return 0; | |
582 | ||
583 | ans = strndup(ans, len); | |
584 | if (!ans) | |
585 | return -ENOMEM; | |
586 | ||
587 | *interpreter = ans; | |
588 | return 1; | |
589 | } | |
69ab8088 ZJS |
590 | |
591 | /** | |
0a7b53bd | 592 | * Retrieve one field from a file like /proc/self/status. pattern |
c4cd1d4d AK |
593 | * should not include whitespace or the delimiter (':'). pattern matches only |
594 | * the beginning of a line. Whitespace before ':' is skipped. Whitespace and | |
595 | * zeros after the ':' will be skipped. field must be freed afterwards. | |
596 | * terminator specifies the terminating characters of the field value (not | |
597 | * included in the value). | |
69ab8088 | 598 | */ |
c4cd1d4d | 599 | int get_proc_field(const char *filename, const char *pattern, const char *terminator, char **field) { |
69ab8088 | 600 | _cleanup_free_ char *status = NULL; |
90110825 | 601 | char *t, *f; |
69ab8088 ZJS |
602 | size_t len; |
603 | int r; | |
604 | ||
c4cd1d4d | 605 | assert(terminator); |
69ab8088 | 606 | assert(filename); |
7ff7394d | 607 | assert(pattern); |
69ab8088 ZJS |
608 | assert(field); |
609 | ||
21b40f16 | 610 | r = read_full_virtual_file(filename, &status, NULL); |
69ab8088 ZJS |
611 | if (r < 0) |
612 | return r; | |
613 | ||
c4cd1d4d AK |
614 | t = status; |
615 | ||
616 | do { | |
617 | bool pattern_ok; | |
618 | ||
619 | do { | |
620 | t = strstr(t, pattern); | |
621 | if (!t) | |
622 | return -ENOENT; | |
623 | ||
624 | /* Check that pattern occurs in beginning of line. */ | |
625 | pattern_ok = (t == status || t[-1] == '\n'); | |
626 | ||
627 | t += strlen(pattern); | |
628 | ||
629 | } while (!pattern_ok); | |
630 | ||
631 | t += strspn(t, " \t"); | |
632 | if (!*t) | |
633 | return -ENOENT; | |
634 | ||
635 | } while (*t != ':'); | |
636 | ||
637 | t++; | |
69ab8088 | 638 | |
4ec29144 | 639 | if (*t) { |
1e5413f7 ZJS |
640 | t += strspn(t, " \t"); |
641 | ||
642 | /* Also skip zeros, because when this is used for | |
643 | * capabilities, we don't want the zeros. This way the | |
644 | * same capability set always maps to the same string, | |
645 | * irrespective of the total capability set size. For | |
646 | * other numbers it shouldn't matter. */ | |
647 | t += strspn(t, "0"); | |
4ec29144 ZJS |
648 | /* Back off one char if there's nothing but whitespace |
649 | and zeros */ | |
1e5413f7 | 650 | if (!*t || isspace(*t)) |
313cefa1 | 651 | t--; |
4ec29144 | 652 | } |
69ab8088 | 653 | |
c4cd1d4d | 654 | len = strcspn(t, terminator); |
69ab8088 | 655 | |
90110825 LP |
656 | f = strndup(t, len); |
657 | if (!f) | |
69ab8088 ZJS |
658 | return -ENOMEM; |
659 | ||
90110825 | 660 | *field = f; |
69ab8088 ZJS |
661 | return 0; |
662 | } | |
0d39fa9c LP |
663 | |
664 | DIR *xopendirat(int fd, const char *name, int flags) { | |
665 | int nfd; | |
666 | DIR *d; | |
667 | ||
668 | assert(!(flags & O_CREAT)); | |
669 | ||
670 | nfd = openat(fd, name, O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC|flags, 0); | |
671 | if (nfd < 0) | |
672 | return NULL; | |
673 | ||
674 | d = fdopendir(nfd); | |
675 | if (!d) { | |
676 | safe_close(nfd); | |
677 | return NULL; | |
678 | } | |
679 | ||
680 | return d; | |
681 | } | |
682 | ||
683 | static int search_and_fopen_internal(const char *path, const char *mode, const char *root, char **search, FILE **_f) { | |
684 | char **i; | |
685 | ||
686 | assert(path); | |
687 | assert(mode); | |
688 | assert(_f); | |
689 | ||
690 | if (!path_strv_resolve_uniq(search, root)) | |
691 | return -ENOMEM; | |
692 | ||
693 | STRV_FOREACH(i, search) { | |
694 | _cleanup_free_ char *p = NULL; | |
695 | FILE *f; | |
696 | ||
657ee2d8 | 697 | p = path_join(root, *i, path); |
0d39fa9c LP |
698 | if (!p) |
699 | return -ENOMEM; | |
700 | ||
701 | f = fopen(p, mode); | |
702 | if (f) { | |
703 | *_f = f; | |
704 | return 0; | |
705 | } | |
706 | ||
707 | if (errno != ENOENT) | |
708 | return -errno; | |
709 | } | |
710 | ||
711 | return -ENOENT; | |
712 | } | |
713 | ||
714 | int search_and_fopen(const char *path, const char *mode, const char *root, const char **search, FILE **_f) { | |
715 | _cleanup_strv_free_ char **copy = NULL; | |
716 | ||
717 | assert(path); | |
718 | assert(mode); | |
719 | assert(_f); | |
720 | ||
721 | if (path_is_absolute(path)) { | |
722 | FILE *f; | |
723 | ||
724 | f = fopen(path, mode); | |
725 | if (f) { | |
726 | *_f = f; | |
727 | return 0; | |
728 | } | |
729 | ||
730 | return -errno; | |
731 | } | |
732 | ||
733 | copy = strv_copy((char**) search); | |
734 | if (!copy) | |
735 | return -ENOMEM; | |
736 | ||
737 | return search_and_fopen_internal(path, mode, root, copy, _f); | |
738 | } | |
739 | ||
740 | int search_and_fopen_nulstr(const char *path, const char *mode, const char *root, const char *search, FILE **_f) { | |
741 | _cleanup_strv_free_ char **s = NULL; | |
742 | ||
743 | if (path_is_absolute(path)) { | |
744 | FILE *f; | |
745 | ||
746 | f = fopen(path, mode); | |
747 | if (f) { | |
748 | *_f = f; | |
749 | return 0; | |
750 | } | |
751 | ||
752 | return -errno; | |
753 | } | |
754 | ||
755 | s = strv_split_nulstr(search); | |
756 | if (!s) | |
757 | return -ENOMEM; | |
758 | ||
759 | return search_and_fopen_internal(path, mode, root, s, _f); | |
760 | } | |
761 | ||
0d39fa9c LP |
762 | int fflush_and_check(FILE *f) { |
763 | assert(f); | |
764 | ||
765 | errno = 0; | |
766 | fflush(f); | |
767 | ||
768 | if (ferror(f)) | |
66855de7 | 769 | return errno_or_else(EIO); |
0d39fa9c LP |
770 | |
771 | return 0; | |
772 | } | |
773 | ||
0675e94a AJ |
774 | int fflush_sync_and_check(FILE *f) { |
775 | int r; | |
776 | ||
777 | assert(f); | |
778 | ||
779 | r = fflush_and_check(f); | |
780 | if (r < 0) | |
781 | return r; | |
782 | ||
783 | if (fsync(fileno(f)) < 0) | |
784 | return -errno; | |
785 | ||
8ac2f74f LP |
786 | r = fsync_directory_of_file(fileno(f)); |
787 | if (r < 0) | |
788 | return r; | |
789 | ||
0675e94a AJ |
790 | return 0; |
791 | } | |
792 | ||
33d52ab9 LP |
793 | int write_timestamp_file_atomic(const char *fn, usec_t n) { |
794 | char ln[DECIMAL_STR_MAX(n)+2]; | |
795 | ||
796 | /* Creates a "timestamp" file, that contains nothing but a | |
797 | * usec_t timestamp, formatted in ASCII. */ | |
798 | ||
799 | if (n <= 0 || n >= USEC_INFINITY) | |
800 | return -ERANGE; | |
801 | ||
802 | xsprintf(ln, USEC_FMT "\n", n); | |
803 | ||
804 | return write_string_file(fn, ln, WRITE_STRING_FILE_CREATE|WRITE_STRING_FILE_ATOMIC); | |
805 | } | |
806 | ||
807 | int read_timestamp_file(const char *fn, usec_t *ret) { | |
808 | _cleanup_free_ char *ln = NULL; | |
809 | uint64_t t; | |
810 | int r; | |
811 | ||
812 | r = read_one_line_file(fn, &ln); | |
813 | if (r < 0) | |
814 | return r; | |
815 | ||
816 | r = safe_atou64(ln, &t); | |
817 | if (r < 0) | |
818 | return r; | |
819 | ||
820 | if (t <= 0 || t >= (uint64_t) USEC_INFINITY) | |
821 | return -ERANGE; | |
822 | ||
823 | *ret = (usec_t) t; | |
824 | return 0; | |
825 | } | |
d390f8ef LP |
826 | |
827 | int fputs_with_space(FILE *f, const char *s, const char *separator, bool *space) { | |
828 | int r; | |
829 | ||
830 | assert(s); | |
831 | ||
832 | /* Outputs the specified string with fputs(), but optionally prefixes it with a separator. The *space parameter | |
833 | * when specified shall initially point to a boolean variable initialized to false. It is set to true after the | |
834 | * first invocation. This call is supposed to be use in loops, where a separator shall be inserted between each | |
835 | * element, but not before the first one. */ | |
836 | ||
837 | if (!f) | |
838 | f = stdout; | |
839 | ||
840 | if (space) { | |
841 | if (!separator) | |
842 | separator = " "; | |
843 | ||
844 | if (*space) { | |
845 | r = fputs(separator, f); | |
846 | if (r < 0) | |
847 | return r; | |
848 | } | |
849 | ||
850 | *space = true; | |
851 | } | |
852 | ||
853 | return fputs(s, f); | |
854 | } | |
03532f0a | 855 | |
838894b0 LP |
856 | /* A bitmask of the EOL markers we know */ |
857 | typedef enum EndOfLineMarker { | |
858 | EOL_NONE = 0, | |
859 | EOL_ZERO = 1 << 0, /* \0 (aka NUL) */ | |
860 | EOL_TEN = 1 << 1, /* \n (aka NL, aka LF) */ | |
861 | EOL_THIRTEEN = 1 << 2, /* \r (aka CR) */ | |
862 | } EndOfLineMarker; | |
863 | ||
41f11239 LP |
864 | static EndOfLineMarker categorize_eol(char c, ReadLineFlags flags) { |
865 | ||
866 | if (!IN_SET(flags, READ_LINE_ONLY_NUL)) { | |
867 | if (c == '\n') | |
868 | return EOL_TEN; | |
869 | if (c == '\r') | |
870 | return EOL_THIRTEEN; | |
871 | } | |
872 | ||
838894b0 LP |
873 | if (c == '\0') |
874 | return EOL_ZERO; | |
875 | ||
876 | return EOL_NONE; | |
877 | } | |
878 | ||
57d6f700 | 879 | DEFINE_TRIVIAL_CLEANUP_FUNC(FILE*, funlockfile); |
f858e514 | 880 | |
41f11239 | 881 | int read_line_full(FILE *f, size_t limit, ReadLineFlags flags, char **ret) { |
4f9a66a3 | 882 | size_t n = 0, allocated = 0, count = 0; |
838894b0 | 883 | _cleanup_free_ char *buffer = NULL; |
ee41670f | 884 | int r, tty = -1; |
4f9a66a3 LP |
885 | |
886 | assert(f); | |
887 | ||
888 | /* Something like a bounded version of getline(). | |
889 | * | |
838894b0 LP |
890 | * Considers EOF, \n, \r and \0 end of line delimiters (or combinations of these), and does not include these |
891 | * delimiters in the string returned. Specifically, recognizes the following combinations of markers as line | |
892 | * endings: | |
893 | * | |
894 | * • \n (UNIX) | |
895 | * • \r (old MacOS) | |
896 | * • \0 (C strings) | |
897 | * • \n\0 | |
898 | * • \r\0 | |
899 | * • \r\n (Windows) | |
900 | * • \n\r | |
901 | * • \r\n\0 | |
902 | * • \n\r\0 | |
4f9a66a3 LP |
903 | * |
904 | * Returns the number of bytes read from the files (i.e. including delimiters — this hence usually differs from | |
905 | * the number of characters in the returned string). When EOF is hit, 0 is returned. | |
906 | * | |
907 | * The input parameter limit is the maximum numbers of characters in the returned string, i.e. excluding | |
908 | * delimiters. If the limit is hit we fail and return -ENOBUFS. | |
909 | * | |
910 | * If a line shall be skipped ret may be initialized as NULL. */ | |
911 | ||
912 | if (ret) { | |
913 | if (!GREEDY_REALLOC(buffer, allocated, 1)) | |
914 | return -ENOMEM; | |
915 | } | |
916 | ||
f858e514 | 917 | { |
3f691417 | 918 | _unused_ _cleanup_(funlockfilep) FILE *flocked = f; |
838894b0 | 919 | EndOfLineMarker previous_eol = EOL_NONE; |
f858e514 | 920 | flockfile(f); |
4f9a66a3 | 921 | |
f858e514 | 922 | for (;;) { |
838894b0 | 923 | EndOfLineMarker eol; |
03a7dbea | 924 | char c; |
4f9a66a3 | 925 | |
f858e514 ZJS |
926 | if (n >= limit) |
927 | return -ENOBUFS; | |
4f9a66a3 | 928 | |
31fd02f0 LP |
929 | if (count >= INT_MAX) /* We couldn't return the counter anymore as "int", hence refuse this */ |
930 | return -ENOBUFS; | |
931 | ||
03a7dbea LP |
932 | r = safe_fgetc(f, &c); |
933 | if (r < 0) | |
934 | return r; | |
91a306b8 | 935 | if (r == 0) /* EOF is definitely EOL */ |
f858e514 | 936 | break; |
4f9a66a3 | 937 | |
41f11239 | 938 | eol = categorize_eol(c, flags); |
838894b0 LP |
939 | |
940 | if (FLAGS_SET(previous_eol, EOL_ZERO) || | |
941 | (eol == EOL_NONE && previous_eol != EOL_NONE) || | |
942 | (eol != EOL_NONE && (previous_eol & eol) != 0)) { | |
943 | /* Previous char was a NUL? This is not an EOL, but the previous char was? This type of | |
517b7760 LP |
944 | * EOL marker has been seen right before? In either of these three cases we are |
945 | * done. But first, let's put this character back in the queue. (Note that we have to | |
946 | * cast this to (unsigned char) here as ungetc() expects a positive 'int', and if we | |
947 | * are on an architecture where 'char' equals 'signed char' we need to ensure we don't | |
948 | * pass a negative value here. That said, to complicate things further ungetc() is | |
949 | * actually happy with most negative characters and implicitly casts them back to | |
950 | * positive ones as needed, except for \xff (aka -1, aka EOF), which it refuses. What a | |
951 | * godawful API!) */ | |
952 | assert_se(ungetc((unsigned char) c, f) != EOF); | |
f858e514 | 953 | break; |
838894b0 LP |
954 | } |
955 | ||
91a306b8 LP |
956 | count++; |
957 | ||
838894b0 | 958 | if (eol != EOL_NONE) { |
ee41670f ZJS |
959 | /* If we are on a tty, we can't wait for more input. But we expect only |
960 | * \n as the single EOL marker, so there is no need to wait. We check | |
961 | * this condition last to avoid isatty() check if not necessary. */ | |
962 | ||
963 | if (tty < 0) | |
964 | tty = isatty(fileno(f)); | |
965 | if (tty > 0) | |
966 | break; | |
967 | } | |
968 | ||
969 | if (eol != EOL_NONE) { | |
838894b0 LP |
970 | previous_eol |= eol; |
971 | continue; | |
972 | } | |
4f9a66a3 | 973 | |
f858e514 ZJS |
974 | if (ret) { |
975 | if (!GREEDY_REALLOC(buffer, allocated, n + 2)) | |
976 | return -ENOMEM; | |
4f9a66a3 | 977 | |
03a7dbea | 978 | buffer[n] = c; |
4f9a66a3 LP |
979 | } |
980 | ||
f858e514 | 981 | n++; |
4f9a66a3 | 982 | } |
4f9a66a3 LP |
983 | } |
984 | ||
4f9a66a3 LP |
985 | if (ret) { |
986 | buffer[n] = 0; | |
987 | ||
1cc6c93a | 988 | *ret = TAKE_PTR(buffer); |
4f9a66a3 LP |
989 | } |
990 | ||
991 | return (int) count; | |
992 | } | |
285a9b27 LP |
993 | |
994 | int safe_fgetc(FILE *f, char *ret) { | |
995 | int k; | |
996 | ||
997 | assert(f); | |
998 | ||
999 | /* A safer version of plain fgetc(): let's propagate the error that happened while reading as such, and | |
1000 | * separate the EOF condition from the byte read, to avoid those confusion signed/unsigned issues fgetc() | |
1001 | * has. */ | |
1002 | ||
1003 | errno = 0; | |
1004 | k = fgetc(f); | |
1005 | if (k == EOF) { | |
1006 | if (ferror(f)) | |
66855de7 | 1007 | return errno_or_else(EIO); |
285a9b27 LP |
1008 | |
1009 | if (ret) | |
1010 | *ret = 0; | |
1011 | ||
1012 | return 0; | |
1013 | } | |
1014 | ||
1015 | if (ret) | |
1016 | *ret = k; | |
1017 | ||
1018 | return 1; | |
1019 | } | |
7a309a8c YW |
1020 | |
1021 | int warn_file_is_world_accessible(const char *filename, struct stat *st, const char *unit, unsigned line) { | |
1022 | struct stat _st; | |
1023 | ||
1024 | if (!filename) | |
1025 | return 0; | |
1026 | ||
1027 | if (!st) { | |
1028 | if (stat(filename, &_st) < 0) | |
1029 | return -errno; | |
1030 | st = &_st; | |
1031 | } | |
1032 | ||
1033 | if ((st->st_mode & S_IRWXO) == 0) | |
1034 | return 0; | |
1035 | ||
1036 | if (unit) | |
1037 | log_syntax(unit, LOG_WARNING, filename, line, 0, | |
0f935776 | 1038 | "%s has %04o mode that is too permissive, please adjust the ownership and access mode.", |
7a309a8c YW |
1039 | filename, st->st_mode & 07777); |
1040 | else | |
0f935776 | 1041 | log_warning("%s has %04o mode that is too permissive, please adjust the ownership and access mode.", |
7a309a8c YW |
1042 | filename, st->st_mode & 07777); |
1043 | return 0; | |
1044 | } |