]> git.ipfire.org Git - thirdparty/systemd.git/blobdiff - src/basic/fileio.c
Add open_memstream_unlocked() wrapper
[thirdparty/systemd.git] / src / basic / fileio.c
index 7196516b9e4012d30680e6c6c1a1fcd3ce43d4ca..99efc2410c9ddcb7ac7050faed2b0964830c47d2 100644 (file)
@@ -17,6 +17,7 @@
 #include "fd-util.h"
 #include "fileio.h"
 #include "fs-util.h"
+#include "hexdecoct.h"
 #include "log.h"
 #include "macro.h"
 #include "missing.h"
 
 #define READ_FULL_BYTES_MAX (4U*1024U*1024U)
 
+int fopen_unlocked(const char *path, const char *options, FILE **ret) {
+        assert(ret);
+
+        FILE *f = fopen(path, options);
+        if (!f)
+                return -errno;
+
+        (void) __fsetlocking(f, FSETLOCKING_BYCALLER);
+
+        *ret = f;
+        return 0;
+}
+
+int fdopen_unlocked(int fd, const char *options, FILE **ret) {
+        assert(ret);
+
+        FILE *f = fdopen(fd, options);
+        if (!f)
+                return -errno;
+
+        (void) __fsetlocking(f, FSETLOCKING_BYCALLER);
+
+        *ret = f;
+        return 0;
+}
+
+FILE* open_memstream_unlocked(char **ptr, size_t *sizeloc) {
+        FILE *f = open_memstream(ptr, sizeloc);
+        if (!f)
+                return NULL;
+
+        (void) __fsetlocking(f, FSETLOCKING_BYCALLER);
+
+        return f;
+}
+
 int write_string_stream_ts(
                 FILE *f,
                 const char *line,
@@ -94,7 +131,6 @@ static int write_string_file_atomic(
         if (r < 0)
                 return r;
 
-        (void) __fsetlocking(f, FSETLOCKING_BYCALLER);
         (void) fchmod_umask(fileno(f), 0644);
 
         r = write_string_stream_ts(f, line, flags, ts);
@@ -140,11 +176,9 @@ int write_string_file_ts(
                 assert(!ts);
 
         if (flags & WRITE_STRING_FILE_CREATE) {
-                f = fopen(fn, "we");
-                if (!f) {
-                        r = -errno;
+                r = fopen_unlocked(fn, "we", &f);
+                if (r < 0)
                         goto fail;
-                }
         } else {
                 int fd;
 
@@ -156,16 +190,13 @@ int write_string_file_ts(
                         goto fail;
                 }
 
-                f = fdopen(fd, "w");
-                if (!f) {
-                        r = -errno;
+                r = fdopen_unlocked(fd, "w", &f);
+                if (r < 0) {
                         safe_close(fd);
                         goto fail;
                 }
         }
 
-        (void) __fsetlocking(f, FSETLOCKING_BYCALLER);
-
         if (flags & WRITE_STRING_FILE_DISABLE_BUFFER)
                 setvbuf(f, NULL, _IONBF, 0);
 
@@ -212,15 +243,14 @@ int write_string_filef(
 
 int read_one_line_file(const char *fn, char **line) {
         _cleanup_fclose_ FILE *f = NULL;
+        int r;
 
         assert(fn);
         assert(line);
 
-        f = fopen(fn, "re");
-        if (!f)
-                return -errno;
-
-        (void) __fsetlocking(f, FSETLOCKING_BYCALLER);
+        r = fopen_unlocked(fn, "re", &f);
+        if (r < 0)
+                return r;
 
         return read_line(f, LONG_LINE_MAX, line);
 }
@@ -229,6 +259,7 @@ int verify_file(const char *fn, const char *blob, bool accept_extra_nl) {
         _cleanup_fclose_ FILE *f = NULL;
         _cleanup_free_ char *buf = NULL;
         size_t l, k;
+        int r;
 
         assert(fn);
         assert(blob);
@@ -242,11 +273,9 @@ int verify_file(const char *fn, const char *blob, bool accept_extra_nl) {
         if (!buf)
                 return -ENOMEM;
 
-        f = fopen(fn, "re");
-        if (!f)
-                return -errno;
-
-        (void) __fsetlocking(f, FSETLOCKING_BYCALLER);
+        r = fopen_unlocked(fn, "re", &f);
+        if (r < 0)
+                return r;
 
         /* We try to read one byte more than we need, so that we know whether we hit eof */
         errno = 0;
@@ -266,6 +295,7 @@ int verify_file(const char *fn, const char *blob, bool accept_extra_nl) {
 
 int read_full_stream_full(
                 FILE *f,
+                const char *filename,
                 ReadFullFileFlags flags,
                 char **ret_contents,
                 size_t *ret_size) {
@@ -277,6 +307,7 @@ int read_full_stream_full(
 
         assert(f);
         assert(ret_contents);
+        assert(!(flags & READ_FULL_FILE_UNBASE64) || ret_size);
 
         n_next = LINE_MAX; /* Start size */
 
@@ -298,6 +329,9 @@ int read_full_stream_full(
                          * already makes us notice the EOF. */
                         if (st.st_size > 0)
                                 n_next = st.st_size + 1;
+
+                        if (flags & READ_FULL_FILE_SECURE)
+                                (void) warn_file_is_world_accessible(filename, &st, NULL, 0);
                 }
         }
 
@@ -350,6 +384,12 @@ int read_full_stream_full(
                 n_next = MIN(n * 2, READ_FULL_BYTES_MAX);
         }
 
+        if (flags & READ_FULL_FILE_UNBASE64) {
+                buf[l++] = 0;
+                r = unbase64mem_full(buf, l, flags & READ_FULL_FILE_SECURE, (void **) ret_contents, ret_size);
+                goto finalize;
+        }
+
         if (!ret_size) {
                 /* Safety check: if the caller doesn't want to know the size of what we just read it will rely on the
                  * trailing NUL byte. But if there's an embedded NUL byte, then we should refuse operation as otherwise
@@ -378,17 +418,16 @@ finalize:
 
 int read_full_file_full(const char *filename, ReadFullFileFlags flags, char **contents, size_t *size) {
         _cleanup_fclose_ FILE *f = NULL;
+        int r;
 
         assert(filename);
         assert(contents);
 
-        f = fopen(filename, "re");
-        if (!f)
-                return -errno;
-
-        (void) __fsetlocking(f, FSETLOCKING_BYCALLER);
+        r = fopen_unlocked(filename, "re", &f);
+        if (r < 0)
+                return r;
 
-        return read_full_stream_full(f, flags, contents, size);
+        return read_full_stream_full(f, filename, flags, contents, size);
 }
 
 int executable_is_script(const char *path, char **interpreter) {