mirror of
https://github.com/asterinas/asterinas.git
synced 2025-06-22 17:03:23 +00:00
Add support for chown syscall
This commit is contained in:
committed by
Tate, Hongliang Tian
parent
3b3d088767
commit
729c6ecd0c
@ -1,6 +1,6 @@
|
||||
# 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 \
|
||||
statfs_test symlink_test sync_test truncate_test uidgid_test unlink_test \
|
||||
vdso_clock_gettime_test write_test
|
||||
|
15
regression/syscall_test/blocklists/chown_test
Normal file
15
regression/syscall_test/blocklists/chown_test
Normal 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
|
@ -7,6 +7,7 @@ use crate::fs::utils::{
|
||||
SuperBlock, NAME_MAX,
|
||||
};
|
||||
use crate::prelude::*;
|
||||
use crate::process::{Gid, Uid};
|
||||
|
||||
use aster_util::{id_allocator::IdAlloc, slot_vec::SlotVec};
|
||||
use core::time::Duration;
|
||||
@ -100,7 +101,7 @@ impl FileSystem for DevPts {
|
||||
struct RootInode {
|
||||
ptmx: Arc<Ptmx>,
|
||||
slaves: RwLock<SlotVec<(String, Arc<PtySlaveInode>)>>,
|
||||
metadata: Metadata,
|
||||
metadata: RwLock<Metadata>,
|
||||
fs: Weak<DevPts>,
|
||||
}
|
||||
|
||||
@ -109,7 +110,11 @@ impl RootInode {
|
||||
Arc::new(Self {
|
||||
ptmx: Ptmx::new(sb, fs.clone()),
|
||||
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,
|
||||
})
|
||||
}
|
||||
@ -138,7 +143,7 @@ impl RootInode {
|
||||
|
||||
impl Inode for RootInode {
|
||||
fn size(&self) -> usize {
|
||||
self.metadata.size
|
||||
self.metadata.read().size
|
||||
}
|
||||
|
||||
fn resize(&self, new_size: usize) -> Result<()> {
|
||||
@ -146,34 +151,59 @@ impl Inode for RootInode {
|
||||
}
|
||||
|
||||
fn metadata(&self) -> Metadata {
|
||||
self.metadata.clone()
|
||||
*self.metadata.read()
|
||||
}
|
||||
|
||||
fn ino(&self) -> u64 {
|
||||
self.metadata.ino as _
|
||||
self.metadata.read().ino as _
|
||||
}
|
||||
|
||||
fn type_(&self) -> InodeType {
|
||||
self.metadata.type_
|
||||
self.metadata.read().type_
|
||||
}
|
||||
|
||||
fn mode(&self) -> InodeMode {
|
||||
self.metadata.mode
|
||||
fn mode(&self) -> Result<InodeMode> {
|
||||
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 {
|
||||
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 {
|
||||
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>> {
|
||||
Err(Error::new(Errno::EPERM))
|
||||
@ -187,20 +217,15 @@ impl Inode for RootInode {
|
||||
let try_readdir = |offset: &mut usize, visitor: &mut dyn DirentVisitor| -> Result<()> {
|
||||
// Read the 3 special entries.
|
||||
if *offset == 0 {
|
||||
visitor.visit(".", self.metadata.ino as u64, self.metadata.type_, *offset)?;
|
||||
visitor.visit(".", self.ino(), self.type_(), *offset)?;
|
||||
*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;
|
||||
}
|
||||
if *offset == 2 {
|
||||
visitor.visit(
|
||||
"ptmx",
|
||||
self.ptmx.metadata().ino as u64,
|
||||
self.ptmx.metadata().type_,
|
||||
*offset,
|
||||
)?;
|
||||
visitor.visit("ptmx", self.ptmx.ino(), self.ptmx.type_(), *offset)?;
|
||||
*offset += 1;
|
||||
}
|
||||
|
||||
@ -212,12 +237,7 @@ impl Inode for RootInode {
|
||||
.map(|(idx, (name, node))| (idx + 3, (name, node)))
|
||||
.skip_while(|(idx, _)| idx < &start_offset)
|
||||
{
|
||||
visitor.visit(
|
||||
name.as_ref(),
|
||||
node.metadata().ino as u64,
|
||||
node.metadata().type_,
|
||||
idx,
|
||||
)?;
|
||||
visitor.visit(name.as_ref(), node.ino(), node.type_(), idx)?;
|
||||
*offset = idx + 1;
|
||||
}
|
||||
Ok(())
|
||||
|
@ -19,7 +19,7 @@ const PTMX_MINOR_NUM: u32 = 2;
|
||||
/// and an corresponding pty slave inode is also created.
|
||||
pub struct Ptmx {
|
||||
inner: Inner,
|
||||
metadata: Metadata,
|
||||
metadata: RwLock<Metadata>,
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
@ -29,12 +29,12 @@ impl Ptmx {
|
||||
pub fn new(sb: &SuperBlock, fs: Weak<DevPts>) -> Arc<Self> {
|
||||
let inner = Inner(fs);
|
||||
Arc::new(Self {
|
||||
metadata: Metadata::new_device(
|
||||
metadata: RwLock::new(Metadata::new_device(
|
||||
PTMX_INO,
|
||||
InodeMode::from_bits_truncate(0o666),
|
||||
sb,
|
||||
&inner,
|
||||
),
|
||||
)),
|
||||
inner,
|
||||
})
|
||||
}
|
||||
@ -64,7 +64,7 @@ impl Ptmx {
|
||||
// it returns the pty master. So the ptmx can not be used at upper layer.
|
||||
impl Inode for Ptmx {
|
||||
fn size(&self) -> usize {
|
||||
self.metadata.size
|
||||
self.metadata.read().size
|
||||
}
|
||||
|
||||
fn resize(&self, new_size: usize) -> Result<()> {
|
||||
@ -72,34 +72,59 @@ impl Inode for Ptmx {
|
||||
}
|
||||
|
||||
fn metadata(&self) -> Metadata {
|
||||
self.metadata.clone()
|
||||
*self.metadata.read()
|
||||
}
|
||||
|
||||
fn ino(&self) -> u64 {
|
||||
self.metadata.ino as _
|
||||
self.metadata.read().ino as _
|
||||
}
|
||||
|
||||
fn type_(&self) -> InodeType {
|
||||
self.metadata.type_
|
||||
self.metadata.read().type_
|
||||
}
|
||||
|
||||
fn mode(&self) -> InodeMode {
|
||||
self.metadata.mode
|
||||
fn mode(&self) -> Result<InodeMode> {
|
||||
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 {
|
||||
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 {
|
||||
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> {
|
||||
Ok(0)
|
||||
|
@ -4,6 +4,7 @@ use crate::events::IoEvents;
|
||||
use crate::fs::inode_handle::FileIo;
|
||||
use crate::prelude::*;
|
||||
use crate::process::signal::Poller;
|
||||
use crate::process::{Gid, Uid};
|
||||
|
||||
use super::*;
|
||||
|
||||
@ -15,19 +16,19 @@ const SLAVE_MAJOR_NUM: u32 = 3;
|
||||
/// Pty slave inode for the slave device.
|
||||
pub struct PtySlaveInode {
|
||||
device: Arc<PtySlave>,
|
||||
metadata: Metadata,
|
||||
metadata: RwLock<Metadata>,
|
||||
fs: Weak<DevPts>,
|
||||
}
|
||||
|
||||
impl PtySlaveInode {
|
||||
pub fn new(device: Arc<PtySlave>, fs: Weak<DevPts>) -> Arc<Self> {
|
||||
Arc::new(Self {
|
||||
metadata: Metadata::new_device(
|
||||
metadata: RwLock::new(Metadata::new_device(
|
||||
device.index() as usize + FIRST_SLAVE_INO,
|
||||
InodeMode::from_bits_truncate(0o620),
|
||||
&fs.upgrade().unwrap().sb(),
|
||||
device.as_ref(),
|
||||
),
|
||||
)),
|
||||
device,
|
||||
fs,
|
||||
})
|
||||
@ -44,7 +45,7 @@ impl Inode for PtySlaveInode {
|
||||
}
|
||||
|
||||
fn size(&self) -> usize {
|
||||
self.metadata.size
|
||||
self.metadata.read().size
|
||||
}
|
||||
|
||||
fn resize(&self, new_size: usize) -> Result<()> {
|
||||
@ -52,34 +53,59 @@ impl Inode for PtySlaveInode {
|
||||
}
|
||||
|
||||
fn metadata(&self) -> Metadata {
|
||||
self.metadata.clone()
|
||||
*self.metadata.read()
|
||||
}
|
||||
|
||||
fn ino(&self) -> u64 {
|
||||
self.metadata.ino as _
|
||||
self.metadata.read().ino as _
|
||||
}
|
||||
|
||||
fn type_(&self) -> InodeType {
|
||||
self.metadata.type_
|
||||
self.metadata.read().type_
|
||||
}
|
||||
|
||||
fn mode(&self) -> InodeMode {
|
||||
self.metadata.mode
|
||||
fn mode(&self) -> Result<InodeMode> {
|
||||
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 {
|
||||
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 {
|
||||
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> {
|
||||
self.device.read(buf)
|
||||
|
@ -6,6 +6,7 @@ use crate::fs::utils::{
|
||||
DirentVisitor, FileSystem, Inode, InodeMode, InodeType, IoctlCmd, Metadata,
|
||||
};
|
||||
use crate::prelude::*;
|
||||
use crate::process::{Gid, Uid};
|
||||
use crate::vm::vmo::Vmo;
|
||||
|
||||
use aster_rights::Full;
|
||||
@ -33,8 +34,8 @@ impl Inode for Ext2Inode {
|
||||
type_: InodeType::from(self.file_type()),
|
||||
mode: InodeMode::from(self.file_perm()),
|
||||
nlinks: self.hard_links() as _,
|
||||
uid: self.uid() as _,
|
||||
gid: self.gid() as _,
|
||||
uid: Uid::new(self.uid()),
|
||||
gid: Gid::new(self.gid()),
|
||||
rdev: self.device_id(),
|
||||
}
|
||||
}
|
||||
@ -63,12 +64,31 @@ impl Inode for Ext2Inode {
|
||||
InodeType::from(self.file_type())
|
||||
}
|
||||
|
||||
fn mode(&self) -> InodeMode {
|
||||
InodeMode::from(self.file_perm())
|
||||
fn mode(&self) -> Result<InodeMode> {
|
||||
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());
|
||||
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>> {
|
||||
|
@ -576,6 +576,8 @@ impl Inode {
|
||||
#[inherit_methods(from = "self.inner.write()")]
|
||||
impl Inode {
|
||||
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_mtime(&self, time: Duration);
|
||||
}
|
||||
@ -601,7 +603,9 @@ impl Inner {
|
||||
pub fn file_perm(&self) -> FilePerm;
|
||||
pub fn set_file_perm(&mut self, perm: FilePerm);
|
||||
pub fn uid(&self) -> u32;
|
||||
pub fn set_uid(&mut self, uid: u32);
|
||||
pub fn gid(&self) -> u32;
|
||||
pub fn set_gid(&mut self, gid: u32);
|
||||
pub fn file_flags(&self) -> FileFlags;
|
||||
pub fn hard_links(&self) -> u16;
|
||||
pub fn inc_hard_links(&mut self);
|
||||
@ -936,10 +940,20 @@ impl InodeImpl {
|
||||
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 {
|
||||
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 {
|
||||
self.0.read().desc.flags
|
||||
}
|
||||
|
@ -4,10 +4,11 @@
|
||||
|
||||
use crate::events::{IoEvents, Observer};
|
||||
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::prelude::*;
|
||||
use crate::process::signal::Poller;
|
||||
use crate::process::{Gid, Uid};
|
||||
|
||||
use core::any::Any;
|
||||
|
||||
@ -41,6 +42,30 @@ pub trait FileLike: Send + Sync + Any {
|
||||
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 {
|
||||
StatusFlags::empty()
|
||||
}
|
||||
|
@ -100,7 +100,7 @@ impl FsResolver {
|
||||
if file_name.ends_with('/') {
|
||||
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");
|
||||
}
|
||||
dir_dentry.create(&file_name, InodeType::File, inode_mode)?
|
||||
@ -182,7 +182,7 @@ impl FsResolver {
|
||||
|
||||
// Iterate next dentry
|
||||
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();
|
||||
|
||||
// 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
|
||||
loop {
|
||||
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 mut link = dentry.inode().read_link()?;
|
||||
if link.is_empty() {
|
||||
|
@ -3,7 +3,10 @@
|
||||
use crate::events::IoEvents;
|
||||
use crate::prelude::*;
|
||||
use crate::process::signal::Poller;
|
||||
use crate::process::{Gid, Uid};
|
||||
|
||||
use aster_rights::{Rights, TRights};
|
||||
use inherit_methods_macro::inherit_methods;
|
||||
|
||||
use super::*;
|
||||
|
||||
@ -14,10 +17,10 @@ impl InodeHandle<Rights> {
|
||||
status_flags: StatusFlags,
|
||||
) -> Result<Self> {
|
||||
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");
|
||||
}
|
||||
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");
|
||||
}
|
||||
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> {
|
||||
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> {
|
||||
if !self.1.contains(Rights::READ) {
|
||||
return_errno_with_message!(Errno::EBADF, "File is not readable");
|
||||
@ -85,14 +102,6 @@ impl FileLike for InodeHandle<Rights> {
|
||||
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<()> {
|
||||
if !self.1.contains(Rights::WRITE) {
|
||||
return_errno_with_message!(Errno::EINVAL, "File is not writable");
|
||||
@ -100,27 +109,11 @@ impl FileLike for InodeHandle<Rights> {
|
||||
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<()> {
|
||||
self.0.set_status_flags(new_status_flags);
|
||||
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<()> {
|
||||
// Close does not guarantee that the data has been successfully saved to disk.
|
||||
Ok(())
|
||||
|
@ -6,15 +6,18 @@ mod dyn_cap;
|
||||
mod static_cap;
|
||||
|
||||
use core::sync::atomic::{AtomicU32, Ordering};
|
||||
use inherit_methods_macro::inherit_methods;
|
||||
|
||||
use crate::events::IoEvents;
|
||||
use crate::fs::device::Device;
|
||||
use crate::fs::file_handle::FileLike;
|
||||
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::process::signal::Poller;
|
||||
use crate::process::{Gid, Uid};
|
||||
use aster_rights::Rights;
|
||||
|
||||
#[derive(Debug)]
|
||||
@ -57,7 +60,7 @@ impl InodeHandle_ {
|
||||
}
|
||||
|
||||
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) {
|
||||
self.dentry.inode().write_direct_at(*offset, buf)?
|
||||
@ -92,7 +95,7 @@ impl InodeHandle_ {
|
||||
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);
|
||||
file_size
|
||||
.checked_add(off)
|
||||
@ -116,15 +119,11 @@ impl InodeHandle_ {
|
||||
*offset
|
||||
}
|
||||
|
||||
pub fn size(&self) -> usize {
|
||||
self.dentry.inode_size()
|
||||
}
|
||||
|
||||
pub fn resize(&self, new_size: usize) -> Result<()> {
|
||||
if self.status_flags().contains(StatusFlags::O_APPEND) {
|
||||
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 {
|
||||
@ -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_ {
|
||||
fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
|
||||
f.debug_struct("InodeHandle_")
|
||||
|
@ -3,6 +3,7 @@
|
||||
use crate::events::{IoEvents, Observer};
|
||||
use crate::prelude::*;
|
||||
use crate::process::signal::Poller;
|
||||
use crate::process::{Gid, Uid};
|
||||
|
||||
use super::file_handle::FileLike;
|
||||
use super::utils::{AccessMode, Consumer, InodeMode, InodeType, Metadata, Producer, StatusFlags};
|
||||
@ -51,8 +52,8 @@ impl FileLike for PipeReader {
|
||||
type_: InodeType::NamedPipe,
|
||||
mode: InodeMode::from_bits_truncate(0o400),
|
||||
nlinks: 1,
|
||||
uid: 0,
|
||||
gid: 0,
|
||||
uid: Uid::new_root(),
|
||||
gid: Gid::new_root(),
|
||||
rdev: 0,
|
||||
}
|
||||
}
|
||||
@ -117,8 +118,8 @@ impl FileLike for PipeWriter {
|
||||
type_: InodeType::NamedPipe,
|
||||
mode: InodeMode::from_bits_truncate(0o200),
|
||||
nlinks: 1,
|
||||
uid: 0,
|
||||
gid: 0,
|
||||
uid: Uid::new_root(),
|
||||
gid: Gid::new_root(),
|
||||
rdev: 0,
|
||||
}
|
||||
}
|
||||
|
@ -2,19 +2,21 @@
|
||||
|
||||
use aster_util::slot_vec::SlotVec;
|
||||
use core::time::Duration;
|
||||
use inherit_methods_macro::inherit_methods;
|
||||
|
||||
use crate::fs::device::Device;
|
||||
use crate::fs::utils::{DirentVisitor, FileSystem, Inode, InodeMode, InodeType, Metadata};
|
||||
use crate::prelude::*;
|
||||
use crate::process::{Gid, Uid};
|
||||
|
||||
use super::{ProcFS, ProcInodeInfo};
|
||||
use super::{Common, ProcFS};
|
||||
|
||||
pub struct ProcDir<D: DirOps> {
|
||||
inner: D,
|
||||
this: Weak<ProcDir<D>>,
|
||||
parent: Option<Weak<dyn Inode>>,
|
||||
cached_children: RwLock<SlotVec<(String, Arc<dyn Inode>)>>,
|
||||
info: ProcInodeInfo,
|
||||
common: Common,
|
||||
}
|
||||
|
||||
impl<D: DirOps> ProcDir<D> {
|
||||
@ -24,21 +26,21 @@ impl<D: DirOps> ProcDir<D> {
|
||||
parent: Option<Weak<dyn Inode>>,
|
||||
is_volatile: bool,
|
||||
) -> Arc<Self> {
|
||||
let info = {
|
||||
let common = {
|
||||
let procfs = fs.downcast_ref::<ProcFS>().unwrap();
|
||||
let metadata = Metadata::new_dir(
|
||||
procfs.alloc_id(),
|
||||
InodeMode::from_bits_truncate(0o555),
|
||||
&fs.sb(),
|
||||
);
|
||||
ProcInodeInfo::new(metadata, Arc::downgrade(&fs), is_volatile)
|
||||
Common::new(metadata, Arc::downgrade(&fs), is_volatile)
|
||||
};
|
||||
Arc::new_cyclic(|weak_self| Self {
|
||||
inner: dir,
|
||||
this: weak_self.clone(),
|
||||
parent,
|
||||
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> {
|
||||
fn size(&self) -> usize {
|
||||
self.info.size()
|
||||
}
|
||||
fn size(&self) -> usize;
|
||||
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<()> {
|
||||
Err(Error::new(Errno::EISDIR))
|
||||
}
|
||||
|
||||
fn metadata(&self) -> Metadata {
|
||||
self.info.metadata()
|
||||
}
|
||||
|
||||
fn ino(&self) -> u64 {
|
||||
self.info.ino()
|
||||
}
|
||||
|
||||
fn type_(&self) -> InodeType {
|
||||
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>> {
|
||||
Err(Error::new(Errno::EPERM))
|
||||
}
|
||||
@ -120,8 +102,8 @@ impl<D: DirOps + 'static> Inode for ProcDir<D> {
|
||||
let this_inode = self.this();
|
||||
visitor.visit(
|
||||
".",
|
||||
this_inode.info.metadata().ino as u64,
|
||||
this_inode.info.metadata().type_,
|
||||
this_inode.common.metadata().ino as u64,
|
||||
this_inode.common.metadata().type_,
|
||||
*offset,
|
||||
)?;
|
||||
*offset += 1;
|
||||
@ -204,12 +186,8 @@ impl<D: DirOps + 'static> Inode for ProcDir<D> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn fs(&self) -> Arc<dyn FileSystem> {
|
||||
self.info.fs().upgrade().unwrap()
|
||||
}
|
||||
|
||||
fn is_dentry_cacheable(&self) -> bool {
|
||||
!self.info.is_volatile()
|
||||
!self.common.is_volatile()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,77 +1,62 @@
|
||||
// SPDX-License-Identifier: MPL-2.0
|
||||
|
||||
use core::time::Duration;
|
||||
use inherit_methods_macro::inherit_methods;
|
||||
|
||||
use crate::fs::utils::{FileSystem, Inode, InodeMode, InodeType, IoctlCmd, Metadata};
|
||||
use crate::prelude::*;
|
||||
use crate::process::{Gid, Uid};
|
||||
|
||||
use super::{ProcFS, ProcInodeInfo};
|
||||
use super::{Common, ProcFS};
|
||||
|
||||
pub struct ProcFile<F: FileOps> {
|
||||
inner: F,
|
||||
info: ProcInodeInfo,
|
||||
common: Common,
|
||||
}
|
||||
|
||||
impl<F: FileOps> ProcFile<F> {
|
||||
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 metadata = Metadata::new_file(
|
||||
procfs.alloc_id(),
|
||||
InodeMode::from_bits_truncate(0o444),
|
||||
&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> {
|
||||
fn size(&self) -> usize {
|
||||
self.info.size()
|
||||
}
|
||||
fn size(&self) -> usize;
|
||||
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<()> {
|
||||
Err(Error::new(Errno::EPERM))
|
||||
}
|
||||
|
||||
fn metadata(&self) -> Metadata {
|
||||
self.info.metadata()
|
||||
}
|
||||
|
||||
fn ino(&self) -> u64 {
|
||||
self.info.ino()
|
||||
}
|
||||
|
||||
fn type_(&self) -> InodeType {
|
||||
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> {
|
||||
let data = self.inner.data()?;
|
||||
let start = data.len().min(offset);
|
||||
@ -109,12 +94,8 @@ impl<F: FileOps + 'static> Inode for ProcFile<F> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn fs(&self) -> Arc<dyn FileSystem> {
|
||||
self.info.fs().upgrade().unwrap()
|
||||
}
|
||||
|
||||
fn is_dentry_cacheable(&self) -> bool {
|
||||
!self.info.is_volatile()
|
||||
!self.common.is_volatile()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -4,6 +4,7 @@ use core::time::Duration;
|
||||
|
||||
use crate::fs::utils::{FileSystem, InodeMode, Metadata};
|
||||
use crate::prelude::*;
|
||||
use crate::process::{Gid, Uid};
|
||||
|
||||
use super::ProcFS;
|
||||
|
||||
@ -17,13 +18,13 @@ mod dir;
|
||||
mod file;
|
||||
mod sym;
|
||||
|
||||
struct ProcInodeInfo {
|
||||
struct Common {
|
||||
metadata: RwLock<Metadata>,
|
||||
fs: Weak<dyn FileSystem>,
|
||||
is_volatile: bool,
|
||||
}
|
||||
|
||||
impl ProcInodeInfo {
|
||||
impl Common {
|
||||
pub fn new(metadata: Metadata, fs: Weak<dyn FileSystem>, is_volatile: bool) -> Self {
|
||||
Self {
|
||||
metadata: RwLock::new(metadata),
|
||||
@ -32,12 +33,12 @@ impl ProcInodeInfo {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn fs(&self) -> &Weak<dyn FileSystem> {
|
||||
&self.fs
|
||||
pub fn fs(&self) -> Arc<dyn FileSystem> {
|
||||
self.fs.upgrade().unwrap()
|
||||
}
|
||||
|
||||
pub fn metadata(&self) -> Metadata {
|
||||
self.metadata.read().clone()
|
||||
*self.metadata.read()
|
||||
}
|
||||
|
||||
pub fn ino(&self) -> u64 {
|
||||
@ -64,12 +65,31 @@ impl ProcInodeInfo {
|
||||
self.metadata.write().mtime = time;
|
||||
}
|
||||
|
||||
pub fn mode(&self) -> InodeMode {
|
||||
self.metadata.read().mode
|
||||
pub fn mode(&self) -> Result<InodeMode> {
|
||||
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;
|
||||
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 {
|
||||
|
@ -1,77 +1,59 @@
|
||||
// SPDX-License-Identifier: MPL-2.0
|
||||
|
||||
use core::time::Duration;
|
||||
use inherit_methods_macro::inherit_methods;
|
||||
|
||||
use crate::fs::utils::{FileSystem, Inode, InodeMode, InodeType, IoctlCmd, Metadata};
|
||||
use crate::prelude::*;
|
||||
use crate::process::{Gid, Uid};
|
||||
|
||||
use super::{ProcFS, ProcInodeInfo};
|
||||
use super::{Common, ProcFS};
|
||||
|
||||
pub struct ProcSym<S: SymOps> {
|
||||
inner: S,
|
||||
info: ProcInodeInfo,
|
||||
common: Common,
|
||||
}
|
||||
|
||||
impl<S: SymOps> ProcSym<S> {
|
||||
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 metadata = Metadata::new_symlink(
|
||||
procfs.alloc_id(),
|
||||
InodeMode::from_bits_truncate(0o777),
|
||||
&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> {
|
||||
fn size(&self) -> usize {
|
||||
self.info.size()
|
||||
}
|
||||
fn size(&self) -> usize;
|
||||
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<()> {
|
||||
Err(Error::new(Errno::EPERM))
|
||||
}
|
||||
|
||||
fn metadata(&self) -> Metadata {
|
||||
self.info.metadata()
|
||||
}
|
||||
|
||||
fn ino(&self) -> u64 {
|
||||
self.info.ino()
|
||||
}
|
||||
|
||||
fn type_(&self) -> InodeType {
|
||||
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> {
|
||||
Err(Error::new(Errno::EPERM))
|
||||
}
|
||||
@ -104,12 +86,8 @@ impl<S: SymOps + 'static> Inode for ProcSym<S> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn fs(&self) -> Arc<dyn FileSystem> {
|
||||
self.info.fs().upgrade().unwrap()
|
||||
}
|
||||
|
||||
fn is_dentry_cacheable(&self) -> bool {
|
||||
!self.info.is_volatile()
|
||||
!self.common.is_volatile()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -17,6 +17,7 @@ use crate::fs::utils::{
|
||||
};
|
||||
use crate::prelude::*;
|
||||
use crate::process::signal::Poller;
|
||||
use crate::process::{Gid, Uid};
|
||||
use crate::vm::vmo::Vmo;
|
||||
|
||||
/// 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_
|
||||
}
|
||||
|
||||
fn mode(&self) -> InodeMode {
|
||||
self.0.read().metadata.mode
|
||||
fn mode(&self) -> Result<InodeMode> {
|
||||
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;
|
||||
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(
|
||||
@ -870,7 +890,7 @@ impl Inode for RamInode {
|
||||
}
|
||||
|
||||
fn metadata(&self) -> Metadata {
|
||||
self.0.read().metadata.clone()
|
||||
self.0.read().metadata
|
||||
}
|
||||
|
||||
fn sync(&self) -> Result<()> {
|
||||
|
@ -2,10 +2,12 @@
|
||||
|
||||
use crate::fs::device::Device;
|
||||
use crate::prelude::*;
|
||||
use crate::process::{Gid, Uid};
|
||||
|
||||
use alloc::string::String;
|
||||
use core::sync::atomic::{AtomicU32, Ordering};
|
||||
use core::time::Duration;
|
||||
use inherit_methods_macro::inherit_methods;
|
||||
|
||||
use super::{FileSystem, Inode, InodeMode, InodeType, Metadata, MountNode, NAME_MAX};
|
||||
|
||||
@ -215,7 +217,7 @@ impl Dentry {
|
||||
if self.inode.type_() != InodeType::Dir {
|
||||
return_errno!(Errno::ENOTDIR);
|
||||
}
|
||||
if !self.inode.mode().is_executable() {
|
||||
if !self.inode.mode()?.is_executable() {
|
||||
return_errno!(Errno::EACCES);
|
||||
}
|
||||
if name.len() > NAME_MAX {
|
||||
@ -380,66 +382,6 @@ impl Dentry {
|
||||
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.
|
||||
///
|
||||
/// 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 {
|
||||
fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
|
||||
f.debug_struct("Dentry")
|
||||
|
@ -9,6 +9,7 @@ use crate::events::IoEvents;
|
||||
use crate::fs::device::{Device, DeviceType};
|
||||
use crate::prelude::*;
|
||||
use crate::process::signal::Poller;
|
||||
use crate::process::{Gid, Uid};
|
||||
use crate::vm::vmo::Vmo;
|
||||
|
||||
#[repr(u32)]
|
||||
@ -112,7 +113,7 @@ impl InodeMode {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
pub struct Metadata {
|
||||
pub dev: u64,
|
||||
pub ino: usize,
|
||||
@ -125,8 +126,8 @@ pub struct Metadata {
|
||||
pub type_: InodeType,
|
||||
pub mode: InodeMode,
|
||||
pub nlinks: usize,
|
||||
pub uid: usize,
|
||||
pub gid: usize,
|
||||
pub uid: Uid,
|
||||
pub gid: Gid,
|
||||
pub rdev: u64,
|
||||
}
|
||||
|
||||
@ -144,8 +145,8 @@ impl Metadata {
|
||||
type_: InodeType::Dir,
|
||||
mode,
|
||||
nlinks: 2,
|
||||
uid: 0,
|
||||
gid: 0,
|
||||
uid: Uid::new_root(),
|
||||
gid: Gid::new_root(),
|
||||
rdev: 0,
|
||||
}
|
||||
}
|
||||
@ -163,8 +164,8 @@ impl Metadata {
|
||||
type_: InodeType::File,
|
||||
mode,
|
||||
nlinks: 1,
|
||||
uid: 0,
|
||||
gid: 0,
|
||||
uid: Uid::new_root(),
|
||||
gid: Gid::new_root(),
|
||||
rdev: 0,
|
||||
}
|
||||
}
|
||||
@ -182,8 +183,8 @@ impl Metadata {
|
||||
type_: InodeType::SymLink,
|
||||
mode,
|
||||
nlinks: 1,
|
||||
uid: 0,
|
||||
gid: 0,
|
||||
uid: Uid::new_root(),
|
||||
gid: Gid::new_root(),
|
||||
rdev: 0,
|
||||
}
|
||||
}
|
||||
@ -200,8 +201,8 @@ impl Metadata {
|
||||
type_: InodeType::from(device.type_()),
|
||||
mode,
|
||||
nlinks: 1,
|
||||
uid: 0,
|
||||
gid: 0,
|
||||
uid: Uid::new_root(),
|
||||
gid: Gid::new_root(),
|
||||
rdev: device.id().into(),
|
||||
}
|
||||
}
|
||||
@ -219,8 +220,8 @@ impl Metadata {
|
||||
type_: InodeType::Socket,
|
||||
mode,
|
||||
nlinks: 1,
|
||||
uid: 0,
|
||||
gid: 0,
|
||||
uid: Uid::new_root(),
|
||||
gid: Gid::new_root(),
|
||||
rdev: 0,
|
||||
}
|
||||
}
|
||||
@ -237,9 +238,17 @@ pub trait Inode: Any + Sync + Send {
|
||||
|
||||
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;
|
||||
|
||||
|
@ -59,7 +59,7 @@ impl MountNode {
|
||||
if !Arc::ptr_eq(&mountpoint.mount_node(), &self.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);
|
||||
}
|
||||
|
||||
|
@ -290,11 +290,11 @@ fn lookup_socket_file(path: &str) -> Result<Arc<Dentry>> {
|
||||
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")
|
||||
}
|
||||
|
||||
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")
|
||||
}
|
||||
Ok(dentry)
|
||||
|
@ -96,15 +96,15 @@ pub fn load_program_to_vm(
|
||||
}
|
||||
|
||||
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");
|
||||
}
|
||||
|
||||
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");
|
||||
}
|
||||
|
||||
if !dentry.inode_mode().is_executable() {
|
||||
if !dentry.mode()?.is_executable() {
|
||||
return_errno_with_message!(Errno::EACCES, "the dentry is not executable");
|
||||
}
|
||||
|
||||
|
@ -26,7 +26,7 @@ pub fn sys_chdir(pathname_addr: Vaddr) -> Result<SyscallReturn> {
|
||||
let fs_path = FsPath::try_from(pathname.as_ref())?;
|
||||
fs.lookup(&fs_path)?
|
||||
};
|
||||
if dentry.inode_type() != InodeType::Dir {
|
||||
if dentry.type_() != InodeType::Dir {
|
||||
return_errno_with_message!(Errno::ENOTDIR, "must be directory");
|
||||
}
|
||||
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"))?;
|
||||
inode_handle.dentry().clone()
|
||||
};
|
||||
if dentry.inode_type() != InodeType::Dir {
|
||||
if dentry.type_() != InodeType::Dir {
|
||||
return_errno_with_message!(Errno::ENOTDIR, "must be directory");
|
||||
}
|
||||
current.fs().write().set_cwd(dentry);
|
||||
|
@ -3,7 +3,6 @@
|
||||
use crate::fs::{
|
||||
file_table::FileDescripter,
|
||||
fs_resolver::{FsPath, AT_FDCWD},
|
||||
inode_handle::InodeHandle,
|
||||
utils::{InodeMode, PATH_MAX},
|
||||
};
|
||||
use crate::log_syscall_entry;
|
||||
@ -20,11 +19,7 @@ pub fn sys_fchmod(fd: FileDescripter, mode: u16) -> Result<SyscallReturn> {
|
||||
let current = current!();
|
||||
let file_table = current.file_table().lock();
|
||||
let file = file_table.get_file(fd)?;
|
||||
let inode_handle = file
|
||||
.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));
|
||||
file.set_mode(InodeMode::from_bits_truncate(mode))?;
|
||||
Ok(SyscallReturn::Return(0))
|
||||
}
|
||||
|
||||
@ -52,6 +47,6 @@ pub fn sys_fchmodat(
|
||||
let fs_path = FsPath::new(dirfd, path.as_ref())?;
|
||||
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))
|
||||
}
|
||||
|
119
services/aster-nix/src/syscall/chown.rs
Normal file
119
services/aster-nix/src/syscall/chown.rs
Normal 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;
|
||||
}
|
||||
}
|
@ -10,9 +10,7 @@ use crate::fs::utils::{Dentry, InodeType};
|
||||
use crate::log_syscall_entry;
|
||||
use crate::prelude::*;
|
||||
use crate::process::posix_thread::{PosixThreadExt, ThreadName};
|
||||
use crate::process::{
|
||||
check_executable_file, credentials_mut, load_program_to_vm, Credentials, Gid, Uid,
|
||||
};
|
||||
use crate::process::{check_executable_file, credentials_mut, load_program_to_vm, Credentials};
|
||||
use crate::syscall::{SYS_EXECVE, SYS_EXECVEAT};
|
||||
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)?;
|
||||
if flags.contains(OpenFlags::AT_SYMLINK_NOFOLLOW) {
|
||||
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");
|
||||
}
|
||||
Ok(dentry)
|
||||
@ -110,8 +108,8 @@ fn do_execve(
|
||||
debug!("load elf in execve succeeds");
|
||||
|
||||
let credentials = credentials_mut();
|
||||
set_uid_from_elf(&credentials, &elf_file);
|
||||
set_gid_from_elf(&credentials, &elf_file);
|
||||
set_uid_from_elf(&credentials, &elf_file)?;
|
||||
set_gid_from_elf(&credentials, &elf_file)?;
|
||||
|
||||
// set 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.
|
||||
fn set_uid_from_elf(credentials: &Credentials<WriteOp>, elf_file: &Arc<Dentry>) {
|
||||
if elf_file.inode_mode().has_set_uid() {
|
||||
let uid = Uid::new(elf_file.inode_metadata().uid as u32);
|
||||
fn set_uid_from_elf(credentials: &Credentials<WriteOp>, elf_file: &Arc<Dentry>) -> Result<()> {
|
||||
if elf_file.mode()?.has_set_uid() {
|
||||
let uid = elf_file.owner()?;
|
||||
credentials.set_euid(uid);
|
||||
}
|
||||
|
||||
// No matter whether the elf_file has `set_uid` bit, suid should be reset.
|
||||
credentials.reset_suid();
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// 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>) {
|
||||
if elf_file.inode_mode().has_set_gid() {
|
||||
let gid = Gid::new(elf_file.inode_metadata().gid as u32);
|
||||
fn set_gid_from_elf(credentials: &Credentials<WriteOp>, elf_file: &Arc<Dentry>) -> Result<()> {
|
||||
if elf_file.mode()?.has_set_gid() {
|
||||
let gid = elf_file.group()?;
|
||||
credentials.set_egid(gid);
|
||||
}
|
||||
|
||||
// No matter whether the the elf file has `set_gid` bit, sgid should be reset.
|
||||
credentials.reset_sgid();
|
||||
Ok(())
|
||||
}
|
||||
|
@ -32,7 +32,7 @@ pub fn sys_getdents64(
|
||||
let inode_handle = file
|
||||
.downcast_ref::<InodeHandle>()
|
||||
.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);
|
||||
}
|
||||
let mut buffer = vec![0u8; buf_len];
|
||||
|
@ -8,6 +8,7 @@ use crate::syscall::arch_prctl::sys_arch_prctl;
|
||||
use crate::syscall::brk::sys_brk;
|
||||
use crate::syscall::chdir::{sys_chdir, sys_fchdir};
|
||||
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_nanosleep::sys_clock_nanosleep;
|
||||
use crate::syscall::clone::sys_clone;
|
||||
@ -115,6 +116,7 @@ mod bind;
|
||||
mod brk;
|
||||
mod chdir;
|
||||
mod chmod;
|
||||
mod chown;
|
||||
mod clock_gettime;
|
||||
mod clock_nanosleep;
|
||||
mod clone;
|
||||
@ -306,6 +308,9 @@ define_syscall_nums!(
|
||||
SYS_READLINK = 89,
|
||||
SYS_CHMOD = 90,
|
||||
SYS_FCHMOD = 91,
|
||||
SYS_CHOWN = 92,
|
||||
SYS_FCHOWN = 93,
|
||||
SYS_LCHOWN = 94,
|
||||
SYS_UMASK = 95,
|
||||
SYS_GETTIMEOFDAY = 96,
|
||||
SYS_GETUID = 102,
|
||||
@ -350,6 +355,7 @@ define_syscall_nums!(
|
||||
SYS_WAITID = 247,
|
||||
SYS_OPENAT = 257,
|
||||
SYS_MKDIRAT = 258,
|
||||
SYS_FCHOWNAT = 260,
|
||||
SYS_FSTATAT = 262,
|
||||
SYS_UNLINKAT = 263,
|
||||
SYS_RENAMEAT = 264,
|
||||
@ -486,6 +492,9 @@ pub fn syscall_dispatch(
|
||||
SYS_READLINK => syscall_handler!(3, sys_readlink, args),
|
||||
SYS_CHMOD => syscall_handler!(2, sys_chmod, 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_GETTIMEOFDAY => syscall_handler!(1, sys_gettimeofday, args),
|
||||
SYS_GETUID => syscall_handler!(0, sys_getuid),
|
||||
@ -530,6 +539,7 @@ pub fn syscall_dispatch(
|
||||
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_FCHOWNAT => syscall_handler!(5, sys_fchownat, args),
|
||||
SYS_FSTATAT => syscall_handler!(4, sys_fstatat, args),
|
||||
SYS_UNLINKAT => syscall_handler!(3, sys_unlinkat, args),
|
||||
SYS_RENAMEAT => syscall_handler!(4, sys_renameat, args),
|
||||
|
@ -45,7 +45,7 @@ pub fn sys_renameat(
|
||||
if new_pathname.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");
|
||||
}
|
||||
let new_fs_path = FsPath::new(new_dirfd, new_pathname.as_ref().trim_end_matches('/'))?;
|
||||
|
@ -67,7 +67,7 @@ pub fn sys_fstatat(
|
||||
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)?;
|
||||
Ok(SyscallReturn::Return(0))
|
||||
}
|
||||
@ -121,8 +121,8 @@ impl From<Metadata> for Stat {
|
||||
st_ino: info.ino,
|
||||
st_nlink: info.nlinks,
|
||||
st_mode: info.type_ as u32 | info.mode.bits() as u32,
|
||||
st_uid: info.uid as u32,
|
||||
st_gid: info.gid as u32,
|
||||
st_uid: info.uid.as_u32(),
|
||||
st_gid: info.gid.as_u32(),
|
||||
__pad0: 0,
|
||||
st_rdev: info.rdev,
|
||||
st_size: info.size as isize,
|
||||
|
@ -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())?;
|
||||
current.fs().read().lookup(&fs_path)?
|
||||
};
|
||||
dentry.set_inode_size(len as usize)?;
|
||||
dentry.resize(len as usize)?;
|
||||
Ok(SyscallReturn::Return(0))
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user