1 /* SPDX-License-Identifier: LGPL-2.1+ */
3 This file is part of systemd.
5 Copyright 2010 Lennart Poettering
7 systemd is free software; you can redistribute it and/or modify it
8 under the terms of the GNU Lesser General Public License as published by
9 the Free Software Foundation; either version 2.1 of the License, or
10 (at your option) any later version.
12 systemd is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 Lesser General Public License for more details.
17 You should have received a copy of the GNU Lesser General Public License
18 along with systemd; If not, see <http://www.gnu.org/licenses/>.
26 #include <stdio_ext.h>
31 #include <sys/types.h>
34 #include "alloc-util.h"
42 #include "hexdecoct.h"
46 #include "parse-util.h"
47 #include "path-util.h"
48 #include "process-util.h"
49 #include "random-util.h"
50 #include "stdio-util.h"
51 #include "string-util.h"
53 //#include "time-util.h"
54 #include "umask-util.h"
57 #define READ_FULL_BYTES_MAX (4U*1024U*1024U)
59 int write_string_stream_ts(
62 WriteStringFileFlags flags,
63 struct timespec *ts) {
73 needs_nl = !(flags & WRITE_STRING_FILE_AVOID_NEWLINE) && !endswith(line, "\n");
75 if (needs_nl && (flags & WRITE_STRING_FILE_DISABLE_BUFFER)) {
76 /* If STDIO buffering was disabled, then let's append the newline character to the string itself, so
77 * that the write goes out in one go, instead of two */
79 line = strjoina(line, "\n");
83 if (fputs(line, f) == EOF)
87 if (fputc('\n', f) == EOF)
91 struct timespec twice[2] = {*ts, *ts};
93 if (futimens(fileno(f), twice) < 0)
97 if (flags & WRITE_STRING_FILE_SYNC)
98 return fflush_sync_and_check(f);
100 return fflush_and_check(f);
103 static int write_string_file_atomic(
106 WriteStringFileFlags flags,
107 struct timespec *ts) {
109 _cleanup_fclose_ FILE *f = NULL;
110 _cleanup_free_ char *p = NULL;
116 r = fopen_temporary(fn, &f, &p);
120 (void) __fsetlocking(f, FSETLOCKING_BYCALLER);
121 (void) fchmod_umask(fileno(f), 0644);
123 r = write_string_stream_ts(f, line, flags, ts);
127 if (rename(p, fn) < 0) {
139 int write_string_file_ts(
142 WriteStringFileFlags flags,
143 struct timespec *ts) {
145 _cleanup_fclose_ FILE *f = NULL;
151 /* We don't know how to verify whether the file contents was already on-disk. */
152 assert(!((flags & WRITE_STRING_FILE_VERIFY_ON_FAILURE) && (flags & WRITE_STRING_FILE_SYNC)));
154 if (flags & WRITE_STRING_FILE_ATOMIC) {
155 assert(flags & WRITE_STRING_FILE_CREATE);
157 r = write_string_file_atomic(fn, line, flags, ts);
165 if (flags & WRITE_STRING_FILE_CREATE) {
174 /* We manually build our own version of fopen(..., "we") that
175 * works without O_CREAT */
176 fd = open(fn, O_WRONLY|O_CLOEXEC|O_NOCTTY);
182 f = fdopen(fd, "we");
190 (void) __fsetlocking(f, FSETLOCKING_BYCALLER);
192 if (flags & WRITE_STRING_FILE_DISABLE_BUFFER)
193 setvbuf(f, NULL, _IONBF, 0);
195 r = write_string_stream_ts(f, line, flags, ts);
202 if (!(flags & WRITE_STRING_FILE_VERIFY_ON_FAILURE))
207 /* OK, the operation failed, but let's see if the right
208 * contents in place already. If so, eat up the error. */
210 q = verify_file(fn, line, !(flags & WRITE_STRING_FILE_AVOID_NEWLINE));
217 int read_one_line_file(const char *fn, char **line) {
218 _cleanup_fclose_ FILE *f = NULL;
228 (void) __fsetlocking(f, FSETLOCKING_BYCALLER);
230 r = read_line(f, LONG_LINE_MAX, line);
231 return r < 0 ? r : 0;
234 int verify_file(const char *fn, const char *blob, bool accept_extra_nl) {
235 _cleanup_fclose_ FILE *f = NULL;
236 _cleanup_free_ char *buf = NULL;
244 if (accept_extra_nl && endswith(blob, "\n"))
245 accept_extra_nl = false;
247 buf = malloc(l + accept_extra_nl + 1);
255 (void) __fsetlocking(f, FSETLOCKING_BYCALLER);
257 /* We try to read one byte more than we need, so that we know whether we hit eof */
259 k = fread(buf, 1, l + accept_extra_nl + 1, f);
261 return errno > 0 ? -errno : -EIO;
263 if (k != l && k != l + accept_extra_nl)
265 if (memcmp(buf, blob, l) != 0)
267 if (k > l && buf[l] != '\n')
273 int read_full_stream(FILE *f, char **contents, size_t *size) {
275 _cleanup_free_ char *buf = NULL;
281 if (fstat(fileno(f), &st) < 0)
286 if (S_ISREG(st.st_mode)) {
289 if (st.st_size > READ_FULL_BYTES_MAX)
292 /* Start with the right file size, but be prepared for files from /proc which generally report a file
293 * size of 0. Note that we increase the size to read here by one, so that the first read attempt
294 * already makes us notice the EOF. */
304 t = realloc(buf, n + 1);
310 k = fread(buf + l, 1, n - l, f);
315 return errno > 0 ? -errno : -EIO;
320 /* We aren't expecting fread() to return a short read outside
321 * of (error && eof), assert buffer is full and enlarge buffer.
326 if (n >= READ_FULL_BYTES_MAX)
329 n = MIN(n * 2, READ_FULL_BYTES_MAX);
334 buf = NULL; /* do not free */
342 int read_full_file(const char *fn, char **contents, size_t *size) {
343 _cleanup_fclose_ FILE *f = NULL;
352 (void) __fsetlocking(f, FSETLOCKING_BYCALLER);
354 return read_full_stream(f, contents, size);
357 static int parse_env_file_internal(
361 int (*push) (const char *filename, unsigned line,
362 const char *key, char *value, void *userdata, int *n_pushed),
366 _cleanup_free_ char *contents = NULL, *key = NULL;
367 size_t key_alloc = 0, n_key = 0, value_alloc = 0, n_value = 0, last_value_whitespace = (size_t) -1, last_key_whitespace = (size_t) -1;
368 char *p, *value = NULL;
379 SINGLE_QUOTE_VALUE_ESCAPE,
381 DOUBLE_QUOTE_VALUE_ESCAPE,
389 r = read_full_stream(f, &contents, NULL);
391 r = read_full_file(fname, &contents, NULL);
395 for (p = contents; *p; p++) {
401 if (strchr(COMMENTS, c))
403 else if (!strchr(WHITESPACE, c)) {
405 last_key_whitespace = (size_t) -1;
407 if (!GREEDY_REALLOC(key, key_alloc, n_key+2)) {
417 if (strchr(newline, c)) {
421 } else if (c == '=') {
423 last_value_whitespace = (size_t) -1;
425 if (!strchr(WHITESPACE, c))
426 last_key_whitespace = (size_t) -1;
427 else if (last_key_whitespace == (size_t) -1)
428 last_key_whitespace = n_key;
430 if (!GREEDY_REALLOC(key, key_alloc, n_key+2)) {
441 if (strchr(newline, c)) {
449 /* strip trailing whitespace from key */
450 if (last_key_whitespace != (size_t) -1)
451 key[last_key_whitespace] = 0;
453 r = push(fname, line, key, value, userdata, n_pushed);
459 value_alloc = n_value = 0;
461 } else if (c == '\'')
462 state = SINGLE_QUOTE_VALUE;
464 state = DOUBLE_QUOTE_VALUE;
466 state = VALUE_ESCAPE;
467 else if (!strchr(WHITESPACE, c)) {
470 if (!GREEDY_REALLOC(value, value_alloc, n_value+2)) {
475 value[n_value++] = c;
481 if (strchr(newline, c)) {
490 /* Chomp off trailing whitespace from value */
491 if (last_value_whitespace != (size_t) -1)
492 value[last_value_whitespace] = 0;
494 /* strip trailing whitespace from key */
495 if (last_key_whitespace != (size_t) -1)
496 key[last_key_whitespace] = 0;
498 r = push(fname, line, key, value, userdata, n_pushed);
504 value_alloc = n_value = 0;
506 } else if (c == '\\') {
507 state = VALUE_ESCAPE;
508 last_value_whitespace = (size_t) -1;
510 if (!strchr(WHITESPACE, c))
511 last_value_whitespace = (size_t) -1;
512 else if (last_value_whitespace == (size_t) -1)
513 last_value_whitespace = n_value;
515 if (!GREEDY_REALLOC(value, value_alloc, n_value+2)) {
520 value[n_value++] = c;
528 if (!strchr(newline, c)) {
529 /* Escaped newlines we eat up entirely */
530 if (!GREEDY_REALLOC(value, value_alloc, n_value+2)) {
535 value[n_value++] = c;
539 case SINGLE_QUOTE_VALUE:
543 state = SINGLE_QUOTE_VALUE_ESCAPE;
545 if (!GREEDY_REALLOC(value, value_alloc, n_value+2)) {
550 value[n_value++] = c;
555 case SINGLE_QUOTE_VALUE_ESCAPE:
556 state = SINGLE_QUOTE_VALUE;
558 if (!strchr(newline, c)) {
559 if (!GREEDY_REALLOC(value, value_alloc, n_value+2)) {
564 value[n_value++] = c;
568 case DOUBLE_QUOTE_VALUE:
572 state = DOUBLE_QUOTE_VALUE_ESCAPE;
574 if (!GREEDY_REALLOC(value, value_alloc, n_value+2)) {
579 value[n_value++] = c;
584 case DOUBLE_QUOTE_VALUE_ESCAPE:
585 state = DOUBLE_QUOTE_VALUE;
587 if (!strchr(newline, c)) {
588 if (!GREEDY_REALLOC(value, value_alloc, n_value+2)) {
593 value[n_value++] = c;
599 state = COMMENT_ESCAPE;
600 else if (strchr(newline, c)) {
617 SINGLE_QUOTE_VALUE_ESCAPE,
619 DOUBLE_QUOTE_VALUE_ESCAPE)) {
627 if (last_value_whitespace != (size_t) -1)
628 value[last_value_whitespace] = 0;
630 /* strip trailing whitespace from key */
631 if (last_key_whitespace != (size_t) -1)
632 key[last_key_whitespace] = 0;
634 r = push(fname, line, key, value, userdata, n_pushed);
646 static int check_utf8ness_and_warn(
647 const char *filename, unsigned line,
648 const char *key, char *value) {
650 if (!utf8_is_valid(key)) {
651 _cleanup_free_ char *p = NULL;
653 p = utf8_escape_invalid(key);
654 log_error("%s:%u: invalid UTF-8 in key '%s', ignoring.", strna(filename), line, p);
658 if (value && !utf8_is_valid(value)) {
659 _cleanup_free_ char *p = NULL;
661 p = utf8_escape_invalid(value);
662 log_error("%s:%u: invalid UTF-8 value for key %s: '%s', ignoring.", strna(filename), line, key, p);
669 static int parse_env_file_push(
670 const char *filename, unsigned line,
671 const char *key, char *value,
676 va_list aq, *ap = userdata;
679 r = check_utf8ness_and_warn(filename, line, key, value);
685 while ((k = va_arg(aq, const char *))) {
688 v = va_arg(aq, char **);
710 const char *newline, ...) {
718 va_start(ap, newline);
719 r = parse_env_file_internal(NULL, fname, newline, parse_env_file_push, &ap, &n_pushed);
722 return r < 0 ? r : n_pushed;
725 #if 0 /// UNNEEDED by elogind
726 static int load_env_file_push(
727 const char *filename, unsigned line,
728 const char *key, char *value,
731 char ***m = userdata;
735 r = check_utf8ness_and_warn(filename, line, key, value);
739 p = strjoin(key, "=", value);
743 r = strv_env_replace(m, p);
756 int load_env_file(FILE *f, const char *fname, const char *newline, char ***rl) {
763 r = parse_env_file_internal(f, fname, newline, load_env_file_push, &m, NULL);
774 static int load_env_file_push_pairs(
775 const char *filename, unsigned line,
776 const char *key, char *value,
779 char ***m = userdata;
782 r = check_utf8ness_and_warn(filename, line, key, value);
786 r = strv_extend(m, key);
791 r = strv_extend(m, "");
795 r = strv_push(m, value);
806 int load_env_file_pairs(FILE *f, const char *fname, const char *newline, char ***rl) {
813 r = parse_env_file_internal(f, fname, newline, load_env_file_push_pairs, &m, NULL);
822 #if 0 /// UNNEEDED by elogind
824 static int merge_env_file_push(
825 const char *filename, unsigned line,
826 const char *key, char *value,
830 char ***env = userdata;
831 char *expanded_value;
836 log_error("%s:%u: invalid syntax (around \"%s\"), ignoring.", strna(filename), line, key);
840 if (!env_name_is_valid(key)) {
841 log_error("%s:%u: invalid variable name \"%s\", ignoring.", strna(filename), line, key);
846 expanded_value = replace_env(value, *env,
847 REPLACE_ENV_USE_ENVIRONMENT|
848 REPLACE_ENV_ALLOW_BRACELESS|
849 REPLACE_ENV_ALLOW_EXTENDED);
853 free_and_replace(value, expanded_value);
855 return load_env_file_push(filename, line, key, value, env, n_pushed);
863 /* NOTE: this function supports braceful and braceless variable expansions,
864 * plus "extended" substitutions, unlike other exported parsing functions.
867 return parse_env_file_internal(f, fname, NEWLINE, merge_env_file_push, env, NULL);
870 static void write_env_var(FILE *f, const char *v) {
876 fputs_unlocked(v, f);
877 fputc_unlocked('\n', f);
882 fwrite_unlocked(v, 1, p-v, f);
884 if (string_has_cc(p, NULL) || chars_intersect(p, WHITESPACE SHELL_NEED_QUOTES)) {
885 fputc_unlocked('\"', f);
888 if (strchr(SHELL_NEED_ESCAPE, *p))
889 fputc_unlocked('\\', f);
891 fputc_unlocked(*p, f);
894 fputc_unlocked('\"', f);
896 fputs_unlocked(p, f);
898 fputc_unlocked('\n', f);
901 int write_env_file(const char *fname, char **l) {
902 _cleanup_fclose_ FILE *f = NULL;
903 _cleanup_free_ char *p = NULL;
909 r = fopen_temporary(fname, &f, &p);
913 (void) __fsetlocking(f, FSETLOCKING_BYCALLER);
914 (void) fchmod_umask(fileno(f), 0644);
917 write_env_var(f, *i);
919 r = fflush_and_check(f);
921 if (rename(p, fname) >= 0)
931 int executable_is_script(const char *path, char **interpreter) {
932 _cleanup_free_ char *line = NULL;
939 r = read_one_line_file(path, &line);
940 if (r == -ENOBUFS) /* First line overly long? if so, then it's not a script */
945 if (!startswith(line, "#!"))
948 ans = strstrip(line + 2);
949 len = strcspn(ans, " \t");
954 ans = strndup(ans, len);
964 * Retrieve one field from a file like /proc/self/status. pattern
965 * should not include whitespace or the delimiter (':'). pattern matches only
966 * the beginning of a line. Whitespace before ':' is skipped. Whitespace and
967 * zeros after the ':' will be skipped. field must be freed afterwards.
968 * terminator specifies the terminating characters of the field value (not
969 * included in the value).
971 int get_proc_field(const char *filename, const char *pattern, const char *terminator, char **field) {
972 _cleanup_free_ char *status = NULL;
982 r = read_full_file(filename, &status, NULL);
992 t = strstr(t, pattern);
996 /* Check that pattern occurs in beginning of line. */
997 pattern_ok = (t == status || t[-1] == '\n');
999 t += strlen(pattern);
1001 } while (!pattern_ok);
1003 t += strspn(t, " \t");
1007 } while (*t != ':');
1012 t += strspn(t, " \t");
1014 /* Also skip zeros, because when this is used for
1015 * capabilities, we don't want the zeros. This way the
1016 * same capability set always maps to the same string,
1017 * irrespective of the total capability set size. For
1018 * other numbers it shouldn't matter. */
1019 t += strspn(t, "0");
1020 /* Back off one char if there's nothing but whitespace
1022 if (!*t || isspace(*t))
1026 len = strcspn(t, terminator);
1028 f = strndup(t, len);
1036 DIR *xopendirat(int fd, const char *name, int flags) {
1040 assert(!(flags & O_CREAT));
1042 nfd = openat(fd, name, O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC|flags, 0);
1055 #if 0 /// UNNEEDED by elogind
1056 static int search_and_fopen_internal(const char *path, const char *mode, const char *root, char **search, FILE **_f) {
1063 if (!path_strv_resolve_uniq(search, root))
1066 STRV_FOREACH(i, search) {
1067 _cleanup_free_ char *p = NULL;
1071 p = strjoin(root, *i, "/", path);
1073 p = strjoin(*i, "/", path);
1083 if (errno != ENOENT)
1090 int search_and_fopen(const char *path, const char *mode, const char *root, const char **search, FILE **_f) {
1091 _cleanup_strv_free_ char **copy = NULL;
1097 if (path_is_absolute(path)) {
1100 f = fopen(path, mode);
1109 copy = strv_copy((char**) search);
1113 return search_and_fopen_internal(path, mode, root, copy, _f);
1116 int search_and_fopen_nulstr(const char *path, const char *mode, const char *root, const char *search, FILE **_f) {
1117 _cleanup_strv_free_ char **s = NULL;
1119 if (path_is_absolute(path)) {
1122 f = fopen(path, mode);
1131 s = strv_split_nulstr(search);
1135 return search_and_fopen_internal(path, mode, root, s, _f);
1139 int fopen_temporary(const char *path, FILE **_f, char **_temp_path) {
1148 r = tempfn_xxxxxx(path, NULL, &t);
1152 fd = mkostemp_safe(t);
1158 f = fdopen(fd, "we");
1172 int fflush_and_check(FILE *f) {
1179 return errno > 0 ? -errno : -EIO;
1184 int fflush_sync_and_check(FILE *f) {
1189 r = fflush_and_check(f);
1193 if (fsync(fileno(f)) < 0)
1199 /* This is much like mkostemp() but is subject to umask(). */
1200 int mkostemp_safe(char *pattern) {
1201 _cleanup_umask_ mode_t u = 0;
1208 fd = mkostemp(pattern, O_CLOEXEC);
1215 int tempfn_xxxxxx(const char *p, const char *extra, char **ret) {
1227 * /foo/bar/.#<extra>waldoXXXXXX
1231 if (!filename_is_valid(fn))
1234 extra = strempty(extra);
1236 t = new(char, strlen(p) + 2 + strlen(extra) + 6 + 1);
1240 strcpy(stpcpy(stpcpy(stpcpy(mempcpy(t, p, fn - p), ".#"), extra), fn), "XXXXXX");
1242 *ret = path_kill_slashes(t);
1246 int tempfn_random(const char *p, const char *extra, char **ret) {
1260 * /foo/bar/.#<extra>waldobaa2a261115984a9
1264 if (!filename_is_valid(fn))
1267 extra = strempty(extra);
1269 t = new(char, strlen(p) + 2 + strlen(extra) + 16 + 1);
1273 x = stpcpy(stpcpy(stpcpy(mempcpy(t, p, fn - p), ".#"), extra), fn);
1276 for (i = 0; i < 16; i++) {
1277 *(x++) = hexchar(u & 0xF);
1283 *ret = path_kill_slashes(t);
1287 #if 0 /// UNNEEDED by elogind
1288 int tempfn_random_child(const char *p, const char *extra, char **ret) {
1299 * /foo/bar/waldo/.#<extra>3c2b6219aa75d7d0
1308 extra = strempty(extra);
1310 t = new(char, strlen(p) + 3 + strlen(extra) + 16 + 1);
1314 x = stpcpy(stpcpy(stpcpy(t, p), "/.#"), extra);
1317 for (i = 0; i < 16; i++) {
1318 *(x++) = hexchar(u & 0xF);
1324 *ret = path_kill_slashes(t);
1328 int write_timestamp_file_atomic(const char *fn, usec_t n) {
1329 char ln[DECIMAL_STR_MAX(n)+2];
1331 /* Creates a "timestamp" file, that contains nothing but a
1332 * usec_t timestamp, formatted in ASCII. */
1334 if (n <= 0 || n >= USEC_INFINITY)
1337 xsprintf(ln, USEC_FMT "\n", n);
1339 return write_string_file(fn, ln, WRITE_STRING_FILE_CREATE|WRITE_STRING_FILE_ATOMIC);
1342 int read_timestamp_file(const char *fn, usec_t *ret) {
1343 _cleanup_free_ char *ln = NULL;
1347 r = read_one_line_file(fn, &ln);
1351 r = safe_atou64(ln, &t);
1355 if (t <= 0 || t >= (uint64_t) USEC_INFINITY)
1362 int fputs_with_space(FILE *f, const char *s, const char *separator, bool *space) {
1367 /* Outputs the specified string with fputs(), but optionally prefixes it with a separator. The *space parameter
1368 * when specified shall initially point to a boolean variable initialized to false. It is set to true after the
1369 * first invocation. This call is supposed to be use in loops, where a separator shall be inserted between each
1370 * element, but not before the first one. */
1380 r = fputs(separator, f);
1392 int open_tmpfile_unlinkable(const char *directory, int flags) {
1397 r = tmp_dir(&directory);
1402 /* Returns an unlinked temporary file that cannot be linked into the file system anymore */
1404 /* Try O_TMPFILE first, if it is supported */
1405 fd = open(directory, flags|O_TMPFILE|O_EXCL, S_IRUSR|S_IWUSR);
1409 /* Fall back to unguessable name + unlinking */
1410 p = strjoina(directory, "/systemd-tmp-XXXXXX");
1412 fd = mkostemp_safe(p);
1421 #if 0 /// UNNEEDED by elogind
1422 int open_tmpfile_linkable(const char *target, int flags, char **ret_path) {
1423 _cleanup_free_ char *tmp = NULL;
1429 /* Don't allow O_EXCL, as that has a special meaning for O_TMPFILE */
1430 assert((flags & O_EXCL) == 0);
1432 /* Creates a temporary file, that shall be renamed to "target" later. If possible, this uses O_TMPFILE – in
1433 * which case "ret_path" will be returned as NULL. If not possible a the tempoary path name used is returned in
1434 * "ret_path". Use link_tmpfile() below to rename the result after writing the file in full. */
1437 _cleanup_free_ char *dn = NULL;
1439 dn = dirname_malloc(target);
1443 fd = open(dn, O_TMPFILE|flags, 0640);
1449 log_debug_errno(errno, "Failed to use O_TMPFILE on %s: %m", dn);
1452 r = tempfn_random(target, NULL, &tmp);
1456 fd = open(tmp, O_CREAT|O_EXCL|O_NOFOLLOW|O_NOCTTY|flags, 0640);
1467 int open_serialization_fd(const char *ident) {
1470 fd = memfd_create(ident, MFD_CLOEXEC);
1474 path = getpid_cached() == 1 ? "/run/systemd" : "/tmp";
1475 fd = open_tmpfile_unlinkable(path, O_RDWR|O_CLOEXEC);
1479 log_debug("Serializing %s to %s.", ident, path);
1481 log_debug("Serializing %s to memfd.", ident);
1486 #if 0 /// UNNEEDED by elogind
1487 int link_tmpfile(int fd, const char *path, const char *target) {
1492 /* Moves a temporary file created with open_tmpfile() above into its final place. if "path" is NULL an fd
1493 * created with O_TMPFILE is assumed, and linkat() is used. Otherwise it is assumed O_TMPFILE is not supported
1494 * on the directory, and renameat2() is used instead.
1496 * Note that in both cases we will not replace existing files. This is because linkat() does not support this
1497 * operation currently (renameat2() does), and there is no nice way to emulate this. */
1500 if (rename_noreplace(AT_FDCWD, path, AT_FDCWD, target) < 0)
1503 char proc_fd_path[STRLEN("/proc/self/fd/") + DECIMAL_STR_MAX(fd) + 1];
1505 xsprintf(proc_fd_path, "/proc/self/fd/%i", fd);
1507 if (linkat(AT_FDCWD, proc_fd_path, AT_FDCWD, target, AT_SYMLINK_FOLLOW) < 0)
1514 int read_nul_string(FILE *f, char **ret) {
1515 _cleanup_free_ char *x = NULL;
1516 size_t allocated = 0, n = 0;
1521 /* Reads a NUL-terminated string from the specified file. */
1526 if (!GREEDY_REALLOC(x, allocated, n+2))
1530 if (c == 0) /* Terminate at NUL byte */
1535 break; /* Terminate at EOF */
1555 int mkdtemp_malloc(const char *template, char **ret) {
1561 p = strdup(template);
1575 DEFINE_TRIVIAL_CLEANUP_FUNC(FILE*, funlockfile);
1577 int read_line(FILE *f, size_t limit, char **ret) {
1578 _cleanup_free_ char *buffer = NULL;
1579 size_t n = 0, allocated = 0, count = 0;
1583 /* Something like a bounded version of getline().
1585 * Considers EOF, \n and \0 end of line delimiters, and does not include these delimiters in the string
1588 * Returns the number of bytes read from the files (i.e. including delimiters — this hence usually differs from
1589 * the number of characters in the returned string). When EOF is hit, 0 is returned.
1591 * The input parameter limit is the maximum numbers of characters in the returned string, i.e. excluding
1592 * delimiters. If the limit is hit we fail and return -ENOBUFS.
1594 * If a line shall be skipped ret may be initialized as NULL. */
1597 if (!GREEDY_REALLOC(buffer, allocated, 1))
1602 _unused_ _cleanup_(funlockfilep) FILE *flocked = f;
1612 c = fgetc_unlocked(f);
1614 /* if we read an error, and have no data to return, then propagate the error */
1615 if (ferror_unlocked(f) && n == 0)
1616 return errno > 0 ? -errno : -EIO;
1623 if (IN_SET(c, '\n', 0)) /* Reached a delimiter */
1627 if (!GREEDY_REALLOC(buffer, allocated, n + 2))
1630 buffer[n] = (char) c;