10fb515b0SLoGin use alloc::sync::Arc;
22eab6dd7S曾俊 use log::warn;
391e9d4abSLoGin use system_error::SystemError;
40fb515b0SLoGin
5bf4a4899SLoGin use super::{
60fb515b0SLoGin fcntl::AtFlags,
70fb515b0SLoGin file::{File, FileMode},
80fb515b0SLoGin syscall::{ModeType, OpenHow, OpenHowResolve},
90fb515b0SLoGin utils::{rsplit_path, user_path_at},
100fb515b0SLoGin FileType, IndexNode, MAX_PATHLEN, ROOT_INODE, VFS_MAX_FOLLOW_SYMLINK_TIMES,
11bf4a4899SLoGin };
126f189d27Slinfeng use crate::filesystem::vfs::syscall::UtimensFlags;
136f189d27Slinfeng use crate::time::{syscall::PosixTimeval, PosixTimeSpec};
146f189d27Slinfeng use crate::{
156f189d27Slinfeng driver::base::block::SeekFrom, process::ProcessManager,
166f189d27Slinfeng syscall::user_access::check_and_clone_cstr,
176f189d27Slinfeng };
186f189d27Slinfeng use alloc::string::String;
199b0abe6dSLoGin
do_faccessat( dirfd: i32, path: *const u8, mode: ModeType, flags: u32, ) -> Result<usize, SystemError>209b0abe6dSLoGin pub(super) fn do_faccessat(
21bf4a4899SLoGin dirfd: i32,
22bf4a4899SLoGin path: *const u8,
239b0abe6dSLoGin mode: ModeType,
249b0abe6dSLoGin flags: u32,
259b0abe6dSLoGin ) -> Result<usize, SystemError> {
26bf4a4899SLoGin if (mode.bits() & (!ModeType::S_IRWXO.bits())) != 0 {
279b0abe6dSLoGin return Err(SystemError::EINVAL);
289b0abe6dSLoGin }
299b0abe6dSLoGin
309b0abe6dSLoGin if (flags
319b0abe6dSLoGin & (!((AtFlags::AT_EACCESS | AtFlags::AT_SYMLINK_NOFOLLOW | AtFlags::AT_EMPTY_PATH).bits()
329b0abe6dSLoGin as u32)))
339b0abe6dSLoGin != 0
349b0abe6dSLoGin {
359b0abe6dSLoGin return Err(SystemError::EINVAL);
369b0abe6dSLoGin }
379b0abe6dSLoGin
389b0abe6dSLoGin // let follow_symlink = flags & AtFlags::AT_SYMLINK_NOFOLLOW.bits() as u32 == 0;
399b0abe6dSLoGin
40bf4a4899SLoGin let path = check_and_clone_cstr(path, Some(MAX_PATHLEN))?;
41*703ce5a7SLoGin let path = path.to_str().map_err(|_| SystemError::EINVAL)?;
42bf4a4899SLoGin
43*703ce5a7SLoGin let (inode, path) = user_path_at(&ProcessManager::current_pcb(), dirfd, path)?;
44bf4a4899SLoGin
45bf4a4899SLoGin // 如果找不到文件,则返回错误码ENOENT
46bf4a4899SLoGin let _inode = inode.lookup_follow_symlink(path.as_str(), VFS_MAX_FOLLOW_SYMLINK_TIMES)?;
47bf4a4899SLoGin
489b0abe6dSLoGin // todo: 接着完善(可以借鉴linux 6.1.9的do_faccessat)
499b0abe6dSLoGin return Ok(0);
509b0abe6dSLoGin }
51bf4a4899SLoGin
do_fchmodat(dirfd: i32, path: *const u8, _mode: ModeType) -> Result<usize, SystemError>52bf4a4899SLoGin pub fn do_fchmodat(dirfd: i32, path: *const u8, _mode: ModeType) -> Result<usize, SystemError> {
53bf4a4899SLoGin let path = check_and_clone_cstr(path, Some(MAX_PATHLEN))?;
54*703ce5a7SLoGin let path = path.to_str().map_err(|_| SystemError::EINVAL)?;
55bf4a4899SLoGin
56*703ce5a7SLoGin let (inode, path) = user_path_at(&ProcessManager::current_pcb(), dirfd, path)?;
57bf4a4899SLoGin
58bf4a4899SLoGin // 如果找不到文件,则返回错误码ENOENT
59bf4a4899SLoGin let _inode = inode.lookup_follow_symlink(path.as_str(), VFS_MAX_FOLLOW_SYMLINK_TIMES)?;
60bf4a4899SLoGin
612eab6dd7S曾俊 warn!("do_fchmodat: not implemented yet\n");
62bf4a4899SLoGin // todo: 真正去改变文件的权限
63bf4a4899SLoGin
64bf4a4899SLoGin return Ok(0);
65bf4a4899SLoGin }
660fb515b0SLoGin
do_sys_open( dfd: i32, path: &str, o_flags: FileMode, mode: ModeType, follow_symlink: bool, ) -> Result<usize, SystemError>670fb515b0SLoGin pub(super) fn do_sys_open(
680fb515b0SLoGin dfd: i32,
690fb515b0SLoGin path: &str,
700fb515b0SLoGin o_flags: FileMode,
710fb515b0SLoGin mode: ModeType,
720fb515b0SLoGin follow_symlink: bool,
730fb515b0SLoGin ) -> Result<usize, SystemError> {
740fb515b0SLoGin let how = OpenHow::new(o_flags, mode, OpenHowResolve::empty());
750fb515b0SLoGin return do_sys_openat2(dfd, path, how, follow_symlink);
760fb515b0SLoGin }
770fb515b0SLoGin
do_sys_openat2( dirfd: i32, path: &str, how: OpenHow, follow_symlink: bool, ) -> Result<usize, SystemError>780fb515b0SLoGin fn do_sys_openat2(
790fb515b0SLoGin dirfd: i32,
800fb515b0SLoGin path: &str,
810fb515b0SLoGin how: OpenHow,
820fb515b0SLoGin follow_symlink: bool,
830fb515b0SLoGin ) -> Result<usize, SystemError> {
842eab6dd7S曾俊 // debug!("open path: {}, how: {:?}", path, how);
8582df0a13Shmt let path = path.trim();
8682df0a13Shmt
870fb515b0SLoGin let (inode_begin, path) = user_path_at(&ProcessManager::current_pcb(), dirfd, path)?;
880fb515b0SLoGin let inode: Result<Arc<dyn IndexNode>, SystemError> = inode_begin.lookup_follow_symlink(
890fb515b0SLoGin &path,
900fb515b0SLoGin if follow_symlink {
910fb515b0SLoGin VFS_MAX_FOLLOW_SYMLINK_TIMES
920fb515b0SLoGin } else {
930fb515b0SLoGin 0
940fb515b0SLoGin },
950fb515b0SLoGin );
960fb515b0SLoGin
97b5b571e0SLoGin let inode: Arc<dyn IndexNode> = match inode {
98b5b571e0SLoGin Ok(inode) => inode,
99b5b571e0SLoGin Err(errno) => {
1000fb515b0SLoGin // 文件不存在,且需要创建
1010fb515b0SLoGin if how.o_flags.contains(FileMode::O_CREAT)
1020fb515b0SLoGin && !how.o_flags.contains(FileMode::O_DIRECTORY)
1030fb515b0SLoGin && errno == SystemError::ENOENT
1040fb515b0SLoGin {
1050fb515b0SLoGin let (filename, parent_path) = rsplit_path(&path);
1060fb515b0SLoGin // 查找父目录
1070fb515b0SLoGin let parent_inode: Arc<dyn IndexNode> =
1080fb515b0SLoGin ROOT_INODE().lookup(parent_path.unwrap_or("/"))?;
1090fb515b0SLoGin // 创建文件
1100fb515b0SLoGin let inode: Arc<dyn IndexNode> = parent_inode.create(
1110fb515b0SLoGin filename,
1120fb515b0SLoGin FileType::File,
1130fb515b0SLoGin ModeType::from_bits_truncate(0o755),
1140fb515b0SLoGin )?;
1150fb515b0SLoGin inode
1160fb515b0SLoGin } else {
1170fb515b0SLoGin // 不需要创建文件,因此返回错误码
1180fb515b0SLoGin return Err(errno);
1190fb515b0SLoGin }
120b5b571e0SLoGin }
1210fb515b0SLoGin };
1220fb515b0SLoGin
1230fb515b0SLoGin let file_type: FileType = inode.metadata()?.file_type;
1240fb515b0SLoGin // 如果要打开的是文件夹,而目标不是文件夹
1250fb515b0SLoGin if how.o_flags.contains(FileMode::O_DIRECTORY) && file_type != FileType::Dir {
1260fb515b0SLoGin return Err(SystemError::ENOTDIR);
1270fb515b0SLoGin }
1280fb515b0SLoGin
1290fb515b0SLoGin // 创建文件对象
1300fb515b0SLoGin
131dfe53cf0SGnoCiYeH let file: File = File::new(inode, how.o_flags)?;
1320fb515b0SLoGin
1330fb515b0SLoGin // 打开模式为“追加”
1340fb515b0SLoGin if how.o_flags.contains(FileMode::O_APPEND) {
1350fb515b0SLoGin file.lseek(SeekFrom::SeekEnd(0))?;
1360fb515b0SLoGin }
1370fb515b0SLoGin
1380fb515b0SLoGin // 如果O_TRUNC,并且,打开模式包含O_RDWR或O_WRONLY,清空文件
1390fb515b0SLoGin if how.o_flags.contains(FileMode::O_TRUNC)
1400fb515b0SLoGin && (how.o_flags.contains(FileMode::O_RDWR) || how.o_flags.contains(FileMode::O_WRONLY))
1410fb515b0SLoGin && file_type == FileType::File
1420fb515b0SLoGin {
1430fb515b0SLoGin file.ftruncate(0)?;
1440fb515b0SLoGin }
1450fb515b0SLoGin // 把文件对象存入pcb
1460fb515b0SLoGin let r = ProcessManager::current_pcb()
1470fb515b0SLoGin .fd_table()
1480fb515b0SLoGin .write()
1490fb515b0SLoGin .alloc_fd(file, None)
1500fb515b0SLoGin .map(|fd| fd as usize);
1510fb515b0SLoGin
1520fb515b0SLoGin return r;
1530fb515b0SLoGin }
1546f189d27Slinfeng
1556f189d27Slinfeng /// On Linux, futimens() is a library function implemented on top of
1566f189d27Slinfeng /// the utimensat() system call. To support this, the Linux
1576f189d27Slinfeng /// utimensat() system call implements a nonstandard feature: if
1586f189d27Slinfeng /// pathname is NULL, then the call modifies the timestamps of the
1596f189d27Slinfeng /// file referred to by the file descriptor dirfd (which may refer to
1606f189d27Slinfeng /// any type of file).
do_utimensat( dirfd: i32, pathname: Option<String>, times: Option<[PosixTimeSpec; 2]>, flags: UtimensFlags, ) -> Result<usize, SystemError>1616f189d27Slinfeng pub fn do_utimensat(
1626f189d27Slinfeng dirfd: i32,
1636f189d27Slinfeng pathname: Option<String>,
1646f189d27Slinfeng times: Option<[PosixTimeSpec; 2]>,
1656f189d27Slinfeng flags: UtimensFlags,
1666f189d27Slinfeng ) -> Result<usize, SystemError> {
1676f189d27Slinfeng const UTIME_NOW: i64 = (1i64 << 30) - 1i64;
1686f189d27Slinfeng const UTIME_OMIT: i64 = (1i64 << 30) - 2i64;
1696f189d27Slinfeng // log::debug!("do_utimensat: dirfd:{}, pathname:{:?}, times:{:?}, flags:{:?}", dirfd, pathname, times, flags);
1706f189d27Slinfeng let inode = match pathname {
1716f189d27Slinfeng Some(path) => {
1726f189d27Slinfeng let (inode_begin, path) =
1736f189d27Slinfeng user_path_at(&ProcessManager::current_pcb(), dirfd, path.as_str())?;
1746f189d27Slinfeng let inode = if flags.contains(UtimensFlags::AT_SYMLINK_NOFOLLOW) {
1756f189d27Slinfeng inode_begin.lookup(path.as_str())?
1766f189d27Slinfeng } else {
1776f189d27Slinfeng inode_begin.lookup_follow_symlink(path.as_str(), VFS_MAX_FOLLOW_SYMLINK_TIMES)?
1786f189d27Slinfeng };
1796f189d27Slinfeng inode
1806f189d27Slinfeng }
1816f189d27Slinfeng None => {
1826f189d27Slinfeng let binding = ProcessManager::current_pcb().fd_table();
1836f189d27Slinfeng let fd_table_guard = binding.write();
1846f189d27Slinfeng let file = fd_table_guard
1856f189d27Slinfeng .get_file_by_fd(dirfd)
1866f189d27Slinfeng .ok_or(SystemError::EBADF)?;
1876f189d27Slinfeng file.inode()
1886f189d27Slinfeng }
1896f189d27Slinfeng };
1906f189d27Slinfeng let now = PosixTimeSpec::now();
1916f189d27Slinfeng let mut meta = inode.metadata()?;
1926f189d27Slinfeng
1936f189d27Slinfeng if let Some([atime, mtime]) = times {
1946f189d27Slinfeng if atime.tv_nsec == UTIME_NOW {
1956f189d27Slinfeng meta.atime = now;
1966f189d27Slinfeng } else if atime.tv_nsec != UTIME_OMIT {
1976f189d27Slinfeng meta.atime = atime;
1986f189d27Slinfeng }
1996f189d27Slinfeng if mtime.tv_nsec == UTIME_NOW {
2006f189d27Slinfeng meta.mtime = now;
2016f189d27Slinfeng } else if mtime.tv_nsec != UTIME_OMIT {
2026f189d27Slinfeng meta.mtime = mtime;
2036f189d27Slinfeng }
2046f189d27Slinfeng inode.set_metadata(&meta).unwrap();
2056f189d27Slinfeng } else {
2066f189d27Slinfeng meta.atime = now;
2076f189d27Slinfeng meta.mtime = now;
2086f189d27Slinfeng inode.set_metadata(&meta).unwrap();
2096f189d27Slinfeng }
2106f189d27Slinfeng return Ok(0);
2116f189d27Slinfeng }
2126f189d27Slinfeng
do_utimes(path: &str, times: Option<[PosixTimeval; 2]>) -> Result<usize, SystemError>2136f189d27Slinfeng pub fn do_utimes(path: &str, times: Option<[PosixTimeval; 2]>) -> Result<usize, SystemError> {
2146f189d27Slinfeng // log::debug!("do_utimes: path:{:?}, times:{:?}", path, times);
2156f189d27Slinfeng let (inode_begin, path) = user_path_at(
2166f189d27Slinfeng &ProcessManager::current_pcb(),
2176f189d27Slinfeng AtFlags::AT_FDCWD.bits(),
2186f189d27Slinfeng path,
2196f189d27Slinfeng )?;
2206f189d27Slinfeng let inode = inode_begin.lookup_follow_symlink(path.as_str(), VFS_MAX_FOLLOW_SYMLINK_TIMES)?;
2216f189d27Slinfeng let mut meta = inode.metadata()?;
2226f189d27Slinfeng
2236f189d27Slinfeng if let Some([atime, mtime]) = times {
2246f189d27Slinfeng meta.atime = PosixTimeSpec::from(atime);
2256f189d27Slinfeng meta.mtime = PosixTimeSpec::from(mtime);
2266f189d27Slinfeng inode.set_metadata(&meta)?;
2276f189d27Slinfeng } else {
2286f189d27Slinfeng let now = PosixTimeSpec::now();
2296f189d27Slinfeng meta.atime = now;
2306f189d27Slinfeng meta.mtime = now;
2316f189d27Slinfeng inode.set_metadata(&meta)?;
2326f189d27Slinfeng }
2336f189d27Slinfeng return Ok(0);
2346f189d27Slinfeng }
235