]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
loop-util: Add loop_device_make_by_path_at() 26949/head
authorDaan De Meyer <daan.j.demeyer@gmail.com>
Thu, 23 Mar 2023 13:42:35 +0000 (14:42 +0100)
committerDaan De Meyer <daan.j.demeyer@gmail.com>
Thu, 23 Mar 2023 16:36:17 +0000 (17:36 +0100)
On top of taking a directory file descriptor, we use xopenat() so
that the function can also be used to work on existing file
descriptors to image files including all the logic to use O_DIRECT
and fallback to O_RDONLY if needed.

src/shared/loop-util.c
src/shared/loop-util.h

index d6b8d086ffbe87d7737986a9ec0bf61bc1972ad6..91477ed003795e6d81e5b29153043ff7ce5c4007 100644 (file)
@@ -24,6 +24,7 @@
 #include "env-util.h"
 #include "errno-util.h"
 #include "fd-util.h"
+#include "fs-util.h"
 #include "fileio.h"
 #include "loop-util.h"
 #include "missing_loop.h"
@@ -650,7 +651,8 @@ int loop_device_make(
                         ret);
 }
 
-int loop_device_make_by_path(
+int loop_device_make_by_path_at(
+                int dir_fd,
                 const char *path,
                 int open_flags,
                 uint32_t sector_size,
@@ -662,6 +664,7 @@ int loop_device_make_by_path(
         _cleanup_close_ int fd = -EBADF;
         bool direct = false;
 
+        assert(dir_fd >= 0 || dir_fd == AT_FDCWD);
         assert(path);
         assert(ret);
         assert(open_flags < 0 || IN_SET(open_flags, O_RDWR, O_RDONLY));
@@ -678,9 +681,9 @@ int loop_device_make_by_path(
         direct_flags = FLAGS_SET(loop_flags, LO_FLAGS_DIRECT_IO) ? O_DIRECT : 0;
         rdwr_flags = open_flags >= 0 ? open_flags : O_RDWR;
 
-        fd = open(path, basic_flags|direct_flags|rdwr_flags);
+        fd = xopenat(dir_fd, path, basic_flags|direct_flags|rdwr_flags, 0);
         if (fd < 0 && direct_flags != 0) /* If we had O_DIRECT on, and things failed with that, let's immediately try again without */
-                fd = open(path, basic_flags|rdwr_flags);
+                fd = xopenat(dir_fd, path, basic_flags|rdwr_flags, 0);
         else
                 direct = direct_flags != 0;
         if (fd < 0) {
@@ -690,9 +693,9 @@ int loop_device_make_by_path(
                 if (open_flags >= 0 || !(ERRNO_IS_PRIVILEGE(r) || r == -EROFS))
                         return r;
 
-                fd = open(path, basic_flags|direct_flags|O_RDONLY);
+                fd = xopenat(dir_fd, path, basic_flags|direct_flags|O_RDONLY, 0);
                 if (fd < 0 && direct_flags != 0) /* as above */
-                        fd = open(path, basic_flags|O_RDONLY);
+                        fd = xopenat(dir_fd, path, basic_flags|O_RDONLY, 0);
                 else
                         direct = direct_flags != 0;
                 if (fd < 0)
@@ -709,7 +712,16 @@ int loop_device_make_by_path(
                   direct ? "enabled" : "disabled",
                   direct != (direct_flags != 0) ? " (O_DIRECT was requested but not supported)" : "");
 
-        return loop_device_make_internal(path, fd, open_flags, 0, 0, sector_size, loop_flags, lock_op, ret);
+        return loop_device_make_internal(
+                        dir_fd == AT_FDCWD ? path : NULL,
+                        fd,
+                        open_flags,
+                        /* offset = */ 0,
+                        /* size = */ 0,
+                        sector_size,
+                        loop_flags,
+                        lock_op,
+                        ret);
 }
 
 int loop_device_make_by_path_memory(
index dda14ec4f01c6a142891c10f52d8543938cd60c9..d77c314af83530b997ddcf0a69f5c3b6219335da 100644 (file)
@@ -1,6 +1,8 @@
 /* SPDX-License-Identifier: LGPL-2.1-or-later */
 #pragma once
 
+#include <fcntl.h>
+
 #include "sd-device.h"
 
 #include "macro.h"
@@ -32,7 +34,10 @@ struct LoopDevice {
 #define LOOP_DEVICE_IS_FOREIGN(d) ((d)->nr < 0)
 
 int loop_device_make(int fd, int open_flags, uint64_t offset, uint64_t size, uint32_t sector_size, uint32_t loop_flags, int lock_op, LoopDevice **ret);
-int loop_device_make_by_path(const char *path, int open_flags, uint32_t sector_size, uint32_t loop_flags, int lock_op, LoopDevice **ret);
+int loop_device_make_by_path_at(int dir_fd, const char *path, int open_flags, uint32_t sector_size, uint32_t loop_flags, int lock_op, LoopDevice **ret);
+static inline int loop_device_make_by_path(const char *path, int open_flags, uint32_t sector_size, uint32_t loop_flags, int lock_op, LoopDevice **ret) {
+        return loop_device_make_by_path_at(AT_FDCWD, path, open_flags, sector_size, loop_flags, lock_op, ret);
+}
 int loop_device_make_by_path_memory(const char *path, int open_flags, uint32_t sector_size, uint32_t loop_flags, int lock_op, LoopDevice **ret);
 int loop_device_open(sd_device *dev, int open_flags, int lock_op, LoopDevice **ret);
 int loop_device_open_from_fd(int fd, int open_flags, int lock_op, LoopDevice **ret);