Remove open-related APIs from FsResolver
This commit is contained in:
parent
c2ab393d57
commit
782301c239
|
|
@ -13,6 +13,7 @@ use crate::{
|
|||
file_table::FdFlags,
|
||||
fs_resolver::FsPath,
|
||||
inode_handle::FileIo,
|
||||
open_args::OpenArgs,
|
||||
utils::{mkmod, AccessMode, Inode, IoctlCmd},
|
||||
},
|
||||
prelude::*,
|
||||
|
|
@ -127,13 +128,13 @@ impl FileIo for PtyMaster {
|
|||
let fs_path = FsPath::try_from(slave_name.as_str())?;
|
||||
|
||||
let inode_handle = {
|
||||
let flags = AccessMode::O_RDWR as u32;
|
||||
let mode = mkmod!(u+rw).bits();
|
||||
let open_args = OpenArgs::from_modes(AccessMode::O_RDWR, mkmod!(u+rw));
|
||||
thread_local
|
||||
.borrow_fs()
|
||||
.resolver()
|
||||
.read()
|
||||
.open(&fs_path, flags, mode)?
|
||||
.lookup(&fs_path)?
|
||||
.open(open_args)?
|
||||
};
|
||||
Arc::new(inode_handle)
|
||||
};
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ pub mod file_table;
|
|||
pub mod fs_resolver;
|
||||
pub mod inode_handle;
|
||||
pub mod named_pipe;
|
||||
pub mod open_args;
|
||||
pub mod overlayfs;
|
||||
pub mod path;
|
||||
pub mod pipe;
|
||||
|
|
@ -33,6 +34,7 @@ use crate::{
|
|||
ext2::Ext2,
|
||||
file_table::FdFlags,
|
||||
fs_resolver::{FsPath, FsResolver},
|
||||
open_args::OpenArgs,
|
||||
utils::{mkmod, AccessMode},
|
||||
},
|
||||
prelude::*,
|
||||
|
|
@ -104,19 +106,28 @@ pub fn init_in_first_process(ctx: &Context) {
|
|||
// Initialize the file table for the first process.
|
||||
let tty_path = FsPath::new(fs_resolver::AT_FDCWD, "/dev/console").expect("cannot find tty");
|
||||
let stdin = {
|
||||
let flags = AccessMode::O_RDONLY as u32;
|
||||
let mode = mkmod!(u+r);
|
||||
fs_resolver.open(&tty_path, flags, mode.bits()).unwrap()
|
||||
let open_args = OpenArgs::from_modes(AccessMode::O_RDONLY, mkmod!(u+r));
|
||||
fs_resolver
|
||||
.lookup(&tty_path)
|
||||
.unwrap()
|
||||
.open(open_args)
|
||||
.unwrap()
|
||||
};
|
||||
let stdout = {
|
||||
let flags = AccessMode::O_WRONLY as u32;
|
||||
let mode = mkmod!(u+w);
|
||||
fs_resolver.open(&tty_path, flags, mode.bits()).unwrap()
|
||||
let open_args = OpenArgs::from_modes(AccessMode::O_WRONLY, mkmod!(u+w));
|
||||
fs_resolver
|
||||
.lookup(&tty_path)
|
||||
.unwrap()
|
||||
.open(open_args)
|
||||
.unwrap()
|
||||
};
|
||||
let stderr = {
|
||||
let flags = AccessMode::O_WRONLY as u32;
|
||||
let mode = mkmod!(u+w);
|
||||
fs_resolver.open(&tty_path, flags, mode.bits()).unwrap()
|
||||
let open_args = OpenArgs::from_modes(AccessMode::O_WRONLY, mkmod!(u+w));
|
||||
fs_resolver
|
||||
.lookup(&tty_path)
|
||||
.unwrap()
|
||||
.open(open_args)
|
||||
.unwrap()
|
||||
};
|
||||
|
||||
let mut file_table_ref = ctx.thread_local.borrow_file_table_mut();
|
||||
|
|
|
|||
|
|
@ -0,0 +1,47 @@
|
|||
// SPDX-License-Identifier: MPL-2.0
|
||||
|
||||
use crate::{
|
||||
fs::utils::{AccessMode, CreationFlags, InodeMode, StatusFlags},
|
||||
prelude::*,
|
||||
};
|
||||
|
||||
/// Arguments for an open request.
|
||||
#[derive(Debug)]
|
||||
pub struct OpenArgs {
|
||||
pub creation_flags: CreationFlags,
|
||||
pub status_flags: StatusFlags,
|
||||
pub access_mode: AccessMode,
|
||||
pub inode_mode: InodeMode,
|
||||
}
|
||||
|
||||
impl OpenArgs {
|
||||
/// Create `OpenArgs` from the given flags and mode.
|
||||
pub fn from_flags_and_mode(flags: u32, inode_mode: InodeMode) -> Result<Self> {
|
||||
let creation_flags = CreationFlags::from_bits_truncate(flags);
|
||||
let status_flags = StatusFlags::from_bits_truncate(flags);
|
||||
let access_mode = AccessMode::from_u32(flags)?;
|
||||
Ok(Self {
|
||||
creation_flags,
|
||||
status_flags,
|
||||
access_mode,
|
||||
inode_mode,
|
||||
})
|
||||
}
|
||||
|
||||
/// Create `OpenArgs` from the given access mode and inode mode.
|
||||
pub fn from_modes(access_mode: AccessMode, inode_mode: InodeMode) -> Self {
|
||||
Self {
|
||||
creation_flags: CreationFlags::empty(),
|
||||
status_flags: StatusFlags::empty(),
|
||||
access_mode,
|
||||
inode_mode,
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns whether to follow the tail link when resolving the path.
|
||||
pub fn follow_tail_link(&self) -> bool {
|
||||
!(self.creation_flags.contains(CreationFlags::O_NOFOLLOW)
|
||||
|| self.creation_flags.contains(CreationFlags::O_CREAT)
|
||||
&& self.creation_flags.contains(CreationFlags::O_EXCL))
|
||||
}
|
||||
}
|
||||
|
|
@ -10,10 +10,12 @@ pub use mount_namespace::MountNamespace;
|
|||
|
||||
use crate::{
|
||||
fs::{
|
||||
inode_handle::InodeHandle,
|
||||
open_args::OpenArgs,
|
||||
path::dentry::{Dentry, DentryKey},
|
||||
utils::{
|
||||
FileSystem, Inode, InodeMode, InodeType, Metadata, MknodType, Permission, XattrName,
|
||||
XattrNamespace, XattrSetFlags, NAME_MAX,
|
||||
CreationFlags, FileSystem, Inode, InodeMode, InodeType, Metadata, MknodType,
|
||||
Permission, StatusFlags, XattrName, XattrNamespace, XattrSetFlags, NAME_MAX,
|
||||
},
|
||||
},
|
||||
prelude::*,
|
||||
|
|
@ -366,6 +368,47 @@ impl Path {
|
|||
|
||||
self.dentry.rename(old_name, &new_dir.dentry, new_name)
|
||||
}
|
||||
|
||||
/// Opens the `Path` with the given `OpenArgs`.
|
||||
///
|
||||
/// Returns an `InodeHandle` on success.
|
||||
pub fn open(&self, open_args: OpenArgs) -> Result<InodeHandle> {
|
||||
let inode = self.inode();
|
||||
let inode_type = inode.type_();
|
||||
let creation_flags = &open_args.creation_flags;
|
||||
|
||||
match inode_type {
|
||||
InodeType::NamedPipe => {
|
||||
warn!("NamedPipe doesn't support additional operation when opening.");
|
||||
debug!("Open NamedPipe with args: {open_args:?}.");
|
||||
}
|
||||
InodeType::SymLink => {
|
||||
if creation_flags.contains(CreationFlags::O_NOFOLLOW)
|
||||
&& !open_args.status_flags.contains(StatusFlags::O_PATH)
|
||||
{
|
||||
return_errno_with_message!(Errno::ELOOP, "file is a symlink");
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
|
||||
if creation_flags.contains(CreationFlags::O_CREAT)
|
||||
&& creation_flags.contains(CreationFlags::O_EXCL)
|
||||
{
|
||||
return_errno_with_message!(Errno::EEXIST, "file exists");
|
||||
}
|
||||
if creation_flags.contains(CreationFlags::O_DIRECTORY) && inode_type != InodeType::Dir {
|
||||
return_errno_with_message!(
|
||||
Errno::ENOTDIR,
|
||||
"O_DIRECTORY is specified but file is not a directory"
|
||||
);
|
||||
}
|
||||
|
||||
if inode_type.is_regular_file() && creation_flags.contains(CreationFlags::O_TRUNC) {
|
||||
self.resize(0)?;
|
||||
}
|
||||
InodeHandle::new(self.clone(), open_args.access_mode, open_args.status_flags)
|
||||
}
|
||||
}
|
||||
|
||||
#[inherit_methods(from = "self.dentry")]
|
||||
|
|
|
|||
|
|
@ -4,8 +4,10 @@ use super::SyscallReturn;
|
|||
use crate::{
|
||||
fs::{
|
||||
file_table::{FdFlags, FileDesc},
|
||||
fs_resolver::{FsPath, AT_FDCWD},
|
||||
utils::{AccessMode, CreationFlags},
|
||||
fs_resolver::{FsPath, FsResolver, LookupResult, AT_FDCWD},
|
||||
inode_handle::InodeHandle,
|
||||
open_args::OpenArgs,
|
||||
utils::{AccessMode, CreationFlags, InodeMode, InodeType},
|
||||
},
|
||||
prelude::*,
|
||||
syscall::constants::MAX_FILENAME_LEN,
|
||||
|
|
@ -31,16 +33,22 @@ pub fn sys_openat(
|
|||
let file_handle = {
|
||||
let path = path.to_string_lossy();
|
||||
let fs_path = FsPath::new(dirfd, path.as_ref())?;
|
||||
|
||||
let fs_ref = ctx.thread_local.borrow_fs();
|
||||
let mask_mode = mode & !fs_ref.umask().get();
|
||||
let inode_handle = fs_ref
|
||||
.resolver()
|
||||
.read()
|
||||
.open(&fs_path, flags, mask_mode)
|
||||
.map_err(|err| match err.error() {
|
||||
Errno::EINTR => Error::new(Errno::ERESTARTSYS),
|
||||
_ => err,
|
||||
})?;
|
||||
|
||||
let fs_resolver = fs_ref.resolver().read();
|
||||
let inode_handle = do_open(
|
||||
&fs_resolver,
|
||||
&fs_path,
|
||||
flags,
|
||||
InodeMode::from_bits_truncate(mask_mode),
|
||||
)
|
||||
.map_err(|err| match err.error() {
|
||||
Errno::EINTR => Error::new(Errno::ERESTARTSYS),
|
||||
_ => err,
|
||||
})?;
|
||||
|
||||
Arc::new(inode_handle)
|
||||
};
|
||||
|
||||
|
|
@ -68,3 +76,49 @@ pub fn sys_creat(path_addr: Vaddr, mode: u16, ctx: &Context) -> Result<SyscallRe
|
|||
AccessMode::O_WRONLY as u32 | CreationFlags::O_CREAT.bits() | CreationFlags::O_TRUNC.bits();
|
||||
self::sys_openat(AT_FDCWD, path_addr, flags, mode, ctx)
|
||||
}
|
||||
|
||||
fn do_open(
|
||||
fs_resolver: &FsResolver,
|
||||
path: &FsPath,
|
||||
flags: u32,
|
||||
mode: InodeMode,
|
||||
) -> Result<InodeHandle> {
|
||||
let open_args = OpenArgs::from_flags_and_mode(flags, mode)?;
|
||||
|
||||
let lookup_res = if open_args.follow_tail_link() {
|
||||
fs_resolver.lookup_unresolved(path)?
|
||||
} else {
|
||||
fs_resolver.lookup_unresolved_no_follow(path)?
|
||||
};
|
||||
|
||||
let inode_handle = match lookup_res {
|
||||
LookupResult::Resolved(target_path) => target_path.open(open_args)?,
|
||||
LookupResult::AtParent(result) => {
|
||||
if !open_args.creation_flags.contains(CreationFlags::O_CREAT) {
|
||||
return_errno_with_message!(Errno::ENOENT, "file does not exist");
|
||||
}
|
||||
if open_args
|
||||
.creation_flags
|
||||
.contains(CreationFlags::O_DIRECTORY)
|
||||
{
|
||||
return_errno_with_message!(Errno::ENOTDIR, "cannot create directory");
|
||||
}
|
||||
if result.target_is_dir() {
|
||||
return_errno_with_message!(Errno::EISDIR, "cannot create directory");
|
||||
}
|
||||
|
||||
let (parent, tail_name) = result.into_parent_and_tail_name();
|
||||
let new_path =
|
||||
parent.new_fs_child(&tail_name, InodeType::File, open_args.inode_mode)?;
|
||||
|
||||
// Don't check access mode for newly created file.
|
||||
InodeHandle::new_unchecked_access(
|
||||
new_path,
|
||||
open_args.access_mode,
|
||||
open_args.status_flags,
|
||||
)?
|
||||
}
|
||||
};
|
||||
|
||||
Ok(inode_handle)
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue