1*1d37ca6dSDonkey Kane use core::ffi::c_void; 282df0a13Shmt use core::mem::size_of; 32dbef785SGnoCiYeH 482df0a13Shmt use alloc::{string::String, sync::Arc, vec::Vec}; 591e9d4abSLoGin use system_error::SystemError; 6004e86ffSlogin 7*1d37ca6dSDonkey Kane use crate::producefs; 8004e86ffSlogin use crate::{ 9c566df45SLoGin driver::base::{block::SeekFrom, device::device_number::DeviceNumber}, 10*1d37ca6dSDonkey Kane filesystem::vfs::{core as Vcore, file::FileDescriptorVec}, 11*1d37ca6dSDonkey Kane kerror, 121496ba7bSLoGin libs::rwlock::RwLockWriteGuard, 134fda81ceSLoGin mm::{verify_area, VirtAddr}, 141496ba7bSLoGin process::ProcessManager, 15709498caSLoGin syscall::{ 16*1d37ca6dSDonkey Kane user_access::{self, check_and_clone_cstr, UserBufferWriter}, 1791e9d4abSLoGin Syscall, 18709498caSLoGin }, 1967b48188Shoumkh time::TimeSpec, 20004e86ffSlogin }; 21004e86ffSlogin 22004e86ffSlogin use super::{ 23ab5c8ca4Slogin core::{do_mkdir, do_remove_dir, do_unlink_at}, 24709498caSLoGin fcntl::{AtFlags, FcntlCommand, FD_CLOEXEC}, 25004e86ffSlogin file::{File, FileMode}, 260fb515b0SLoGin open::{do_faccessat, do_fchmodat, do_sys_open}, 279b0abe6dSLoGin utils::{rsplit_path, user_path_at}, 28*1d37ca6dSDonkey Kane Dirent, FileType, IndexNode, FSMAKER, MAX_PATHLEN, ROOT_INODE, VFS_MAX_FOLLOW_SYMLINK_TIMES, 29004e86ffSlogin }; 3040314b30SXiaoye Zheng // use crate::kdebug; 31004e86ffSlogin 32ab5c8ca4Slogin pub const SEEK_SET: u32 = 0; 33ab5c8ca4Slogin pub const SEEK_CUR: u32 = 1; 34ab5c8ca4Slogin pub const SEEK_END: u32 = 2; 35ab5c8ca4Slogin pub const SEEK_MAX: u32 = 3; 36004e86ffSlogin 3767b48188Shoumkh bitflags! { 3867b48188Shoumkh /// 文件类型和权限 396b4e7a29SLoGin #[repr(C)] 4067b48188Shoumkh pub struct ModeType: u32 { 4167b48188Shoumkh /// 掩码 4267b48188Shoumkh const S_IFMT = 0o0_170_000; 4367b48188Shoumkh /// 文件类型 4467b48188Shoumkh const S_IFSOCK = 0o140000; 4567b48188Shoumkh const S_IFLNK = 0o120000; 4667b48188Shoumkh const S_IFREG = 0o100000; 4767b48188Shoumkh const S_IFBLK = 0o060000; 4867b48188Shoumkh const S_IFDIR = 0o040000; 4967b48188Shoumkh const S_IFCHR = 0o020000; 5067b48188Shoumkh const S_IFIFO = 0o010000; 5167b48188Shoumkh 5267b48188Shoumkh const S_ISUID = 0o004000; 5367b48188Shoumkh const S_ISGID = 0o002000; 5467b48188Shoumkh const S_ISVTX = 0o001000; 5567b48188Shoumkh /// 文件用户权限 5667b48188Shoumkh const S_IRWXU = 0o0700; 5767b48188Shoumkh const S_IRUSR = 0o0400; 5867b48188Shoumkh const S_IWUSR = 0o0200; 5967b48188Shoumkh const S_IXUSR = 0o0100; 6067b48188Shoumkh /// 文件组权限 6167b48188Shoumkh const S_IRWXG = 0o0070; 6267b48188Shoumkh const S_IRGRP = 0o0040; 6367b48188Shoumkh const S_IWGRP = 0o0020; 6467b48188Shoumkh const S_IXGRP = 0o0010; 6567b48188Shoumkh /// 文件其他用户权限 6667b48188Shoumkh const S_IRWXO = 0o0007; 6767b48188Shoumkh const S_IROTH = 0o0004; 6867b48188Shoumkh const S_IWOTH = 0o0002; 6967b48188Shoumkh const S_IXOTH = 0o0001; 7006d5e247SLoGin 7106d5e247SLoGin /// 0o777 7206d5e247SLoGin const S_IRWXUGO = Self::S_IRWXU.bits | Self::S_IRWXG.bits | Self::S_IRWXO.bits; 7306d5e247SLoGin /// 0o7777 7406d5e247SLoGin const S_IALLUGO = Self::S_ISUID.bits | Self::S_ISGID.bits | Self::S_ISVTX.bits| Self::S_IRWXUGO.bits; 7506d5e247SLoGin /// 0o444 7606d5e247SLoGin const S_IRUGO = Self::S_IRUSR.bits | Self::S_IRGRP.bits | Self::S_IROTH.bits; 7706d5e247SLoGin /// 0o222 7806d5e247SLoGin const S_IWUGO = Self::S_IWUSR.bits | Self::S_IWGRP.bits | Self::S_IWOTH.bits; 7906d5e247SLoGin /// 0o111 8006d5e247SLoGin const S_IXUGO = Self::S_IXUSR.bits | Self::S_IXGRP.bits | Self::S_IXOTH.bits; 8106d5e247SLoGin 8206d5e247SLoGin 8367b48188Shoumkh } 8467b48188Shoumkh } 8567b48188Shoumkh 8667b48188Shoumkh #[repr(C)] 8782df0a13Shmt #[derive(Clone, Copy)] 8867b48188Shoumkh /// # 文件信息结构体 8967b48188Shoumkh pub struct PosixKstat { 9067b48188Shoumkh /// 硬件设备ID 9167b48188Shoumkh dev_id: u64, 9267b48188Shoumkh /// inode号 9367b48188Shoumkh inode: u64, 9467b48188Shoumkh /// 硬链接数 9567b48188Shoumkh nlink: u64, 9667b48188Shoumkh /// 文件权限 9767b48188Shoumkh mode: ModeType, 9867b48188Shoumkh /// 所有者用户ID 9967b48188Shoumkh uid: i32, 10067b48188Shoumkh /// 所有者组ID 10167b48188Shoumkh gid: i32, 10267b48188Shoumkh /// 设备ID 10367b48188Shoumkh rdev: i64, 10467b48188Shoumkh /// 文件大小 10567b48188Shoumkh size: i64, 10667b48188Shoumkh /// 文件系统块大小 10767b48188Shoumkh blcok_size: i64, 10867b48188Shoumkh /// 分配的512B块数 10967b48188Shoumkh blocks: u64, 11067b48188Shoumkh /// 最后访问时间 11167b48188Shoumkh atime: TimeSpec, 11267b48188Shoumkh /// 最后修改时间 11367b48188Shoumkh mtime: TimeSpec, 11467b48188Shoumkh /// 最后状态变化时间 11567b48188Shoumkh ctime: TimeSpec, 11667b48188Shoumkh /// 用于填充结构体大小的空白数据 11767b48188Shoumkh pub _pad: [i8; 24], 11867b48188Shoumkh } 11967b48188Shoumkh impl PosixKstat { 12067b48188Shoumkh fn new() -> Self { 12167b48188Shoumkh Self { 12267b48188Shoumkh inode: 0, 12367b48188Shoumkh dev_id: 0, 12467b48188Shoumkh mode: ModeType { bits: 0 }, 12567b48188Shoumkh nlink: 0, 12667b48188Shoumkh uid: 0, 12767b48188Shoumkh gid: 0, 12867b48188Shoumkh rdev: 0, 12967b48188Shoumkh size: 0, 13067b48188Shoumkh atime: TimeSpec { 13167b48188Shoumkh tv_sec: 0, 13267b48188Shoumkh tv_nsec: 0, 13367b48188Shoumkh }, 13467b48188Shoumkh mtime: TimeSpec { 13567b48188Shoumkh tv_sec: 0, 13667b48188Shoumkh tv_nsec: 0, 13767b48188Shoumkh }, 13867b48188Shoumkh ctime: TimeSpec { 13967b48188Shoumkh tv_sec: 0, 14067b48188Shoumkh tv_nsec: 0, 14167b48188Shoumkh }, 14267b48188Shoumkh blcok_size: 0, 14367b48188Shoumkh blocks: 0, 14467b48188Shoumkh _pad: Default::default(), 14567b48188Shoumkh } 14667b48188Shoumkh } 14767b48188Shoumkh } 1480fb515b0SLoGin 1490fb515b0SLoGin /// 1500fb515b0SLoGin /// Arguments for how openat2(2) should open the target path. If only @flags and 1510fb515b0SLoGin /// @mode are non-zero, then openat2(2) operates very similarly to openat(2). 1520fb515b0SLoGin /// 1530fb515b0SLoGin /// However, unlike openat(2), unknown or invalid bits in @flags result in 1540fb515b0SLoGin /// -EINVAL rather than being silently ignored. @mode must be zero unless one of 1550fb515b0SLoGin /// {O_CREAT, O_TMPFILE} are set. 1560fb515b0SLoGin /// 1570fb515b0SLoGin /// ## 成员变量 1580fb515b0SLoGin /// 1590fb515b0SLoGin /// - flags: O_* flags. 1600fb515b0SLoGin /// - mode: O_CREAT/O_TMPFILE file mode. 1610fb515b0SLoGin /// - resolve: RESOLVE_* flags. 1620fb515b0SLoGin #[derive(Debug, Clone, Copy)] 1630fb515b0SLoGin #[repr(C)] 1640fb515b0SLoGin pub struct PosixOpenHow { 1650fb515b0SLoGin pub flags: u64, 1660fb515b0SLoGin pub mode: u64, 1670fb515b0SLoGin pub resolve: u64, 1680fb515b0SLoGin } 1690fb515b0SLoGin 1700fb515b0SLoGin impl PosixOpenHow { 1710fb515b0SLoGin #[allow(dead_code)] 1720fb515b0SLoGin pub fn new(flags: u64, mode: u64, resolve: u64) -> Self { 1730fb515b0SLoGin Self { 1740fb515b0SLoGin flags, 1750fb515b0SLoGin mode, 1760fb515b0SLoGin resolve, 1770fb515b0SLoGin } 1780fb515b0SLoGin } 1790fb515b0SLoGin } 1800fb515b0SLoGin 1810fb515b0SLoGin #[derive(Debug, Clone, Copy)] 1820fb515b0SLoGin pub struct OpenHow { 1830fb515b0SLoGin pub o_flags: FileMode, 1840fb515b0SLoGin pub mode: ModeType, 1850fb515b0SLoGin pub resolve: OpenHowResolve, 1860fb515b0SLoGin } 1870fb515b0SLoGin 1880fb515b0SLoGin impl OpenHow { 1890fb515b0SLoGin pub fn new(mut o_flags: FileMode, mut mode: ModeType, resolve: OpenHowResolve) -> Self { 1900fb515b0SLoGin if !o_flags.contains(FileMode::O_CREAT) { 1910fb515b0SLoGin mode = ModeType::empty(); 1920fb515b0SLoGin } 1930fb515b0SLoGin 1940fb515b0SLoGin if o_flags.contains(FileMode::O_PATH) { 1950fb515b0SLoGin o_flags = o_flags.intersection(FileMode::O_PATH_FLAGS); 1960fb515b0SLoGin } 1970fb515b0SLoGin 1980fb515b0SLoGin Self { 1990fb515b0SLoGin o_flags, 2000fb515b0SLoGin mode, 2010fb515b0SLoGin resolve, 2020fb515b0SLoGin } 2030fb515b0SLoGin } 2040fb515b0SLoGin } 2050fb515b0SLoGin 2060fb515b0SLoGin impl From<PosixOpenHow> for OpenHow { 2070fb515b0SLoGin fn from(posix_open_how: PosixOpenHow) -> Self { 2080fb515b0SLoGin let o_flags = FileMode::from_bits_truncate(posix_open_how.flags as u32); 2090fb515b0SLoGin let mode = ModeType::from_bits_truncate(posix_open_how.mode as u32); 2100fb515b0SLoGin let resolve = OpenHowResolve::from_bits_truncate(posix_open_how.resolve as u64); 2110fb515b0SLoGin return Self::new(o_flags, mode, resolve); 2120fb515b0SLoGin } 2130fb515b0SLoGin } 2140fb515b0SLoGin 2150fb515b0SLoGin bitflags! { 2160fb515b0SLoGin pub struct OpenHowResolve: u64{ 2170fb515b0SLoGin /// Block mount-point crossings 2180fb515b0SLoGin /// (including bind-mounts). 2190fb515b0SLoGin const RESOLVE_NO_XDEV = 0x01; 2200fb515b0SLoGin 2210fb515b0SLoGin /// Block traversal through procfs-style 2220fb515b0SLoGin /// "magic-links" 2230fb515b0SLoGin const RESOLVE_NO_MAGICLINKS = 0x02; 2240fb515b0SLoGin 2250fb515b0SLoGin /// Block traversal through all symlinks 2260fb515b0SLoGin /// (implies OEXT_NO_MAGICLINKS) 2270fb515b0SLoGin const RESOLVE_NO_SYMLINKS = 0x04; 2280fb515b0SLoGin /// Block "lexical" trickery like 2290fb515b0SLoGin /// "..", symlinks, and absolute 2300fb515b0SLoGin const RESOLVE_BENEATH = 0x08; 2310fb515b0SLoGin /// Make all jumps to "/" and ".." 2320fb515b0SLoGin /// be scoped inside the dirfd 2330fb515b0SLoGin /// (similar to chroot(2)). 2340fb515b0SLoGin const RESOLVE_IN_ROOT = 0x10; 2350fb515b0SLoGin // Only complete if resolution can be 2360fb515b0SLoGin // completed through cached lookup. May 2370fb515b0SLoGin // return -EAGAIN if that's not 2380fb515b0SLoGin // possible. 2390fb515b0SLoGin const RESOLVE_CACHED = 0x20; 2400fb515b0SLoGin } 2410fb515b0SLoGin } 242ab5c8ca4Slogin impl Syscall { 243ab5c8ca4Slogin /// @brief 为当前进程打开一个文件 244ab5c8ca4Slogin /// 245ab5c8ca4Slogin /// @param path 文件路径 246ab5c8ca4Slogin /// @param o_flags 打开文件的标志位 247ab5c8ca4Slogin /// 248ab5c8ca4Slogin /// @return 文件描述符编号,或者是错误码 2490fb515b0SLoGin pub fn open( 25082df0a13Shmt path: *const u8, 25182df0a13Shmt o_flags: u32, 25282df0a13Shmt mode: u32, 2530fb515b0SLoGin follow_symlink: bool, 2540fb515b0SLoGin ) -> Result<usize, SystemError> { 25582df0a13Shmt let path = check_and_clone_cstr(path, Some(MAX_PATHLEN))?; 25682df0a13Shmt let open_flags: FileMode = FileMode::from_bits(o_flags).ok_or(SystemError::EINVAL)?; 25782df0a13Shmt let mode = ModeType::from_bits(mode as u32).ok_or(SystemError::EINVAL)?; 25882df0a13Shmt return do_sys_open( 25982df0a13Shmt AtFlags::AT_FDCWD.bits(), 26082df0a13Shmt &path, 26182df0a13Shmt open_flags, 26282df0a13Shmt mode, 26382df0a13Shmt follow_symlink, 26482df0a13Shmt ); 265ab5c8ca4Slogin } 266ab5c8ca4Slogin 2670fb515b0SLoGin pub fn openat( 2680fb515b0SLoGin dirfd: i32, 26982df0a13Shmt path: *const u8, 27082df0a13Shmt o_flags: u32, 27182df0a13Shmt mode: u32, 2720fb515b0SLoGin follow_symlink: bool, 2730fb515b0SLoGin ) -> Result<usize, SystemError> { 27482df0a13Shmt let path = check_and_clone_cstr(path, Some(MAX_PATHLEN))?; 27582df0a13Shmt let open_flags: FileMode = FileMode::from_bits(o_flags).ok_or(SystemError::EINVAL)?; 27682df0a13Shmt let mode = ModeType::from_bits(mode as u32).ok_or(SystemError::EINVAL)?; 27782df0a13Shmt return do_sys_open(dirfd, &path, open_flags, mode, follow_symlink); 278ab5c8ca4Slogin } 279ab5c8ca4Slogin 280ab5c8ca4Slogin /// @brief 关闭文件 281ab5c8ca4Slogin /// 282ab5c8ca4Slogin /// @param fd 文件描述符编号 283ab5c8ca4Slogin /// 284ab5c8ca4Slogin /// @return 成功返回0,失败返回错误码 285ab5c8ca4Slogin pub fn close(fd: usize) -> Result<usize, SystemError> { 2861496ba7bSLoGin let binding = ProcessManager::current_pcb().fd_table(); 2871496ba7bSLoGin let mut fd_table_guard = binding.write(); 2881496ba7bSLoGin 28934e6d6c8Syuyi2439 let res = fd_table_guard.drop_fd(fd as i32).map(|_| 0); 29034e6d6c8Syuyi2439 29134e6d6c8Syuyi2439 return res; 292ab5c8ca4Slogin } 293ab5c8ca4Slogin 29440314b30SXiaoye Zheng /// @brief 发送命令到文件描述符对应的设备, 29540314b30SXiaoye Zheng /// 29640314b30SXiaoye Zheng /// @param fd 文件描述符编号 29740314b30SXiaoye Zheng /// @param cmd 设备相关的请求类型 29840314b30SXiaoye Zheng /// 29940314b30SXiaoye Zheng /// @return Ok(usize) 成功返回0 30040314b30SXiaoye Zheng /// @return Err(SystemError) 读取失败,返回posix错误码 30140314b30SXiaoye Zheng pub fn ioctl(fd: usize, cmd: u32, data: usize) -> Result<usize, SystemError> { 30240314b30SXiaoye Zheng let binding = ProcessManager::current_pcb().fd_table(); 30340314b30SXiaoye Zheng let fd_table_guard = binding.read(); 30440314b30SXiaoye Zheng 30540314b30SXiaoye Zheng let file = fd_table_guard 30640314b30SXiaoye Zheng .get_file_by_fd(fd as i32) 30740314b30SXiaoye Zheng .ok_or(SystemError::EBADF)?; 30840314b30SXiaoye Zheng 30940314b30SXiaoye Zheng // drop guard 以避免无法调度的问题 31040314b30SXiaoye Zheng drop(fd_table_guard); 31152da9a59SGnoCiYeH let file = file.lock_no_preempt(); 31252da9a59SGnoCiYeH let r = file.inode().ioctl(cmd, data, &file.private_data); 31340314b30SXiaoye Zheng return r; 31440314b30SXiaoye Zheng } 31540314b30SXiaoye Zheng 316ab5c8ca4Slogin /// @brief 根据文件描述符,读取文件数据。尝试读取的数据长度与buf的长度相同。 317ab5c8ca4Slogin /// 318ab5c8ca4Slogin /// @param fd 文件描述符编号 31927b967a3S裕依 /// @param buf 输出缓冲区 320ab5c8ca4Slogin /// 321ab5c8ca4Slogin /// @return Ok(usize) 成功读取的数据的字节数 322ab5c8ca4Slogin /// @return Err(SystemError) 读取失败,返回posix错误码 323ab5c8ca4Slogin pub fn read(fd: i32, buf: &mut [u8]) -> Result<usize, SystemError> { 3241496ba7bSLoGin let binding = ProcessManager::current_pcb().fd_table(); 3251496ba7bSLoGin let fd_table_guard = binding.read(); 3261496ba7bSLoGin 3271496ba7bSLoGin let file = fd_table_guard.get_file_by_fd(fd); 328ab5c8ca4Slogin if file.is_none() { 329ab5c8ca4Slogin return Err(SystemError::EBADF); 330ab5c8ca4Slogin } 3311496ba7bSLoGin // drop guard 以避免无法调度的问题 3321496ba7bSLoGin drop(fd_table_guard); 3331496ba7bSLoGin let file = file.unwrap(); 334ab5c8ca4Slogin 3351496ba7bSLoGin return file.lock_no_preempt().read(buf.len(), buf); 336ab5c8ca4Slogin } 337ab5c8ca4Slogin 338ab5c8ca4Slogin /// @brief 根据文件描述符,向文件写入数据。尝试写入的数据长度与buf的长度相同。 339ab5c8ca4Slogin /// 340ab5c8ca4Slogin /// @param fd 文件描述符编号 34127b967a3S裕依 /// @param buf 输入缓冲区 342ab5c8ca4Slogin /// 343ab5c8ca4Slogin /// @return Ok(usize) 成功写入的数据的字节数 344ab5c8ca4Slogin /// @return Err(SystemError) 写入失败,返回posix错误码 345ab5c8ca4Slogin pub fn write(fd: i32, buf: &[u8]) -> Result<usize, SystemError> { 3461496ba7bSLoGin let binding = ProcessManager::current_pcb().fd_table(); 3471496ba7bSLoGin let fd_table_guard = binding.read(); 348ab5c8ca4Slogin 3491496ba7bSLoGin let file = fd_table_guard 3501496ba7bSLoGin .get_file_by_fd(fd) 3511496ba7bSLoGin .ok_or(SystemError::EBADF)?; 3521496ba7bSLoGin 3531496ba7bSLoGin // drop guard 以避免无法调度的问题 3541496ba7bSLoGin drop(fd_table_guard); 3551496ba7bSLoGin return file.lock_no_preempt().write(buf.len(), buf); 356ab5c8ca4Slogin } 357ab5c8ca4Slogin 358ab5c8ca4Slogin /// @brief 调整文件操作指针的位置 359ab5c8ca4Slogin /// 360ab5c8ca4Slogin /// @param fd 文件描述符编号 361ab5c8ca4Slogin /// @param seek 调整的方式 362ab5c8ca4Slogin /// 363ab5c8ca4Slogin /// @return Ok(usize) 调整后,文件访问指针相对于文件头部的偏移量 364ab5c8ca4Slogin /// @return Err(SystemError) 调整失败,返回posix错误码 36582df0a13Shmt pub fn lseek(fd: i32, offset: i64, seek: u32) -> Result<usize, SystemError> { 36682df0a13Shmt let seek = match seek { 36782df0a13Shmt SEEK_SET => Ok(SeekFrom::SeekSet(offset)), 36882df0a13Shmt SEEK_CUR => Ok(SeekFrom::SeekCurrent(offset)), 36982df0a13Shmt SEEK_END => Ok(SeekFrom::SeekEnd(offset)), 37082df0a13Shmt SEEK_MAX => Ok(SeekFrom::SeekEnd(0)), 37182df0a13Shmt _ => Err(SystemError::EINVAL), 37282df0a13Shmt }?; 37382df0a13Shmt 3741496ba7bSLoGin let binding = ProcessManager::current_pcb().fd_table(); 3751496ba7bSLoGin let fd_table_guard = binding.read(); 3761496ba7bSLoGin let file = fd_table_guard 3771496ba7bSLoGin .get_file_by_fd(fd) 3781496ba7bSLoGin .ok_or(SystemError::EBADF)?; 3791496ba7bSLoGin 3801496ba7bSLoGin // drop guard 以避免无法调度的问题 3811496ba7bSLoGin drop(fd_table_guard); 3821496ba7bSLoGin return file.lock_no_preempt().lseek(seek); 383004e86ffSlogin } 384004e86ffSlogin 38527b967a3S裕依 /// # sys_pread64 系统调用的实际执行函数 38627b967a3S裕依 /// 38727b967a3S裕依 /// ## 参数 38827b967a3S裕依 /// - `fd`: 文件描述符 38927b967a3S裕依 /// - `buf`: 读出缓冲区 39027b967a3S裕依 /// - `len`: 要读取的字节数 39127b967a3S裕依 /// - `offset`: 文件偏移量 39227b967a3S裕依 pub fn pread(fd: i32, buf: &mut [u8], len: usize, offset: usize) -> Result<usize, SystemError> { 39327b967a3S裕依 let binding = ProcessManager::current_pcb().fd_table(); 39427b967a3S裕依 let fd_table_guard = binding.read(); 39527b967a3S裕依 39627b967a3S裕依 let file = fd_table_guard.get_file_by_fd(fd); 39727b967a3S裕依 if file.is_none() { 39827b967a3S裕依 return Err(SystemError::EBADF); 39927b967a3S裕依 } 40027b967a3S裕依 // drop guard 以避免无法调度的问题 40127b967a3S裕依 drop(fd_table_guard); 40227b967a3S裕依 let file = file.unwrap(); 40327b967a3S裕依 40427b967a3S裕依 return file.lock_no_preempt().pread(offset, len, buf); 40527b967a3S裕依 } 40627b967a3S裕依 40727b967a3S裕依 /// # sys_pwrite64 系统调用的实际执行函数 40827b967a3S裕依 /// 40927b967a3S裕依 /// ## 参数 41027b967a3S裕依 /// - `fd`: 文件描述符 41127b967a3S裕依 /// - `buf`: 写入缓冲区 41227b967a3S裕依 /// - `len`: 要写入的字节数 41327b967a3S裕依 /// - `offset`: 文件偏移量 41427b967a3S裕依 pub fn pwrite(fd: i32, buf: &[u8], len: usize, offset: usize) -> Result<usize, SystemError> { 41527b967a3S裕依 let binding = ProcessManager::current_pcb().fd_table(); 41627b967a3S裕依 let fd_table_guard = binding.read(); 41727b967a3S裕依 41827b967a3S裕依 let file = fd_table_guard.get_file_by_fd(fd); 41927b967a3S裕依 if file.is_none() { 42027b967a3S裕依 return Err(SystemError::EBADF); 42127b967a3S裕依 } 42227b967a3S裕依 // drop guard 以避免无法调度的问题 42327b967a3S裕依 drop(fd_table_guard); 42427b967a3S裕依 let file = file.unwrap(); 42527b967a3S裕依 42627b967a3S裕依 return file.lock_no_preempt().pwrite(offset, len, buf); 42727b967a3S裕依 } 42827b967a3S裕依 429004e86ffSlogin /// @brief 切换工作目录 430004e86ffSlogin /// 431004e86ffSlogin /// @param dest_path 目标路径 432004e86ffSlogin /// 433004e86ffSlogin /// @return 返回码 描述 434004e86ffSlogin /// 0 | 成功 435004e86ffSlogin /// 436004e86ffSlogin /// EACCESS | 权限不足 437004e86ffSlogin /// 438004e86ffSlogin /// ELOOP | 解析path时遇到路径循环 439004e86ffSlogin /// 440004e86ffSlogin /// ENAMETOOLONG | 路径名过长 441004e86ffSlogin /// 442004e86ffSlogin /// ENOENT | 目标文件或目录不存在 443004e86ffSlogin /// 444004e86ffSlogin /// ENODIR | 检索期间发现非目录项 445004e86ffSlogin /// 446004e86ffSlogin /// ENOMEM | 系统内存不足 447004e86ffSlogin /// 448004e86ffSlogin /// EFAULT | 错误的地址 449004e86ffSlogin /// 450004e86ffSlogin /// ENAMETOOLONG | 路径过长 45182df0a13Shmt pub fn chdir(path: *const u8) -> Result<usize, SystemError> { 45282df0a13Shmt if path.is_null() { 45382df0a13Shmt return Err(SystemError::EFAULT); 45482df0a13Shmt } 45582df0a13Shmt 45682df0a13Shmt let path = check_and_clone_cstr(path, Some(MAX_PATHLEN))?; 4571496ba7bSLoGin let proc = ProcessManager::current_pcb(); 458ab5c8ca4Slogin // Copy path to kernel space to avoid some security issues 4591496ba7bSLoGin let mut new_path = String::from(""); 4601496ba7bSLoGin if path.len() > 0 { 4611496ba7bSLoGin let cwd = match path.as_bytes()[0] { 4621496ba7bSLoGin b'/' => String::from("/"), 4631496ba7bSLoGin _ => proc.basic().cwd(), 4641496ba7bSLoGin }; 4651496ba7bSLoGin let mut cwd_vec: Vec<_> = cwd.split("/").filter(|&x| x != "").collect(); 4661496ba7bSLoGin let path_split = path.split("/").filter(|&x| x != ""); 4671496ba7bSLoGin for seg in path_split { 4681496ba7bSLoGin if seg == ".." { 4691496ba7bSLoGin cwd_vec.pop(); 4701496ba7bSLoGin } else if seg == "." { 4711496ba7bSLoGin // 当前目录 4721496ba7bSLoGin } else { 4731496ba7bSLoGin cwd_vec.push(seg); 4741496ba7bSLoGin } 4751496ba7bSLoGin } 4761496ba7bSLoGin //proc.basic().set_path(String::from("")); 4771496ba7bSLoGin for seg in cwd_vec { 4781496ba7bSLoGin new_path.push_str("/"); 4791496ba7bSLoGin new_path.push_str(seg); 4801496ba7bSLoGin } 4811496ba7bSLoGin if new_path == "" { 4821496ba7bSLoGin new_path = String::from("/"); 4831496ba7bSLoGin } 4841496ba7bSLoGin } 485a03c4f9dSLoGin let inode = 486a03c4f9dSLoGin match ROOT_INODE().lookup_follow_symlink(&new_path, VFS_MAX_FOLLOW_SYMLINK_TIMES) { 48782df0a13Shmt Err(_) => { 488ab5c8ca4Slogin return Err(SystemError::ENOENT); 489004e86ffSlogin } 490004e86ffSlogin Ok(i) => i, 491004e86ffSlogin }; 4921496ba7bSLoGin let metadata = inode.metadata()?; 4931496ba7bSLoGin if metadata.file_type == FileType::Dir { 4941496ba7bSLoGin proc.basic_mut().set_cwd(String::from(new_path)); 495ab5c8ca4Slogin return Ok(0); 496004e86ffSlogin } else { 497ab5c8ca4Slogin return Err(SystemError::ENOTDIR); 498004e86ffSlogin } 499004e86ffSlogin } 5001496ba7bSLoGin 5011496ba7bSLoGin /// @brief 获取当前进程的工作目录路径 5021496ba7bSLoGin /// 5031496ba7bSLoGin /// @param buf 指向缓冲区的指针 5041496ba7bSLoGin /// @param size 缓冲区的大小 5051496ba7bSLoGin /// 5061496ba7bSLoGin /// @return 成功,返回的指针指向包含工作目录路径的字符串 5071496ba7bSLoGin /// @return 错误,没有足够的空间 5081496ba7bSLoGin pub fn getcwd(buf: &mut [u8]) -> Result<VirtAddr, SystemError> { 5091496ba7bSLoGin let proc = ProcessManager::current_pcb(); 5101496ba7bSLoGin let cwd = proc.basic().cwd(); 5111496ba7bSLoGin 5121496ba7bSLoGin let cwd_bytes = cwd.as_bytes(); 5131496ba7bSLoGin let cwd_len = cwd_bytes.len(); 5141496ba7bSLoGin if cwd_len + 1 > buf.len() { 5151496ba7bSLoGin return Err(SystemError::ENOMEM); 516004e86ffSlogin } 5171496ba7bSLoGin buf[..cwd_len].copy_from_slice(cwd_bytes); 5181496ba7bSLoGin buf[cwd_len] = 0; 5191496ba7bSLoGin 5201496ba7bSLoGin return Ok(VirtAddr::new(buf.as_ptr() as usize)); 521004e86ffSlogin } 522004e86ffSlogin 523004e86ffSlogin /// @brief 获取目录中的数据 524004e86ffSlogin /// 525ab5c8ca4Slogin /// TODO: 这个函数的语义与Linux不一致,需要修改!!! 526ab5c8ca4Slogin /// 527004e86ffSlogin /// @param fd 文件描述符号 528ab5c8ca4Slogin /// @param buf 输出缓冲区 529ab5c8ca4Slogin /// 530ab5c8ca4Slogin /// @return 成功返回读取的字节数,失败返回错误码 531ab5c8ca4Slogin pub fn getdents(fd: i32, buf: &mut [u8]) -> Result<usize, SystemError> { 532ab5c8ca4Slogin let dirent = 533ab5c8ca4Slogin unsafe { (buf.as_mut_ptr() as *mut Dirent).as_mut() }.ok_or(SystemError::EFAULT)?; 534004e86ffSlogin 53546e234aeSLoGin if fd < 0 || fd as usize > FileDescriptorVec::PROCESS_MAX_FD { 536ab5c8ca4Slogin return Err(SystemError::EBADF); 537004e86ffSlogin } 538004e86ffSlogin 539004e86ffSlogin // 获取fd 5401496ba7bSLoGin let binding = ProcessManager::current_pcb().fd_table(); 5411496ba7bSLoGin let fd_table_guard = binding.read(); 5421496ba7bSLoGin let file = fd_table_guard 5431496ba7bSLoGin .get_file_by_fd(fd) 5441496ba7bSLoGin .ok_or(SystemError::EBADF)?; 545004e86ffSlogin 5461496ba7bSLoGin // drop guard 以避免无法调度的问题 5471496ba7bSLoGin drop(fd_table_guard); 54834e6d6c8Syuyi2439 54934e6d6c8Syuyi2439 let res = file.lock_no_preempt().readdir(dirent).map(|x| x as usize); 55034e6d6c8Syuyi2439 55134e6d6c8Syuyi2439 return res; 552004e86ffSlogin } 553004e86ffSlogin 554004e86ffSlogin /// @brief 创建文件夹 555004e86ffSlogin /// 556004e86ffSlogin /// @param path(r8) 路径 / mode(r9) 模式 557004e86ffSlogin /// 558004e86ffSlogin /// @return uint64_t 负数错误码 / 0表示成功 55982df0a13Shmt pub fn mkdir(path: *const u8, mode: usize) -> Result<usize, SystemError> { 56082df0a13Shmt let path = check_and_clone_cstr(path, Some(MAX_PATHLEN))?; 56182df0a13Shmt return do_mkdir(&path, FileMode::from_bits_truncate(mode as u32)).map(|x| x as usize); 562004e86ffSlogin } 563004e86ffSlogin 564ab5c8ca4Slogin /// **删除文件夹、取消文件的链接、删除文件的系统调用** 565004e86ffSlogin /// 566ab5c8ca4Slogin /// ## 参数 567004e86ffSlogin /// 568ab5c8ca4Slogin /// - `dirfd`:文件夹的文件描述符.目前暂未实现 569ab5c8ca4Slogin /// - `pathname`:文件夹的路径 570ab5c8ca4Slogin /// - `flags`:标志位 571004e86ffSlogin /// 572004e86ffSlogin /// 57382df0a13Shmt pub fn unlinkat(dirfd: i32, path: *const u8, flags: u32) -> Result<usize, SystemError> { 574bf4a4899SLoGin let flags = AtFlags::from_bits(flags as i32).ok_or(SystemError::EINVAL)?; 575004e86ffSlogin 57682df0a13Shmt let path = check_and_clone_cstr(path, Some(MAX_PATHLEN))?; 57782df0a13Shmt 578bf4a4899SLoGin if flags.contains(AtFlags::AT_REMOVEDIR) { 579004e86ffSlogin // kdebug!("rmdir"); 58082df0a13Shmt match do_remove_dir(dirfd, &path) { 581004e86ffSlogin Err(err) => { 582ab5c8ca4Slogin return Err(err); 583004e86ffSlogin } 584004e86ffSlogin Ok(_) => { 585ab5c8ca4Slogin return Ok(0); 586004e86ffSlogin } 587004e86ffSlogin } 588004e86ffSlogin } 589004e86ffSlogin 59082df0a13Shmt match do_unlink_at(dirfd, &path) { 591004e86ffSlogin Err(err) => { 592ab5c8ca4Slogin return Err(err); 593004e86ffSlogin } 594004e86ffSlogin Ok(_) => { 595ab5c8ca4Slogin return Ok(0); 596004e86ffSlogin } 597004e86ffSlogin } 598004e86ffSlogin } 5992b771e32SGou Ngai 60082df0a13Shmt pub fn rmdir(path: *const u8) -> Result<usize, SystemError> { 60182df0a13Shmt let path = check_and_clone_cstr(path, Some(MAX_PATHLEN))?; 60282df0a13Shmt return do_remove_dir(AtFlags::AT_FDCWD.bits(), &path).map(|v| v as usize); 6035eeefb8cSChenzx } 6045eeefb8cSChenzx 60582df0a13Shmt pub fn unlink(path: *const u8) -> Result<usize, SystemError> { 60682df0a13Shmt let path = check_and_clone_cstr(path, Some(MAX_PATHLEN))?; 60782df0a13Shmt return do_unlink_at(AtFlags::AT_FDCWD.bits(), &path).map(|v| v as usize); 608bf4a4899SLoGin } 609bf4a4899SLoGin 6109e481b3bSTTaq /// # 修改文件名 6119e481b3bSTTaq /// 6129e481b3bSTTaq /// 6139e481b3bSTTaq /// ## 参数 6149e481b3bSTTaq /// 6159e481b3bSTTaq /// - oldfd: 源文件描述符 6169e481b3bSTTaq /// - filename_from: 源文件路径 6179e481b3bSTTaq /// - newfd: 目标文件描述符 6189e481b3bSTTaq /// - filename_to: 目标文件路径 6199e481b3bSTTaq /// - flags: 标志位 6209e481b3bSTTaq /// 6219e481b3bSTTaq /// 6229e481b3bSTTaq /// ## 返回值 6239e481b3bSTTaq /// - Ok(返回值类型): 返回值的说明 6249e481b3bSTTaq /// - Err(错误值类型): 错误的说明 6259e481b3bSTTaq /// 6269e481b3bSTTaq pub fn do_renameat2( 6279e481b3bSTTaq oldfd: i32, 6289e481b3bSTTaq filename_from: *const u8, 6299e481b3bSTTaq newfd: i32, 6309e481b3bSTTaq filename_to: *const u8, 6319e481b3bSTTaq _flags: u32, 6329e481b3bSTTaq ) -> Result<usize, SystemError> { 6339e481b3bSTTaq let filename_from = check_and_clone_cstr(filename_from, Some(MAX_PATHLEN)).unwrap(); 6349e481b3bSTTaq let filename_to = check_and_clone_cstr(filename_to, Some(MAX_PATHLEN)).unwrap(); 6359e481b3bSTTaq // 文件名过长 6369e481b3bSTTaq if filename_from.len() > MAX_PATHLEN as usize || filename_to.len() > MAX_PATHLEN as usize { 6379e481b3bSTTaq return Err(SystemError::ENAMETOOLONG); 6389e481b3bSTTaq } 6399e481b3bSTTaq 6409e481b3bSTTaq //获取pcb,文件节点 6419e481b3bSTTaq let pcb = ProcessManager::current_pcb(); 6429e481b3bSTTaq let (_old_inode_begin, old_remain_path) = user_path_at(&pcb, oldfd, &filename_from)?; 6439e481b3bSTTaq let (_new_inode_begin, new_remain_path) = user_path_at(&pcb, newfd, &filename_to)?; 6449e481b3bSTTaq //获取父目录 6459e481b3bSTTaq let (old_filename, old_parent_path) = rsplit_path(&old_remain_path); 6469e481b3bSTTaq let old_parent_inode = ROOT_INODE() 6479e481b3bSTTaq .lookup_follow_symlink(old_parent_path.unwrap_or("/"), VFS_MAX_FOLLOW_SYMLINK_TIMES)?; 6489e481b3bSTTaq let (new_filename, new_parent_path) = rsplit_path(&new_remain_path); 6499e481b3bSTTaq let new_parent_inode = ROOT_INODE() 6509e481b3bSTTaq .lookup_follow_symlink(new_parent_path.unwrap_or("/"), VFS_MAX_FOLLOW_SYMLINK_TIMES)?; 6519e481b3bSTTaq old_parent_inode.move_to(old_filename, &new_parent_inode, new_filename)?; 6529e481b3bSTTaq return Ok(0); 6539e481b3bSTTaq } 6549e481b3bSTTaq 655ab5c8ca4Slogin /// @brief 根据提供的文件描述符的fd,复制对应的文件结构体,并返回新复制的文件结构体对应的fd 656ab5c8ca4Slogin pub fn dup(oldfd: i32) -> Result<usize, SystemError> { 6571496ba7bSLoGin let binding = ProcessManager::current_pcb().fd_table(); 6581496ba7bSLoGin let mut fd_table_guard = binding.write(); 659ab5c8ca4Slogin 6601496ba7bSLoGin let old_file = fd_table_guard 6611496ba7bSLoGin .get_file_by_fd(oldfd) 6621496ba7bSLoGin .ok_or(SystemError::EBADF)?; 6631496ba7bSLoGin 6641496ba7bSLoGin let new_file = old_file 6651496ba7bSLoGin .lock_no_preempt() 6661496ba7bSLoGin .try_clone() 6671496ba7bSLoGin .ok_or(SystemError::EBADF)?; 6682b771e32SGou Ngai // 申请文件描述符,并把文件对象存入其中 6691496ba7bSLoGin let res = fd_table_guard.alloc_fd(new_file, None).map(|x| x as usize); 6702b771e32SGou Ngai return res; 6712b771e32SGou Ngai } 6722b771e32SGou Ngai 673ab5c8ca4Slogin /// 根据提供的文件描述符的fd,和指定新fd,复制对应的文件结构体, 674ab5c8ca4Slogin /// 并返回新复制的文件结构体对应的fd. 675ab5c8ca4Slogin /// 如果新fd已经打开,则会先关闭新fd. 676ab5c8ca4Slogin /// 677ab5c8ca4Slogin /// ## 参数 678ab5c8ca4Slogin /// 679ab5c8ca4Slogin /// - `oldfd`:旧文件描述符 680ab5c8ca4Slogin /// - `newfd`:新文件描述符 681ab5c8ca4Slogin /// 682ab5c8ca4Slogin /// ## 返回值 683ab5c8ca4Slogin /// 684ab5c8ca4Slogin /// - 成功:新文件描述符 685ab5c8ca4Slogin /// - 失败:错误码 686ab5c8ca4Slogin pub fn dup2(oldfd: i32, newfd: i32) -> Result<usize, SystemError> { 6871496ba7bSLoGin let binding = ProcessManager::current_pcb().fd_table(); 6881496ba7bSLoGin let mut fd_table_guard = binding.write(); 6891496ba7bSLoGin return Self::do_dup2(oldfd, newfd, &mut fd_table_guard); 6901496ba7bSLoGin } 6911496ba7bSLoGin 6921496ba7bSLoGin fn do_dup2( 6931496ba7bSLoGin oldfd: i32, 6941496ba7bSLoGin newfd: i32, 6951496ba7bSLoGin fd_table_guard: &mut RwLockWriteGuard<'_, FileDescriptorVec>, 6961496ba7bSLoGin ) -> Result<usize, SystemError> { 6972b771e32SGou Ngai // 确认oldfd, newid是否有效 6981496ba7bSLoGin if !(FileDescriptorVec::validate_fd(oldfd) && FileDescriptorVec::validate_fd(newfd)) { 6991496ba7bSLoGin return Err(SystemError::EBADF); 7001496ba7bSLoGin } 7011496ba7bSLoGin 7022b771e32SGou Ngai if oldfd == newfd { 7032b771e32SGou Ngai // 若oldfd与newfd相等 704ab5c8ca4Slogin return Ok(newfd as usize); 7052b771e32SGou Ngai } 7061496ba7bSLoGin let new_exists = fd_table_guard.get_file_by_fd(newfd).is_some(); 7071496ba7bSLoGin if new_exists { 7082b771e32SGou Ngai // close newfd 7091496ba7bSLoGin if let Err(_) = fd_table_guard.drop_fd(newfd) { 7102b771e32SGou Ngai // An I/O error occurred while attempting to close fildes2. 7112b771e32SGou Ngai return Err(SystemError::EIO); 7122b771e32SGou Ngai } 7132b771e32SGou Ngai } 7142b771e32SGou Ngai 7151496ba7bSLoGin let old_file = fd_table_guard 7161496ba7bSLoGin .get_file_by_fd(oldfd) 7171496ba7bSLoGin .ok_or(SystemError::EBADF)?; 7181496ba7bSLoGin let new_file = old_file 7191496ba7bSLoGin .lock_no_preempt() 7201496ba7bSLoGin .try_clone() 7211496ba7bSLoGin .ok_or(SystemError::EBADF)?; 7222b771e32SGou Ngai // 申请文件描述符,并把文件对象存入其中 7231496ba7bSLoGin let res = fd_table_guard 7241496ba7bSLoGin .alloc_fd(new_file, Some(newfd)) 725ab5c8ca4Slogin .map(|x| x as usize); 7262b771e32SGou Ngai return res; 7272b771e32SGou Ngai } 7286d81180bSLoGin 7296d81180bSLoGin /// # fcntl 7306d81180bSLoGin /// 7316d81180bSLoGin /// ## 参数 7326d81180bSLoGin /// 7336d81180bSLoGin /// - `fd`:文件描述符 7346d81180bSLoGin /// - `cmd`:命令 7356d81180bSLoGin /// - `arg`:参数 7366d81180bSLoGin pub fn fcntl(fd: i32, cmd: FcntlCommand, arg: i32) -> Result<usize, SystemError> { 7376d81180bSLoGin match cmd { 7386d81180bSLoGin FcntlCommand::DupFd => { 7396d81180bSLoGin if arg < 0 || arg as usize >= FileDescriptorVec::PROCESS_MAX_FD { 7406d81180bSLoGin return Err(SystemError::EBADF); 7416d81180bSLoGin } 7426d81180bSLoGin let arg = arg as usize; 7436d81180bSLoGin for i in arg..FileDescriptorVec::PROCESS_MAX_FD { 7441496ba7bSLoGin let binding = ProcessManager::current_pcb().fd_table(); 7451496ba7bSLoGin let mut fd_table_guard = binding.write(); 74652da9a59SGnoCiYeH if fd_table_guard.get_file_by_fd(i as i32).is_none() { 7471496ba7bSLoGin return Self::do_dup2(fd, i as i32, &mut fd_table_guard); 7486d81180bSLoGin } 7496d81180bSLoGin } 7506d81180bSLoGin return Err(SystemError::EMFILE); 7516d81180bSLoGin } 7526d81180bSLoGin FcntlCommand::GetFd => { 7536d81180bSLoGin // Get file descriptor flags. 7541496ba7bSLoGin let binding = ProcessManager::current_pcb().fd_table(); 7551496ba7bSLoGin let fd_table_guard = binding.read(); 7561496ba7bSLoGin if let Some(file) = fd_table_guard.get_file_by_fd(fd) { 7571496ba7bSLoGin // drop guard 以避免无法调度的问题 7581496ba7bSLoGin drop(fd_table_guard); 7596d81180bSLoGin 7601496ba7bSLoGin if file.lock().close_on_exec() { 7616d81180bSLoGin return Ok(FD_CLOEXEC as usize); 7626d81180bSLoGin } 7636d81180bSLoGin } 7646d81180bSLoGin return Err(SystemError::EBADF); 7656d81180bSLoGin } 7666d81180bSLoGin FcntlCommand::SetFd => { 7676d81180bSLoGin // Set file descriptor flags. 7681496ba7bSLoGin let binding = ProcessManager::current_pcb().fd_table(); 7691496ba7bSLoGin let fd_table_guard = binding.write(); 7701496ba7bSLoGin 7711496ba7bSLoGin if let Some(file) = fd_table_guard.get_file_by_fd(fd) { 7721496ba7bSLoGin // drop guard 以避免无法调度的问题 7731496ba7bSLoGin drop(fd_table_guard); 7746d81180bSLoGin let arg = arg as u32; 7756d81180bSLoGin if arg & FD_CLOEXEC != 0 { 7761496ba7bSLoGin file.lock().set_close_on_exec(true); 7776d81180bSLoGin } else { 7781496ba7bSLoGin file.lock().set_close_on_exec(false); 7796d81180bSLoGin } 7806d81180bSLoGin return Ok(0); 7816d81180bSLoGin } 7826d81180bSLoGin return Err(SystemError::EBADF); 7836d81180bSLoGin } 7846d81180bSLoGin 7856d81180bSLoGin FcntlCommand::GetFlags => { 7866d81180bSLoGin // Get file status flags. 7871496ba7bSLoGin let binding = ProcessManager::current_pcb().fd_table(); 7881496ba7bSLoGin let fd_table_guard = binding.read(); 7891496ba7bSLoGin 7901496ba7bSLoGin if let Some(file) = fd_table_guard.get_file_by_fd(fd) { 7911496ba7bSLoGin // drop guard 以避免无法调度的问题 7921496ba7bSLoGin drop(fd_table_guard); 7931496ba7bSLoGin return Ok(file.lock_no_preempt().mode().bits() as usize); 7946d81180bSLoGin } 7951496ba7bSLoGin 7966d81180bSLoGin return Err(SystemError::EBADF); 7976d81180bSLoGin } 7986d81180bSLoGin FcntlCommand::SetFlags => { 7996d81180bSLoGin // Set file status flags. 8001496ba7bSLoGin let binding = ProcessManager::current_pcb().fd_table(); 8011496ba7bSLoGin let fd_table_guard = binding.write(); 8021496ba7bSLoGin 8031496ba7bSLoGin if let Some(file) = fd_table_guard.get_file_by_fd(fd) { 8046d81180bSLoGin let arg = arg as u32; 8056d81180bSLoGin let mode = FileMode::from_bits(arg).ok_or(SystemError::EINVAL)?; 8061496ba7bSLoGin // drop guard 以避免无法调度的问题 8071496ba7bSLoGin drop(fd_table_guard); 8081496ba7bSLoGin file.lock_no_preempt().set_mode(mode)?; 8096d81180bSLoGin return Ok(0); 8106d81180bSLoGin } 8111496ba7bSLoGin 8126d81180bSLoGin return Err(SystemError::EBADF); 8136d81180bSLoGin } 8146d81180bSLoGin _ => { 8156d81180bSLoGin // TODO: unimplemented 8166d81180bSLoGin // 未实现的命令,返回0,不报错。 8176d81180bSLoGin 8186d81180bSLoGin // kwarn!("fcntl: unimplemented command: {:?}, defaults to 0.", cmd); 8196d81180bSLoGin return Ok(0); 8206d81180bSLoGin } 8216d81180bSLoGin } 8226d81180bSLoGin } 8236d81180bSLoGin 8246d81180bSLoGin /// # ftruncate 8256d81180bSLoGin /// 8266d81180bSLoGin /// ## 描述 8276d81180bSLoGin /// 8286d81180bSLoGin /// 改变文件大小. 8296d81180bSLoGin /// 如果文件大小大于原来的大小,那么文件的内容将会被扩展到指定的大小,新的空间将会用0填充. 8306d81180bSLoGin /// 如果文件大小小于原来的大小,那么文件的内容将会被截断到指定的大小. 8316d81180bSLoGin /// 8326d81180bSLoGin /// ## 参数 8336d81180bSLoGin /// 8346d81180bSLoGin /// - `fd`:文件描述符 8356d81180bSLoGin /// - `len`:文件大小 8366d81180bSLoGin /// 8376d81180bSLoGin /// ## 返回值 8386d81180bSLoGin /// 8396d81180bSLoGin /// 如果成功,返回0,否则返回错误码. 8406d81180bSLoGin pub fn ftruncate(fd: i32, len: usize) -> Result<usize, SystemError> { 8411496ba7bSLoGin let binding = ProcessManager::current_pcb().fd_table(); 8421496ba7bSLoGin let fd_table_guard = binding.read(); 8431496ba7bSLoGin 8441496ba7bSLoGin if let Some(file) = fd_table_guard.get_file_by_fd(fd) { 8451496ba7bSLoGin // drop guard 以避免无法调度的问题 8461496ba7bSLoGin drop(fd_table_guard); 8471496ba7bSLoGin let r = file.lock_no_preempt().ftruncate(len).map(|_| 0); 8486d81180bSLoGin return r; 8496d81180bSLoGin } 8501496ba7bSLoGin 8516d81180bSLoGin return Err(SystemError::EBADF); 8526d81180bSLoGin } 8531496ba7bSLoGin 85467b48188Shoumkh fn do_fstat(fd: i32) -> Result<PosixKstat, SystemError> { 8551496ba7bSLoGin let binding = ProcessManager::current_pcb().fd_table(); 8561496ba7bSLoGin let fd_table_guard = binding.read(); 8571496ba7bSLoGin let file = fd_table_guard 8581496ba7bSLoGin .get_file_by_fd(fd) 8591496ba7bSLoGin .ok_or(SystemError::EBADF)?; 8601496ba7bSLoGin // drop guard 以避免无法调度的问题 8611496ba7bSLoGin drop(fd_table_guard); 8621496ba7bSLoGin 86367b48188Shoumkh let mut kstat = PosixKstat::new(); 86467b48188Shoumkh // 获取文件信息 8651496ba7bSLoGin let metadata = file.lock().metadata()?; 86667b48188Shoumkh kstat.size = metadata.size as i64; 86767b48188Shoumkh kstat.dev_id = metadata.dev_id as u64; 8686b4e7a29SLoGin kstat.inode = metadata.inode_id.into() as u64; 86967b48188Shoumkh kstat.blcok_size = metadata.blk_size as i64; 87067b48188Shoumkh kstat.blocks = metadata.blocks as u64; 87167b48188Shoumkh 87267b48188Shoumkh kstat.atime.tv_sec = metadata.atime.tv_sec; 87367b48188Shoumkh kstat.atime.tv_nsec = metadata.atime.tv_nsec; 87467b48188Shoumkh kstat.mtime.tv_sec = metadata.mtime.tv_sec; 87567b48188Shoumkh kstat.mtime.tv_nsec = metadata.mtime.tv_nsec; 87667b48188Shoumkh kstat.ctime.tv_sec = metadata.ctime.tv_sec; 87767b48188Shoumkh kstat.ctime.tv_nsec = metadata.ctime.tv_nsec; 87867b48188Shoumkh 87967b48188Shoumkh kstat.nlink = metadata.nlinks as u64; 88067b48188Shoumkh kstat.uid = metadata.uid as i32; 88167b48188Shoumkh kstat.gid = metadata.gid as i32; 88202343d0bSLoGin kstat.rdev = metadata.raw_dev.data() as i64; 8836b4e7a29SLoGin kstat.mode = metadata.mode; 8841496ba7bSLoGin match file.lock().file_type() { 8857eda31b2SLoGin FileType::File => kstat.mode.insert(ModeType::S_IFREG), 88667b48188Shoumkh FileType::Dir => kstat.mode.insert(ModeType::S_IFDIR), 88767b48188Shoumkh FileType::BlockDevice => kstat.mode.insert(ModeType::S_IFBLK), 88867b48188Shoumkh FileType::CharDevice => kstat.mode.insert(ModeType::S_IFCHR), 88967b48188Shoumkh FileType::SymLink => kstat.mode.insert(ModeType::S_IFLNK), 89067b48188Shoumkh FileType::Socket => kstat.mode.insert(ModeType::S_IFSOCK), 89167b48188Shoumkh FileType::Pipe => kstat.mode.insert(ModeType::S_IFIFO), 89240314b30SXiaoye Zheng FileType::KvmDevice => kstat.mode.insert(ModeType::S_IFCHR), 89302343d0bSLoGin FileType::FramebufferDevice => kstat.mode.insert(ModeType::S_IFCHR), 89467b48188Shoumkh } 89567b48188Shoumkh 89667b48188Shoumkh return Ok(kstat); 89767b48188Shoumkh } 8981496ba7bSLoGin 89967b48188Shoumkh pub fn fstat(fd: i32, usr_kstat: *mut PosixKstat) -> Result<usize, SystemError> { 90082df0a13Shmt let mut writer = UserBufferWriter::new(usr_kstat, size_of::<PosixKstat>(), true)?; 9011496ba7bSLoGin let kstat = Self::do_fstat(fd)?; 90282df0a13Shmt 90382df0a13Shmt writer.copy_one_to_user(&kstat, 0)?; 90467b48188Shoumkh return Ok(0); 90567b48188Shoumkh } 9062dbef785SGnoCiYeH 90782df0a13Shmt pub fn stat(path: *const u8, user_kstat: *mut PosixKstat) -> Result<usize, SystemError> { 90882df0a13Shmt let fd = Self::open( 90982df0a13Shmt path, 91082df0a13Shmt FileMode::O_RDONLY.bits(), 91182df0a13Shmt ModeType::empty().bits(), 91282df0a13Shmt true, 91382df0a13Shmt )?; 914bf4a4899SLoGin let r = Self::fstat(fd as i32, user_kstat); 915971462beSGnoCiYeH Self::close(fd).ok(); 916bf4a4899SLoGin return r; 917bf4a4899SLoGin } 918bf4a4899SLoGin 91982df0a13Shmt pub fn lstat(path: *const u8, user_kstat: *mut PosixKstat) -> Result<usize, SystemError> { 92082df0a13Shmt let fd = Self::open( 92182df0a13Shmt path, 92282df0a13Shmt FileMode::O_RDONLY.bits(), 92382df0a13Shmt ModeType::empty().bits(), 92482df0a13Shmt false, 92582df0a13Shmt )?; 926bf4a4899SLoGin let r = Self::fstat(fd as i32, user_kstat); 927bf4a4899SLoGin Self::close(fd).ok(); 928bf4a4899SLoGin return r; 929971462beSGnoCiYeH } 930971462beSGnoCiYeH 9312dbef785SGnoCiYeH pub fn mknod( 93282df0a13Shmt path: *const u8, 9332dbef785SGnoCiYeH mode: ModeType, 9342dbef785SGnoCiYeH dev_t: DeviceNumber, 9352dbef785SGnoCiYeH ) -> Result<usize, SystemError> { 93682df0a13Shmt let path = check_and_clone_cstr(path, Some(MAX_PATHLEN))?; 93782df0a13Shmt let path = path.as_str().trim(); 9382dbef785SGnoCiYeH 939a03c4f9dSLoGin let inode: Result<Arc<dyn IndexNode>, SystemError> = 940a03c4f9dSLoGin ROOT_INODE().lookup_follow_symlink(path, VFS_MAX_FOLLOW_SYMLINK_TIMES); 9412dbef785SGnoCiYeH 9422dbef785SGnoCiYeH if inode.is_ok() { 9432dbef785SGnoCiYeH return Err(SystemError::EEXIST); 9442dbef785SGnoCiYeH } 9452dbef785SGnoCiYeH 9462dbef785SGnoCiYeH let (filename, parent_path) = rsplit_path(path); 9472dbef785SGnoCiYeH 9482dbef785SGnoCiYeH // 查找父目录 949a03c4f9dSLoGin let parent_inode: Arc<dyn IndexNode> = ROOT_INODE() 950a03c4f9dSLoGin .lookup_follow_symlink(parent_path.unwrap_or("/"), VFS_MAX_FOLLOW_SYMLINK_TIMES)?; 9512dbef785SGnoCiYeH // 创建nod 9522dbef785SGnoCiYeH parent_inode.mknod(filename, mode, dev_t)?; 9532dbef785SGnoCiYeH 9542dbef785SGnoCiYeH return Ok(0); 9552dbef785SGnoCiYeH } 956971462beSGnoCiYeH 957971462beSGnoCiYeH pub fn writev(fd: i32, iov: usize, count: usize) -> Result<usize, SystemError> { 958971462beSGnoCiYeH // IoVecs会进行用户态检验 959971462beSGnoCiYeH let iovecs = unsafe { IoVecs::from_user(iov as *const IoVec, count, false) }?; 960971462beSGnoCiYeH 961971462beSGnoCiYeH let data = iovecs.gather(); 962971462beSGnoCiYeH 963971462beSGnoCiYeH Self::write(fd, &data) 964971462beSGnoCiYeH } 965709498caSLoGin 966bf4a4899SLoGin pub fn readv(fd: i32, iov: usize, count: usize) -> Result<usize, SystemError> { 967bf4a4899SLoGin // IoVecs会进行用户态检验 968bf4a4899SLoGin let mut iovecs = unsafe { IoVecs::from_user(iov as *const IoVec, count, true) }?; 969bf4a4899SLoGin 970bf4a4899SLoGin let mut data = Vec::new(); 971bf4a4899SLoGin data.resize(iovecs.0.iter().map(|x| x.len()).sum(), 0); 972bf4a4899SLoGin 973bf4a4899SLoGin let len = Self::read(fd, &mut data)?; 974bf4a4899SLoGin 975bf4a4899SLoGin iovecs.scatter(&data[..len]); 976bf4a4899SLoGin 977bf4a4899SLoGin return Ok(len); 978bf4a4899SLoGin } 979bf4a4899SLoGin 980709498caSLoGin pub fn readlink_at( 981709498caSLoGin dirfd: i32, 982709498caSLoGin path: *const u8, 983709498caSLoGin user_buf: *mut u8, 984709498caSLoGin buf_size: usize, 985709498caSLoGin ) -> Result<usize, SystemError> { 9869b0abe6dSLoGin let path = check_and_clone_cstr(path, Some(MAX_PATHLEN))?; 98782df0a13Shmt let path = path.as_str().trim(); 988709498caSLoGin let mut user_buf = UserBufferWriter::new(user_buf, buf_size, true)?; 989709498caSLoGin 9900fb515b0SLoGin let (inode, path) = user_path_at(&ProcessManager::current_pcb(), dirfd, &path)?; 991709498caSLoGin 992709498caSLoGin let inode = inode.lookup(path.as_str())?; 993709498caSLoGin if inode.metadata()?.file_type != FileType::SymLink { 994709498caSLoGin return Err(SystemError::EINVAL); 995709498caSLoGin } 996709498caSLoGin 997709498caSLoGin let ubuf = user_buf.buffer::<u8>(0).unwrap(); 998709498caSLoGin 999709498caSLoGin let mut file = File::new(inode, FileMode::O_RDONLY)?; 1000709498caSLoGin 1001709498caSLoGin let len = file.read(buf_size, ubuf)?; 1002709498caSLoGin 1003709498caSLoGin return Ok(len); 1004709498caSLoGin } 1005709498caSLoGin 1006709498caSLoGin pub fn readlink( 1007709498caSLoGin path: *const u8, 1008709498caSLoGin user_buf: *mut u8, 1009709498caSLoGin buf_size: usize, 1010709498caSLoGin ) -> Result<usize, SystemError> { 10119b0abe6dSLoGin return Self::readlink_at(AtFlags::AT_FDCWD.bits(), path, user_buf, buf_size); 10129b0abe6dSLoGin } 10139b0abe6dSLoGin 10149b0abe6dSLoGin pub fn access(pathname: *const u8, mode: u32) -> Result<usize, SystemError> { 10159b0abe6dSLoGin return do_faccessat( 10169b0abe6dSLoGin AtFlags::AT_FDCWD.bits(), 10179b0abe6dSLoGin pathname, 1018bf4a4899SLoGin ModeType::from_bits(mode).ok_or(SystemError::EINVAL)?, 10199b0abe6dSLoGin 0, 10209b0abe6dSLoGin ); 10219b0abe6dSLoGin } 10229b0abe6dSLoGin 10239b0abe6dSLoGin pub fn faccessat2( 10249b0abe6dSLoGin dirfd: i32, 10259b0abe6dSLoGin pathname: *const u8, 10269b0abe6dSLoGin mode: u32, 10279b0abe6dSLoGin flags: u32, 10289b0abe6dSLoGin ) -> Result<usize, SystemError> { 1029bf4a4899SLoGin return do_faccessat( 1030bf4a4899SLoGin dirfd, 1031bf4a4899SLoGin pathname, 1032bf4a4899SLoGin ModeType::from_bits(mode).ok_or(SystemError::EINVAL)?, 1033bf4a4899SLoGin flags, 1034bf4a4899SLoGin ); 1035bf4a4899SLoGin } 1036bf4a4899SLoGin 1037bf4a4899SLoGin pub fn chmod(pathname: *const u8, mode: u32) -> Result<usize, SystemError> { 1038bf4a4899SLoGin return do_fchmodat( 1039bf4a4899SLoGin AtFlags::AT_FDCWD.bits(), 1040bf4a4899SLoGin pathname, 1041bf4a4899SLoGin ModeType::from_bits(mode).ok_or(SystemError::EINVAL)?, 1042bf4a4899SLoGin ); 1043bf4a4899SLoGin } 1044bf4a4899SLoGin 1045bf4a4899SLoGin pub fn fchmodat(dirfd: i32, pathname: *const u8, mode: u32) -> Result<usize, SystemError> { 1046bf4a4899SLoGin return do_fchmodat( 1047bf4a4899SLoGin dirfd, 1048bf4a4899SLoGin pathname, 1049bf4a4899SLoGin ModeType::from_bits(mode).ok_or(SystemError::EINVAL)?, 1050bf4a4899SLoGin ); 1051bf4a4899SLoGin } 1052bf4a4899SLoGin 1053bf4a4899SLoGin pub fn fchmod(fd: i32, mode: u32) -> Result<usize, SystemError> { 1054bf4a4899SLoGin let _mode = ModeType::from_bits(mode).ok_or(SystemError::EINVAL)?; 1055bf4a4899SLoGin let binding = ProcessManager::current_pcb().fd_table(); 1056bf4a4899SLoGin let fd_table_guard = binding.read(); 1057bf4a4899SLoGin let _file = fd_table_guard 1058bf4a4899SLoGin .get_file_by_fd(fd) 1059bf4a4899SLoGin .ok_or(SystemError::EBADF)?; 1060bf4a4899SLoGin 1061bf4a4899SLoGin // fchmod没完全实现,因此不修改文件的权限 1062bf4a4899SLoGin // todo: 实现fchmod 1063bf4a4899SLoGin kwarn!("fchmod not fully implemented"); 1064bf4a4899SLoGin return Ok(0); 1065709498caSLoGin } 1066*1d37ca6dSDonkey Kane /// #挂载文件系统 1067*1d37ca6dSDonkey Kane /// 1068*1d37ca6dSDonkey Kane /// 用于挂载文件系统,目前仅支持ramfs挂载 1069*1d37ca6dSDonkey Kane /// 1070*1d37ca6dSDonkey Kane /// ## 参数: 1071*1d37ca6dSDonkey Kane /// 1072*1d37ca6dSDonkey Kane /// - source 挂载设备(暂时不支持) 1073*1d37ca6dSDonkey Kane /// - target 挂载目录 1074*1d37ca6dSDonkey Kane /// - filesystemtype 文件系统 1075*1d37ca6dSDonkey Kane /// - mountflags 挂载选项(暂未实现) 1076*1d37ca6dSDonkey Kane /// - data 带数据挂载 1077*1d37ca6dSDonkey Kane /// 1078*1d37ca6dSDonkey Kane /// ## 返回值 1079*1d37ca6dSDonkey Kane /// - Ok(0): 挂载成功 1080*1d37ca6dSDonkey Kane /// - Err(SystemError) :挂载过程中出错 1081*1d37ca6dSDonkey Kane pub fn mount( 1082*1d37ca6dSDonkey Kane _source: *const u8, 1083*1d37ca6dSDonkey Kane target: *const u8, 1084*1d37ca6dSDonkey Kane filesystemtype: *const u8, 1085*1d37ca6dSDonkey Kane _mountflags: usize, 1086*1d37ca6dSDonkey Kane _data: *const c_void, 1087*1d37ca6dSDonkey Kane ) -> Result<usize, SystemError> { 1088*1d37ca6dSDonkey Kane let target = user_access::check_and_clone_cstr(target, Some(MAX_PATHLEN))?; 1089*1d37ca6dSDonkey Kane 1090*1d37ca6dSDonkey Kane let filesystemtype = user_access::check_and_clone_cstr(filesystemtype, Some(MAX_PATHLEN))?; 1091*1d37ca6dSDonkey Kane 1092*1d37ca6dSDonkey Kane let filesystemtype = producefs!(FSMAKER, filesystemtype)?; 1093*1d37ca6dSDonkey Kane 1094*1d37ca6dSDonkey Kane return Vcore::do_mount(filesystemtype, (format!("{target}")).as_str()); 1095*1d37ca6dSDonkey Kane } 1096*1d37ca6dSDonkey Kane 1097*1d37ca6dSDonkey Kane // 想法:可以在VFS中实现一个文件系统分发器,流程如下: 1098*1d37ca6dSDonkey Kane // 1. 接受从上方传来的文件类型字符串 1099*1d37ca6dSDonkey Kane // 2. 将传入值与启动时准备好的字符串数组逐个比较(probe) 1100*1d37ca6dSDonkey Kane // 3. 直接在函数内调用构造方法并直接返回文件系统对象 1101709498caSLoGin } 1102709498caSLoGin 1103cde5492fSlogin #[repr(C)] 1104cde5492fSlogin #[derive(Debug, Clone, Copy)] 1105cde5492fSlogin pub struct IoVec { 1106cde5492fSlogin /// 缓冲区的起始地址 1107cde5492fSlogin pub iov_base: *mut u8, 1108cde5492fSlogin /// 缓冲区的长度 1109cde5492fSlogin pub iov_len: usize, 1110cde5492fSlogin } 1111cde5492fSlogin 1112cde5492fSlogin /// 用于存储多个来自用户空间的IoVec 1113cde5492fSlogin /// 1114cde5492fSlogin /// 由于目前内核中的文件系统还不支持分散读写,所以暂时只支持将用户空间的IoVec聚合成一个缓冲区,然后进行操作。 1115cde5492fSlogin /// TODO:支持分散读写 1116cde5492fSlogin #[derive(Debug)] 1117cde5492fSlogin pub struct IoVecs(Vec<&'static mut [u8]>); 1118cde5492fSlogin 1119cde5492fSlogin impl IoVecs { 1120cde5492fSlogin /// 从用户空间的IoVec中构造IoVecs 1121cde5492fSlogin /// 1122cde5492fSlogin /// @param iov 用户空间的IoVec 1123cde5492fSlogin /// @param iovcnt 用户空间的IoVec的数量 1124cde5492fSlogin /// @param readv 是否为readv系统调用 1125cde5492fSlogin /// 1126cde5492fSlogin /// @return 构造成功返回IoVecs,否则返回错误码 1127cde5492fSlogin pub unsafe fn from_user( 1128cde5492fSlogin iov: *const IoVec, 1129cde5492fSlogin iovcnt: usize, 1130cde5492fSlogin _readv: bool, 1131cde5492fSlogin ) -> Result<Self, SystemError> { 1132cde5492fSlogin // 检查iov指针所在空间是否合法 11334fda81ceSLoGin verify_area( 11344fda81ceSLoGin VirtAddr::new(iov as usize), 11354fda81ceSLoGin iovcnt * core::mem::size_of::<IoVec>(), 11364fda81ceSLoGin ) 11374fda81ceSLoGin .map_err(|_| SystemError::EFAULT)?; 1138cde5492fSlogin 1139cde5492fSlogin // 将用户空间的IoVec转换为引用(注意:这里的引用是静态的,因为用户空间的IoVec不会被释放) 1140cde5492fSlogin let iovs: &[IoVec] = core::slice::from_raw_parts(iov, iovcnt); 1141cde5492fSlogin 1142cde5492fSlogin let mut slices: Vec<&mut [u8]> = vec![]; 1143cde5492fSlogin slices.reserve(iovs.len()); 1144cde5492fSlogin 1145cde5492fSlogin for iov in iovs.iter() { 1146cde5492fSlogin if iov.iov_len == 0 { 1147cde5492fSlogin continue; 1148cde5492fSlogin } 1149cde5492fSlogin 11504fda81ceSLoGin verify_area( 11514fda81ceSLoGin VirtAddr::new(iov.iov_base as usize), 11524fda81ceSLoGin iovcnt * core::mem::size_of::<IoVec>(), 11534fda81ceSLoGin ) 11544fda81ceSLoGin .map_err(|_| SystemError::EFAULT)?; 1155cde5492fSlogin 1156cde5492fSlogin slices.push(core::slice::from_raw_parts_mut(iov.iov_base, iov.iov_len)); 1157cde5492fSlogin } 1158cde5492fSlogin 1159cde5492fSlogin return Ok(Self(slices)); 1160cde5492fSlogin } 1161cde5492fSlogin 1162cde5492fSlogin /// @brief 将IoVecs中的数据聚合到一个缓冲区中 1163cde5492fSlogin /// 1164cde5492fSlogin /// @return 返回聚合后的缓冲区 1165cde5492fSlogin pub fn gather(&self) -> Vec<u8> { 1166cde5492fSlogin let mut buf = Vec::new(); 1167cde5492fSlogin for slice in self.0.iter() { 1168cde5492fSlogin buf.extend_from_slice(slice); 1169cde5492fSlogin } 1170cde5492fSlogin return buf; 1171cde5492fSlogin } 1172cde5492fSlogin 1173cde5492fSlogin /// @brief 将给定的数据分散写入到IoVecs中 1174cde5492fSlogin pub fn scatter(&mut self, data: &[u8]) { 1175cde5492fSlogin let mut data: &[u8] = data; 1176cde5492fSlogin for slice in self.0.iter_mut() { 1177cde5492fSlogin let len = core::cmp::min(slice.len(), data.len()); 1178cde5492fSlogin if len == 0 { 1179cde5492fSlogin continue; 1180cde5492fSlogin } 1181cde5492fSlogin 1182cde5492fSlogin slice[..len].copy_from_slice(&data[..len]); 1183cde5492fSlogin data = &data[len..]; 1184cde5492fSlogin } 1185cde5492fSlogin } 1186cde5492fSlogin 1187cde5492fSlogin /// @brief 创建与IoVecs等长的缓冲区 1188cde5492fSlogin /// 1189cde5492fSlogin /// @param set_len 是否设置返回的Vec的len。 1190cde5492fSlogin /// 如果为true,则返回的Vec的len为所有IoVec的长度之和; 1191cde5492fSlogin /// 否则返回的Vec的len为0,capacity为所有IoVec的长度之和. 1192cde5492fSlogin /// 1193cde5492fSlogin /// @return 返回创建的缓冲区 1194cde5492fSlogin pub fn new_buf(&self, set_len: bool) -> Vec<u8> { 1195cde5492fSlogin let total_len: usize = self.0.iter().map(|slice| slice.len()).sum(); 1196cde5492fSlogin let mut buf: Vec<u8> = Vec::with_capacity(total_len); 1197cde5492fSlogin 1198cde5492fSlogin if set_len { 11997ae679ddSLoGin buf.resize(total_len, 0); 1200cde5492fSlogin } 1201cde5492fSlogin return buf; 1202cde5492fSlogin } 1203cde5492fSlogin } 1204