mirror of
https://github.com/asterinas/asterinas.git
synced 2025-06-08 21:06:48 +00:00
Merge pull request #75 from liqinggd/dev-fs-syscall
Add some basic fs syscalls
This commit is contained in:
commit
c7ade129e9
@ -28,4 +28,8 @@ pub trait File: Send + Sync + Any {
|
||||
fn poll(&self) -> IoEvents {
|
||||
IoEvents::empty()
|
||||
}
|
||||
|
||||
fn flush(&self) -> Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
@ -6,6 +6,7 @@ mod inode_handle;
|
||||
use crate::prelude::*;
|
||||
use crate::rights::{ReadOp, WriteOp};
|
||||
use alloc::sync::Arc;
|
||||
use core::ops::Range;
|
||||
|
||||
pub use self::file::File;
|
||||
pub use self::inode_handle::InodeHandle;
|
||||
@ -65,4 +66,20 @@ impl FileHandle {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn clean_for_close(&self) -> Result<()> {
|
||||
match &self.inner {
|
||||
Inner::Inode(inode_handle) => {
|
||||
let dentry = inode_handle.dentry();
|
||||
let ref_count = Arc::strong_count(dentry);
|
||||
// The dentry is held by dentry cache and self
|
||||
if ref_count == 2 {
|
||||
let page_cache_size = dentry.vnode().pages().size();
|
||||
dentry.vnode().pages().decommit(0..page_cache_size)?;
|
||||
}
|
||||
}
|
||||
Inner::File(file) => file.flush()?,
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
@ -58,8 +58,8 @@ impl FileTable {
|
||||
fd
|
||||
}
|
||||
|
||||
pub fn close_file(&mut self, fd: FileDescripter) {
|
||||
self.table.remove(&fd);
|
||||
pub fn close_file(&mut self, fd: FileDescripter) -> Option<FileHandle> {
|
||||
self.table.remove(&fd)
|
||||
}
|
||||
|
||||
pub fn get_file(&self, fd: FileDescripter) -> Result<&FileHandle> {
|
||||
|
@ -404,9 +404,28 @@ impl Inode for RamInode {
|
||||
let self_dir = self_inode.inner.as_direntry_mut().unwrap();
|
||||
let (idx, other) = self_dir.get_entry(name).ok_or(Error::new(Errno::ENOENT))?;
|
||||
let other_inode = other.0.read();
|
||||
if other_inode.metadata.type_ == InodeType::Dir
|
||||
&& !other_inode.inner.as_direntry().unwrap().is_empty_children()
|
||||
{
|
||||
if other_inode.metadata.type_ == InodeType::Dir {
|
||||
return_errno_with_message!(Errno::EISDIR, "unlink on dir");
|
||||
}
|
||||
self_dir.remove_entry(idx);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn rmdir(&self, name: &str) -> Result<()> {
|
||||
if self.0.read().metadata.type_ != InodeType::Dir {
|
||||
return_errno_with_message!(Errno::ENOTDIR, "self is not dir");
|
||||
}
|
||||
if name == "." || name == ".." {
|
||||
return_errno_with_message!(Errno::EISDIR, "rmdir on . or ..");
|
||||
}
|
||||
let mut self_inode = self.0.write();
|
||||
let self_dir = self_inode.inner.as_direntry_mut().unwrap();
|
||||
let (idx, other) = self_dir.get_entry(name).ok_or(Error::new(Errno::ENOENT))?;
|
||||
let other_inode = other.0.read();
|
||||
if other_inode.metadata.type_ != InodeType::Dir {
|
||||
return_errno_with_message!(Errno::ENOTDIR, "rmdir on not dir");
|
||||
}
|
||||
if other_inode.inner.as_direntry().unwrap().is_empty_children() {
|
||||
return_errno_with_message!(Errno::ENOTEMPTY, "dir not empty");
|
||||
}
|
||||
self_dir.remove_entry(idx);
|
||||
|
@ -65,6 +65,9 @@ impl Dentry {
|
||||
|
||||
pub fn create(&self, name: &str, type_: InodeType, mode: InodeMode) -> Result<Arc<Self>> {
|
||||
let mut inner = self.inner.write();
|
||||
if inner.children.get(name).is_some() {
|
||||
return_errno!(Errno::EEXIST);
|
||||
}
|
||||
let child = {
|
||||
let vnode = Vnode::new(self.vnode.inode().mknod(name, type_, mode)?)?;
|
||||
Dentry::new(name, vnode, Some(inner.this.clone()))
|
||||
@ -73,7 +76,7 @@ impl Dentry {
|
||||
Ok(child)
|
||||
}
|
||||
|
||||
pub fn lookup(&self, name: &str) -> Result<Arc<Dentry>> {
|
||||
pub fn lookup(&self, name: &str) -> Result<Arc<Self>> {
|
||||
if self.vnode.inode().metadata().type_ != InodeType::Dir {
|
||||
return_errno!(Errno::ENOTDIR);
|
||||
}
|
||||
@ -99,6 +102,41 @@ impl Dentry {
|
||||
Ok(dentry)
|
||||
}
|
||||
|
||||
pub fn link(&self, old: &Arc<Self>, name: &str) -> Result<()> {
|
||||
if self.vnode.inode().metadata().type_ != InodeType::Dir {
|
||||
return_errno!(Errno::ENOTDIR);
|
||||
}
|
||||
let mut inner = self.inner.write();
|
||||
if inner.children.get(name).is_some() {
|
||||
return_errno!(Errno::EEXIST);
|
||||
}
|
||||
let target_vnode = old.vnode();
|
||||
self.vnode.inode().link(target_vnode.inode(), name)?;
|
||||
let new_dentry = Self::new(name, target_vnode.clone(), Some(inner.this.clone()));
|
||||
inner.children.insert(String::from(name), new_dentry);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn unlink(&self, name: &str) -> Result<()> {
|
||||
if self.vnode.inode().metadata().type_ != InodeType::Dir {
|
||||
return_errno!(Errno::ENOTDIR);
|
||||
}
|
||||
let mut inner = self.inner.write();
|
||||
self.vnode.inode().unlink(name)?;
|
||||
inner.children.remove(name);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn rmdir(&self, name: &str) -> Result<()> {
|
||||
if self.vnode.inode().metadata().type_ != InodeType::Dir {
|
||||
return_errno!(Errno::ENOTDIR);
|
||||
}
|
||||
let mut inner = self.inner.write();
|
||||
self.vnode.inode().rmdir(name)?;
|
||||
inner.children.remove(name);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn abs_path(&self) -> String {
|
||||
let mut path = self.name();
|
||||
let mut dentry = self.this();
|
||||
|
@ -176,6 +176,8 @@ pub trait Inode: Any + Sync + Send {
|
||||
|
||||
fn unlink(&self, name: &str) -> Result<()>;
|
||||
|
||||
fn rmdir(&self, name: &str) -> Result<()>;
|
||||
|
||||
fn lookup(&self, name: &str) -> Result<Arc<dyn Inode>>;
|
||||
|
||||
fn rename(&self, old_name: &str, target: &Arc<dyn Inode>, new_name: &str) -> Result<()>;
|
||||
|
@ -9,6 +9,7 @@ pub fn sys_close(fd: FileDescripter) -> Result<SyscallReturn> {
|
||||
let current = current!();
|
||||
let mut file_table = current.file_table().lock();
|
||||
let _ = file_table.get_file(fd)?;
|
||||
file_table.close_file(fd);
|
||||
let file = file_table.close_file(fd).unwrap();
|
||||
file.clean_for_close()?;
|
||||
Ok(SyscallReturn::Return(0))
|
||||
}
|
||||
|
71
src/services/libs/jinux-std/src/syscall/link.rs
Normal file
71
src/services/libs/jinux-std/src/syscall/link.rs
Normal file
@ -0,0 +1,71 @@
|
||||
use crate::fs::{
|
||||
file_table::FileDescripter,
|
||||
fs_resolver::{FsPath, AT_FDCWD},
|
||||
};
|
||||
use crate::log_syscall_entry;
|
||||
use crate::prelude::*;
|
||||
use crate::syscall::constants::MAX_FILENAME_LEN;
|
||||
use crate::util::read_cstring_from_user;
|
||||
|
||||
use super::SyscallReturn;
|
||||
use super::SYS_LINKAT;
|
||||
|
||||
pub fn sys_linkat(
|
||||
old_dirfd: FileDescripter,
|
||||
old_pathname_addr: Vaddr,
|
||||
new_dirfd: FileDescripter,
|
||||
new_pathname_addr: Vaddr,
|
||||
flags: u32,
|
||||
) -> Result<SyscallReturn> {
|
||||
log_syscall_entry!(SYS_LINKAT);
|
||||
let old_pathname = read_cstring_from_user(old_pathname_addr, MAX_FILENAME_LEN)?;
|
||||
let new_pathname = read_cstring_from_user(new_pathname_addr, MAX_FILENAME_LEN)?;
|
||||
let flags =
|
||||
LinkFlags::from_bits(flags).ok_or(Error::with_message(Errno::EINVAL, "invalid flags"))?;
|
||||
debug!(
|
||||
"old_dirfd = {}, old_pathname = {:?}, new_dirfd = {}, new_pathname = {:?}, flags = {:?}",
|
||||
old_dirfd, old_pathname, new_dirfd, new_pathname, flags
|
||||
);
|
||||
|
||||
let current = current!();
|
||||
let (old_dentry, new_dir_dentry, new_name) = {
|
||||
let old_pathname = old_pathname.to_string_lossy();
|
||||
if old_pathname.ends_with("/") {
|
||||
return_errno_with_message!(Errno::EPERM, "oldpath is dir");
|
||||
}
|
||||
if old_pathname.is_empty() && !flags.contains(LinkFlags::AT_EMPTY_PATH) {
|
||||
return_errno_with_message!(Errno::ENOENT, "oldpath is empty");
|
||||
}
|
||||
let new_pathname = new_pathname.to_string_lossy();
|
||||
if new_pathname.ends_with("/") {
|
||||
return_errno_with_message!(Errno::EPERM, "newpath is dir");
|
||||
}
|
||||
if new_pathname.is_empty() {
|
||||
return_errno_with_message!(Errno::ENOENT, "newpath is empty");
|
||||
}
|
||||
|
||||
let old_fs_path = FsPath::new(old_dirfd, old_pathname.as_ref())?;
|
||||
let new_fs_path = FsPath::new(new_dirfd, new_pathname.as_ref())?;
|
||||
let fs = current.fs().read();
|
||||
let old_dentry = if flags.contains(LinkFlags::AT_SYMLINK_FOLLOW) {
|
||||
fs.lookup(&old_fs_path)?
|
||||
} else {
|
||||
fs.lookup_no_follow(&old_fs_path)?
|
||||
};
|
||||
let (new_dir_dentry, new_name) = fs.lookup_dir_and_base_name(&new_fs_path)?;
|
||||
(old_dentry, new_dir_dentry, new_name)
|
||||
};
|
||||
new_dir_dentry.link(&old_dentry, &new_name)?;
|
||||
Ok(SyscallReturn::Return(0))
|
||||
}
|
||||
|
||||
pub fn sys_link(old_pathname_addr: Vaddr, new_pathname_addr: Vaddr) -> Result<SyscallReturn> {
|
||||
self::sys_linkat(AT_FDCWD, old_pathname_addr, AT_FDCWD, new_pathname_addr, 0)
|
||||
}
|
||||
|
||||
bitflags::bitflags! {
|
||||
pub struct LinkFlags: u32 {
|
||||
const AT_EMPTY_PATH = 0x1000;
|
||||
const AT_SYMLINK_FOLLOW = 0x400;
|
||||
}
|
||||
}
|
42
src/services/libs/jinux-std/src/syscall/mkdir.rs
Normal file
42
src/services/libs/jinux-std/src/syscall/mkdir.rs
Normal file
@ -0,0 +1,42 @@
|
||||
use crate::fs::{
|
||||
file_table::FileDescripter,
|
||||
fs_resolver::{FsPath, AT_FDCWD},
|
||||
utils::{InodeMode, InodeType},
|
||||
};
|
||||
use crate::log_syscall_entry;
|
||||
use crate::prelude::*;
|
||||
use crate::syscall::constants::MAX_FILENAME_LEN;
|
||||
use crate::util::read_cstring_from_user;
|
||||
|
||||
use super::SyscallReturn;
|
||||
use super::SYS_MKDIRAT;
|
||||
|
||||
pub fn sys_mkdirat(
|
||||
dirfd: FileDescripter,
|
||||
pathname_addr: Vaddr,
|
||||
mode: u16,
|
||||
) -> Result<SyscallReturn> {
|
||||
log_syscall_entry!(SYS_MKDIRAT);
|
||||
let pathname = read_cstring_from_user(pathname_addr, MAX_FILENAME_LEN)?;
|
||||
debug!(
|
||||
"dirfd = {}, pathname = {:?}, mode = {}",
|
||||
dirfd, pathname, mode
|
||||
);
|
||||
|
||||
let current = current!();
|
||||
let (dir_dentry, name) = {
|
||||
let pathname = pathname.to_string_lossy();
|
||||
if pathname.is_empty() {
|
||||
return_errno_with_message!(Errno::ENOENT, "path is empty");
|
||||
}
|
||||
let fs_path = FsPath::new(dirfd, pathname.as_ref())?;
|
||||
current.fs().read().lookup_dir_and_base_name(&fs_path)?
|
||||
};
|
||||
let inode_mode = InodeMode::from_bits_truncate(mode);
|
||||
let _ = dir_dentry.create(&name.trim_end_matches('/'), InodeType::Dir, inode_mode)?;
|
||||
Ok(SyscallReturn::Return(0))
|
||||
}
|
||||
|
||||
pub fn sys_mkdir(pathname_addr: Vaddr, mode: u16) -> Result<SyscallReturn> {
|
||||
self::sys_mkdirat(AT_FDCWD, pathname_addr, mode)
|
||||
}
|
@ -25,18 +25,21 @@ use crate::syscall::gettid::sys_gettid;
|
||||
use crate::syscall::getuid::sys_getuid;
|
||||
use crate::syscall::ioctl::sys_ioctl;
|
||||
use crate::syscall::kill::sys_kill;
|
||||
use crate::syscall::link::{sys_link, sys_linkat};
|
||||
use crate::syscall::lseek::sys_lseek;
|
||||
use crate::syscall::lstat::sys_lstat;
|
||||
use crate::syscall::madvise::sys_madvise;
|
||||
use crate::syscall::mkdir::{sys_mkdir, sys_mkdirat};
|
||||
use crate::syscall::mmap::sys_mmap;
|
||||
use crate::syscall::mprotect::sys_mprotect;
|
||||
use crate::syscall::munmap::sys_munmap;
|
||||
use crate::syscall::openat::sys_openat;
|
||||
use crate::syscall::open::{sys_open, sys_openat};
|
||||
use crate::syscall::poll::sys_poll;
|
||||
use crate::syscall::prctl::sys_prctl;
|
||||
use crate::syscall::prlimit64::sys_prlimit64;
|
||||
use crate::syscall::read::sys_read;
|
||||
use crate::syscall::readlink::sys_readlink;
|
||||
use crate::syscall::rmdir::sys_rmdir;
|
||||
use crate::syscall::rt_sigaction::sys_rt_sigaction;
|
||||
use crate::syscall::rt_sigprocmask::sys_rt_sigprocmask;
|
||||
use crate::syscall::rt_sigreturn::sys_rt_sigreturn;
|
||||
@ -47,6 +50,7 @@ use crate::syscall::setpgid::sys_setpgid;
|
||||
use crate::syscall::stat::sys_stat;
|
||||
use crate::syscall::tgkill::sys_tgkill;
|
||||
use crate::syscall::uname::sys_uname;
|
||||
use crate::syscall::unlink::{sys_unlink, sys_unlinkat};
|
||||
use crate::syscall::wait4::sys_wait4;
|
||||
use crate::syscall::waitid::sys_waitid;
|
||||
use crate::syscall::write::sys_write;
|
||||
@ -78,18 +82,21 @@ mod gettid;
|
||||
mod getuid;
|
||||
mod ioctl;
|
||||
mod kill;
|
||||
mod link;
|
||||
mod lseek;
|
||||
mod lstat;
|
||||
mod madvise;
|
||||
mod mkdir;
|
||||
mod mmap;
|
||||
mod mprotect;
|
||||
mod munmap;
|
||||
mod openat;
|
||||
mod open;
|
||||
mod poll;
|
||||
mod prctl;
|
||||
mod prlimit64;
|
||||
mod read;
|
||||
mod readlink;
|
||||
mod rmdir;
|
||||
mod rt_sigaction;
|
||||
mod rt_sigprocmask;
|
||||
mod rt_sigreturn;
|
||||
@ -100,6 +107,7 @@ mod setpgid;
|
||||
mod stat;
|
||||
mod tgkill;
|
||||
mod uname;
|
||||
mod unlink;
|
||||
mod wait4;
|
||||
mod waitid;
|
||||
mod write;
|
||||
@ -138,6 +146,7 @@ macro_rules! syscall_handler {
|
||||
define_syscall_nums!(
|
||||
SYS_READ = 0,
|
||||
SYS_WRITE = 1,
|
||||
SYS_OPEN = 2,
|
||||
SYS_CLOSE = 3,
|
||||
SYS_STAT = 4,
|
||||
SYS_FSTAT = 5,
|
||||
@ -166,6 +175,10 @@ define_syscall_nums!(
|
||||
SYS_UNAME = 63,
|
||||
SYS_FCNTL = 72,
|
||||
SYS_GETCWD = 79,
|
||||
SYS_MKDIR = 83,
|
||||
SYS_RMDIR = 84,
|
||||
SYS_LINK = 86,
|
||||
SYS_UNLINK = 87,
|
||||
SYS_READLINK = 89,
|
||||
SYS_GETUID = 102,
|
||||
SYS_GETGID = 104,
|
||||
@ -184,6 +197,9 @@ define_syscall_nums!(
|
||||
SYS_TGKILL = 234,
|
||||
SYS_WAITID = 247,
|
||||
SYS_OPENAT = 257,
|
||||
SYS_MKDIRAT = 258,
|
||||
SYS_UNLINKAT = 263,
|
||||
SYS_LINKAT = 265,
|
||||
SYS_SET_ROBUST_LIST = 273,
|
||||
SYS_PRLIMIT64 = 302
|
||||
);
|
||||
@ -246,6 +262,7 @@ pub fn syscall_dispatch(
|
||||
match syscall_number {
|
||||
SYS_READ => syscall_handler!(3, sys_read, args),
|
||||
SYS_WRITE => syscall_handler!(3, sys_write, args),
|
||||
SYS_OPEN => syscall_handler!(3, sys_open, args),
|
||||
SYS_CLOSE => syscall_handler!(1, sys_close, args),
|
||||
SYS_STAT => syscall_handler!(2, sys_stat, args),
|
||||
SYS_FSTAT => syscall_handler!(2, sys_fstat, args),
|
||||
@ -274,6 +291,10 @@ pub fn syscall_dispatch(
|
||||
SYS_UNAME => syscall_handler!(1, sys_uname, args),
|
||||
SYS_FCNTL => syscall_handler!(3, sys_fcntl, args),
|
||||
SYS_GETCWD => syscall_handler!(2, sys_getcwd, args),
|
||||
SYS_MKDIR => syscall_handler!(2, sys_mkdir, args),
|
||||
SYS_RMDIR => syscall_handler!(1, sys_rmdir, args),
|
||||
SYS_LINK => syscall_handler!(2, sys_link, args),
|
||||
SYS_UNLINK => syscall_handler!(1, sys_unlink, args),
|
||||
SYS_READLINK => syscall_handler!(3, sys_readlink, args),
|
||||
SYS_GETUID => syscall_handler!(0, sys_getuid),
|
||||
SYS_GETGID => syscall_handler!(0, sys_getgid),
|
||||
@ -292,6 +313,9 @@ pub fn syscall_dispatch(
|
||||
SYS_TGKILL => syscall_handler!(3, sys_tgkill, args),
|
||||
SYS_WAITID => syscall_handler!(5, sys_waitid, args),
|
||||
SYS_OPENAT => syscall_handler!(4, sys_openat, args),
|
||||
SYS_MKDIRAT => syscall_handler!(3, sys_mkdirat, args),
|
||||
SYS_UNLINKAT => syscall_handler!(3, sys_unlinkat, args),
|
||||
SYS_LINKAT => syscall_handler!(5, sys_linkat, args),
|
||||
SYS_SET_ROBUST_LIST => syscall_handler!(2, sys_set_robust_list, args),
|
||||
SYS_PRLIMIT64 => syscall_handler!(4, sys_prlimit64, args),
|
||||
_ => {
|
||||
|
@ -67,6 +67,10 @@ pub fn sys_openat(
|
||||
Ok(SyscallReturn::Return(fd as _))
|
||||
}
|
||||
|
||||
pub fn sys_open(pathname_addr: Vaddr, flags: u32, mode: u16) -> Result<SyscallReturn> {
|
||||
self::sys_openat(AT_FDCWD, pathname_addr, flags, mode)
|
||||
}
|
||||
|
||||
/// File for output busybox ash log.
|
||||
struct BusyBoxTraceFile;
|
||||
|
23
src/services/libs/jinux-std/src/syscall/rmdir.rs
Normal file
23
src/services/libs/jinux-std/src/syscall/rmdir.rs
Normal file
@ -0,0 +1,23 @@
|
||||
use crate::fs::fs_resolver::FsPath;
|
||||
use crate::log_syscall_entry;
|
||||
use crate::prelude::*;
|
||||
use crate::syscall::constants::MAX_FILENAME_LEN;
|
||||
use crate::util::read_cstring_from_user;
|
||||
|
||||
use super::SyscallReturn;
|
||||
use super::SYS_RMDIR;
|
||||
|
||||
pub fn sys_rmdir(pathname_addr: Vaddr) -> Result<SyscallReturn> {
|
||||
log_syscall_entry!(SYS_RMDIR);
|
||||
let pathname = read_cstring_from_user(pathname_addr, MAX_FILENAME_LEN)?;
|
||||
debug!("pathname = {:?}", pathname);
|
||||
|
||||
let current = current!();
|
||||
let (dir_dentry, name) = {
|
||||
let pathname = pathname.to_string_lossy();
|
||||
let fs_path = FsPath::try_from(pathname.as_ref())?;
|
||||
current.fs().read().lookup_dir_and_base_name(&fs_path)?
|
||||
};
|
||||
dir_dentry.rmdir(&name.trim_end_matches('/'))?;
|
||||
Ok(SyscallReturn::Return(0))
|
||||
}
|
52
src/services/libs/jinux-std/src/syscall/unlink.rs
Normal file
52
src/services/libs/jinux-std/src/syscall/unlink.rs
Normal file
@ -0,0 +1,52 @@
|
||||
use crate::fs::{
|
||||
file_table::FileDescripter,
|
||||
fs_resolver::{FsPath, AT_FDCWD},
|
||||
};
|
||||
use crate::log_syscall_entry;
|
||||
use crate::prelude::*;
|
||||
use crate::syscall::constants::MAX_FILENAME_LEN;
|
||||
use crate::util::read_cstring_from_user;
|
||||
|
||||
use super::SyscallReturn;
|
||||
use super::SYS_UNLINKAT;
|
||||
|
||||
pub fn sys_unlinkat(
|
||||
dirfd: FileDescripter,
|
||||
pathname_addr: Vaddr,
|
||||
flags: u32,
|
||||
) -> Result<SyscallReturn> {
|
||||
let flags =
|
||||
UnlinkFlags::from_bits(flags).ok_or(Error::with_message(Errno::EINVAL, "invalid flags"))?;
|
||||
if flags.contains(UnlinkFlags::AT_REMOVEDIR) {
|
||||
return super::rmdir::sys_rmdir(pathname_addr);
|
||||
}
|
||||
|
||||
log_syscall_entry!(SYS_UNLINKAT);
|
||||
let pathname = read_cstring_from_user(pathname_addr, MAX_FILENAME_LEN)?;
|
||||
debug!("dirfd = {}, pathname = {:?}", dirfd, pathname);
|
||||
|
||||
let current = current!();
|
||||
let (dir_dentry, name) = {
|
||||
let pathname = pathname.to_string_lossy();
|
||||
if pathname.is_empty() {
|
||||
return_errno_with_message!(Errno::ENOENT, "path is empty");
|
||||
}
|
||||
if pathname.ends_with("/") {
|
||||
return_errno_with_message!(Errno::EISDIR, "unlink on directory");
|
||||
}
|
||||
let fs_path = FsPath::new(dirfd, pathname.as_ref())?;
|
||||
current.fs().read().lookup_dir_and_base_name(&fs_path)?
|
||||
};
|
||||
dir_dentry.unlink(&name)?;
|
||||
Ok(SyscallReturn::Return(0))
|
||||
}
|
||||
|
||||
pub fn sys_unlink(pathname_addr: Vaddr) -> Result<SyscallReturn> {
|
||||
self::sys_unlinkat(AT_FDCWD, pathname_addr, 0)
|
||||
}
|
||||
|
||||
bitflags::bitflags! {
|
||||
struct UnlinkFlags: u32 {
|
||||
const AT_REMOVEDIR = 0x200;
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user