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/>.
30 #include <sys/types.h>
33 #include "alloc-util.h"
41 #include "hexdecoct.h"
45 #include "parse-util.h"
46 #include "path-util.h"
47 #include "process-util.h"
48 #include "random-util.h"
49 #include "stdio-util.h"
50 #include "string-util.h"
52 #include "time-util.h"
53 #include "umask-util.h"
56 #define READ_FULL_BYTES_MAX (4U*1024U*1024U)
58 int write_string_stream_ts(
61 WriteStringFileFlags flags
,
62 struct timespec
*ts
) {
68 if (!(flags
& WRITE_STRING_FILE_AVOID_NEWLINE
) && !endswith(line
, "\n"))
72 struct timespec twice
[2] = {*ts
, *ts
};
74 if (futimens(fileno(f
), twice
) < 0)
78 if (flags
& WRITE_STRING_FILE_SYNC
)
79 return fflush_sync_and_check(f
);
81 return fflush_and_check(f
);
84 static int write_string_file_atomic(
87 WriteStringFileFlags flags
,
88 struct timespec
*ts
) {
90 _cleanup_fclose_
FILE *f
= NULL
;
91 _cleanup_free_
char *p
= NULL
;
97 r
= fopen_temporary(fn
, &f
, &p
);
101 (void) fchmod_umask(fileno(f
), 0644);
103 r
= write_string_stream_ts(f
, line
, flags
, ts
);
107 if (rename(p
, fn
) < 0) {
119 int write_string_file_ts(
122 WriteStringFileFlags flags
,
123 struct timespec
*ts
) {
125 _cleanup_fclose_
FILE *f
= NULL
;
131 /* We don't know how to verify whether the file contents was already on-disk. */
132 assert(!((flags
& WRITE_STRING_FILE_VERIFY_ON_FAILURE
) && (flags
& WRITE_STRING_FILE_SYNC
)));
134 if (flags
& WRITE_STRING_FILE_ATOMIC
) {
135 assert(flags
& WRITE_STRING_FILE_CREATE
);
137 r
= write_string_file_atomic(fn
, line
, flags
, ts
);
145 if (flags
& WRITE_STRING_FILE_CREATE
) {
154 /* We manually build our own version of fopen(..., "we") that
155 * works without O_CREAT */
156 fd
= open(fn
, O_WRONLY
|O_CLOEXEC
|O_NOCTTY
);
162 f
= fdopen(fd
, "we");
170 if (flags
& WRITE_STRING_FILE_DISABLE_BUFFER
)
171 setvbuf(f
, NULL
, _IONBF
, 0);
173 r
= write_string_stream_ts(f
, line
, flags
, ts
);
180 if (!(flags
& WRITE_STRING_FILE_VERIFY_ON_FAILURE
))
185 /* OK, the operation failed, but let's see if the right
186 * contents in place already. If so, eat up the error. */
188 q
= verify_file(fn
, line
, !(flags
& WRITE_STRING_FILE_AVOID_NEWLINE
));
195 int read_one_line_file(const char *fn
, char **line
) {
196 _cleanup_fclose_
FILE *f
= NULL
;
206 r
= read_line(f
, LONG_LINE_MAX
, line
);
207 return r
< 0 ? r
: 0;
210 int verify_file(const char *fn
, const char *blob
, bool accept_extra_nl
) {
211 _cleanup_fclose_
FILE *f
= NULL
;
212 _cleanup_free_
char *buf
= NULL
;
220 if (accept_extra_nl
&& endswith(blob
, "\n"))
221 accept_extra_nl
= false;
223 buf
= malloc(l
+ accept_extra_nl
+ 1);
231 /* We try to read one byte more than we need, so that we know whether we hit eof */
233 k
= fread(buf
, 1, l
+ accept_extra_nl
+ 1, f
);
235 return errno
> 0 ? -errno
: -EIO
;
237 if (k
!= l
&& k
!= l
+ accept_extra_nl
)
239 if (memcmp(buf
, blob
, l
) != 0)
241 if (k
> l
&& buf
[l
] != '\n')
247 int read_full_stream(FILE *f
, char **contents
, size_t *size
) {
249 _cleanup_free_
char *buf
= NULL
;
255 if (fstat(fileno(f
), &st
) < 0)
260 if (S_ISREG(st
.st_mode
)) {
263 if (st
.st_size
> READ_FULL_BYTES_MAX
)
266 /* Start with the right file size, but be prepared for files from /proc which generally report a file
267 * size of 0. Note that we increase the size to read here by one, so that the first read attempt
268 * already makes us notice the EOF. */
278 t
= realloc(buf
, n
+ 1);
284 k
= fread(buf
+ l
, 1, n
- l
, f
);
289 return errno
> 0 ? -errno
: -EIO
;
294 /* We aren't expecting fread() to return a short read outside
295 * of (error && eof), assert buffer is full and enlarge buffer.
300 if (n
>= READ_FULL_BYTES_MAX
)
303 n
= MIN(n
* 2, READ_FULL_BYTES_MAX
);
308 buf
= NULL
; /* do not free */
316 int read_full_file(const char *fn
, char **contents
, size_t *size
) {
317 _cleanup_fclose_
FILE *f
= NULL
;
326 return read_full_stream(f
, contents
, size
);
329 static int parse_env_file_internal(
333 int (*push
) (const char *filename
, unsigned line
,
334 const char *key
, char *value
, void *userdata
, int *n_pushed
),
338 _cleanup_free_
char *contents
= NULL
, *key
= NULL
;
339 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;
340 char *p
, *value
= NULL
;
351 SINGLE_QUOTE_VALUE_ESCAPE
,
353 DOUBLE_QUOTE_VALUE_ESCAPE
,
361 r
= read_full_stream(f
, &contents
, NULL
);
363 r
= read_full_file(fname
, &contents
, NULL
);
367 for (p
= contents
; *p
; p
++) {
373 if (strchr(COMMENTS
, c
))
375 else if (!strchr(WHITESPACE
, c
)) {
377 last_key_whitespace
= (size_t) -1;
379 if (!GREEDY_REALLOC(key
, key_alloc
, n_key
+2)) {
389 if (strchr(newline
, c
)) {
393 } else if (c
== '=') {
395 last_value_whitespace
= (size_t) -1;
397 if (!strchr(WHITESPACE
, c
))
398 last_key_whitespace
= (size_t) -1;
399 else if (last_key_whitespace
== (size_t) -1)
400 last_key_whitespace
= n_key
;
402 if (!GREEDY_REALLOC(key
, key_alloc
, n_key
+2)) {
413 if (strchr(newline
, c
)) {
421 /* strip trailing whitespace from key */
422 if (last_key_whitespace
!= (size_t) -1)
423 key
[last_key_whitespace
] = 0;
425 r
= push(fname
, line
, key
, value
, userdata
, n_pushed
);
431 value_alloc
= n_value
= 0;
433 } else if (c
== '\'')
434 state
= SINGLE_QUOTE_VALUE
;
436 state
= DOUBLE_QUOTE_VALUE
;
438 state
= VALUE_ESCAPE
;
439 else if (!strchr(WHITESPACE
, c
)) {
442 if (!GREEDY_REALLOC(value
, value_alloc
, n_value
+2)) {
447 value
[n_value
++] = c
;
453 if (strchr(newline
, c
)) {
462 /* Chomp off trailing whitespace from value */
463 if (last_value_whitespace
!= (size_t) -1)
464 value
[last_value_whitespace
] = 0;
466 /* strip trailing whitespace from key */
467 if (last_key_whitespace
!= (size_t) -1)
468 key
[last_key_whitespace
] = 0;
470 r
= push(fname
, line
, key
, value
, userdata
, n_pushed
);
476 value_alloc
= n_value
= 0;
478 } else if (c
== '\\') {
479 state
= VALUE_ESCAPE
;
480 last_value_whitespace
= (size_t) -1;
482 if (!strchr(WHITESPACE
, c
))
483 last_value_whitespace
= (size_t) -1;
484 else if (last_value_whitespace
== (size_t) -1)
485 last_value_whitespace
= n_value
;
487 if (!GREEDY_REALLOC(value
, value_alloc
, n_value
+2)) {
492 value
[n_value
++] = c
;
500 if (!strchr(newline
, c
)) {
501 /* Escaped newlines we eat up entirely */
502 if (!GREEDY_REALLOC(value
, value_alloc
, n_value
+2)) {
507 value
[n_value
++] = c
;
511 case SINGLE_QUOTE_VALUE
:
515 state
= SINGLE_QUOTE_VALUE_ESCAPE
;
517 if (!GREEDY_REALLOC(value
, value_alloc
, n_value
+2)) {
522 value
[n_value
++] = c
;
527 case SINGLE_QUOTE_VALUE_ESCAPE
:
528 state
= SINGLE_QUOTE_VALUE
;
530 if (!strchr(newline
, c
)) {
531 if (!GREEDY_REALLOC(value
, value_alloc
, n_value
+2)) {
536 value
[n_value
++] = c
;
540 case DOUBLE_QUOTE_VALUE
:
544 state
= DOUBLE_QUOTE_VALUE_ESCAPE
;
546 if (!GREEDY_REALLOC(value
, value_alloc
, n_value
+2)) {
551 value
[n_value
++] = c
;
556 case DOUBLE_QUOTE_VALUE_ESCAPE
:
557 state
= DOUBLE_QUOTE_VALUE
;
559 if (!strchr(newline
, c
)) {
560 if (!GREEDY_REALLOC(value
, value_alloc
, n_value
+2)) {
565 value
[n_value
++] = c
;
571 state
= COMMENT_ESCAPE
;
572 else if (strchr(newline
, c
)) {
589 SINGLE_QUOTE_VALUE_ESCAPE
,
591 DOUBLE_QUOTE_VALUE_ESCAPE
)) {
599 if (last_value_whitespace
!= (size_t) -1)
600 value
[last_value_whitespace
] = 0;
602 /* strip trailing whitespace from key */
603 if (last_key_whitespace
!= (size_t) -1)
604 key
[last_key_whitespace
] = 0;
606 r
= push(fname
, line
, key
, value
, userdata
, n_pushed
);
618 static int check_utf8ness_and_warn(
619 const char *filename
, unsigned line
,
620 const char *key
, char *value
) {
622 if (!utf8_is_valid(key
)) {
623 _cleanup_free_
char *p
= NULL
;
625 p
= utf8_escape_invalid(key
);
626 log_error("%s:%u: invalid UTF-8 in key '%s', ignoring.", strna(filename
), line
, p
);
630 if (value
&& !utf8_is_valid(value
)) {
631 _cleanup_free_
char *p
= NULL
;
633 p
= utf8_escape_invalid(value
);
634 log_error("%s:%u: invalid UTF-8 value for key %s: '%s', ignoring.", strna(filename
), line
, key
, p
);
641 static int parse_env_file_push(
642 const char *filename
, unsigned line
,
643 const char *key
, char *value
,
648 va_list aq
, *ap
= userdata
;
651 r
= check_utf8ness_and_warn(filename
, line
, key
, value
);
657 while ((k
= va_arg(aq
, const char *))) {
660 v
= va_arg(aq
, char **);
682 const char *newline
, ...) {
690 va_start(ap
, newline
);
691 r
= parse_env_file_internal(NULL
, fname
, newline
, parse_env_file_push
, &ap
, &n_pushed
);
694 return r
< 0 ? r
: n_pushed
;
697 static int load_env_file_push(
698 const char *filename
, unsigned line
,
699 const char *key
, char *value
,
702 char ***m
= userdata
;
706 r
= check_utf8ness_and_warn(filename
, line
, key
, value
);
710 p
= strjoin(key
, "=", value
);
714 r
= strv_env_replace(m
, p
);
727 int load_env_file(FILE *f
, const char *fname
, const char *newline
, char ***rl
) {
734 r
= parse_env_file_internal(f
, fname
, newline
, load_env_file_push
, &m
, NULL
);
744 static int load_env_file_push_pairs(
745 const char *filename
, unsigned line
,
746 const char *key
, char *value
,
749 char ***m
= userdata
;
752 r
= check_utf8ness_and_warn(filename
, line
, key
, value
);
756 r
= strv_extend(m
, key
);
761 r
= strv_extend(m
, "");
765 r
= strv_push(m
, value
);
776 int load_env_file_pairs(FILE *f
, const char *fname
, const char *newline
, char ***rl
) {
783 r
= parse_env_file_internal(f
, fname
, newline
, load_env_file_push_pairs
, &m
, NULL
);
793 static int merge_env_file_push(
794 const char *filename
, unsigned line
,
795 const char *key
, char *value
,
799 char ***env
= userdata
;
800 char *expanded_value
;
805 log_error("%s:%u: invalid syntax (around \"%s\"), ignoring.", strna(filename
), line
, key
);
809 if (!env_name_is_valid(key
)) {
810 log_error("%s:%u: invalid variable name \"%s\", ignoring.", strna(filename
), line
, key
);
815 expanded_value
= replace_env(value
, *env
,
816 REPLACE_ENV_USE_ENVIRONMENT
|
817 REPLACE_ENV_ALLOW_BRACELESS
|
818 REPLACE_ENV_ALLOW_EXTENDED
);
822 free_and_replace(value
, expanded_value
);
824 return load_env_file_push(filename
, line
, key
, value
, env
, n_pushed
);
832 /* NOTE: this function supports braceful and braceless variable expansions,
833 * plus "extended" substitutions, unlike other exported parsing functions.
836 return parse_env_file_internal(f
, fname
, NEWLINE
, merge_env_file_push
, env
, NULL
);
839 static void write_env_var(FILE *f
, const char *v
) {
845 fputs_unlocked(v
, f
);
846 fputc_unlocked('\n', f
);
851 fwrite_unlocked(v
, 1, p
-v
, f
);
853 if (string_has_cc(p
, NULL
) || chars_intersect(p
, WHITESPACE SHELL_NEED_QUOTES
)) {
854 fputc_unlocked('\"', f
);
857 if (strchr(SHELL_NEED_ESCAPE
, *p
))
858 fputc_unlocked('\\', f
);
860 fputc_unlocked(*p
, f
);
863 fputc_unlocked('\"', f
);
865 fputs_unlocked(p
, f
);
867 fputc_unlocked('\n', f
);
870 int write_env_file(const char *fname
, char **l
) {
871 _cleanup_fclose_
FILE *f
= NULL
;
872 _cleanup_free_
char *p
= NULL
;
878 r
= fopen_temporary(fname
, &f
, &p
);
882 fchmod_umask(fileno(f
), 0644);
885 write_env_var(f
, *i
);
887 r
= fflush_and_check(f
);
889 if (rename(p
, fname
) >= 0)
899 int executable_is_script(const char *path
, char **interpreter
) {
901 _cleanup_free_
char *line
= NULL
;
907 r
= read_one_line_file(path
, &line
);
911 if (!startswith(line
, "#!"))
914 ans
= strstrip(line
+ 2);
915 len
= strcspn(ans
, " \t");
920 ans
= strndup(ans
, len
);
929 * Retrieve one field from a file like /proc/self/status. pattern
930 * should not include whitespace or the delimiter (':'). pattern matches only
931 * the beginning of a line. Whitespace before ':' is skipped. Whitespace and
932 * zeros after the ':' will be skipped. field must be freed afterwards.
933 * terminator specifies the terminating characters of the field value (not
934 * included in the value).
936 int get_proc_field(const char *filename
, const char *pattern
, const char *terminator
, char **field
) {
937 _cleanup_free_
char *status
= NULL
;
947 r
= read_full_file(filename
, &status
, NULL
);
957 t
= strstr(t
, pattern
);
961 /* Check that pattern occurs in beginning of line. */
962 pattern_ok
= (t
== status
|| t
[-1] == '\n');
964 t
+= strlen(pattern
);
966 } while (!pattern_ok
);
968 t
+= strspn(t
, " \t");
977 t
+= strspn(t
, " \t");
979 /* Also skip zeros, because when this is used for
980 * capabilities, we don't want the zeros. This way the
981 * same capability set always maps to the same string,
982 * irrespective of the total capability set size. For
983 * other numbers it shouldn't matter. */
985 /* Back off one char if there's nothing but whitespace
987 if (!*t
|| isspace(*t
))
991 len
= strcspn(t
, terminator
);
1001 DIR *xopendirat(int fd
, const char *name
, int flags
) {
1005 assert(!(flags
& O_CREAT
));
1007 nfd
= openat(fd
, name
, O_RDONLY
|O_NONBLOCK
|O_DIRECTORY
|O_CLOEXEC
|flags
, 0);
1020 static int search_and_fopen_internal(const char *path
, const char *mode
, const char *root
, char **search
, FILE **_f
) {
1027 if (!path_strv_resolve_uniq(search
, root
))
1030 STRV_FOREACH(i
, search
) {
1031 _cleanup_free_
char *p
= NULL
;
1035 p
= strjoin(root
, *i
, "/", path
);
1037 p
= strjoin(*i
, "/", path
);
1047 if (errno
!= ENOENT
)
1054 int search_and_fopen(const char *path
, const char *mode
, const char *root
, const char **search
, FILE **_f
) {
1055 _cleanup_strv_free_
char **copy
= NULL
;
1061 if (path_is_absolute(path
)) {
1064 f
= fopen(path
, mode
);
1073 copy
= strv_copy((char**) search
);
1077 return search_and_fopen_internal(path
, mode
, root
, copy
, _f
);
1080 int search_and_fopen_nulstr(const char *path
, const char *mode
, const char *root
, const char *search
, FILE **_f
) {
1081 _cleanup_strv_free_
char **s
= NULL
;
1083 if (path_is_absolute(path
)) {
1086 f
= fopen(path
, mode
);
1095 s
= strv_split_nulstr(search
);
1099 return search_and_fopen_internal(path
, mode
, root
, s
, _f
);
1102 int fopen_temporary(const char *path
, FILE **_f
, char **_temp_path
) {
1111 r
= tempfn_xxxxxx(path
, NULL
, &t
);
1115 fd
= mkostemp_safe(t
);
1121 f
= fdopen(fd
, "we");
1135 int fflush_and_check(FILE *f
) {
1142 return errno
> 0 ? -errno
: -EIO
;
1147 int fflush_sync_and_check(FILE *f
) {
1152 r
= fflush_and_check(f
);
1156 if (fsync(fileno(f
)) < 0)
1162 /* This is much like mkostemp() but is subject to umask(). */
1163 int mkostemp_safe(char *pattern
) {
1164 _cleanup_umask_ mode_t u
= 0;
1171 fd
= mkostemp(pattern
, O_CLOEXEC
);
1178 int tempfn_xxxxxx(const char *p
, const char *extra
, char **ret
) {
1190 * /foo/bar/.#<extra>waldoXXXXXX
1194 if (!filename_is_valid(fn
))
1200 t
= new(char, strlen(p
) + 2 + strlen(extra
) + 6 + 1);
1204 strcpy(stpcpy(stpcpy(stpcpy(mempcpy(t
, p
, fn
- p
), ".#"), extra
), fn
), "XXXXXX");
1206 *ret
= path_kill_slashes(t
);
1210 int tempfn_random(const char *p
, const char *extra
, char **ret
) {
1224 * /foo/bar/.#<extra>waldobaa2a261115984a9
1228 if (!filename_is_valid(fn
))
1234 t
= new(char, strlen(p
) + 2 + strlen(extra
) + 16 + 1);
1238 x
= stpcpy(stpcpy(stpcpy(mempcpy(t
, p
, fn
- p
), ".#"), extra
), fn
);
1241 for (i
= 0; i
< 16; i
++) {
1242 *(x
++) = hexchar(u
& 0xF);
1248 *ret
= path_kill_slashes(t
);
1252 int tempfn_random_child(const char *p
, const char *extra
, char **ret
) {
1263 * /foo/bar/waldo/.#<extra>3c2b6219aa75d7d0
1275 t
= new(char, strlen(p
) + 3 + strlen(extra
) + 16 + 1);
1279 x
= stpcpy(stpcpy(stpcpy(t
, p
), "/.#"), extra
);
1282 for (i
= 0; i
< 16; i
++) {
1283 *(x
++) = hexchar(u
& 0xF);
1289 *ret
= path_kill_slashes(t
);
1293 int write_timestamp_file_atomic(const char *fn
, usec_t n
) {
1294 char ln
[DECIMAL_STR_MAX(n
)+2];
1296 /* Creates a "timestamp" file, that contains nothing but a
1297 * usec_t timestamp, formatted in ASCII. */
1299 if (n
<= 0 || n
>= USEC_INFINITY
)
1302 xsprintf(ln
, USEC_FMT
"\n", n
);
1304 return write_string_file(fn
, ln
, WRITE_STRING_FILE_CREATE
|WRITE_STRING_FILE_ATOMIC
);
1307 int read_timestamp_file(const char *fn
, usec_t
*ret
) {
1308 _cleanup_free_
char *ln
= NULL
;
1312 r
= read_one_line_file(fn
, &ln
);
1316 r
= safe_atou64(ln
, &t
);
1320 if (t
<= 0 || t
>= (uint64_t) USEC_INFINITY
)
1327 int fputs_with_space(FILE *f
, const char *s
, const char *separator
, bool *space
) {
1332 /* Outputs the specified string with fputs(), but optionally prefixes it with a separator. The *space parameter
1333 * when specified shall initially point to a boolean variable initialized to false. It is set to true after the
1334 * first invocation. This call is supposed to be use in loops, where a separator shall be inserted between each
1335 * element, but not before the first one. */
1345 r
= fputs(separator
, f
);
1356 int open_tmpfile_unlinkable(const char *directory
, int flags
) {
1361 r
= tmp_dir(&directory
);
1366 /* Returns an unlinked temporary file that cannot be linked into the file system anymore */
1368 /* Try O_TMPFILE first, if it is supported */
1369 fd
= open(directory
, flags
|O_TMPFILE
|O_EXCL
, S_IRUSR
|S_IWUSR
);
1373 /* Fall back to unguessable name + unlinking */
1374 p
= strjoina(directory
, "/systemd-tmp-XXXXXX");
1376 fd
= mkostemp_safe(p
);
1385 int open_tmpfile_linkable(const char *target
, int flags
, char **ret_path
) {
1386 _cleanup_free_
char *tmp
= NULL
;
1392 /* Don't allow O_EXCL, as that has a special meaning for O_TMPFILE */
1393 assert((flags
& O_EXCL
) == 0);
1395 /* Creates a temporary file, that shall be renamed to "target" later. If possible, this uses O_TMPFILE – in
1396 * which case "ret_path" will be returned as NULL. If not possible a the tempoary path name used is returned in
1397 * "ret_path". Use link_tmpfile() below to rename the result after writing the file in full. */
1400 _cleanup_free_
char *dn
= NULL
;
1402 dn
= dirname_malloc(target
);
1406 fd
= open(dn
, O_TMPFILE
|flags
, 0640);
1412 log_debug_errno(errno
, "Failed to use O_TMPFILE on %s: %m", dn
);
1415 r
= tempfn_random(target
, NULL
, &tmp
);
1419 fd
= open(tmp
, O_CREAT
|O_EXCL
|O_NOFOLLOW
|O_NOCTTY
|flags
, 0640);
1429 int open_serialization_fd(const char *ident
) {
1432 fd
= memfd_create(ident
, MFD_CLOEXEC
);
1436 path
= getpid_cached() == 1 ? "/run/systemd" : "/tmp";
1437 fd
= open_tmpfile_unlinkable(path
, O_RDWR
|O_CLOEXEC
);
1441 log_debug("Serializing %s to %s.", ident
, path
);
1443 log_debug("Serializing %s to memfd.", ident
);
1448 int link_tmpfile(int fd
, const char *path
, const char *target
) {
1453 /* Moves a temporary file created with open_tmpfile() above into its final place. if "path" is NULL an fd
1454 * created with O_TMPFILE is assumed, and linkat() is used. Otherwise it is assumed O_TMPFILE is not supported
1455 * on the directory, and renameat2() is used instead.
1457 * Note that in both cases we will not replace existing files. This is because linkat() does not support this
1458 * operation currently (renameat2() does), and there is no nice way to emulate this. */
1461 if (rename_noreplace(AT_FDCWD
, path
, AT_FDCWD
, target
) < 0)
1464 char proc_fd_path
[strlen("/proc/self/fd/") + DECIMAL_STR_MAX(fd
) + 1];
1466 xsprintf(proc_fd_path
, "/proc/self/fd/%i", fd
);
1468 if (linkat(AT_FDCWD
, proc_fd_path
, AT_FDCWD
, target
, AT_SYMLINK_FOLLOW
) < 0)
1475 int read_nul_string(FILE *f
, char **ret
) {
1476 _cleanup_free_
char *x
= NULL
;
1477 size_t allocated
= 0, n
= 0;
1482 /* Reads a NUL-terminated string from the specified file. */
1487 if (!GREEDY_REALLOC(x
, allocated
, n
+2))
1491 if (c
== 0) /* Terminate at NUL byte */
1496 break; /* Terminate at EOF */
1516 int mkdtemp_malloc(const char *template, char **ret
) {
1522 p
= strdup(template);
1535 DEFINE_TRIVIAL_CLEANUP_FUNC(FILE*, funlockfile
);
1537 int read_line(FILE *f
, size_t limit
, char **ret
) {
1538 _cleanup_free_
char *buffer
= NULL
;
1539 size_t n
= 0, allocated
= 0, count
= 0;
1543 /* Something like a bounded version of getline().
1545 * Considers EOF, \n and \0 end of line delimiters, and does not include these delimiters in the string
1548 * Returns the number of bytes read from the files (i.e. including delimiters — this hence usually differs from
1549 * the number of characters in the returned string). When EOF is hit, 0 is returned.
1551 * The input parameter limit is the maximum numbers of characters in the returned string, i.e. excluding
1552 * delimiters. If the limit is hit we fail and return -ENOBUFS.
1554 * If a line shall be skipped ret may be initialized as NULL. */
1557 if (!GREEDY_REALLOC(buffer
, allocated
, 1))
1562 _unused_
_cleanup_(funlockfilep
) FILE *flocked
= f
;
1572 c
= fgetc_unlocked(f
);
1574 /* if we read an error, and have no data to return, then propagate the error */
1575 if (ferror_unlocked(f
) && n
== 0)
1576 return errno
> 0 ? -errno
: -EIO
;
1583 if (IN_SET(c
, '\n', 0)) /* Reached a delimiter */
1587 if (!GREEDY_REALLOC(buffer
, allocated
, n
+ 2))
1590 buffer
[n
] = (char) c
;