From 135da1bde3942a92a0e8fb530c7cb58e8f793fab Mon Sep 17 00:00:00 2001 From: LoveSy <shana@zju.edu.cn> Date: Wed, 19 Jul 2023 22:11:10 +0800 Subject: [PATCH 1/3] Add new mount api syscall for linux_raw --- src/backend/linux_raw/conv.rs | 49 +++++++ src/backend/linux_raw/fs/syscalls.rs | 199 +++++++++++++++++++++++++++ src/backend/linux_raw/fs/types.rs | 186 +++++++++++++++++++++++++ 3 files changed, 434 insertions(+) diff --git a/src/backend/linux_raw/conv.rs b/src/backend/linux_raw/conv.rs index 05d040204..43242455c 100644 --- a/src/backend/linux_raw/conv.rs +++ b/src/backend/linux_raw/conv.rs @@ -450,6 +450,55 @@ pub(crate) mod fs { c_uint(flags.bits()) } } + + impl<'a, Num: ArgNumber> From<crate::fs::FsConfigCmd> for ArgReg<'a, Num> { + #[inline] + fn from(cmd: crate::fs::FsConfigCmd) -> Self { + c_uint(cmd as c::c_uint) + } + } + + impl<'a, Num: ArgNumber> From<crate::backend::fs::types::FsOpenFlags> for ArgReg<'a, Num> { + #[inline] + fn from(flags: crate::backend::fs::types::FsOpenFlags) -> Self { + c_uint(flags.bits()) + } + } + + impl<'a, Num: ArgNumber> From<crate::backend::fs::types::FsMountFlags> for ArgReg<'a, Num> { + #[inline] + fn from(flags: crate::backend::fs::types::FsMountFlags) -> Self { + c_uint(flags.bits()) + } + } + + impl<'a, Num: ArgNumber> From<crate::backend::fs::types::MountAttrFlags> for ArgReg<'a, Num> { + #[inline] + fn from(flags: crate::backend::fs::types::MountAttrFlags) -> Self { + c_uint(flags.bits()) + } + } + + impl<'a, Num: ArgNumber> From<crate::backend::fs::types::OpenTreeFlags> for ArgReg<'a, Num> { + #[inline] + fn from(flags: crate::backend::fs::types::OpenTreeFlags) -> Self { + c_uint(flags.bits()) + } + } + + impl<'a, Num: ArgNumber> From<crate::backend::fs::types::FsPickFlags> for ArgReg<'a, Num> { + #[inline] + fn from(flags: crate::backend::fs::types::FsPickFlags) -> Self { + c_uint(flags.bits()) + } + } + + impl<'a, Num: ArgNumber> From<crate::backend::fs::types::MoveMountFlags> for ArgReg<'a, Num> { + #[inline] + fn from(flags: crate::backend::fs::types::MoveMountFlags) -> Self { + c_uint(flags.bits()) + } + } } impl<'a, Num: ArgNumber> From<crate::io::FdFlags> for ArgReg<'a, Num> { diff --git a/src/backend/linux_raw/fs/syscalls.rs b/src/backend/linux_raw/fs/syscalls.rs index 837fb0a76..8d8b76c7a 100644 --- a/src/backend/linux_raw/fs/syscalls.rs +++ b/src/backend/linux_raw/fs/syscalls.rs @@ -1436,6 +1436,205 @@ pub(crate) fn mount( } } +#[allow(dead_code)] +#[inline] +pub(crate) fn fsopen(fs_name: &CStr, flags: super::types::FsOpenFlags) -> io::Result<OwnedFd> { + unsafe { ret_owned_fd(syscall_readonly!(__NR_fsopen, fs_name, flags)) } +} + +#[allow(dead_code)] +#[inline] +pub(crate) fn fsmount( + fs_fd: BorrowedFd<'_>, + flags: super::types::FsMountFlags, + attr_flags: super::types::MountAttrFlags, +) -> io::Result<()> { + unsafe { ret(syscall_readonly!(__NR_fsmount, fs_fd, flags, attr_flags)) } +} + +#[allow(dead_code)] +#[inline] +pub(crate) fn move_mount( + from_dfd: BorrowedFd<'_>, + from_pathname: &CStr, + to_dfd: BorrowedFd<'_>, + to_pathname: &CStr, + flags: super::types::MoveMountFlags, +) -> io::Result<()> { + unsafe { + ret(syscall_readonly!( + __NR_move_mount, + from_dfd, + from_pathname, + to_dfd, + to_pathname, + flags + )) + } +} + +#[allow(dead_code)] +#[inline] +pub(crate) fn open_tree( + dfd: BorrowedFd<'_>, + filename: &CStr, + flags: super::types::OpenTreeFlags, +) -> io::Result<OwnedFd> { + unsafe { ret_owned_fd(syscall_readonly!(__NR_open_tree, dfd, filename, flags)) } +} + +#[allow(dead_code)] +#[inline] +pub(crate) fn fspick( + dfd: BorrowedFd<'_>, + path: &CStr, + flags: super::types::FsPickFlags, +) -> io::Result<OwnedFd> { + unsafe { ret_owned_fd(syscall_readonly!(__NR_fspick, dfd, path, flags)) } +} + +#[allow(dead_code)] +#[inline] +pub(crate) fn fsconfig_set_flag(fs_fd: BorrowedFd<'_>, key: &CStr) -> io::Result<()> { + unsafe { + ret(syscall_readonly!( + __NR_fsconfig, + fs_fd, + super::types::FsConfigCmd::SetFlag, + key, + zero(), + zero() + )) + } +} + +#[allow(dead_code)] +#[inline] +pub(crate) fn fsconfig_set_string( + fs_fd: BorrowedFd<'_>, + key: &CStr, + value: &CStr, +) -> io::Result<()> { + unsafe { + ret(syscall_readonly!( + __NR_fsconfig, + fs_fd, + super::types::FsConfigCmd::SetString, + key, + value, + zero() + )) + } +} + +#[allow(dead_code)] +#[inline] +pub(crate) fn fsconfig_set_binary( + fs_fd: BorrowedFd<'_>, + key: &CStr, + value: &[u8], +) -> io::Result<()> { + let (value_addr, value_len) = slice(value); + unsafe { + ret(syscall_readonly!( + __NR_fsconfig, + fs_fd, + super::types::FsConfigCmd::SetBinary, + key, + value_addr, + value_len + )) + } +} + +#[allow(dead_code)] +#[inline] +pub(crate) fn fsconfig_set_fd( + fs_fd: BorrowedFd<'_>, + key: &CStr, + fd: BorrowedFd<'_>, +) -> io::Result<()> { + unsafe { + ret(syscall_readonly!( + __NR_fsconfig, + fs_fd, + super::types::FsConfigCmd::SetFd, + key, + zero(), + fd + )) + } +} + +#[allow(dead_code)] +#[inline] +pub(crate) fn fsconfig_set_path( + fs_fd: BorrowedFd<'_>, + key: &CStr, + path: &CStr, + fd: BorrowedFd<'_>, +) -> io::Result<()> { + unsafe { + ret(syscall_readonly!( + __NR_fsconfig, + fs_fd, + super::types::FsConfigCmd::SetPath, + key, + path, + fd + )) + } +} + +#[allow(dead_code)] +#[inline] +pub(crate) fn fsconfig_set_path_empty( + fs_fd: BorrowedFd<'_>, + key: &CStr, + fd: BorrowedFd<'_>, +) -> io::Result<()> { + unsafe { + ret(syscall_readonly!( + __NR_fsconfig, + fs_fd, + super::types::FsConfigCmd::SetPathEmpty, + key, + cstr!(""), + fd + )) + } +} + +#[allow(dead_code)] +#[inline] +pub(crate) fn fsconfig_create(fs_fd: BorrowedFd<'_>) -> io::Result<()> { + unsafe { + ret(syscall_readonly!( + __NR_fsconfig, + fs_fd, + super::types::FsConfigCmd::Create, + zero(), + zero(), + zero() + )) + } +} + +#[allow(dead_code)] +#[inline] +pub(crate) fn fsconfig_reconfigure(fs_fd: BorrowedFd<'_>) -> io::Result<()> { + unsafe { + ret(syscall_readonly!( + __NR_fsconfig, + fs_fd, + super::types::FsConfigCmd::Reconfigure, + zero(), + zero(), + zero() + )) + } +} + #[inline] pub(crate) fn unmount(target: &CStr, flags: super::types::UnmountFlags) -> io::Result<()> { unsafe { ret(syscall_readonly!(__NR_umount2, target, flags)) } diff --git a/src/backend/linux_raw/fs/types.rs b/src/backend/linux_raw/fs/types.rs index df61cf721..00fb2b370 100644 --- a/src/backend/linux_raw/fs/types.rs +++ b/src/backend/linux_raw/fs/types.rs @@ -392,6 +392,37 @@ pub enum Advice { DontNeed = linux_raw_sys::general::POSIX_FADV_DONTNEED, } +/// `FSCONFIG_*` constants for use with [`fsconfig`]. +/// +/// [`fsconfig`]: crate::fs::fsconfig +#[derive(Debug, Copy, Clone, Eq, PartialEq)] +#[repr(u32)] +pub enum FsConfigCmd { + /// `FSCONFIG_SET_FLAG` + SetFlag = linux_raw_sys::general::fsconfig_command::FSCONFIG_SET_FLAG as u32, + + /// `FSCONFIG_SET_STRING` + SetString = linux_raw_sys::general::fsconfig_command::FSCONFIG_SET_STRING as u32, + + /// `FSCONFIG_SET_BINARY` + SetBinary = linux_raw_sys::general::fsconfig_command::FSCONFIG_SET_BINARY as u32, + + /// `FSCONFIG_SET_PATH` + SetPath = linux_raw_sys::general::fsconfig_command::FSCONFIG_SET_PATH as u32, + + /// `FSCONFIG_SET_PATH_EMPTY` + SetPathEmpty = linux_raw_sys::general::fsconfig_command::FSCONFIG_SET_PATH_EMPTY as u32, + + /// `FSCONFIG_SET_FD` + SetFd = linux_raw_sys::general::fsconfig_command::FSCONFIG_SET_FD as u32, + + /// `FSCONFIG_CMD_CREATE` + Create = linux_raw_sys::general::fsconfig_command::FSCONFIG_CMD_CREATE as u32, + + /// `FSCONFIG_CMD_RECONFIGURE` + Reconfigure = linux_raw_sys::general::fsconfig_command::FSCONFIG_CMD_RECONFIGURE as u32, +} + bitflags! { /// `MFD_*` constants for use with [`memfd_create`]. /// @@ -753,6 +784,161 @@ bitflags! { } } +bitflags! { + /// `FSOPEN_*` constants for use with [`fsopen`]. + /// + /// [`fsopen`]: crate::fs::fsopen + #[repr(transparent)] + #[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)] + pub struct FsOpenFlags: c::c_uint { + + /// `FSOPEN_CLOEXEC` + const FSOPEN_CLOEXEC = linux_raw_sys::general::FSOPEN_CLOEXEC; + } +} + +bitflags! { + /// `FSMOUNT_*` constants for use with [`fsmount`]. + /// + /// [`fsmount`]: crate::fs::fsmount + #[repr(transparent)] + #[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)] + pub struct FsMountFlags: c::c_uint { + /// `FSMOUNT_CLOEXEC` + const FSMOUNT_CLOEXEC = linux_raw_sys::general::FSMOUNT_CLOEXEC; + } +} + +bitflags! { + /// `MOUNT_ATTR_*` constants for use with [`fsmount`]. + /// + /// [`fsmount`]: crate::fs::fsmount + #[repr(transparent)] + #[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)] + pub struct MountAttrFlags: c::c_uint { + /// `MOUNT_ATTR_RDONLY` + const MOUNT_ATTR_RDONLY = linux_raw_sys::general::MOUNT_ATTR_RDONLY; + + /// `MOUNT_ATTR_NOSUID` + const MOUNT_ATTR_NOSUID = linux_raw_sys::general::MOUNT_ATTR_NOSUID; + + /// `MOUNT_ATTR_NODEV` + const MOUNT_ATTR_NODEV = linux_raw_sys::general::MOUNT_ATTR_NODEV; + + /// `MOUNT_ATTR_NOEXEC` + const MOUNT_ATTR_NOEXEC = linux_raw_sys::general::MOUNT_ATTR_NOEXEC; + + /// `MOUNT_ATTR__ATIME` + const MOUNT_ATTR__ATIME = linux_raw_sys::general::MOUNT_ATTR__ATIME; + + /// `MOUNT_ATTR_RELATIME` + const MOUNT_ATTR_RELATIME = linux_raw_sys::general::MOUNT_ATTR_RELATIME; + + /// `MOUNT_ATTR_NOATIME` + const MOUNT_ATTR_NOATIME = linux_raw_sys::general::MOUNT_ATTR_NOATIME; + + /// `MOUNT_ATTR_STRICTATIME` + const MOUNT_ATTR_STRICTATIME = linux_raw_sys::general::MOUNT_ATTR_STRICTATIME; + + /// `MOUNT_ATTR_NODIRATIME` + const MOUNT_ATTR_NODIRATIME = linux_raw_sys::general::MOUNT_ATTR_NODIRATIME; + + /// `MOUNT_ATTR_NOUSER` + const MOUNT_ATTR_IDMAP = linux_raw_sys::general::MOUNT_ATTR_IDMAP; + + /// `MOUNT_ATTR__ATIME_FLAGS` + const MOUNT_ATTR_NOSYMFOLLOW = linux_raw_sys::general::MOUNT_ATTR_NOSYMFOLLOW; + + /// `MOUNT_ATTR__ATIME_FLAGS` + const MOUNT_ATTR_SIZE_VER0 = linux_raw_sys::general::MOUNT_ATTR_SIZE_VER0; + } +} + +bitflags! { + /// `MOVE_MOUNT_*` constants for use with [`move_mount`]. + /// + /// [`move_mount`]: crate::fs::move_mount + #[repr(transparent)] + #[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)] + pub struct MoveMountFlags: c::c_uint { + /// `MOVE_MOUNT_F_EMPTY_PATH` + const MOVE_MOUNT_F_SYMLINKS = linux_raw_sys::general::MOVE_MOUNT_F_SYMLINKS; + + /// `MOVE_MOUNT_F_AUTOMOUNTS` + const MOVE_MOUNT_F_AUTOMOUNTS = linux_raw_sys::general::MOVE_MOUNT_F_AUTOMOUNTS; + + /// `MOVE_MOUNT_F_EMPTY_PATH` + const MOVE_MOUNT_F_EMPTY_PATH = linux_raw_sys::general::MOVE_MOUNT_F_EMPTY_PATH; + + /// `MOVE_MOUNT_T_SYMLINKS` + const MOVE_MOUNT_T_SYMLINKS = linux_raw_sys::general::MOVE_MOUNT_T_SYMLINKS; + + /// `MOVE_MOUNT_T_AUTOMOUNTS` + const MOVE_MOUNT_T_AUTOMOUNTS = linux_raw_sys::general::MOVE_MOUNT_T_AUTOMOUNTS; + + /// `MOVE_MOUNT_T_EMPTY_PATH` + const MOVE_MOUNT_T_EMPTY_PATH = linux_raw_sys::general::MOVE_MOUNT_T_EMPTY_PATH; + + /// `MOVE_MOUNT__MASK` + const MOVE_MOUNT_SET_GROUP = linux_raw_sys::general::MOVE_MOUNT_SET_GROUP; + + // TODO: add when linux 6.5 is released + // /// `MOVE_MOUNT_BENEATH` + // const MOVE_MOUNT_BENEATH = linux_raw_sys::general::MOVE_MOUNT_BENEATH; + + /// `MOVE_MOUNT__MASK` + const MOVE_MOUNT__MASK = linux_raw_sys::general::MOVE_MOUNT__MASK; + } +} + +bitflags! { + /// `OPENTREE_*` constants for use with [`open_tree`]. + /// + /// [`open_tree`]: crate::fs::open_tree + #[repr(transparent)] + #[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)] + pub struct OpenTreeFlags: c::c_uint { + /// `OPENTREE_CLONE` + const OPEN_TREE_CLONE = linux_raw_sys::general::OPEN_TREE_CLONE; + + /// `OPENTREE_CLOEXEC` + const OPEN_TREE_CLOEXEC = linux_raw_sys::general::OPEN_TREE_CLOEXEC; + + /// `AT_EMPTY_PATH` + const AT_EMPTY_PATH = linux_raw_sys::general::AT_EMPTY_PATH; + + /// `AT_NO_AUTOMOUNT` + const AT_NO_AUTOMOUNT = linux_raw_sys::general::AT_NO_AUTOMOUNT; + + /// `AT_RECURSIVE` + const AT_RECURSIVE = linux_raw_sys::general::AT_RECURSIVE; + + /// `AT_SYMLINK_NOFOLLOW` + const AT_SYMLINK_NOFOLLOW = linux_raw_sys::general::AT_SYMLINK_NOFOLLOW; + } +} + +bitflags! { + /// `FSPICK_*` constants for use with [`fspick`]. + /// + /// [`fspick`]: crate::fs::fspick + #[repr(transparent)] + #[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)] + pub struct FsPickFlags: c::c_uint { + /// `FSPICK_CLOEXEC` + const FSPICK_CLOEXEC = linux_raw_sys::general::FSPICK_CLOEXEC; + + /// `FSPICK_SYMLINK_NOFOLLOW` + const FSPICK_SYMLINK_NOFOLLOW = linux_raw_sys::general::FSPICK_SYMLINK_NOFOLLOW; + + /// `FSPICK_NO_AUTOMOUNT` + const FSPICK_NO_AUTOMOUNT = linux_raw_sys::general::FSPICK_NO_AUTOMOUNT; + + /// `FSPICK_EMPTY_PATH` + const FSPICK_EMPTY_PATH = linux_raw_sys::general::FSPICK_EMPTY_PATH; + } +} + bitflags! { /// `MS_*` constants for use with [`change_mount`]. /// From 48bc8c20440888755419991979c8db73f72d579f Mon Sep 17 00:00:00 2001 From: LoveSy <shana@zju.edu.cn> Date: Wed, 19 Jul 2023 22:11:18 +0800 Subject: [PATCH 2/3] Add new mount api syscall for libc of linux --- src/backend/libc/fs/syscalls.rs | 238 ++++++++++++++++++++++++++++++++ src/backend/libc/fs/types.rs | 193 ++++++++++++++++++++++++++ 2 files changed, 431 insertions(+) diff --git a/src/backend/libc/fs/syscalls.rs b/src/backend/libc/fs/syscalls.rs index fefd4f3af..c38b4b6bf 100644 --- a/src/backend/libc/fs/syscalls.rs +++ b/src/backend/libc/fs/syscalls.rs @@ -2087,6 +2087,244 @@ pub(crate) fn unmount(target: &CStr, flags: super::types::UnmountFlags) -> io::R unsafe { ret(c::umount2(target.as_ptr(), bitflags_bits!(flags))) } } +#[allow(dead_code)] +#[cfg(linux_kernel)] +pub(crate) fn fsopen(fs_name: &CStr, flags: super::types::FsOpenFlags) -> io::Result<OwnedFd> { + syscall! { + fn fsopen( + fs_name: *const c::c_char, + flags: c::c_uint + ) via SYS_fsopen -> c::c_int + } + unsafe { ret_owned_fd(fsopen(c_str(fs_name), flags.bits())) } +} + +#[allow(dead_code)] +#[cfg(linux_kernel)] +pub(crate) fn fsmount( + fs_fd: BorrowedFd<'_>, + flags: super::types::FsMountFlags, + attr_flags: super::types::MountAttrFlags, +) -> io::Result<()> { + syscall! { + fn fsmount( + fs_fd: c::c_int, + flags: c::c_uint, + attr_flags: c::c_uint + ) via SYS_fsmount -> c::c_int + } + unsafe { ret(fsmount(borrowed_fd(fs_fd), flags.bits(), attr_flags.bits())) } +} + +#[allow(dead_code)] +#[cfg(linux_kernel)] +pub(crate) fn move_mount( + from_dfd: BorrowedFd<'_>, + from_pathname: &CStr, + to_dfd: BorrowedFd<'_>, + to_pathname: &CStr, + flags: super::types::MoveMountFlags, +) -> io::Result<()> { + syscall! { + fn move_mount( + from_dfd: c::c_int, + from_pathname: *const c::c_char, + to_dfd: c::c_int, + to_pathname: *const c::c_char, + flags: c::c_uint + ) via SYS_move_mount -> c::c_int + } + unsafe { + ret(move_mount( + borrowed_fd(from_dfd), + c_str(from_pathname), + borrowed_fd(to_dfd), + c_str(to_pathname), + flags.bits(), + )) + } +} + +#[allow(dead_code)] +#[cfg(linux_kernel)] +pub(crate) fn open_tree( + dfd: BorrowedFd<'_>, + filename: &CStr, + flags: super::types::OpenTreeFlags, +) -> io::Result<OwnedFd> { + syscall! { + fn open_tree( + dfd: c::c_int, + filename: *const c::c_char, + flags: c::c_uint + ) via SYS_open_tree -> c::c_int + } + + unsafe { ret_owned_fd(open_tree(borrowed_fd(dfd), c_str(filename), flags.bits())) } +} + +#[allow(dead_code)] +#[cfg(linux_kernel)] +pub(crate) fn fspick( + dfd: BorrowedFd<'_>, + path: &CStr, + flags: super::types::FsPickFlags, +) -> io::Result<OwnedFd> { + syscall! { + fn fspick( + dfd: c::c_int, + path: *const c::c_char, + flags: c::c_uint + ) via SYS_fspick -> c::c_int + } + + unsafe { ret_owned_fd(fspick(borrowed_fd(dfd), c_str(path), flags.bits())) } +} + +#[cfg(linux_kernel)] +syscall! { + fn fsconfig( + fs_fd: c::c_int, + cmd: c::c_uint, + key: *const c::c_char, + val: *const c::c_char, + aux: c::c_int + ) via SYS_fsconfig -> c::c_int +} + +#[allow(dead_code)] +#[cfg(linux_kernel)] +pub(crate) fn fsconfig_set_flag(fs_fd: BorrowedFd<'_>, key: &CStr) -> io::Result<()> { + unsafe { + ret(fsconfig( + borrowed_fd(fs_fd), + super::types::FsConfigCmd::SetFlag as _, + c_str(key), + null(), + 0, + )) + } +} + +#[allow(dead_code)] +#[cfg(linux_kernel)] +pub(crate) fn fsconfig_set_string( + fs_fd: BorrowedFd<'_>, + key: &CStr, + value: &CStr, +) -> io::Result<()> { + unsafe { + ret(fsconfig( + borrowed_fd(fs_fd), + super::types::FsConfigCmd::SetString as _, + c_str(key), + c_str(value), + 0, + )) + } +} + +#[allow(dead_code)] +#[cfg(linux_kernel)] +pub(crate) fn fsconfig_set_binary( + fs_fd: BorrowedFd<'_>, + key: &CStr, + value: &[u8], +) -> io::Result<()> { + unsafe { + ret(fsconfig( + borrowed_fd(fs_fd), + super::types::FsConfigCmd::SetBinary as _, + c_str(key), + value.as_ptr().cast(), + value.len().try_into().map_err(|_| io::Errno::OVERFLOW)?, + )) + } +} + +#[allow(dead_code)] +#[cfg(linux_kernel)] +pub(crate) fn fsconfig_set_fd( + fs_fd: BorrowedFd<'_>, + key: &CStr, + fd: BorrowedFd<'_>, +) -> io::Result<()> { + unsafe { + ret(fsconfig( + borrowed_fd(fs_fd), + super::types::FsConfigCmd::SetFd as _, + c_str(key), + null(), + borrowed_fd(fd), + )) + } +} + +#[allow(dead_code)] +#[cfg(linux_kernel)] +pub(crate) fn fsconfig_set_path( + fs_fd: BorrowedFd<'_>, + key: &CStr, + path: &CStr, + fd: BorrowedFd<'_>, +) -> io::Result<()> { + unsafe { + ret(fsconfig( + borrowed_fd(fs_fd), + super::types::FsConfigCmd::SetPath as _, + c_str(key), + c_str(path), + borrowed_fd(fd), + )) + } +} + +#[allow(dead_code)] +#[cfg(linux_kernel)] +pub(crate) fn fsconfig_set_path_empty( + fs_fd: BorrowedFd<'_>, + key: &CStr, + fd: BorrowedFd<'_>, +) -> io::Result<()> { + unsafe { + ret(fsconfig( + borrowed_fd(fs_fd), + super::types::FsConfigCmd::SetPathEmpty as _, + c_str(key), + c_str(cstr!("")), + borrowed_fd(fd), + )) + } +} + +#[allow(dead_code)] +#[cfg(linux_kernel)] +pub(crate) fn fsconfig_create(fs_fd: BorrowedFd<'_>) -> io::Result<()> { + unsafe { + ret(fsconfig( + borrowed_fd(fs_fd), + super::types::FsConfigCmd::Create as _, + null(), + null(), + 0, + )) + } +} + +#[allow(dead_code)] +#[cfg(linux_kernel)] +pub(crate) fn fsconfig_reconfigure(fs_fd: BorrowedFd<'_>) -> io::Result<()> { + unsafe { + ret(fsconfig( + borrowed_fd(fs_fd), + super::types::FsConfigCmd::Reconfigure as _, + null(), + null(), + 0, + )) + } +} + #[cfg(any(apple, linux_kernel))] pub(crate) fn getxattr(path: &CStr, name: &CStr, value: &mut [u8]) -> io::Result<usize> { let value_ptr = value.as_mut_ptr(); diff --git a/src/backend/libc/fs/types.rs b/src/backend/libc/fs/types.rs index 29aba5e2c..8a3e372d2 100644 --- a/src/backend/libc/fs/types.rs +++ b/src/backend/libc/fs/types.rs @@ -554,6 +554,38 @@ pub enum Advice { DontNeed = c::POSIX_FADV_DONTNEED as c::c_uint, } +/// `FSCONFIG_*` constants for use with [`fsconfig`]. +/// +/// [`fsconfig`]: crate::fs::fsconfig +#[cfg(linux_kernel)] +#[derive(Debug, Copy, Clone, Eq, PartialEq)] +#[repr(u32)] +pub enum FsConfigCmd { + /// `FSCONFIG_SET_FLAG` + SetFlag = 0, + + /// `FSCONFIG_SET_STRING` + SetString = 1, + + /// `FSCONFIG_SET_BINARY` + SetBinary = 2, + + /// `FSCONFIG_SET_PATH` + SetPath = 3, + + /// `FSCONFIG_SET_PATH_EMPTY` + SetPathEmpty = 4, + + /// `FSCONFIG_SET_FD` + SetFd = 5, + + /// `FSCONFIG_CMD_CREATE` + Create = 6, + + /// `FSCONFIG_CMD_RECONFIGURE` + Reconfigure = 7, +} + #[cfg(any(linux_kernel, target_os = "freebsd"))] bitflags! { /// `MFD_*` constants for use with [`memfd_create`]. @@ -1162,6 +1194,167 @@ bitflags! { } } +#[cfg(linux_kernel)] +bitflags! { + /// `FSOPEN_*` constants for use with [`fsopen`]. + /// + /// [`fsopen`]: crate::fs::fsopen + #[repr(transparent)] + #[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)] + pub struct FsOpenFlags: c::c_uint { + + /// `FSOPEN_CLOEXEC` + const FSOPEN_CLOEXEC = 0x00000001; + } +} + +#[cfg(linux_kernel)] +bitflags! { + /// `FSMOUNT_*` constants for use with [`fsmount`]. + /// + /// [`fsmount`]: crate::fs::fsmount + #[repr(transparent)] + #[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)] + pub struct FsMountFlags: c::c_uint { + /// `FSMOUNT_CLOEXEC` + const FSMOUNT_CLOEXEC = 0x00000001; + } +} + +#[cfg(linux_kernel)] +bitflags! { + /// `MOUNT_ATTR_*` constants for use with [`fsmount`]. + /// + /// [`fsmount`]: crate::fs::fsmount + #[repr(transparent)] + #[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)] + pub struct MountAttrFlags: c::c_uint { + /// `MOUNT_ATTR_RDONLY` + const MOUNT_ATTR_RDONLY = 0x00000001; + + /// `MOUNT_ATTR_NOSUID` + const MOUNT_ATTR_NOSUID = 0x00000002; + + /// `MOUNT_ATTR_NODEV` + const MOUNT_ATTR_NODEV = 0x00000004; + + /// `MOUNT_ATTR_NOEXEC` + const MOUNT_ATTR_NOEXEC = 0x00000008; + + /// `MOUNT_ATTR__ATIME` + const MOUNT_ATTR__ATIME = 0x00000070; + + /// `MOUNT_ATTR_RELATIME` + const MOUNT_ATTR_RELATIME = 0x00000000; + + /// `MOUNT_ATTR_NOATIME` + const MOUNT_ATTR_NOATIME = 0x00000010; + + /// `MOUNT_ATTR_STRICTATIME` + const MOUNT_ATTR_STRICTATIME = 0x00000020; + + /// `MOUNT_ATTR_NODIRATIME` + const MOUNT_ATTR_NODIRATIME = 0x00000080; + + /// `MOUNT_ATTR_NOUSER` + const MOUNT_ATTR_IDMAP = 0x00100000; + + /// `MOUNT_ATTR__ATIME_FLAGS` + const MOUNT_ATTR_NOSYMFOLLOW = 0x00200000; + + /// `MOUNT_ATTR__ATIME_FLAGS` + const MOUNT_ATTR_SIZE_VER0 = 32; + } +} + +#[cfg(linux_kernel)] +bitflags! { + /// `MOVE_MOUNT_*` constants for use with [`move_mount`]. + /// + /// [`move_mount`]: crate::fs::move_mount + #[repr(transparent)] + #[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)] + pub struct MoveMountFlags: c::c_uint { + /// `MOVE_MOUNT_F_EMPTY_PATH` + const MOVE_MOUNT_F_SYMLINKS = 0x00000001; + + /// `MOVE_MOUNT_F_AUTOMOUNTS` + const MOVE_MOUNT_F_AUTOMOUNTS = 0x00000002; + + /// `MOVE_MOUNT_F_EMPTY_PATH` + const MOVE_MOUNT_F_EMPTY_PATH = 0x00000004; + + /// `MOVE_MOUNT_T_SYMLINKS` + const MOVE_MOUNT_T_SYMLINKS = 0x00000010; + + /// `MOVE_MOUNT_T_AUTOMOUNTS` + const MOVE_MOUNT_T_AUTOMOUNTS = 0x00000020; + + /// `MOVE_MOUNT_T_EMPTY_PATH` + const MOVE_MOUNT_T_EMPTY_PATH = 0x00000040; + + /// `MOVE_MOUNT__MASK` + const MOVE_MOUNT_SET_GROUP = 0x00000100; + + // TODO: add when linux 6.5 is released + // /// `MOVE_MOUNT_BENEATH` + // const MOVE_MOUNT_BENEATH = 0x00000200; + + /// `MOVE_MOUNT__MASK` + const MOVE_MOUNT__MASK = 0x00000377; + } +} + +#[cfg(linux_kernel)] +bitflags! { + /// `OPENTREE_*` constants for use with [`open_tree`]. + /// + /// [`open_tree`]: crate::fs::open_tree + #[repr(transparent)] + #[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)] + pub struct OpenTreeFlags: c::c_uint { + /// `OPENTREE_CLONE` + const OPEN_TREE_CLONE = 1; + + /// `OPENTREE_CLOEXEC` + const OPEN_TREE_CLOEXEC = c::O_CLOEXEC as c::c_uint; + + /// `AT_EMPTY_PATH` + const AT_EMPTY_PATH = c::AT_EMPTY_PATH as c::c_uint; + + /// `AT_NO_AUTOMOUNT` + const AT_NO_AUTOMOUNT = c::AT_NO_AUTOMOUNT as c::c_uint; + + /// `AT_RECURSIVE` + const AT_RECURSIVE = c::AT_RECURSIVE as c::c_uint; + + /// `AT_SYMLINK_NOFOLLOW` + const AT_SYMLINK_NOFOLLOW = c::AT_SYMLINK_NOFOLLOW as c::c_uint; + } +} + +#[cfg(linux_kernel)] +bitflags! { + /// `FSPICK_*` constants for use with [`fspick`]. + /// + /// [`fspick`]: crate::fs::fspick + #[repr(transparent)] + #[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)] + pub struct FsPickFlags: c::c_uint { + /// `FSPICK_CLOEXEC` + const FSPICK_CLOEXEC = 0x00000001; + + /// `FSPICK_SYMLINK_NOFOLLOW` + const FSPICK_SYMLINK_NOFOLLOW = 0x00000002; + + /// `FSPICK_NO_AUTOMOUNT` + const FSPICK_NO_AUTOMOUNT = 0x00000004; + + /// `FSPICK_EMPTY_PATH` + const FSPICK_EMPTY_PATH = 0x00000008; + } +} + #[cfg(linux_kernel)] bitflags! { /// `MS_*` constants for use with [`change_mount`]. From 2bac50739feca034429daebd6029f9b8970c15a4 Mon Sep 17 00:00:00 2001 From: LoveSy <shana@zju.edu.cn> Date: Wed, 19 Jul 2023 23:03:48 +0800 Subject: [PATCH 3/3] Add new mount api syscall for linux --- src/backend/libc/fs/syscalls.rs | 13 --- src/backend/linux_raw/fs/syscalls.rs | 13 --- src/fs/mount.rs | 145 ++++++++++++++++++++++++++- 3 files changed, 144 insertions(+), 27 deletions(-) diff --git a/src/backend/libc/fs/syscalls.rs b/src/backend/libc/fs/syscalls.rs index c38b4b6bf..817d89c19 100644 --- a/src/backend/libc/fs/syscalls.rs +++ b/src/backend/libc/fs/syscalls.rs @@ -2087,7 +2087,6 @@ pub(crate) fn unmount(target: &CStr, flags: super::types::UnmountFlags) -> io::R unsafe { ret(c::umount2(target.as_ptr(), bitflags_bits!(flags))) } } -#[allow(dead_code)] #[cfg(linux_kernel)] pub(crate) fn fsopen(fs_name: &CStr, flags: super::types::FsOpenFlags) -> io::Result<OwnedFd> { syscall! { @@ -2099,7 +2098,6 @@ pub(crate) fn fsopen(fs_name: &CStr, flags: super::types::FsOpenFlags) -> io::Re unsafe { ret_owned_fd(fsopen(c_str(fs_name), flags.bits())) } } -#[allow(dead_code)] #[cfg(linux_kernel)] pub(crate) fn fsmount( fs_fd: BorrowedFd<'_>, @@ -2116,7 +2114,6 @@ pub(crate) fn fsmount( unsafe { ret(fsmount(borrowed_fd(fs_fd), flags.bits(), attr_flags.bits())) } } -#[allow(dead_code)] #[cfg(linux_kernel)] pub(crate) fn move_mount( from_dfd: BorrowedFd<'_>, @@ -2145,7 +2142,6 @@ pub(crate) fn move_mount( } } -#[allow(dead_code)] #[cfg(linux_kernel)] pub(crate) fn open_tree( dfd: BorrowedFd<'_>, @@ -2163,7 +2159,6 @@ pub(crate) fn open_tree( unsafe { ret_owned_fd(open_tree(borrowed_fd(dfd), c_str(filename), flags.bits())) } } -#[allow(dead_code)] #[cfg(linux_kernel)] pub(crate) fn fspick( dfd: BorrowedFd<'_>, @@ -2192,7 +2187,6 @@ syscall! { ) via SYS_fsconfig -> c::c_int } -#[allow(dead_code)] #[cfg(linux_kernel)] pub(crate) fn fsconfig_set_flag(fs_fd: BorrowedFd<'_>, key: &CStr) -> io::Result<()> { unsafe { @@ -2206,7 +2200,6 @@ pub(crate) fn fsconfig_set_flag(fs_fd: BorrowedFd<'_>, key: &CStr) -> io::Result } } -#[allow(dead_code)] #[cfg(linux_kernel)] pub(crate) fn fsconfig_set_string( fs_fd: BorrowedFd<'_>, @@ -2224,7 +2217,6 @@ pub(crate) fn fsconfig_set_string( } } -#[allow(dead_code)] #[cfg(linux_kernel)] pub(crate) fn fsconfig_set_binary( fs_fd: BorrowedFd<'_>, @@ -2242,7 +2234,6 @@ pub(crate) fn fsconfig_set_binary( } } -#[allow(dead_code)] #[cfg(linux_kernel)] pub(crate) fn fsconfig_set_fd( fs_fd: BorrowedFd<'_>, @@ -2260,7 +2251,6 @@ pub(crate) fn fsconfig_set_fd( } } -#[allow(dead_code)] #[cfg(linux_kernel)] pub(crate) fn fsconfig_set_path( fs_fd: BorrowedFd<'_>, @@ -2279,7 +2269,6 @@ pub(crate) fn fsconfig_set_path( } } -#[allow(dead_code)] #[cfg(linux_kernel)] pub(crate) fn fsconfig_set_path_empty( fs_fd: BorrowedFd<'_>, @@ -2297,7 +2286,6 @@ pub(crate) fn fsconfig_set_path_empty( } } -#[allow(dead_code)] #[cfg(linux_kernel)] pub(crate) fn fsconfig_create(fs_fd: BorrowedFd<'_>) -> io::Result<()> { unsafe { @@ -2311,7 +2299,6 @@ pub(crate) fn fsconfig_create(fs_fd: BorrowedFd<'_>) -> io::Result<()> { } } -#[allow(dead_code)] #[cfg(linux_kernel)] pub(crate) fn fsconfig_reconfigure(fs_fd: BorrowedFd<'_>) -> io::Result<()> { unsafe { diff --git a/src/backend/linux_raw/fs/syscalls.rs b/src/backend/linux_raw/fs/syscalls.rs index 8d8b76c7a..425c0efc2 100644 --- a/src/backend/linux_raw/fs/syscalls.rs +++ b/src/backend/linux_raw/fs/syscalls.rs @@ -1436,13 +1436,11 @@ pub(crate) fn mount( } } -#[allow(dead_code)] #[inline] pub(crate) fn fsopen(fs_name: &CStr, flags: super::types::FsOpenFlags) -> io::Result<OwnedFd> { unsafe { ret_owned_fd(syscall_readonly!(__NR_fsopen, fs_name, flags)) } } -#[allow(dead_code)] #[inline] pub(crate) fn fsmount( fs_fd: BorrowedFd<'_>, @@ -1452,7 +1450,6 @@ pub(crate) fn fsmount( unsafe { ret(syscall_readonly!(__NR_fsmount, fs_fd, flags, attr_flags)) } } -#[allow(dead_code)] #[inline] pub(crate) fn move_mount( from_dfd: BorrowedFd<'_>, @@ -1473,7 +1470,6 @@ pub(crate) fn move_mount( } } -#[allow(dead_code)] #[inline] pub(crate) fn open_tree( dfd: BorrowedFd<'_>, @@ -1483,7 +1479,6 @@ pub(crate) fn open_tree( unsafe { ret_owned_fd(syscall_readonly!(__NR_open_tree, dfd, filename, flags)) } } -#[allow(dead_code)] #[inline] pub(crate) fn fspick( dfd: BorrowedFd<'_>, @@ -1493,7 +1488,6 @@ pub(crate) fn fspick( unsafe { ret_owned_fd(syscall_readonly!(__NR_fspick, dfd, path, flags)) } } -#[allow(dead_code)] #[inline] pub(crate) fn fsconfig_set_flag(fs_fd: BorrowedFd<'_>, key: &CStr) -> io::Result<()> { unsafe { @@ -1508,7 +1502,6 @@ pub(crate) fn fsconfig_set_flag(fs_fd: BorrowedFd<'_>, key: &CStr) -> io::Result } } -#[allow(dead_code)] #[inline] pub(crate) fn fsconfig_set_string( fs_fd: BorrowedFd<'_>, @@ -1527,7 +1520,6 @@ pub(crate) fn fsconfig_set_string( } } -#[allow(dead_code)] #[inline] pub(crate) fn fsconfig_set_binary( fs_fd: BorrowedFd<'_>, @@ -1547,7 +1539,6 @@ pub(crate) fn fsconfig_set_binary( } } -#[allow(dead_code)] #[inline] pub(crate) fn fsconfig_set_fd( fs_fd: BorrowedFd<'_>, @@ -1566,7 +1557,6 @@ pub(crate) fn fsconfig_set_fd( } } -#[allow(dead_code)] #[inline] pub(crate) fn fsconfig_set_path( fs_fd: BorrowedFd<'_>, @@ -1586,7 +1576,6 @@ pub(crate) fn fsconfig_set_path( } } -#[allow(dead_code)] #[inline] pub(crate) fn fsconfig_set_path_empty( fs_fd: BorrowedFd<'_>, @@ -1605,7 +1594,6 @@ pub(crate) fn fsconfig_set_path_empty( } } -#[allow(dead_code)] #[inline] pub(crate) fn fsconfig_create(fs_fd: BorrowedFd<'_>) -> io::Result<()> { unsafe { @@ -1620,7 +1608,6 @@ pub(crate) fn fsconfig_create(fs_fd: BorrowedFd<'_>) -> io::Result<()> { } } -#[allow(dead_code)] #[inline] pub(crate) fn fsconfig_reconfigure(fs_fd: BorrowedFd<'_>) -> io::Result<()> { unsafe { diff --git a/src/fs/mount.rs b/src/fs/mount.rs index 1439b1f32..7cf7b2e9b 100644 --- a/src/fs/mount.rs +++ b/src/fs/mount.rs @@ -1,8 +1,10 @@ //! Linux `mount`. use crate::backend::fs::types::{ - InternalMountFlags, MountFlags, MountFlagsArg, MountPropagationFlags, UnmountFlags, + FsMountFlags, FsOpenFlags, FsPickFlags, InternalMountFlags, MountAttrFlags, MountFlags, + MountFlagsArg, MountPropagationFlags, MoveMountFlags, OpenTreeFlags, UnmountFlags, }; +use crate::fd::{BorrowedFd, OwnedFd}; use crate::{backend, io, path}; /// `mount(source, target, filesystemtype, mountflags, data)` @@ -131,6 +133,10 @@ pub fn change_mount<Target: path::Arg>( /// `mount(source, target, NULL, MS_MOVE, NULL)` /// +/// This is not the same as the `move_mount` syscall. If you want to use that, +/// use [`move_mount_syscall`] instead. +/// Its name will be changed in the next semver bump to avoid confusion. +/// /// # References /// - [Linux] /// @@ -160,7 +166,144 @@ pub fn move_mount<Source: path::Arg, Target: path::Arg>( /// - [Linux] /// /// [Linux]: https://man7.org/linux/man-pages/man2/umount.2.html +#[inline] #[doc(alias = "umount", alias = "umount2")] pub fn unmount<Target: path::Arg>(target: Target, flags: UnmountFlags) -> io::Result<()> { target.into_with_c_str(|target| backend::fs::syscalls::unmount(target, flags)) } + +/// `fsopen(fs_name, flags)` +#[inline] +pub fn fsopen<Fs: path::Arg>(fs_name: Fs, flags: FsOpenFlags) -> io::Result<OwnedFd> { + fs_name.into_with_c_str(|fs_name| backend::fs::syscalls::fsopen(fs_name, flags)) +} + +/// `fsmount(fs_fd, flags, attr_flags)` +#[inline] +pub fn fsmount( + fs_fd: BorrowedFd<'_>, + flags: FsMountFlags, + attr_flags: MountAttrFlags, +) -> io::Result<()> { + backend::fs::syscalls::fsmount(fs_fd, flags, attr_flags) +} + +/// `move_mount(from_dfd, from_pathname, to_dfd, to_pathname, flags)` +/// This is the `move_mount` syscall, and it will be renamed to `move_mount` +/// in the next semver bump. +#[inline] +#[doc(alias = "move_mount")] +pub fn move_mount_syscall<From: path::Arg, To: path::Arg>( + from_dfd: BorrowedFd<'_>, + from_pathname: From, + to_dfd: BorrowedFd<'_>, + to_pathname: To, + flags: MoveMountFlags, +) -> io::Result<()> { + from_pathname.into_with_c_str(|from_pathname| { + to_pathname.into_with_c_str(|to_pathname| { + backend::fs::syscalls::move_mount(from_dfd, from_pathname, to_dfd, to_pathname, flags) + }) + }) +} + +/// `open_tree(dfd, filename, flags)` +#[inline] +pub fn open_tree<Path: path::Arg>( + dfd: BorrowedFd<'_>, + filename: Path, + flags: OpenTreeFlags, +) -> io::Result<OwnedFd> { + filename.into_with_c_str(|filename| backend::fs::syscalls::open_tree(dfd, filename, flags)) +} + +/// `fspick(dfd, path, flags)` +#[inline] +pub fn fspick<Path: path::Arg>( + dfd: BorrowedFd<'_>, + path: Path, + flags: FsPickFlags, +) -> io::Result<OwnedFd> { + path.into_with_c_str(|path| backend::fs::syscalls::fspick(dfd, path, flags)) +} + +/// `fsconfig(fs_fd, FSCONFIG_SET_FLAG, key, NULL, 0)` +#[inline] +#[doc(alias = "fsconfig")] +pub fn fsconfig_set_flag<Key: path::Arg>(fs_fd: BorrowedFd<'_>, key: Key) -> io::Result<()> { + key.into_with_c_str(|key| backend::fs::syscalls::fsconfig_set_flag(fs_fd, key)) +} + +/// `fsconfig(fs_fd, FSCONFIG_SET_STRING, key, value, 0)` +#[inline] +#[doc(alias = "fsconfig")] +pub fn fsconfig_set_string<Key: path::Arg, Value: path::Arg>( + fs_fd: BorrowedFd<'_>, + key: Key, + value: Value, +) -> io::Result<()> { + key.into_with_c_str(|key| { + value.into_with_c_str(|value| backend::fs::syscalls::fsconfig_set_string(fs_fd, key, value)) + }) +} + +/// `fsconfig(fs_fd, FSCONFIG_SET_BINARY, key, value, value.len())` +#[inline] +#[doc(alias = "fsconfig")] +pub fn fsconfig_set_binary<Key: path::Arg>( + fs_fd: BorrowedFd<'_>, + key: Key, + value: &[u8], +) -> io::Result<()> { + key.into_with_c_str(|key| backend::fs::syscalls::fsconfig_set_binary(fs_fd, key, value)) +} + +/// `fsconfig(fs_fd, FSCONFIG_SET_PATH, key, path, fd)` +#[inline] +#[doc(alias = "fsconfig")] +pub fn fsconfig_set_path<Key: path::Arg, Path: path::Arg>( + fs_fd: BorrowedFd<'_>, + key: Key, + path: Path, + fd: BorrowedFd<'_>, +) -> io::Result<()> { + key.into_with_c_str(|key| { + path.into_with_c_str(|path| backend::fs::syscalls::fsconfig_set_path(fs_fd, key, path, fd)) + }) +} + +/// `fsconfig(fs_fd, FSCONFIG_SET_PATH_EMPTY, key, "", fd)` +#[inline] +#[doc(alias = "fsconfig")] +pub fn fsconfig_set_path_empty<Key: path::Arg>( + fs_fd: BorrowedFd<'_>, + key: Key, + fd: BorrowedFd<'_>, +) -> io::Result<()> { + key.into_with_c_str(|key| backend::fs::syscalls::fsconfig_set_path_empty(fs_fd, key, fd)) +} + +/// `fsconfig(fs_fd, FSCONFIG_SET_FD, key, NULL, fd)` +#[inline] +#[doc(alias = "fsconfig")] +pub fn fsconfig_set_fd<Key: path::Arg>( + fs_fd: BorrowedFd<'_>, + key: Key, + fd: BorrowedFd<'_>, +) -> io::Result<()> { + key.into_with_c_str(|key| backend::fs::syscalls::fsconfig_set_fd(fs_fd, key, fd)) +} + +/// `fsconfig(fs_fd, FSCONFIG_CMD_CREATE, key, NULL, 0)` +#[inline] +#[doc(alias = "fsconfig")] +pub fn fsconfig_create(fs_fd: BorrowedFd<'_>) -> io::Result<()> { + backend::fs::syscalls::fsconfig_create(fs_fd) +} + +/// `fsconfig(fs_fd, FSCONFIG_CMD_RECONFIGURE, key, NULL, 0)` +#[inline] +#[doc(alias = "fsconfig")] +pub fn fsconfig_reconfigure(fs_fd: BorrowedFd<'_>) -> io::Result<()> { + backend::fs::syscalls::fsconfig_reconfigure(fs_fd) +}