]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
fileio: Add openat() like helpers
authorDaan De Meyer <daan.j.demeyer@gmail.com>
Mon, 26 Sep 2022 09:34:47 +0000 (11:34 +0200)
committerDaan De Meyer <daan.j.demeyer@gmail.com>
Wed, 9 Nov 2022 10:14:10 +0000 (11:14 +0100)
src/basic/fileio.c
src/basic/fileio.h

index 2c4ba89a15022a6b2c9d22e8cb2b829607edad4c..a5c44f184a9cae5c901a5d018d684217e877bdac 100644 (file)
  * can detect EOFs. */
 #define READ_VIRTUAL_BYTES_MAX (4U*1024U*1024U - 2U)
 
-int fopen_unlocked(const char *path, const char *options, FILE **ret) {
+int fopen_unlocked_at(int dir_fd, const char *path, const char *options, int flags, FILE **ret) {
+        int r;
+
         assert(ret);
 
-        FILE *f = fopen(path, options);
-        if (!f)
-                return -errno;
+        r = xfopenat(dir_fd, path, options, flags, ret);
+        if (r < 0)
+                return r;
 
-        (void) __fsetlocking(f, FSETLOCKING_BYCALLER);
+        (void) __fsetlocking(*ret, FSETLOCKING_BYCALLER);
 
-        *ret = f;
         return 0;
 }
 
@@ -209,7 +210,8 @@ int write_string_stream_ts(
         return 0;
 }
 
-static int write_string_file_atomic(
+static int write_string_file_atomic_at(
+                int dir_fd,
                 const char *fn,
                 const char *line,
                 WriteStringFileFlags flags,
@@ -225,7 +227,7 @@ static int write_string_file_atomic(
         /* Note that we'd really like to use O_TMPFILE here, but can't really, since we want replacement
          * semantics here, and O_TMPFILE can't offer that. i.e. rename() replaces but linkat() doesn't. */
 
-        r = fopen_temporary(fn, &f, &p);
+        r = fopen_temporary_at(dir_fd, fn, &f, &p);
         if (r < 0)
                 return r;
 
@@ -237,7 +239,7 @@ static int write_string_file_atomic(
         if (r < 0)
                 goto fail;
 
-        if (rename(p, fn) < 0) {
+        if (renameat(dir_fd, p, dir_fd, fn) < 0) {
                 r = -errno;
                 goto fail;
         }
@@ -252,11 +254,12 @@ static int write_string_file_atomic(
         return 0;
 
 fail:
-        (void) unlink(p);
+        (void) unlinkat(dir_fd, p, 0);
         return r;
 }
 
-int write_string_file_ts(
+int write_string_file_ts_at(
+                int dir_fd,
                 const char *fn,
                 const char *line,
                 WriteStringFileFlags flags,
@@ -272,7 +275,7 @@ int write_string_file_ts(
         assert(!((flags & WRITE_STRING_FILE_VERIFY_ON_FAILURE) && (flags & WRITE_STRING_FILE_SYNC)));
 
         if (flags & WRITE_STRING_FILE_MKDIR_0755) {
-                r = mkdir_parents(fn, 0755);
+                r = mkdirat_parents(dir_fd, fn, 0755);
                 if (r < 0)
                         return r;
         }
@@ -280,7 +283,7 @@ int write_string_file_ts(
         if (flags & WRITE_STRING_FILE_ATOMIC) {
                 assert(flags & WRITE_STRING_FILE_CREATE);
 
-                r = write_string_file_atomic(fn, line, flags, ts);
+                r = write_string_file_atomic_at(dir_fd, fn, line, flags, ts);
                 if (r < 0)
                         goto fail;
 
@@ -289,12 +292,12 @@ int write_string_file_ts(
                 assert(!ts);
 
         /* We manually build our own version of fopen(..., "we") that works without O_CREAT and with O_NOFOLLOW if needed. */
-        fd = open(fn, O_CLOEXEC|O_NOCTTY |
-                  (FLAGS_SET(flags, WRITE_STRING_FILE_NOFOLLOW) ? O_NOFOLLOW : 0) |
-                  (FLAGS_SET(flags, WRITE_STRING_FILE_CREATE) ? O_CREAT : 0) |
-                  (FLAGS_SET(flags, WRITE_STRING_FILE_TRUNCATE) ? O_TRUNC : 0) |
-                  (FLAGS_SET(flags, WRITE_STRING_FILE_SUPPRESS_REDUNDANT_VIRTUAL) ? O_RDWR : O_WRONLY),
-                  (FLAGS_SET(flags, WRITE_STRING_FILE_MODE_0600) ? 0600 : 0666));
+        fd = openat(dir_fd, fn, O_CLOEXEC|O_NOCTTY |
+                    (FLAGS_SET(flags, WRITE_STRING_FILE_NOFOLLOW) ? O_NOFOLLOW : 0) |
+                    (FLAGS_SET(flags, WRITE_STRING_FILE_CREATE) ? O_CREAT : 0) |
+                    (FLAGS_SET(flags, WRITE_STRING_FILE_TRUNCATE) ? O_TRUNC : 0) |
+                    (FLAGS_SET(flags, WRITE_STRING_FILE_SUPPRESS_REDUNDANT_VIRTUAL) ? O_RDWR : O_WRONLY),
+                    (FLAGS_SET(flags, WRITE_STRING_FILE_MODE_0600) ? 0600 : 0666));
         if (fd < 0) {
                 r = -errno;
                 goto fail;
@@ -364,7 +367,7 @@ int read_one_line_file(const char *fn, char **line) {
         return read_line(f, LONG_LINE_MAX, line);
 }
 
-int verify_file(const char *fn, const char *blob, bool accept_extra_nl) {
+int verify_file_at(int dir_fd, const char *fn, const char *blob, bool accept_extra_nl) {
         _cleanup_fclose_ FILE *f = NULL;
         _cleanup_free_ char *buf = NULL;
         size_t l, k;
@@ -382,7 +385,7 @@ int verify_file(const char *fn, const char *blob, bool accept_extra_nl) {
         if (!buf)
                 return -ENOMEM;
 
-        r = fopen_unlocked(fn, "re", &f);
+        r = fopen_unlocked_at(dir_fd, fn, "re", 0, &f);
         if (r < 0)
                 return r;
 
index 9151d8237a84baea806c92a5a8e9132912a628d2..7da3ee33e09e9568456b4f3d9013cd85bafa49f5 100644 (file)
@@ -43,7 +43,10 @@ typedef enum {
         READ_FULL_FILE_FAIL_WHEN_LARGER    = 1 << 5, /* fail loading if file is larger than specified size */
 } ReadFullFileFlags;
 
-int fopen_unlocked(const char *path, const char *options, FILE **ret);
+int fopen_unlocked_at(int dir_fd, const char *path, const char *options, int flags, FILE **ret);
+static inline int fopen_unlocked(const char *path, const char *options, FILE **ret) {
+        return fopen_unlocked_at(AT_FDCWD, path, options, 0, ret);
+}
 int fdopen_unlocked(int fd, const char *options, FILE **ret);
 int take_fdopen_unlocked(int *fd, const char *options, FILE **ret);
 FILE* take_fdopen(int *fd, const char *options);
@@ -55,7 +58,13 @@ int write_string_stream_ts(FILE *f, const char *line, WriteStringFileFlags flags
 static inline int write_string_stream(FILE *f, const char *line, WriteStringFileFlags flags) {
         return write_string_stream_ts(f, line, flags, NULL);
 }
-int write_string_file_ts(const char *fn, const char *line, WriteStringFileFlags flags, const struct timespec *ts);
+int write_string_file_ts_at(int dir_fd, const char *fn, const char *line, WriteStringFileFlags flags, const struct timespec *ts);
+static inline int write_string_file_ts(const char *fn, const char *line, WriteStringFileFlags flags, const struct timespec *ts) {
+        return write_string_file_ts_at(AT_FDCWD, fn, line, flags, ts);
+}
+static inline int write_string_file_at(int dir_fd, const char *fn, const char *line, WriteStringFileFlags flags) {
+        return write_string_file_ts_at(dir_fd, fn, line, flags, NULL);
+}
 static inline int write_string_file(const char *fn, const char *line, WriteStringFileFlags flags) {
         return write_string_file_ts(fn, line, flags, NULL);
 }
@@ -64,6 +73,9 @@ int write_string_filef(const char *fn, WriteStringFileFlags flags, const char *f
 
 int read_one_line_file(const char *filename, char **line);
 int read_full_file_full(int dir_fd, const char *filename, uint64_t offset, size_t size, ReadFullFileFlags flags, const char *bind_name, char **ret_contents, size_t *ret_size);
+static inline int read_full_file_at(int dir_fd, const char *filename, char **ret_contents, size_t *ret_size) {
+        return read_full_file_full(dir_fd, filename, UINT64_MAX, SIZE_MAX, 0, NULL, ret_contents, ret_size);
+}
 static inline int read_full_file(const char *filename, char **ret_contents, size_t *ret_size) {
         return read_full_file_full(AT_FDCWD, filename, UINT64_MAX, SIZE_MAX, 0, NULL, ret_contents, ret_size);
 }
@@ -82,7 +94,10 @@ static inline int read_full_stream(FILE *f, char **ret_contents, size_t *ret_siz
         return read_full_stream_full(f, NULL, UINT64_MAX, SIZE_MAX, 0, ret_contents, ret_size);
 }
 
-int verify_file(const char *fn, const char *blob, bool accept_extra_nl);
+int verify_file_at(int dir_fd, const char *fn, const char *blob, bool accept_extra_nl);
+static inline int verify_file(const char *fn, const char *blob, bool accept_extra_nl) {
+        return verify_file_at(AT_FDCWD, fn, blob, accept_extra_nl);
+}
 
 int executable_is_script(const char *path, char **interpreter);