From 0739b5df11f2125f2f4b592e19c0d240620c5df6 Mon Sep 17 00:00:00 2001 From: Liav A Date: Fri, 9 Feb 2024 17:17:14 +0200 Subject: [PATCH] Utilities/mount: Automatically mount regular files with loop devices Check if the source fd is not a block device file using the fstat syscall and if that's the case, try to mount the file using a temporary loop device. --- Base/usr/share/man/man8/mount.md | 3 +++ Userland/Utilities/mount.cpp | 22 +++++++++++++++++++++- 2 files changed, 24 insertions(+), 1 deletion(-) diff --git a/Base/usr/share/man/man8/mount.md b/Base/usr/share/man/man8/mount.md index 44827728d2..b69e1fb385 100644 --- a/Base/usr/share/man/man8/mount.md +++ b/Base/usr/share/man/man8/mount.md @@ -44,6 +44,9 @@ Additionally, the name `defaults` is accepted and ignored. ```sh # mount devpts /dev/pts -t devpts -o noexec,nosuid # mount /home/anon/myfile.txt /tmp/foo -o bind + +# mount a regular file using a temporary loop device +$ mount /home/anon/myfilesystem.bin /mnt ``` ## See also diff --git a/Userland/Utilities/mount.cpp b/Userland/Utilities/mount.cpp index dca6e69255..573fbececb 100644 --- a/Userland/Utilities/mount.cpp +++ b/Userland/Utilities/mount.cpp @@ -7,6 +7,7 @@ #include #include #include +#include #include #include #include @@ -197,6 +198,21 @@ static ErrorOr print_mounts() return {}; } +static ErrorOr mount_using_loop_device(int inode_fd, StringView mountpoint, StringView fs_type, int flags) +{ + int devctl_fd = TRY(Core::System::open("/dev/devctl"sv, O_RDONLY)); + int value = inode_fd; + TRY(Core::System::ioctl(devctl_fd, DEVCTL_CREATE_LOOP_DEVICE, &value)); + int loop_device_index = value; + + auto loop_device_path = TRY(String::formatted("/dev/loop/{}", loop_device_index)); + int loop_device_fd = TRY(Core::System::open(loop_device_path.bytes_as_string_view(), O_RDONLY)); + + auto result = Core::System::mount(loop_device_fd, mountpoint, fs_type, flags); + TRY(Core::System::ioctl(devctl_fd, DEVCTL_DESTROY_LOOP_DEVICE, &loop_device_index)); + return result; +} + ErrorOr serenity_main(Main::Arguments arguments) { StringView source; @@ -242,7 +258,11 @@ ErrorOr serenity_main(Main::Arguments arguments) } else { if (fs_type.is_empty()) fs_type = "ext2"sv; - TRY(Core::System::mount(fd, mountpoint, fs_type, flags)); + auto stat = TRY(Core::System::fstat(fd)); + if (!S_ISBLK(stat.st_mode)) + TRY(mount_using_loop_device(fd, mountpoint, fs_type, flags)); + else + TRY(Core::System::mount(fd, mountpoint, fs_type, flags)); } return 0; }