]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
loop-util: add new loop_device_make_by_path_memory() helper
authorLennart Poettering <lennart@poettering.net>
Thu, 8 Dec 2022 11:45:48 +0000 (12:45 +0100)
committerLennart Poettering <lennart@poettering.net>
Thu, 8 Dec 2022 11:47:28 +0000 (12:47 +0100)
This uses the new memfd_clone_fd() call to make an in-memory copy of
some file before setting up a loopback block device on it.

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

index fb7e80b1b5c0c2c9a7f08a01bb82322531812f67..ed31454e313d08510f8c646fca291df6184da225 100644 (file)
@@ -17,6 +17,7 @@
 
 #include "alloc-util.h"
 #include "blockdev-util.h"
+#include "data-fd-util.h"
 #include "device-util.h"
 #include "devnum-util.h"
 #include "env-util.h"
@@ -640,6 +641,47 @@ int loop_device_make_by_path(
         return loop_device_make_internal(path, fd, open_flags, 0, 0, 0, loop_flags, lock_op, ret);
 }
 
+int loop_device_make_by_path_memory(
+                const char *path,
+                int open_flags,
+                uint32_t loop_flags,
+                int lock_op,
+                LoopDevice **ret) {
+
+        _cleanup_close_ int fd = -EBADF, mfd = -EBADF;
+        _cleanup_free_ char *fn = NULL;
+        struct stat st;
+        int r;
+
+        assert(path);
+        assert(IN_SET(open_flags, O_RDWR, O_RDONLY));
+        assert(ret);
+
+        loop_flags &= ~LO_FLAGS_DIRECT_IO; /* memfds don't support O_DIRECT, hence LO_FLAGS_DIRECT_IO can't be used either */
+
+        fd = open(path, O_CLOEXEC|O_NONBLOCK|O_NOCTTY|O_RDONLY);
+        if (fd < 0)
+                return -errno;
+
+        if (fstat(fd, &st) < 0)
+                return -errno;
+
+        if (!S_ISREG(st.st_mode) && !S_ISBLK(st.st_mode))
+                return -EBADF;
+
+        r = path_extract_filename(path, &fn);
+        if (r < 0)
+                return r;
+
+        mfd = memfd_clone_fd(fd, fn, open_flags|O_CLOEXEC);
+        if (mfd < 0)
+                return mfd;
+
+        fd = safe_close(fd); /* Let's close the original early */
+
+        return loop_device_make_internal(NULL, mfd, open_flags, 0, 0, 0, loop_flags, lock_op, ret);
+}
+
 static LoopDevice* loop_device_free(LoopDevice *d) {
         _cleanup_close_ int control = -1;
         int r;
index e466a5abbdf9dd3e66bffa6799d25407c439b923..512b5ab4a22d6510b5388bf07a0fb42130d06995 100644 (file)
@@ -30,6 +30,7 @@ struct LoopDevice {
 
 int loop_device_make(int fd, int open_flags, uint64_t offset, uint64_t size, uint32_t block_size, uint32_t loop_flags, int lock_op, LoopDevice **ret);
 int loop_device_make_by_path(const char *path, int open_flags, uint32_t loop_flags, int lock_op, LoopDevice **ret);
+int loop_device_make_by_path_memory(const char *path, int open_flags, 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);
 int loop_device_open_from_path(const char *path, int open_flags, int lock_op, LoopDevice **ret);