Add support for chown syscall

This commit is contained in:
LI Qing
2024-01-04 17:52:27 +08:00
committed by Tate, Hongliang Tian
parent 3b3d088767
commit 729c6ecd0c
31 changed files with 583 additions and 361 deletions

View File

@ -1,6 +1,6 @@
# SPDX-License-Identifier: MPL-2.0 # SPDX-License-Identifier: MPL-2.0
TESTS ?= chmod_test fsync_test getdents_test link_test lseek_test mkdir_test \ TESTS ?= chmod_test chown_test fsync_test getdents_test link_test lseek_test mkdir_test \
open_create_test open_test pty_test read_test rename_test stat_test \ open_create_test open_test pty_test read_test rename_test stat_test \
statfs_test symlink_test sync_test truncate_test uidgid_test unlink_test \ statfs_test symlink_test sync_test truncate_test uidgid_test unlink_test \
vdso_clock_gettime_test write_test vdso_clock_gettime_test write_test

View File

@ -0,0 +1,15 @@
ChownKinds/ChownParamTest.ChownFileSucceeds/0
ChownKinds/ChownParamTest.ChownFileSucceeds/1
ChownKinds/ChownParamTest.ChownFileSucceeds/2
ChownKinds/ChownParamTest.ChownFileSucceeds/3
ChownKinds/ChownParamTest.ChownFileSucceeds/4
ChownKinds/ChownParamTest.ChownFilePermissionDenied/0
ChownKinds/ChownParamTest.ChownFilePermissionDenied/1
ChownKinds/ChownParamTest.ChownFilePermissionDenied/2
ChownKinds/ChownParamTest.ChownFilePermissionDenied/3
ChownKinds/ChownParamTest.ChownFilePermissionDenied/4
ChownKinds/ChownParamTest.ChownFileSucceedsAsRoot/0
ChownKinds/ChownParamTest.ChownFileSucceedsAsRoot/1
ChownKinds/ChownParamTest.ChownFileSucceedsAsRoot/2
ChownKinds/ChownParamTest.ChownFileSucceedsAsRoot/3
ChownKinds/ChownParamTest.ChownFileSucceedsAsRoot/4

View File

@ -7,6 +7,7 @@ use crate::fs::utils::{
SuperBlock, NAME_MAX, SuperBlock, NAME_MAX,
}; };
use crate::prelude::*; use crate::prelude::*;
use crate::process::{Gid, Uid};
use aster_util::{id_allocator::IdAlloc, slot_vec::SlotVec}; use aster_util::{id_allocator::IdAlloc, slot_vec::SlotVec};
use core::time::Duration; use core::time::Duration;
@ -100,7 +101,7 @@ impl FileSystem for DevPts {
struct RootInode { struct RootInode {
ptmx: Arc<Ptmx>, ptmx: Arc<Ptmx>,
slaves: RwLock<SlotVec<(String, Arc<PtySlaveInode>)>>, slaves: RwLock<SlotVec<(String, Arc<PtySlaveInode>)>>,
metadata: Metadata, metadata: RwLock<Metadata>,
fs: Weak<DevPts>, fs: Weak<DevPts>,
} }
@ -109,7 +110,11 @@ impl RootInode {
Arc::new(Self { Arc::new(Self {
ptmx: Ptmx::new(sb, fs.clone()), ptmx: Ptmx::new(sb, fs.clone()),
slaves: RwLock::new(SlotVec::new()), slaves: RwLock::new(SlotVec::new()),
metadata: Metadata::new_dir(ROOT_INO, InodeMode::from_bits_truncate(0o755), sb), metadata: RwLock::new(Metadata::new_dir(
ROOT_INO,
InodeMode::from_bits_truncate(0o755),
sb,
)),
fs, fs,
}) })
} }
@ -138,7 +143,7 @@ impl RootInode {
impl Inode for RootInode { impl Inode for RootInode {
fn size(&self) -> usize { fn size(&self) -> usize {
self.metadata.size self.metadata.read().size
} }
fn resize(&self, new_size: usize) -> Result<()> { fn resize(&self, new_size: usize) -> Result<()> {
@ -146,34 +151,59 @@ impl Inode for RootInode {
} }
fn metadata(&self) -> Metadata { fn metadata(&self) -> Metadata {
self.metadata.clone() *self.metadata.read()
} }
fn ino(&self) -> u64 { fn ino(&self) -> u64 {
self.metadata.ino as _ self.metadata.read().ino as _
} }
fn type_(&self) -> InodeType { fn type_(&self) -> InodeType {
self.metadata.type_ self.metadata.read().type_
} }
fn mode(&self) -> InodeMode { fn mode(&self) -> Result<InodeMode> {
self.metadata.mode Ok(self.metadata.read().mode)
} }
fn set_mode(&self, mode: InodeMode) {} fn set_mode(&self, mode: InodeMode) -> Result<()> {
self.metadata.write().mode = mode;
Ok(())
}
fn owner(&self) -> Result<Uid> {
Ok(self.metadata.read().uid)
}
fn set_owner(&self, uid: Uid) -> Result<()> {
self.metadata.write().uid = uid;
Ok(())
}
fn group(&self) -> Result<Gid> {
Ok(self.metadata.read().gid)
}
fn set_group(&self, gid: Gid) -> Result<()> {
self.metadata.write().gid = gid;
Ok(())
}
fn atime(&self) -> Duration { fn atime(&self) -> Duration {
self.metadata.atime self.metadata.read().atime
} }
fn set_atime(&self, time: Duration) {} fn set_atime(&self, time: Duration) {
self.metadata.write().atime = time;
}
fn mtime(&self) -> Duration { fn mtime(&self) -> Duration {
self.metadata.mtime self.metadata.read().mtime
} }
fn set_mtime(&self, time: Duration) {} fn set_mtime(&self, time: Duration) {
self.metadata.write().mtime = time;
}
fn create(&self, name: &str, type_: InodeType, mode: InodeMode) -> Result<Arc<dyn Inode>> { fn create(&self, name: &str, type_: InodeType, mode: InodeMode) -> Result<Arc<dyn Inode>> {
Err(Error::new(Errno::EPERM)) Err(Error::new(Errno::EPERM))
@ -187,20 +217,15 @@ impl Inode for RootInode {
let try_readdir = |offset: &mut usize, visitor: &mut dyn DirentVisitor| -> Result<()> { let try_readdir = |offset: &mut usize, visitor: &mut dyn DirentVisitor| -> Result<()> {
// Read the 3 special entries. // Read the 3 special entries.
if *offset == 0 { if *offset == 0 {
visitor.visit(".", self.metadata.ino as u64, self.metadata.type_, *offset)?; visitor.visit(".", self.ino(), self.type_(), *offset)?;
*offset += 1; *offset += 1;
} }
if *offset == 1 { if *offset == 1 {
visitor.visit("..", self.metadata.ino as u64, self.metadata.type_, *offset)?; visitor.visit("..", self.ino(), self.type_(), *offset)?;
*offset += 1; *offset += 1;
} }
if *offset == 2 { if *offset == 2 {
visitor.visit( visitor.visit("ptmx", self.ptmx.ino(), self.ptmx.type_(), *offset)?;
"ptmx",
self.ptmx.metadata().ino as u64,
self.ptmx.metadata().type_,
*offset,
)?;
*offset += 1; *offset += 1;
} }
@ -212,12 +237,7 @@ impl Inode for RootInode {
.map(|(idx, (name, node))| (idx + 3, (name, node))) .map(|(idx, (name, node))| (idx + 3, (name, node)))
.skip_while(|(idx, _)| idx < &start_offset) .skip_while(|(idx, _)| idx < &start_offset)
{ {
visitor.visit( visitor.visit(name.as_ref(), node.ino(), node.type_(), idx)?;
name.as_ref(),
node.metadata().ino as u64,
node.metadata().type_,
idx,
)?;
*offset = idx + 1; *offset = idx + 1;
} }
Ok(()) Ok(())

View File

@ -19,7 +19,7 @@ const PTMX_MINOR_NUM: u32 = 2;
/// and an corresponding pty slave inode is also created. /// and an corresponding pty slave inode is also created.
pub struct Ptmx { pub struct Ptmx {
inner: Inner, inner: Inner,
metadata: Metadata, metadata: RwLock<Metadata>,
} }
#[derive(Clone)] #[derive(Clone)]
@ -29,12 +29,12 @@ impl Ptmx {
pub fn new(sb: &SuperBlock, fs: Weak<DevPts>) -> Arc<Self> { pub fn new(sb: &SuperBlock, fs: Weak<DevPts>) -> Arc<Self> {
let inner = Inner(fs); let inner = Inner(fs);
Arc::new(Self { Arc::new(Self {
metadata: Metadata::new_device( metadata: RwLock::new(Metadata::new_device(
PTMX_INO, PTMX_INO,
InodeMode::from_bits_truncate(0o666), InodeMode::from_bits_truncate(0o666),
sb, sb,
&inner, &inner,
), )),
inner, inner,
}) })
} }
@ -64,7 +64,7 @@ impl Ptmx {
// it returns the pty master. So the ptmx can not be used at upper layer. // it returns the pty master. So the ptmx can not be used at upper layer.
impl Inode for Ptmx { impl Inode for Ptmx {
fn size(&self) -> usize { fn size(&self) -> usize {
self.metadata.size self.metadata.read().size
} }
fn resize(&self, new_size: usize) -> Result<()> { fn resize(&self, new_size: usize) -> Result<()> {
@ -72,34 +72,59 @@ impl Inode for Ptmx {
} }
fn metadata(&self) -> Metadata { fn metadata(&self) -> Metadata {
self.metadata.clone() *self.metadata.read()
} }
fn ino(&self) -> u64 { fn ino(&self) -> u64 {
self.metadata.ino as _ self.metadata.read().ino as _
} }
fn type_(&self) -> InodeType { fn type_(&self) -> InodeType {
self.metadata.type_ self.metadata.read().type_
} }
fn mode(&self) -> InodeMode { fn mode(&self) -> Result<InodeMode> {
self.metadata.mode Ok(self.metadata.read().mode)
} }
fn set_mode(&self, mode: InodeMode) {} fn set_mode(&self, mode: InodeMode) -> Result<()> {
self.metadata.write().mode = mode;
Ok(())
}
fn owner(&self) -> Result<Uid> {
Ok(self.metadata.read().uid)
}
fn set_owner(&self, uid: Uid) -> Result<()> {
self.metadata.write().uid = uid;
Ok(())
}
fn group(&self) -> Result<Gid> {
Ok(self.metadata.read().gid)
}
fn set_group(&self, gid: Gid) -> Result<()> {
self.metadata.write().gid = gid;
Ok(())
}
fn atime(&self) -> Duration { fn atime(&self) -> Duration {
self.metadata.atime self.metadata.read().atime
} }
fn set_atime(&self, time: Duration) {} fn set_atime(&self, time: Duration) {
self.metadata.write().atime = time;
}
fn mtime(&self) -> Duration { fn mtime(&self) -> Duration {
self.metadata.mtime self.metadata.read().mtime
} }
fn set_mtime(&self, time: Duration) {} fn set_mtime(&self, time: Duration) {
self.metadata.write().mtime = time;
}
fn read_at(&self, offset: usize, buf: &mut [u8]) -> Result<usize> { fn read_at(&self, offset: usize, buf: &mut [u8]) -> Result<usize> {
Ok(0) Ok(0)

View File

@ -4,6 +4,7 @@ use crate::events::IoEvents;
use crate::fs::inode_handle::FileIo; use crate::fs::inode_handle::FileIo;
use crate::prelude::*; use crate::prelude::*;
use crate::process::signal::Poller; use crate::process::signal::Poller;
use crate::process::{Gid, Uid};
use super::*; use super::*;
@ -15,19 +16,19 @@ const SLAVE_MAJOR_NUM: u32 = 3;
/// Pty slave inode for the slave device. /// Pty slave inode for the slave device.
pub struct PtySlaveInode { pub struct PtySlaveInode {
device: Arc<PtySlave>, device: Arc<PtySlave>,
metadata: Metadata, metadata: RwLock<Metadata>,
fs: Weak<DevPts>, fs: Weak<DevPts>,
} }
impl PtySlaveInode { impl PtySlaveInode {
pub fn new(device: Arc<PtySlave>, fs: Weak<DevPts>) -> Arc<Self> { pub fn new(device: Arc<PtySlave>, fs: Weak<DevPts>) -> Arc<Self> {
Arc::new(Self { Arc::new(Self {
metadata: Metadata::new_device( metadata: RwLock::new(Metadata::new_device(
device.index() as usize + FIRST_SLAVE_INO, device.index() as usize + FIRST_SLAVE_INO,
InodeMode::from_bits_truncate(0o620), InodeMode::from_bits_truncate(0o620),
&fs.upgrade().unwrap().sb(), &fs.upgrade().unwrap().sb(),
device.as_ref(), device.as_ref(),
), )),
device, device,
fs, fs,
}) })
@ -44,7 +45,7 @@ impl Inode for PtySlaveInode {
} }
fn size(&self) -> usize { fn size(&self) -> usize {
self.metadata.size self.metadata.read().size
} }
fn resize(&self, new_size: usize) -> Result<()> { fn resize(&self, new_size: usize) -> Result<()> {
@ -52,34 +53,59 @@ impl Inode for PtySlaveInode {
} }
fn metadata(&self) -> Metadata { fn metadata(&self) -> Metadata {
self.metadata.clone() *self.metadata.read()
} }
fn ino(&self) -> u64 { fn ino(&self) -> u64 {
self.metadata.ino as _ self.metadata.read().ino as _
} }
fn type_(&self) -> InodeType { fn type_(&self) -> InodeType {
self.metadata.type_ self.metadata.read().type_
} }
fn mode(&self) -> InodeMode { fn mode(&self) -> Result<InodeMode> {
self.metadata.mode Ok(self.metadata.read().mode)
} }
fn set_mode(&self, mode: InodeMode) {} fn set_mode(&self, mode: InodeMode) -> Result<()> {
self.metadata.write().mode = mode;
Ok(())
}
fn owner(&self) -> Result<Uid> {
Ok(self.metadata.read().uid)
}
fn set_owner(&self, uid: Uid) -> Result<()> {
self.metadata.write().uid = uid;
Ok(())
}
fn group(&self) -> Result<Gid> {
Ok(self.metadata.read().gid)
}
fn set_group(&self, gid: Gid) -> Result<()> {
self.metadata.write().gid = gid;
Ok(())
}
fn atime(&self) -> Duration { fn atime(&self) -> Duration {
self.metadata.atime self.metadata.read().atime
} }
fn set_atime(&self, time: Duration) {} fn set_atime(&self, time: Duration) {
self.metadata.write().atime = time;
}
fn mtime(&self) -> Duration { fn mtime(&self) -> Duration {
self.metadata.mtime self.metadata.read().mtime
} }
fn set_mtime(&self, time: Duration) {} fn set_mtime(&self, time: Duration) {
self.metadata.write().mtime = time;
}
fn read_at(&self, offset: usize, buf: &mut [u8]) -> Result<usize> { fn read_at(&self, offset: usize, buf: &mut [u8]) -> Result<usize> {
self.device.read(buf) self.device.read(buf)

View File

@ -6,6 +6,7 @@ use crate::fs::utils::{
DirentVisitor, FileSystem, Inode, InodeMode, InodeType, IoctlCmd, Metadata, DirentVisitor, FileSystem, Inode, InodeMode, InodeType, IoctlCmd, Metadata,
}; };
use crate::prelude::*; use crate::prelude::*;
use crate::process::{Gid, Uid};
use crate::vm::vmo::Vmo; use crate::vm::vmo::Vmo;
use aster_rights::Full; use aster_rights::Full;
@ -33,8 +34,8 @@ impl Inode for Ext2Inode {
type_: InodeType::from(self.file_type()), type_: InodeType::from(self.file_type()),
mode: InodeMode::from(self.file_perm()), mode: InodeMode::from(self.file_perm()),
nlinks: self.hard_links() as _, nlinks: self.hard_links() as _,
uid: self.uid() as _, uid: Uid::new(self.uid()),
gid: self.gid() as _, gid: Gid::new(self.gid()),
rdev: self.device_id(), rdev: self.device_id(),
} }
} }
@ -63,12 +64,31 @@ impl Inode for Ext2Inode {
InodeType::from(self.file_type()) InodeType::from(self.file_type())
} }
fn mode(&self) -> InodeMode { fn mode(&self) -> Result<InodeMode> {
InodeMode::from(self.file_perm()) Ok(InodeMode::from(self.file_perm()))
} }
fn set_mode(&self, mode: InodeMode) { fn set_mode(&self, mode: InodeMode) -> Result<()> {
self.set_file_perm(mode.into()); self.set_file_perm(mode.into());
Ok(())
}
fn owner(&self) -> Result<Uid> {
Ok(Uid::new(self.uid()))
}
fn set_owner(&self, uid: Uid) -> Result<()> {
self.set_uid(uid.as_u32());
Ok(())
}
fn group(&self) -> Result<Gid> {
Ok(Gid::new(self.gid()))
}
fn set_group(&self, gid: Gid) -> Result<()> {
self.set_gid(gid.as_u32());
Ok(())
} }
fn page_cache(&self) -> Option<Vmo<Full>> { fn page_cache(&self) -> Option<Vmo<Full>> {

View File

@ -576,6 +576,8 @@ impl Inode {
#[inherit_methods(from = "self.inner.write()")] #[inherit_methods(from = "self.inner.write()")]
impl Inode { impl Inode {
pub fn set_file_perm(&self, perm: FilePerm); pub fn set_file_perm(&self, perm: FilePerm);
pub fn set_uid(&self, uid: u32);
pub fn set_gid(&self, gid: u32);
pub fn set_atime(&self, time: Duration); pub fn set_atime(&self, time: Duration);
pub fn set_mtime(&self, time: Duration); pub fn set_mtime(&self, time: Duration);
} }
@ -601,7 +603,9 @@ impl Inner {
pub fn file_perm(&self) -> FilePerm; pub fn file_perm(&self) -> FilePerm;
pub fn set_file_perm(&mut self, perm: FilePerm); pub fn set_file_perm(&mut self, perm: FilePerm);
pub fn uid(&self) -> u32; pub fn uid(&self) -> u32;
pub fn set_uid(&mut self, uid: u32);
pub fn gid(&self) -> u32; pub fn gid(&self) -> u32;
pub fn set_gid(&mut self, gid: u32);
pub fn file_flags(&self) -> FileFlags; pub fn file_flags(&self) -> FileFlags;
pub fn hard_links(&self) -> u16; pub fn hard_links(&self) -> u16;
pub fn inc_hard_links(&mut self); pub fn inc_hard_links(&mut self);
@ -936,10 +940,20 @@ impl InodeImpl {
self.0.read().desc.uid self.0.read().desc.uid
} }
pub fn set_uid(&self, uid: u32) {
let mut inner = self.0.write();
inner.desc.uid = uid;
}
pub fn gid(&self) -> u32 { pub fn gid(&self) -> u32 {
self.0.read().desc.gid self.0.read().desc.gid
} }
pub fn set_gid(&self, gid: u32) {
let mut inner = self.0.write();
inner.desc.gid = gid;
}
pub fn file_flags(&self) -> FileFlags { pub fn file_flags(&self) -> FileFlags {
self.0.read().desc.flags self.0.read().desc.flags
} }

View File

@ -4,10 +4,11 @@
use crate::events::{IoEvents, Observer}; use crate::events::{IoEvents, Observer};
use crate::fs::device::Device; use crate::fs::device::Device;
use crate::fs::utils::{AccessMode, IoctlCmd, Metadata, SeekFrom, StatusFlags}; use crate::fs::utils::{AccessMode, InodeMode, IoctlCmd, Metadata, SeekFrom, StatusFlags};
use crate::net::socket::Socket; use crate::net::socket::Socket;
use crate::prelude::*; use crate::prelude::*;
use crate::process::signal::Poller; use crate::process::signal::Poller;
use crate::process::{Gid, Uid};
use core::any::Any; use core::any::Any;
@ -41,6 +42,30 @@ pub trait FileLike: Send + Sync + Any {
panic!("metadata unsupported"); panic!("metadata unsupported");
} }
fn mode(&self) -> Result<InodeMode> {
return_errno_with_message!(Errno::EINVAL, "mode is not supported");
}
fn set_mode(&self, mode: InodeMode) -> Result<()> {
return_errno_with_message!(Errno::EINVAL, "set_mode is not supported");
}
fn owner(&self) -> Result<Uid> {
return_errno_with_message!(Errno::EPERM, "owner is not supported");
}
fn set_owner(&self, uid: Uid) -> Result<()> {
return_errno_with_message!(Errno::EPERM, "set_owner is not supported");
}
fn group(&self) -> Result<Gid> {
return_errno_with_message!(Errno::EPERM, "group is not supported");
}
fn set_group(&self, gid: Gid) -> Result<()> {
return_errno_with_message!(Errno::EPERM, "set_group is not supported");
}
fn status_flags(&self) -> StatusFlags { fn status_flags(&self) -> StatusFlags {
StatusFlags::empty() StatusFlags::empty()
} }

View File

@ -100,7 +100,7 @@ impl FsResolver {
if file_name.ends_with('/') { if file_name.ends_with('/') {
return_errno_with_message!(Errno::EISDIR, "path refers to a directory"); return_errno_with_message!(Errno::EISDIR, "path refers to a directory");
} }
if !dir_dentry.inode_mode().is_writable() { if !dir_dentry.mode()?.is_writable() {
return_errno_with_message!(Errno::EACCES, "file cannot be created"); return_errno_with_message!(Errno::EACCES, "file cannot be created");
} }
dir_dentry.create(&file_name, InodeType::File, inode_mode)? dir_dentry.create(&file_name, InodeType::File, inode_mode)?
@ -182,7 +182,7 @@ impl FsResolver {
// Iterate next dentry // Iterate next dentry
let next_dentry = dentry.lookup(next_name)?; let next_dentry = dentry.lookup(next_name)?;
let next_type = next_dentry.inode_type(); let next_type = next_dentry.type_();
let next_is_tail = path_remain.is_empty(); let next_is_tail = path_remain.is_empty();
// If next inode is a symlink, follow symlinks at most `SYMLINKS_MAX` times. // If next inode is a symlink, follow symlinks at most `SYMLINKS_MAX` times.
@ -280,7 +280,7 @@ impl FsResolver {
// Dereference the tail symlinks if needed // Dereference the tail symlinks if needed
loop { loop {
match dir_dentry.lookup(base_name.trim_end_matches('/')) { match dir_dentry.lookup(base_name.trim_end_matches('/')) {
Ok(dentry) if dentry.inode_type() == InodeType::SymLink => { Ok(dentry) if dentry.type_() == InodeType::SymLink => {
let link = { let link = {
let mut link = dentry.inode().read_link()?; let mut link = dentry.inode().read_link()?;
if link.is_empty() { if link.is_empty() {

View File

@ -3,7 +3,10 @@
use crate::events::IoEvents; use crate::events::IoEvents;
use crate::prelude::*; use crate::prelude::*;
use crate::process::signal::Poller; use crate::process::signal::Poller;
use crate::process::{Gid, Uid};
use aster_rights::{Rights, TRights}; use aster_rights::{Rights, TRights};
use inherit_methods_macro::inherit_methods;
use super::*; use super::*;
@ -14,10 +17,10 @@ impl InodeHandle<Rights> {
status_flags: StatusFlags, status_flags: StatusFlags,
) -> Result<Self> { ) -> Result<Self> {
let inode = dentry.inode(); let inode = dentry.inode();
if access_mode.is_readable() && !inode.mode().is_readable() { if access_mode.is_readable() && !inode.mode()?.is_readable() {
return_errno_with_message!(Errno::EACCES, "File is not readable"); return_errno_with_message!(Errno::EACCES, "File is not readable");
} }
if access_mode.is_writable() && !inode.mode().is_writable() { if access_mode.is_writable() && !inode.mode()?.is_writable() {
return_errno_with_message!(Errno::EACCES, "File is not writable"); return_errno_with_message!(Errno::EACCES, "File is not writable");
} }
if access_mode.is_writable() && inode.type_() == InodeType::Dir { if access_mode.is_writable() && inode.type_() == InodeType::Dir {
@ -70,7 +73,21 @@ impl Clone for InodeHandle<Rights> {
} }
} }
#[inherit_methods(from = "self.0")]
impl FileLike for InodeHandle<Rights> { impl FileLike for InodeHandle<Rights> {
fn poll(&self, mask: IoEvents, poller: Option<&Poller>) -> IoEvents;
fn ioctl(&self, cmd: IoctlCmd, arg: usize) -> Result<i32>;
fn status_flags(&self) -> StatusFlags;
fn access_mode(&self) -> AccessMode;
fn metadata(&self) -> Metadata;
fn mode(&self) -> Result<InodeMode>;
fn set_mode(&self, mode: InodeMode) -> Result<()>;
fn owner(&self) -> Result<Uid>;
fn set_owner(&self, uid: Uid) -> Result<()>;
fn group(&self) -> Result<Gid>;
fn set_group(&self, gid: Gid) -> Result<()>;
fn seek(&self, seek_from: SeekFrom) -> Result<usize>;
fn read(&self, buf: &mut [u8]) -> Result<usize> { fn read(&self, buf: &mut [u8]) -> Result<usize> {
if !self.1.contains(Rights::READ) { if !self.1.contains(Rights::READ) {
return_errno_with_message!(Errno::EBADF, "File is not readable"); return_errno_with_message!(Errno::EBADF, "File is not readable");
@ -85,14 +102,6 @@ impl FileLike for InodeHandle<Rights> {
self.0.write(buf) self.0.write(buf)
} }
fn poll(&self, mask: IoEvents, poller: Option<&Poller>) -> IoEvents {
self.0.poll(mask, poller)
}
fn ioctl(&self, cmd: IoctlCmd, arg: usize) -> Result<i32> {
self.0.ioctl(cmd, arg)
}
fn resize(&self, new_size: usize) -> Result<()> { fn resize(&self, new_size: usize) -> Result<()> {
if !self.1.contains(Rights::WRITE) { if !self.1.contains(Rights::WRITE) {
return_errno_with_message!(Errno::EINVAL, "File is not writable"); return_errno_with_message!(Errno::EINVAL, "File is not writable");
@ -100,27 +109,11 @@ impl FileLike for InodeHandle<Rights> {
self.0.resize(new_size) self.0.resize(new_size)
} }
fn metadata(&self) -> Metadata {
self.dentry().inode_metadata()
}
fn status_flags(&self) -> StatusFlags {
self.0.status_flags()
}
fn set_status_flags(&self, new_status_flags: StatusFlags) -> Result<()> { fn set_status_flags(&self, new_status_flags: StatusFlags) -> Result<()> {
self.0.set_status_flags(new_status_flags); self.0.set_status_flags(new_status_flags);
Ok(()) Ok(())
} }
fn access_mode(&self) -> AccessMode {
self.0.access_mode()
}
fn seek(&self, seek_from: SeekFrom) -> Result<usize> {
self.0.seek(seek_from)
}
fn clean_for_close(&self) -> Result<()> { fn clean_for_close(&self) -> Result<()> {
// Close does not guarantee that the data has been successfully saved to disk. // Close does not guarantee that the data has been successfully saved to disk.
Ok(()) Ok(())

View File

@ -6,15 +6,18 @@ mod dyn_cap;
mod static_cap; mod static_cap;
use core::sync::atomic::{AtomicU32, Ordering}; use core::sync::atomic::{AtomicU32, Ordering};
use inherit_methods_macro::inherit_methods;
use crate::events::IoEvents; use crate::events::IoEvents;
use crate::fs::device::Device; use crate::fs::device::Device;
use crate::fs::file_handle::FileLike; use crate::fs::file_handle::FileLike;
use crate::fs::utils::{ use crate::fs::utils::{
AccessMode, Dentry, DirentVisitor, InodeType, IoctlCmd, Metadata, SeekFrom, StatusFlags, AccessMode, Dentry, DirentVisitor, InodeMode, InodeType, IoctlCmd, Metadata, SeekFrom,
StatusFlags,
}; };
use crate::prelude::*; use crate::prelude::*;
use crate::process::signal::Poller; use crate::process::signal::Poller;
use crate::process::{Gid, Uid};
use aster_rights::Rights; use aster_rights::Rights;
#[derive(Debug)] #[derive(Debug)]
@ -57,7 +60,7 @@ impl InodeHandle_ {
} }
if self.status_flags().contains(StatusFlags::O_APPEND) { if self.status_flags().contains(StatusFlags::O_APPEND) {
*offset = self.dentry.inode_size(); *offset = self.dentry.size();
} }
let len = if self.status_flags().contains(StatusFlags::O_DIRECT) { let len = if self.status_flags().contains(StatusFlags::O_DIRECT) {
self.dentry.inode().write_direct_at(*offset, buf)? self.dentry.inode().write_direct_at(*offset, buf)?
@ -92,7 +95,7 @@ impl InodeHandle_ {
off as isize off as isize
} }
SeekFrom::End(off /* as isize */) => { SeekFrom::End(off /* as isize */) => {
let file_size = self.dentry.inode_size() as isize; let file_size = self.dentry.size() as isize;
assert!(file_size >= 0); assert!(file_size >= 0);
file_size file_size
.checked_add(off) .checked_add(off)
@ -116,15 +119,11 @@ impl InodeHandle_ {
*offset *offset
} }
pub fn size(&self) -> usize {
self.dentry.inode_size()
}
pub fn resize(&self, new_size: usize) -> Result<()> { pub fn resize(&self, new_size: usize) -> Result<()> {
if self.status_flags().contains(StatusFlags::O_APPEND) { if self.status_flags().contains(StatusFlags::O_APPEND) {
return_errno_with_message!(Errno::EPERM, "can not resize append-only file"); return_errno_with_message!(Errno::EPERM, "can not resize append-only file");
} }
self.dentry.set_inode_size(new_size) self.dentry.resize(new_size)
} }
pub fn access_mode(&self) -> AccessMode { pub fn access_mode(&self) -> AccessMode {
@ -165,6 +164,18 @@ impl InodeHandle_ {
} }
} }
#[inherit_methods(from = "self.dentry")]
impl InodeHandle_ {
pub fn size(&self) -> usize;
pub fn metadata(&self) -> Metadata;
pub fn mode(&self) -> Result<InodeMode>;
pub fn set_mode(&self, mode: InodeMode) -> Result<()>;
pub fn owner(&self) -> Result<Uid>;
pub fn set_owner(&self, uid: Uid) -> Result<()>;
pub fn group(&self) -> Result<Gid>;
pub fn set_group(&self, gid: Gid) -> Result<()>;
}
impl Debug for InodeHandle_ { impl Debug for InodeHandle_ {
fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result { fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
f.debug_struct("InodeHandle_") f.debug_struct("InodeHandle_")

View File

@ -3,6 +3,7 @@
use crate::events::{IoEvents, Observer}; use crate::events::{IoEvents, Observer};
use crate::prelude::*; use crate::prelude::*;
use crate::process::signal::Poller; use crate::process::signal::Poller;
use crate::process::{Gid, Uid};
use super::file_handle::FileLike; use super::file_handle::FileLike;
use super::utils::{AccessMode, Consumer, InodeMode, InodeType, Metadata, Producer, StatusFlags}; use super::utils::{AccessMode, Consumer, InodeMode, InodeType, Metadata, Producer, StatusFlags};
@ -51,8 +52,8 @@ impl FileLike for PipeReader {
type_: InodeType::NamedPipe, type_: InodeType::NamedPipe,
mode: InodeMode::from_bits_truncate(0o400), mode: InodeMode::from_bits_truncate(0o400),
nlinks: 1, nlinks: 1,
uid: 0, uid: Uid::new_root(),
gid: 0, gid: Gid::new_root(),
rdev: 0, rdev: 0,
} }
} }
@ -117,8 +118,8 @@ impl FileLike for PipeWriter {
type_: InodeType::NamedPipe, type_: InodeType::NamedPipe,
mode: InodeMode::from_bits_truncate(0o200), mode: InodeMode::from_bits_truncate(0o200),
nlinks: 1, nlinks: 1,
uid: 0, uid: Uid::new_root(),
gid: 0, gid: Gid::new_root(),
rdev: 0, rdev: 0,
} }
} }

View File

@ -2,19 +2,21 @@
use aster_util::slot_vec::SlotVec; use aster_util::slot_vec::SlotVec;
use core::time::Duration; use core::time::Duration;
use inherit_methods_macro::inherit_methods;
use crate::fs::device::Device; use crate::fs::device::Device;
use crate::fs::utils::{DirentVisitor, FileSystem, Inode, InodeMode, InodeType, Metadata}; use crate::fs::utils::{DirentVisitor, FileSystem, Inode, InodeMode, InodeType, Metadata};
use crate::prelude::*; use crate::prelude::*;
use crate::process::{Gid, Uid};
use super::{ProcFS, ProcInodeInfo}; use super::{Common, ProcFS};
pub struct ProcDir<D: DirOps> { pub struct ProcDir<D: DirOps> {
inner: D, inner: D,
this: Weak<ProcDir<D>>, this: Weak<ProcDir<D>>,
parent: Option<Weak<dyn Inode>>, parent: Option<Weak<dyn Inode>>,
cached_children: RwLock<SlotVec<(String, Arc<dyn Inode>)>>, cached_children: RwLock<SlotVec<(String, Arc<dyn Inode>)>>,
info: ProcInodeInfo, common: Common,
} }
impl<D: DirOps> ProcDir<D> { impl<D: DirOps> ProcDir<D> {
@ -24,21 +26,21 @@ impl<D: DirOps> ProcDir<D> {
parent: Option<Weak<dyn Inode>>, parent: Option<Weak<dyn Inode>>,
is_volatile: bool, is_volatile: bool,
) -> Arc<Self> { ) -> Arc<Self> {
let info = { let common = {
let procfs = fs.downcast_ref::<ProcFS>().unwrap(); let procfs = fs.downcast_ref::<ProcFS>().unwrap();
let metadata = Metadata::new_dir( let metadata = Metadata::new_dir(
procfs.alloc_id(), procfs.alloc_id(),
InodeMode::from_bits_truncate(0o555), InodeMode::from_bits_truncate(0o555),
&fs.sb(), &fs.sb(),
); );
ProcInodeInfo::new(metadata, Arc::downgrade(&fs), is_volatile) Common::new(metadata, Arc::downgrade(&fs), is_volatile)
}; };
Arc::new_cyclic(|weak_self| Self { Arc::new_cyclic(|weak_self| Self {
inner: dir, inner: dir,
this: weak_self.clone(), this: weak_self.clone(),
parent, parent,
cached_children: RwLock::new(SlotVec::new()), cached_children: RwLock::new(SlotVec::new()),
info, common,
}) })
} }
@ -55,51 +57,31 @@ impl<D: DirOps> ProcDir<D> {
} }
} }
#[inherit_methods(from = "self.common")]
impl<D: DirOps + 'static> Inode for ProcDir<D> { impl<D: DirOps + 'static> Inode for ProcDir<D> {
fn size(&self) -> usize { fn size(&self) -> usize;
self.info.size() fn metadata(&self) -> Metadata;
} fn ino(&self) -> u64;
fn mode(&self) -> Result<InodeMode>;
fn set_mode(&self, mode: InodeMode) -> Result<()>;
fn owner(&self) -> Result<Uid>;
fn set_owner(&self, uid: Uid) -> Result<()>;
fn group(&self) -> Result<Gid>;
fn set_group(&self, gid: Gid) -> Result<()>;
fn atime(&self) -> Duration;
fn set_atime(&self, time: Duration);
fn mtime(&self) -> Duration;
fn set_mtime(&self, time: Duration);
fn fs(&self) -> Arc<dyn FileSystem>;
fn resize(&self, _new_size: usize) -> Result<()> { fn resize(&self, _new_size: usize) -> Result<()> {
Err(Error::new(Errno::EISDIR)) Err(Error::new(Errno::EISDIR))
} }
fn metadata(&self) -> Metadata {
self.info.metadata()
}
fn ino(&self) -> u64 {
self.info.ino()
}
fn type_(&self) -> InodeType { fn type_(&self) -> InodeType {
InodeType::Dir InodeType::Dir
} }
fn mode(&self) -> InodeMode {
self.info.mode()
}
fn set_mode(&self, mode: InodeMode) {
self.info.set_mode(mode)
}
fn atime(&self) -> Duration {
self.info.atime()
}
fn set_atime(&self, time: Duration) {
self.info.set_atime(time)
}
fn mtime(&self) -> Duration {
self.info.mtime()
}
fn set_mtime(&self, time: Duration) {
self.info.set_mtime(time)
}
fn create(&self, _name: &str, _type_: InodeType, _mode: InodeMode) -> Result<Arc<dyn Inode>> { fn create(&self, _name: &str, _type_: InodeType, _mode: InodeMode) -> Result<Arc<dyn Inode>> {
Err(Error::new(Errno::EPERM)) Err(Error::new(Errno::EPERM))
} }
@ -120,8 +102,8 @@ impl<D: DirOps + 'static> Inode for ProcDir<D> {
let this_inode = self.this(); let this_inode = self.this();
visitor.visit( visitor.visit(
".", ".",
this_inode.info.metadata().ino as u64, this_inode.common.metadata().ino as u64,
this_inode.info.metadata().type_, this_inode.common.metadata().type_,
*offset, *offset,
)?; )?;
*offset += 1; *offset += 1;
@ -204,12 +186,8 @@ impl<D: DirOps + 'static> Inode for ProcDir<D> {
Ok(()) Ok(())
} }
fn fs(&self) -> Arc<dyn FileSystem> {
self.info.fs().upgrade().unwrap()
}
fn is_dentry_cacheable(&self) -> bool { fn is_dentry_cacheable(&self) -> bool {
!self.info.is_volatile() !self.common.is_volatile()
} }
} }

View File

@ -1,77 +1,62 @@
// SPDX-License-Identifier: MPL-2.0 // SPDX-License-Identifier: MPL-2.0
use core::time::Duration; use core::time::Duration;
use inherit_methods_macro::inherit_methods;
use crate::fs::utils::{FileSystem, Inode, InodeMode, InodeType, IoctlCmd, Metadata}; use crate::fs::utils::{FileSystem, Inode, InodeMode, InodeType, IoctlCmd, Metadata};
use crate::prelude::*; use crate::prelude::*;
use crate::process::{Gid, Uid};
use super::{ProcFS, ProcInodeInfo}; use super::{Common, ProcFS};
pub struct ProcFile<F: FileOps> { pub struct ProcFile<F: FileOps> {
inner: F, inner: F,
info: ProcInodeInfo, common: Common,
} }
impl<F: FileOps> ProcFile<F> { impl<F: FileOps> ProcFile<F> {
pub fn new(file: F, fs: Arc<dyn FileSystem>, is_volatile: bool) -> Arc<Self> { pub fn new(file: F, fs: Arc<dyn FileSystem>, is_volatile: bool) -> Arc<Self> {
let info = { let common = {
let procfs = fs.downcast_ref::<ProcFS>().unwrap(); let procfs = fs.downcast_ref::<ProcFS>().unwrap();
let metadata = Metadata::new_file( let metadata = Metadata::new_file(
procfs.alloc_id(), procfs.alloc_id(),
InodeMode::from_bits_truncate(0o444), InodeMode::from_bits_truncate(0o444),
&fs.sb(), &fs.sb(),
); );
ProcInodeInfo::new(metadata, Arc::downgrade(&fs), is_volatile) Common::new(metadata, Arc::downgrade(&fs), is_volatile)
}; };
Arc::new(Self { inner: file, info }) Arc::new(Self {
inner: file,
common,
})
} }
} }
#[inherit_methods(from = "self.common")]
impl<F: FileOps + 'static> Inode for ProcFile<F> { impl<F: FileOps + 'static> Inode for ProcFile<F> {
fn size(&self) -> usize { fn size(&self) -> usize;
self.info.size() fn metadata(&self) -> Metadata;
} fn ino(&self) -> u64;
fn mode(&self) -> Result<InodeMode>;
fn set_mode(&self, mode: InodeMode) -> Result<()>;
fn owner(&self) -> Result<Uid>;
fn set_owner(&self, uid: Uid) -> Result<()>;
fn group(&self) -> Result<Gid>;
fn set_group(&self, gid: Gid) -> Result<()>;
fn atime(&self) -> Duration;
fn set_atime(&self, time: Duration);
fn mtime(&self) -> Duration;
fn set_mtime(&self, time: Duration);
fn fs(&self) -> Arc<dyn FileSystem>;
fn resize(&self, _new_size: usize) -> Result<()> { fn resize(&self, _new_size: usize) -> Result<()> {
Err(Error::new(Errno::EPERM)) Err(Error::new(Errno::EPERM))
} }
fn metadata(&self) -> Metadata {
self.info.metadata()
}
fn ino(&self) -> u64 {
self.info.ino()
}
fn type_(&self) -> InodeType { fn type_(&self) -> InodeType {
InodeType::File InodeType::File
} }
fn mode(&self) -> InodeMode {
self.info.mode()
}
fn set_mode(&self, mode: InodeMode) {
self.info.set_mode(mode)
}
fn atime(&self) -> Duration {
self.info.atime()
}
fn set_atime(&self, time: Duration) {
self.info.set_atime(time)
}
fn mtime(&self) -> Duration {
self.info.mtime()
}
fn set_mtime(&self, time: Duration) {
self.info.set_mtime(time)
}
fn read_at(&self, offset: usize, buf: &mut [u8]) -> Result<usize> { fn read_at(&self, offset: usize, buf: &mut [u8]) -> Result<usize> {
let data = self.inner.data()?; let data = self.inner.data()?;
let start = data.len().min(offset); let start = data.len().min(offset);
@ -109,12 +94,8 @@ impl<F: FileOps + 'static> Inode for ProcFile<F> {
Ok(()) Ok(())
} }
fn fs(&self) -> Arc<dyn FileSystem> {
self.info.fs().upgrade().unwrap()
}
fn is_dentry_cacheable(&self) -> bool { fn is_dentry_cacheable(&self) -> bool {
!self.info.is_volatile() !self.common.is_volatile()
} }
} }

View File

@ -4,6 +4,7 @@ use core::time::Duration;
use crate::fs::utils::{FileSystem, InodeMode, Metadata}; use crate::fs::utils::{FileSystem, InodeMode, Metadata};
use crate::prelude::*; use crate::prelude::*;
use crate::process::{Gid, Uid};
use super::ProcFS; use super::ProcFS;
@ -17,13 +18,13 @@ mod dir;
mod file; mod file;
mod sym; mod sym;
struct ProcInodeInfo { struct Common {
metadata: RwLock<Metadata>, metadata: RwLock<Metadata>,
fs: Weak<dyn FileSystem>, fs: Weak<dyn FileSystem>,
is_volatile: bool, is_volatile: bool,
} }
impl ProcInodeInfo { impl Common {
pub fn new(metadata: Metadata, fs: Weak<dyn FileSystem>, is_volatile: bool) -> Self { pub fn new(metadata: Metadata, fs: Weak<dyn FileSystem>, is_volatile: bool) -> Self {
Self { Self {
metadata: RwLock::new(metadata), metadata: RwLock::new(metadata),
@ -32,12 +33,12 @@ impl ProcInodeInfo {
} }
} }
pub fn fs(&self) -> &Weak<dyn FileSystem> { pub fn fs(&self) -> Arc<dyn FileSystem> {
&self.fs self.fs.upgrade().unwrap()
} }
pub fn metadata(&self) -> Metadata { pub fn metadata(&self) -> Metadata {
self.metadata.read().clone() *self.metadata.read()
} }
pub fn ino(&self) -> u64 { pub fn ino(&self) -> u64 {
@ -64,12 +65,31 @@ impl ProcInodeInfo {
self.metadata.write().mtime = time; self.metadata.write().mtime = time;
} }
pub fn mode(&self) -> InodeMode { pub fn mode(&self) -> Result<InodeMode> {
self.metadata.read().mode Ok(self.metadata.read().mode)
} }
pub fn set_mode(&self, mode: InodeMode) { pub fn set_mode(&self, mode: InodeMode) -> Result<()> {
self.metadata.write().mode = mode; self.metadata.write().mode = mode;
Ok(())
}
pub fn owner(&self) -> Result<Uid> {
Ok(self.metadata.read().uid)
}
pub fn set_owner(&self, uid: Uid) -> Result<()> {
self.metadata.write().uid = uid;
Ok(())
}
pub fn group(&self) -> Result<Gid> {
Ok(self.metadata.read().gid)
}
pub fn set_group(&self, gid: Gid) -> Result<()> {
self.metadata.write().gid = gid;
Ok(())
} }
pub fn is_volatile(&self) -> bool { pub fn is_volatile(&self) -> bool {

View File

@ -1,77 +1,59 @@
// SPDX-License-Identifier: MPL-2.0 // SPDX-License-Identifier: MPL-2.0
use core::time::Duration; use core::time::Duration;
use inherit_methods_macro::inherit_methods;
use crate::fs::utils::{FileSystem, Inode, InodeMode, InodeType, IoctlCmd, Metadata}; use crate::fs::utils::{FileSystem, Inode, InodeMode, InodeType, IoctlCmd, Metadata};
use crate::prelude::*; use crate::prelude::*;
use crate::process::{Gid, Uid};
use super::{ProcFS, ProcInodeInfo}; use super::{Common, ProcFS};
pub struct ProcSym<S: SymOps> { pub struct ProcSym<S: SymOps> {
inner: S, inner: S,
info: ProcInodeInfo, common: Common,
} }
impl<S: SymOps> ProcSym<S> { impl<S: SymOps> ProcSym<S> {
pub fn new(sym: S, fs: Arc<dyn FileSystem>, is_volatile: bool) -> Arc<Self> { pub fn new(sym: S, fs: Arc<dyn FileSystem>, is_volatile: bool) -> Arc<Self> {
let info = { let common = {
let procfs = fs.downcast_ref::<ProcFS>().unwrap(); let procfs = fs.downcast_ref::<ProcFS>().unwrap();
let metadata = Metadata::new_symlink( let metadata = Metadata::new_symlink(
procfs.alloc_id(), procfs.alloc_id(),
InodeMode::from_bits_truncate(0o777), InodeMode::from_bits_truncate(0o777),
&fs.sb(), &fs.sb(),
); );
ProcInodeInfo::new(metadata, Arc::downgrade(&fs), is_volatile) Common::new(metadata, Arc::downgrade(&fs), is_volatile)
}; };
Arc::new(Self { inner: sym, info }) Arc::new(Self { inner: sym, common })
} }
} }
#[inherit_methods(from = "self.common")]
impl<S: SymOps + 'static> Inode for ProcSym<S> { impl<S: SymOps + 'static> Inode for ProcSym<S> {
fn size(&self) -> usize { fn size(&self) -> usize;
self.info.size() fn metadata(&self) -> Metadata;
} fn ino(&self) -> u64;
fn mode(&self) -> Result<InodeMode>;
fn set_mode(&self, mode: InodeMode) -> Result<()>;
fn owner(&self) -> Result<Uid>;
fn set_owner(&self, uid: Uid) -> Result<()>;
fn group(&self) -> Result<Gid>;
fn set_group(&self, gid: Gid) -> Result<()>;
fn atime(&self) -> Duration;
fn set_atime(&self, time: Duration);
fn mtime(&self) -> Duration;
fn set_mtime(&self, time: Duration);
fn fs(&self) -> Arc<dyn FileSystem>;
fn resize(&self, _new_size: usize) -> Result<()> { fn resize(&self, _new_size: usize) -> Result<()> {
Err(Error::new(Errno::EPERM)) Err(Error::new(Errno::EPERM))
} }
fn metadata(&self) -> Metadata {
self.info.metadata()
}
fn ino(&self) -> u64 {
self.info.ino()
}
fn type_(&self) -> InodeType { fn type_(&self) -> InodeType {
InodeType::SymLink InodeType::SymLink
} }
fn mode(&self) -> InodeMode {
self.info.mode()
}
fn set_mode(&self, mode: InodeMode) {
self.info.set_mode(mode)
}
fn atime(&self) -> Duration {
self.info.atime()
}
fn set_atime(&self, time: Duration) {
self.info.set_atime(time)
}
fn mtime(&self) -> Duration {
self.info.mtime()
}
fn set_mtime(&self, time: Duration) {
self.info.set_mtime(time)
}
fn read_at(&self, _offset: usize, _buf: &mut [u8]) -> Result<usize> { fn read_at(&self, _offset: usize, _buf: &mut [u8]) -> Result<usize> {
Err(Error::new(Errno::EPERM)) Err(Error::new(Errno::EPERM))
} }
@ -104,12 +86,8 @@ impl<S: SymOps + 'static> Inode for ProcSym<S> {
Ok(()) Ok(())
} }
fn fs(&self) -> Arc<dyn FileSystem> {
self.info.fs().upgrade().unwrap()
}
fn is_dentry_cacheable(&self) -> bool { fn is_dentry_cacheable(&self) -> bool {
!self.info.is_volatile() !self.common.is_volatile()
} }
} }

View File

@ -17,6 +17,7 @@ use crate::fs::utils::{
}; };
use crate::prelude::*; use crate::prelude::*;
use crate::process::signal::Poller; use crate::process::signal::Poller;
use crate::process::{Gid, Uid};
use crate::vm::vmo::Vmo; use crate::vm::vmo::Vmo;
/// A volatile file system whose data and metadata exists only in memory. /// A volatile file system whose data and metadata exists only in memory.
@ -537,12 +538,31 @@ impl Inode for RamInode {
self.0.read().metadata.type_ self.0.read().metadata.type_
} }
fn mode(&self) -> InodeMode { fn mode(&self) -> Result<InodeMode> {
self.0.read().metadata.mode Ok(self.0.read().metadata.mode)
} }
fn set_mode(&self, mode: InodeMode) { fn set_mode(&self, mode: InodeMode) -> Result<()> {
self.0.write().metadata.mode = mode; self.0.write().metadata.mode = mode;
Ok(())
}
fn owner(&self) -> Result<Uid> {
Ok(self.0.read().metadata.uid)
}
fn set_owner(&self, uid: Uid) -> Result<()> {
self.0.write().metadata.uid = uid;
Ok(())
}
fn group(&self) -> Result<Gid> {
Ok(self.0.read().metadata.gid)
}
fn set_group(&self, gid: Gid) -> Result<()> {
self.0.write().metadata.gid = gid;
Ok(())
} }
fn mknod( fn mknod(
@ -870,7 +890,7 @@ impl Inode for RamInode {
} }
fn metadata(&self) -> Metadata { fn metadata(&self) -> Metadata {
self.0.read().metadata.clone() self.0.read().metadata
} }
fn sync(&self) -> Result<()> { fn sync(&self) -> Result<()> {

View File

@ -2,10 +2,12 @@
use crate::fs::device::Device; use crate::fs::device::Device;
use crate::prelude::*; use crate::prelude::*;
use crate::process::{Gid, Uid};
use alloc::string::String; use alloc::string::String;
use core::sync::atomic::{AtomicU32, Ordering}; use core::sync::atomic::{AtomicU32, Ordering};
use core::time::Duration; use core::time::Duration;
use inherit_methods_macro::inherit_methods;
use super::{FileSystem, Inode, InodeMode, InodeType, Metadata, MountNode, NAME_MAX}; use super::{FileSystem, Inode, InodeMode, InodeType, Metadata, MountNode, NAME_MAX};
@ -215,7 +217,7 @@ impl Dentry {
if self.inode.type_() != InodeType::Dir { if self.inode.type_() != InodeType::Dir {
return_errno!(Errno::ENOTDIR); return_errno!(Errno::ENOTDIR);
} }
if !self.inode.mode().is_executable() { if !self.inode.mode()?.is_executable() {
return_errno!(Errno::EACCES); return_errno!(Errno::EACCES);
} }
if name.len() > NAME_MAX { if name.len() > NAME_MAX {
@ -380,66 +382,6 @@ impl Dentry {
Ok(child_mount) Ok(child_mount)
} }
/// Get the filesystem the inode belongs to
pub fn fs(&self) -> Arc<dyn FileSystem> {
self.inode.fs()
}
/// Flushes all changes made to data and metadata to the device.
pub fn sync(&self) -> Result<()> {
self.inode.sync()
}
/// Get the inode metadata
pub fn inode_metadata(&self) -> Metadata {
self.inode.metadata()
}
/// Get the inode type
pub fn inode_type(&self) -> InodeType {
self.inode.type_()
}
/// Get the inode permission mode
pub fn inode_mode(&self) -> InodeMode {
self.inode.mode()
}
/// Set the inode permission mode
pub fn set_inode_mode(&self, mode: InodeMode) {
self.inode.set_mode(mode)
}
/// Gets the size of the inode
pub fn inode_size(&self) -> usize {
self.inode.size()
}
/// Sets the size of the inode
pub fn set_inode_size(&self, new_size: usize) -> Result<()> {
self.inode.resize(new_size)
}
/// Get the access timestamp
pub fn atime(&self) -> Duration {
self.inode.atime()
}
/// Set the access timestamp
pub fn set_atime(&self, time: Duration) {
self.inode.set_atime(time)
}
/// Get the modified timestamp
pub fn mtime(&self) -> Duration {
self.inode.mtime()
}
/// Set the modified timestamp
pub fn set_mtime(&self, time: Duration) {
self.inode.set_mtime(time)
}
/// Get the absolute path. /// Get the absolute path.
/// ///
/// It will resolve the mountpoint automatically. /// It will resolve the mountpoint automatically.
@ -469,6 +411,26 @@ impl Dentry {
} }
} }
#[inherit_methods(from = "self.inode")]
impl Dentry {
pub fn fs(&self) -> Arc<dyn FileSystem>;
pub fn sync(&self) -> Result<()>;
pub fn metadata(&self) -> Metadata;
pub fn type_(&self) -> InodeType;
pub fn mode(&self) -> Result<InodeMode>;
pub fn set_mode(&self, mode: InodeMode) -> Result<()>;
pub fn size(&self) -> usize;
pub fn resize(&self, size: usize) -> Result<()>;
pub fn owner(&self) -> Result<Uid>;
pub fn set_owner(&self, uid: Uid) -> Result<()>;
pub fn group(&self) -> Result<Gid>;
pub fn set_group(&self, gid: Gid) -> Result<()>;
pub fn atime(&self) -> Duration;
pub fn set_atime(&self, time: Duration);
pub fn mtime(&self) -> Duration;
pub fn set_mtime(&self, time: Duration);
}
impl Debug for Dentry { impl Debug for Dentry {
fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result { fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
f.debug_struct("Dentry") f.debug_struct("Dentry")

View File

@ -9,6 +9,7 @@ use crate::events::IoEvents;
use crate::fs::device::{Device, DeviceType}; use crate::fs::device::{Device, DeviceType};
use crate::prelude::*; use crate::prelude::*;
use crate::process::signal::Poller; use crate::process::signal::Poller;
use crate::process::{Gid, Uid};
use crate::vm::vmo::Vmo; use crate::vm::vmo::Vmo;
#[repr(u32)] #[repr(u32)]
@ -112,7 +113,7 @@ impl InodeMode {
} }
} }
#[derive(Debug, Clone)] #[derive(Debug, Clone, Copy)]
pub struct Metadata { pub struct Metadata {
pub dev: u64, pub dev: u64,
pub ino: usize, pub ino: usize,
@ -125,8 +126,8 @@ pub struct Metadata {
pub type_: InodeType, pub type_: InodeType,
pub mode: InodeMode, pub mode: InodeMode,
pub nlinks: usize, pub nlinks: usize,
pub uid: usize, pub uid: Uid,
pub gid: usize, pub gid: Gid,
pub rdev: u64, pub rdev: u64,
} }
@ -144,8 +145,8 @@ impl Metadata {
type_: InodeType::Dir, type_: InodeType::Dir,
mode, mode,
nlinks: 2, nlinks: 2,
uid: 0, uid: Uid::new_root(),
gid: 0, gid: Gid::new_root(),
rdev: 0, rdev: 0,
} }
} }
@ -163,8 +164,8 @@ impl Metadata {
type_: InodeType::File, type_: InodeType::File,
mode, mode,
nlinks: 1, nlinks: 1,
uid: 0, uid: Uid::new_root(),
gid: 0, gid: Gid::new_root(),
rdev: 0, rdev: 0,
} }
} }
@ -182,8 +183,8 @@ impl Metadata {
type_: InodeType::SymLink, type_: InodeType::SymLink,
mode, mode,
nlinks: 1, nlinks: 1,
uid: 0, uid: Uid::new_root(),
gid: 0, gid: Gid::new_root(),
rdev: 0, rdev: 0,
} }
} }
@ -200,8 +201,8 @@ impl Metadata {
type_: InodeType::from(device.type_()), type_: InodeType::from(device.type_()),
mode, mode,
nlinks: 1, nlinks: 1,
uid: 0, uid: Uid::new_root(),
gid: 0, gid: Gid::new_root(),
rdev: device.id().into(), rdev: device.id().into(),
} }
} }
@ -219,8 +220,8 @@ impl Metadata {
type_: InodeType::Socket, type_: InodeType::Socket,
mode, mode,
nlinks: 1, nlinks: 1,
uid: 0, uid: Uid::new_root(),
gid: 0, gid: Gid::new_root(),
rdev: 0, rdev: 0,
} }
} }
@ -237,9 +238,17 @@ pub trait Inode: Any + Sync + Send {
fn type_(&self) -> InodeType; fn type_(&self) -> InodeType;
fn mode(&self) -> InodeMode; fn mode(&self) -> Result<InodeMode>;
fn set_mode(&self, mode: InodeMode); fn set_mode(&self, mode: InodeMode) -> Result<()>;
fn owner(&self) -> Result<Uid>;
fn set_owner(&self, uid: Uid) -> Result<()>;
fn group(&self) -> Result<Gid>;
fn set_group(&self, gid: Gid) -> Result<()>;
fn atime(&self) -> Duration; fn atime(&self) -> Duration;

View File

@ -59,7 +59,7 @@ impl MountNode {
if !Arc::ptr_eq(&mountpoint.mount_node(), &self.this()) { if !Arc::ptr_eq(&mountpoint.mount_node(), &self.this()) {
return_errno_with_message!(Errno::EINVAL, "mountpoint not belongs to this"); return_errno_with_message!(Errno::EINVAL, "mountpoint not belongs to this");
} }
if mountpoint.inode_type() != InodeType::Dir { if mountpoint.type_() != InodeType::Dir {
return_errno!(Errno::ENOTDIR); return_errno!(Errno::ENOTDIR);
} }

View File

@ -290,11 +290,11 @@ fn lookup_socket_file(path: &str) -> Result<Arc<Dentry>> {
fs.lookup(&fs_path)? fs.lookup(&fs_path)?
}; };
if dentry.inode_type() != InodeType::Socket { if dentry.type_() != InodeType::Socket {
return_errno_with_message!(Errno::ENOTSOCK, "not a socket file") return_errno_with_message!(Errno::ENOTSOCK, "not a socket file")
} }
if !dentry.inode_mode().is_readable() || !dentry.inode_mode().is_writable() { if !dentry.mode()?.is_readable() || !dentry.mode()?.is_writable() {
return_errno_with_message!(Errno::EACCES, "the socket cannot be read or written") return_errno_with_message!(Errno::EACCES, "the socket cannot be read or written")
} }
Ok(dentry) Ok(dentry)

View File

@ -96,15 +96,15 @@ pub fn load_program_to_vm(
} }
pub fn check_executable_file(dentry: &Arc<Dentry>) -> Result<()> { pub fn check_executable_file(dentry: &Arc<Dentry>) -> Result<()> {
if dentry.inode_type().is_directory() { if dentry.type_().is_directory() {
return_errno_with_message!(Errno::EISDIR, "the file is a directory"); return_errno_with_message!(Errno::EISDIR, "the file is a directory");
} }
if !dentry.inode_type().is_reguler_file() { if !dentry.type_().is_reguler_file() {
return_errno_with_message!(Errno::EACCES, "the dentry is not a regular file"); return_errno_with_message!(Errno::EACCES, "the dentry is not a regular file");
} }
if !dentry.inode_mode().is_executable() { if !dentry.mode()?.is_executable() {
return_errno_with_message!(Errno::EACCES, "the dentry is not executable"); return_errno_with_message!(Errno::EACCES, "the dentry is not executable");
} }

View File

@ -26,7 +26,7 @@ pub fn sys_chdir(pathname_addr: Vaddr) -> Result<SyscallReturn> {
let fs_path = FsPath::try_from(pathname.as_ref())?; let fs_path = FsPath::try_from(pathname.as_ref())?;
fs.lookup(&fs_path)? fs.lookup(&fs_path)?
}; };
if dentry.inode_type() != InodeType::Dir { if dentry.type_() != InodeType::Dir {
return_errno_with_message!(Errno::ENOTDIR, "must be directory"); return_errno_with_message!(Errno::ENOTDIR, "must be directory");
} }
fs.set_cwd(dentry); fs.set_cwd(dentry);
@ -46,7 +46,7 @@ pub fn sys_fchdir(fd: FileDescripter) -> Result<SyscallReturn> {
.ok_or(Error::with_message(Errno::EBADF, "not inode"))?; .ok_or(Error::with_message(Errno::EBADF, "not inode"))?;
inode_handle.dentry().clone() inode_handle.dentry().clone()
}; };
if dentry.inode_type() != InodeType::Dir { if dentry.type_() != InodeType::Dir {
return_errno_with_message!(Errno::ENOTDIR, "must be directory"); return_errno_with_message!(Errno::ENOTDIR, "must be directory");
} }
current.fs().write().set_cwd(dentry); current.fs().write().set_cwd(dentry);

View File

@ -3,7 +3,6 @@
use crate::fs::{ use crate::fs::{
file_table::FileDescripter, file_table::FileDescripter,
fs_resolver::{FsPath, AT_FDCWD}, fs_resolver::{FsPath, AT_FDCWD},
inode_handle::InodeHandle,
utils::{InodeMode, PATH_MAX}, utils::{InodeMode, PATH_MAX},
}; };
use crate::log_syscall_entry; use crate::log_syscall_entry;
@ -20,11 +19,7 @@ pub fn sys_fchmod(fd: FileDescripter, mode: u16) -> Result<SyscallReturn> {
let current = current!(); let current = current!();
let file_table = current.file_table().lock(); let file_table = current.file_table().lock();
let file = file_table.get_file(fd)?; let file = file_table.get_file(fd)?;
let inode_handle = file file.set_mode(InodeMode::from_bits_truncate(mode))?;
.downcast_ref::<InodeHandle>()
.ok_or(Error::with_message(Errno::EBADF, "not inode"))?;
let dentry = inode_handle.dentry();
dentry.set_inode_mode(InodeMode::from_bits_truncate(mode));
Ok(SyscallReturn::Return(0)) Ok(SyscallReturn::Return(0))
} }
@ -52,6 +47,6 @@ pub fn sys_fchmodat(
let fs_path = FsPath::new(dirfd, path.as_ref())?; let fs_path = FsPath::new(dirfd, path.as_ref())?;
current.fs().read().lookup(&fs_path)? current.fs().read().lookup(&fs_path)?
}; };
dentry.set_inode_mode(InodeMode::from_bits_truncate(mode)); dentry.set_mode(InodeMode::from_bits_truncate(mode))?;
Ok(SyscallReturn::Return(0)) Ok(SyscallReturn::Return(0))
} }

View File

@ -0,0 +1,119 @@
// SPDX-License-Identifier: MPL-2.0
use crate::fs::{
file_table::FileDescripter,
fs_resolver::{FsPath, AT_FDCWD},
utils::PATH_MAX,
};
use crate::log_syscall_entry;
use crate::prelude::*;
use crate::process::{Gid, Uid};
use crate::util::read_cstring_from_user;
use super::SyscallReturn;
use super::{SYS_FCHOWN, SYS_FCHOWNAT};
pub fn sys_fchown(fd: FileDescripter, uid: i32, gid: i32) -> Result<SyscallReturn> {
log_syscall_entry!(SYS_FCHOWN);
debug!("fd = {}, uid = {}, gid = {}", fd, uid, gid);
let uid = to_optional_id(uid, Uid::new)?;
let gid = to_optional_id(gid, Gid::new)?;
if uid.is_none() && gid.is_none() {
return Ok(SyscallReturn::Return(0));
}
let current = current!();
let file_table = current.file_table().lock();
let file = file_table.get_file(fd)?;
if let Some(uid) = uid {
file.set_owner(uid)?;
}
if let Some(gid) = gid {
file.set_group(gid)?;
}
Ok(SyscallReturn::Return(0))
}
pub fn sys_chown(path_ptr: Vaddr, uid: i32, gid: i32) -> Result<SyscallReturn> {
self::sys_fchownat(AT_FDCWD, path_ptr, uid, gid, 0)
}
pub fn sys_lchown(path_ptr: Vaddr, uid: i32, gid: i32) -> Result<SyscallReturn> {
self::sys_fchownat(
AT_FDCWD,
path_ptr,
uid,
gid,
ChownFlags::AT_SYMLINK_NOFOLLOW.bits(),
)
}
pub fn sys_fchownat(
dirfd: FileDescripter,
path_ptr: Vaddr,
uid: i32,
gid: i32,
flags: u32,
) -> Result<SyscallReturn> {
log_syscall_entry!(SYS_FCHOWNAT);
let path = read_cstring_from_user(path_ptr, PATH_MAX)?;
let flags = ChownFlags::from_bits(flags)
.ok_or_else(|| Error::with_message(Errno::EINVAL, "invalid flags"))?;
debug!(
"dirfd = {}, path = {:?}, uid = {}, gid = {}, flags = {:?}",
dirfd, path, uid, gid, flags
);
if path.is_empty() {
if !flags.contains(ChownFlags::AT_EMPTY_PATH) {
return_errno_with_message!(Errno::ENOENT, "path is empty");
}
return self::sys_fchown(dirfd, uid, gid);
}
let uid = to_optional_id(uid, Uid::new)?;
let gid = to_optional_id(gid, Gid::new)?;
if uid.is_none() && gid.is_none() {
return Ok(SyscallReturn::Return(0));
}
let current = current!();
let dentry = {
let path = path.to_string_lossy();
let fs_path = FsPath::new(dirfd, path.as_ref())?;
let fs = current.fs().read();
if flags.contains(ChownFlags::AT_SYMLINK_NOFOLLOW) {
fs.lookup_no_follow(&fs_path)?
} else {
fs.lookup(&fs_path)?
}
};
if let Some(uid) = uid {
dentry.set_owner(uid)?;
}
if let Some(gid) = gid {
dentry.set_group(gid)?;
}
Ok(SyscallReturn::Return(0))
}
fn to_optional_id<T>(id: i32, f: impl Fn(u32) -> T) -> Result<Option<T>> {
let id = if id >= 0 {
Some(f(id as u32))
} else if id == -1 {
// If the owner or group is specified as -1, then that ID is not changed.
None
} else {
return_errno!(Errno::EINVAL);
};
Ok(id)
}
bitflags! {
struct ChownFlags: u32 {
const AT_SYMLINK_NOFOLLOW = 1 << 8;
const AT_EMPTY_PATH = 1 << 12;
}
}

View File

@ -10,9 +10,7 @@ use crate::fs::utils::{Dentry, InodeType};
use crate::log_syscall_entry; use crate::log_syscall_entry;
use crate::prelude::*; use crate::prelude::*;
use crate::process::posix_thread::{PosixThreadExt, ThreadName}; use crate::process::posix_thread::{PosixThreadExt, ThreadName};
use crate::process::{ use crate::process::{check_executable_file, credentials_mut, load_program_to_vm, Credentials};
check_executable_file, credentials_mut, load_program_to_vm, Credentials, Gid, Uid,
};
use crate::syscall::{SYS_EXECVE, SYS_EXECVEAT}; use crate::syscall::{SYS_EXECVE, SYS_EXECVEAT};
use crate::util::{read_cstring_from_user, read_val_from_user}; use crate::util::{read_cstring_from_user, read_val_from_user};
@ -65,7 +63,7 @@ fn lookup_executable_file(
let fs_path = FsPath::new(dfd, &filename)?; let fs_path = FsPath::new(dfd, &filename)?;
if flags.contains(OpenFlags::AT_SYMLINK_NOFOLLOW) { if flags.contains(OpenFlags::AT_SYMLINK_NOFOLLOW) {
let dentry = fs_resolver.lookup_no_follow(&fs_path)?; let dentry = fs_resolver.lookup_no_follow(&fs_path)?;
if dentry.inode_type() == InodeType::SymLink { if dentry.type_() == InodeType::SymLink {
return_errno_with_message!(Errno::ELOOP, "the executable file is a symlink"); return_errno_with_message!(Errno::ELOOP, "the executable file is a symlink");
} }
Ok(dentry) Ok(dentry)
@ -110,8 +108,8 @@ fn do_execve(
debug!("load elf in execve succeeds"); debug!("load elf in execve succeeds");
let credentials = credentials_mut(); let credentials = credentials_mut();
set_uid_from_elf(&credentials, &elf_file); set_uid_from_elf(&credentials, &elf_file)?;
set_gid_from_elf(&credentials, &elf_file); set_gid_from_elf(&credentials, &elf_file)?;
// set executable path // set executable path
current.set_executable_path(new_executable_path); current.set_executable_path(new_executable_path);
@ -169,23 +167,25 @@ fn read_cstring_vec(
} }
/// Sets uid for credentials as the same of uid of elf file if elf file has `set_uid` bit. /// Sets uid for credentials as the same of uid of elf file if elf file has `set_uid` bit.
fn set_uid_from_elf(credentials: &Credentials<WriteOp>, elf_file: &Arc<Dentry>) { fn set_uid_from_elf(credentials: &Credentials<WriteOp>, elf_file: &Arc<Dentry>) -> Result<()> {
if elf_file.inode_mode().has_set_uid() { if elf_file.mode()?.has_set_uid() {
let uid = Uid::new(elf_file.inode_metadata().uid as u32); let uid = elf_file.owner()?;
credentials.set_euid(uid); credentials.set_euid(uid);
} }
// No matter whether the elf_file has `set_uid` bit, suid should be reset. // No matter whether the elf_file has `set_uid` bit, suid should be reset.
credentials.reset_suid(); credentials.reset_suid();
Ok(())
} }
/// Sets gid for credentials as the same of gid of elf file if elf file has `set_gid` bit. /// Sets gid for credentials as the same of gid of elf file if elf file has `set_gid` bit.
fn set_gid_from_elf(credentials: &Credentials<WriteOp>, elf_file: &Arc<Dentry>) { fn set_gid_from_elf(credentials: &Credentials<WriteOp>, elf_file: &Arc<Dentry>) -> Result<()> {
if elf_file.inode_mode().has_set_gid() { if elf_file.mode()?.has_set_gid() {
let gid = Gid::new(elf_file.inode_metadata().gid as u32); let gid = elf_file.group()?;
credentials.set_egid(gid); credentials.set_egid(gid);
} }
// No matter whether the the elf file has `set_gid` bit, sgid should be reset. // No matter whether the the elf file has `set_gid` bit, sgid should be reset.
credentials.reset_sgid(); credentials.reset_sgid();
Ok(())
} }

View File

@ -32,7 +32,7 @@ pub fn sys_getdents64(
let inode_handle = file let inode_handle = file
.downcast_ref::<InodeHandle>() .downcast_ref::<InodeHandle>()
.ok_or(Error::with_message(Errno::EBADF, "not inode"))?; .ok_or(Error::with_message(Errno::EBADF, "not inode"))?;
if inode_handle.dentry().inode_type() != InodeType::Dir { if inode_handle.dentry().type_() != InodeType::Dir {
return_errno!(Errno::ENOTDIR); return_errno!(Errno::ENOTDIR);
} }
let mut buffer = vec![0u8; buf_len]; let mut buffer = vec![0u8; buf_len];

View File

@ -8,6 +8,7 @@ use crate::syscall::arch_prctl::sys_arch_prctl;
use crate::syscall::brk::sys_brk; use crate::syscall::brk::sys_brk;
use crate::syscall::chdir::{sys_chdir, sys_fchdir}; use crate::syscall::chdir::{sys_chdir, sys_fchdir};
use crate::syscall::chmod::{sys_chmod, sys_fchmod, sys_fchmodat}; use crate::syscall::chmod::{sys_chmod, sys_fchmod, sys_fchmodat};
use crate::syscall::chown::{sys_chown, sys_fchown, sys_fchownat, sys_lchown};
use crate::syscall::clock_gettime::sys_clock_gettime; use crate::syscall::clock_gettime::sys_clock_gettime;
use crate::syscall::clock_nanosleep::sys_clock_nanosleep; use crate::syscall::clock_nanosleep::sys_clock_nanosleep;
use crate::syscall::clone::sys_clone; use crate::syscall::clone::sys_clone;
@ -115,6 +116,7 @@ mod bind;
mod brk; mod brk;
mod chdir; mod chdir;
mod chmod; mod chmod;
mod chown;
mod clock_gettime; mod clock_gettime;
mod clock_nanosleep; mod clock_nanosleep;
mod clone; mod clone;
@ -306,6 +308,9 @@ define_syscall_nums!(
SYS_READLINK = 89, SYS_READLINK = 89,
SYS_CHMOD = 90, SYS_CHMOD = 90,
SYS_FCHMOD = 91, SYS_FCHMOD = 91,
SYS_CHOWN = 92,
SYS_FCHOWN = 93,
SYS_LCHOWN = 94,
SYS_UMASK = 95, SYS_UMASK = 95,
SYS_GETTIMEOFDAY = 96, SYS_GETTIMEOFDAY = 96,
SYS_GETUID = 102, SYS_GETUID = 102,
@ -350,6 +355,7 @@ define_syscall_nums!(
SYS_WAITID = 247, SYS_WAITID = 247,
SYS_OPENAT = 257, SYS_OPENAT = 257,
SYS_MKDIRAT = 258, SYS_MKDIRAT = 258,
SYS_FCHOWNAT = 260,
SYS_FSTATAT = 262, SYS_FSTATAT = 262,
SYS_UNLINKAT = 263, SYS_UNLINKAT = 263,
SYS_RENAMEAT = 264, SYS_RENAMEAT = 264,
@ -486,6 +492,9 @@ pub fn syscall_dispatch(
SYS_READLINK => syscall_handler!(3, sys_readlink, args), SYS_READLINK => syscall_handler!(3, sys_readlink, args),
SYS_CHMOD => syscall_handler!(2, sys_chmod, args), SYS_CHMOD => syscall_handler!(2, sys_chmod, args),
SYS_FCHMOD => syscall_handler!(2, sys_fchmod, args), SYS_FCHMOD => syscall_handler!(2, sys_fchmod, args),
SYS_CHOWN => syscall_handler!(3, sys_chown, args),
SYS_FCHOWN => syscall_handler!(3, sys_fchown, args),
SYS_LCHOWN => syscall_handler!(3, sys_lchown, args),
SYS_UMASK => syscall_handler!(1, sys_umask, args), SYS_UMASK => syscall_handler!(1, sys_umask, args),
SYS_GETTIMEOFDAY => syscall_handler!(1, sys_gettimeofday, args), SYS_GETTIMEOFDAY => syscall_handler!(1, sys_gettimeofday, args),
SYS_GETUID => syscall_handler!(0, sys_getuid), SYS_GETUID => syscall_handler!(0, sys_getuid),
@ -530,6 +539,7 @@ pub fn syscall_dispatch(
SYS_WAITID => syscall_handler!(5, sys_waitid, args), SYS_WAITID => syscall_handler!(5, sys_waitid, args),
SYS_OPENAT => syscall_handler!(4, sys_openat, args), SYS_OPENAT => syscall_handler!(4, sys_openat, args),
SYS_MKDIRAT => syscall_handler!(3, sys_mkdirat, args), SYS_MKDIRAT => syscall_handler!(3, sys_mkdirat, args),
SYS_FCHOWNAT => syscall_handler!(5, sys_fchownat, args),
SYS_FSTATAT => syscall_handler!(4, sys_fstatat, args), SYS_FSTATAT => syscall_handler!(4, sys_fstatat, args),
SYS_UNLINKAT => syscall_handler!(3, sys_unlinkat, args), SYS_UNLINKAT => syscall_handler!(3, sys_unlinkat, args),
SYS_RENAMEAT => syscall_handler!(4, sys_renameat, args), SYS_RENAMEAT => syscall_handler!(4, sys_renameat, args),

View File

@ -45,7 +45,7 @@ pub fn sys_renameat(
if new_pathname.is_empty() { if new_pathname.is_empty() {
return_errno_with_message!(Errno::ENOENT, "newpath is empty"); return_errno_with_message!(Errno::ENOENT, "newpath is empty");
} }
if new_pathname.ends_with('/') && old_dentry.inode_type() != InodeType::Dir { if new_pathname.ends_with('/') && old_dentry.type_() != InodeType::Dir {
return_errno_with_message!(Errno::ENOTDIR, "oldpath is not dir"); return_errno_with_message!(Errno::ENOTDIR, "oldpath is not dir");
} }
let new_fs_path = FsPath::new(new_dirfd, new_pathname.as_ref().trim_end_matches('/'))?; let new_fs_path = FsPath::new(new_dirfd, new_pathname.as_ref().trim_end_matches('/'))?;

View File

@ -67,7 +67,7 @@ pub fn sys_fstatat(
fs.lookup(&fs_path)? fs.lookup(&fs_path)?
} }
}; };
let stat = Stat::from(dentry.inode_metadata()); let stat = Stat::from(dentry.metadata());
write_val_to_user(stat_buf_ptr, &stat)?; write_val_to_user(stat_buf_ptr, &stat)?;
Ok(SyscallReturn::Return(0)) Ok(SyscallReturn::Return(0))
} }
@ -121,8 +121,8 @@ impl From<Metadata> for Stat {
st_ino: info.ino, st_ino: info.ino,
st_nlink: info.nlinks, st_nlink: info.nlinks,
st_mode: info.type_ as u32 | info.mode.bits() as u32, st_mode: info.type_ as u32 | info.mode.bits() as u32,
st_uid: info.uid as u32, st_uid: info.uid.as_u32(),
st_gid: info.gid as u32, st_gid: info.gid.as_u32(),
__pad0: 0, __pad0: 0,
st_rdev: info.rdev, st_rdev: info.rdev,
st_size: info.size as isize, st_size: info.size as isize,

View File

@ -42,7 +42,7 @@ pub fn sys_truncate(path_ptr: Vaddr, len: isize) -> Result<SyscallReturn> {
let fs_path = FsPath::new(AT_FDCWD, path.as_ref())?; let fs_path = FsPath::new(AT_FDCWD, path.as_ref())?;
current.fs().read().lookup(&fs_path)? current.fs().read().lookup(&fs_path)?
}; };
dentry.set_inode_size(len as usize)?; dentry.resize(len as usize)?;
Ok(SyscallReturn::Return(0)) Ok(SyscallReturn::Return(0))
} }