Skip to content

Commit

Permalink
Implements Host mkdir for unix (#714)
Browse files Browse the repository at this point in the history
  • Loading branch information
SuchAFuriousDeath authored Mar 2, 2024
1 parent 2509287 commit 727cc08
Show file tree
Hide file tree
Showing 6 changed files with 84 additions and 14 deletions.
30 changes: 30 additions & 0 deletions src/kernel/src/fs/host/file.rs
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,35 @@ impl HostFile {
Ok(child)
}

pub fn mkdir(self: &Arc<Self>, name: &str, mode: u32) -> Result<Arc<Self>, Error> {
let raw = Self::raw_mkdir(self.raw, name, mode)?;

Ok(Arc::new(Self {
raw,
parent: Some(self.clone()),
children: Mutex::default(),
}))
}

#[cfg(unix)]
fn raw_mkdir(parent: RawFile, name: &str, mode: u32) -> Result<RawFile, Error> {
use libc::{mkdirat, mode_t};
use std::ffi::CString;

let c_name = CString::new(name).unwrap();

if unsafe { mkdirat(parent, c_name.as_ptr(), (mode & 0o777) as mode_t) } < 0 {
Err(Error::last_os_error())
} else {
Self::raw_open(parent, name)
}
}

#[cfg(windows)]
fn raw_mkdir(parent: RawFile, name: &str, mode: u32) -> Result<RawFile, Error> {
todo!()
}

#[cfg(unix)]
fn stat(&self) -> Result<libc::stat, Error> {
use libc::fstat;
Expand Down Expand Up @@ -338,6 +367,7 @@ pub struct HostId {
dev: libc::dev_t,
#[cfg(unix)]
ino: libc::ino_t,

#[cfg(windows)]
volume: u32,
#[cfg(windows)]
Expand Down
43 changes: 38 additions & 5 deletions src/kernel/src/fs/host/vnode.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use super::file::HostFile;
use super::{get_vnode, GetVnodeError, HostFs};
use crate::errno::{Errno, EIO, ENOENT, ENOTDIR};
use crate::errno::{Errno, EEXIST, EIO, ENOENT, ENOTDIR};
use crate::fs::{Access, IoCmd, Mode, OpenFlags, VFile, Vnode, VnodeAttrs, VnodeType};
use crate::process::VThread;
use crate::ucred::{Gid, Uid};
Expand All @@ -25,9 +25,9 @@ impl VnodeBackend {
impl crate::fs::VnodeBackend for VnodeBackend {
fn access(
self: Arc<Self>,
vn: &Arc<Vnode>,
td: Option<&VThread>,
mode: Access,
_: &Arc<Vnode>,
_: Option<&VThread>,
_: Access,
) -> Result<(), Box<dyn Errno>> {
// TODO: Check how the PS4 check file permission for exfatfs.
Ok(())
Expand Down Expand Up @@ -104,9 +104,22 @@ impl crate::fs::VnodeBackend for VnodeBackend {
mode: u32,
td: Option<&VThread>,
) -> Result<Arc<Vnode>, Box<dyn Errno>> {
todo!()
parent.access(td, Access::WRITE)?;

let dir = self
.file
.mkdir(name, mode)
.map_err(|e| MkDirError::from(e))?;

Ok(Vnode::new(
parent.fs(),
VnodeType::Directory(false),
"exfatfs",
VnodeBackend::new(self.fs.clone(), dir),
))
}

#[allow(unused_variables)] // TODO: remove when implementing.
fn open(
self: Arc<Self>,
vn: &Arc<Vnode>,
Expand Down Expand Up @@ -151,3 +164,23 @@ enum LookupError {
#[error("cannot get vnode")]
GetVnodeFailed(#[source] GetVnodeError),
}

#[derive(Debug, Error, Errno)]
enum MkDirError {
#[error("couldn't create directory")]
#[errno(EIO)]
CreateFailed(#[source] std::io::Error),

#[error("directory already exists")]
#[errno(EEXIST)]
AlreadyExists,
}

impl From<std::io::Error> for MkDirError {
fn from(e: std::io::Error) -> Self {
match e.kind() {
std::io::ErrorKind::AlreadyExists => MkDirError::AlreadyExists,
_ => MkDirError::CreateFailed(e),
}
}
}
5 changes: 3 additions & 2 deletions src/kernel/src/fs/tmp/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ use super::{Filesystem, FsConfig, Mount, MountFlags, MountOpts, MountSource, VPa
use crate::errno::{Errno, EINVAL};
use crate::ucred::{Ucred, Uid};
use macros::Errno;
use std::num::NonZeroU64;
use std::sync::atomic::AtomicI32;
use std::sync::Arc;
use thiserror::Error;
Expand Down Expand Up @@ -55,7 +56,7 @@ pub fn mount(
let size: usize = opts.remove_or("size", 0);

// Get maximum file size.
let file_size = opts.remove_or("maxfilesize", 0);
let file_size = NonZeroU64::new(opts.remove_or("maxfilesize", 0));

// TODO: Refactor this for readability.
let pages = if size.wrapping_sub(0x4000) < 0xffffffffffff8000 {
Expand Down Expand Up @@ -87,7 +88,7 @@ pub fn mount(
flags | MountFlags::MNT_LOCAL,
TempFs {
max_pages: pages,
max_file_size: if file_size == 0 { u64::MAX } else { file_size },
max_file_size: file_size.map_or(u64::MAX, |x| x.get()),
next_inode: AtomicI32::new(2), // TODO: Use a proper implementation.
nodes,
root,
Expand Down
6 changes: 3 additions & 3 deletions src/kernel/src/fs/vnode.rs
Original file line number Diff line number Diff line change
Expand Up @@ -242,7 +242,7 @@ pub(super) trait VnodeBackend: Debug + Send + Sync + 'static {
#[allow(unused_variables)] cmd: IoCmd,
#[allow(unused_variables)] td: Option<&VThread>,
) -> Result<(), Box<dyn Errno>> {
Err(Box::new(DefaultError::IoctlNotSupported))
Err(Box::new(DefaultError::CommandNotSupported))
}

/// An implementation of `vop_lookup`.
Expand Down Expand Up @@ -327,7 +327,7 @@ impl VnodeAttrs {
}
}

/// Represents an error when [`DEFAULT_VNODEOPS`] is failed.
/// Represents an error when [`DEFAULT_VNODEOPS`] fails.
#[derive(Debug, Error, Errno)]
enum DefaultError {
#[error("operation not supported")]
Expand All @@ -344,7 +344,7 @@ enum DefaultError {

#[error("ioctl not supported")]
#[errno(ENOTTY)]
IoctlNotSupported,
CommandNotSupported,
}

static ACTIVE: AtomicUsize = AtomicUsize::new(0); // numvnodes
2 changes: 1 addition & 1 deletion src/kernel/src/net/socket.rs
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ impl FileBackend for Socket {
_: TruncateLength,
_: Option<&VThread>,
) -> Result<(), Box<dyn Errno>> {
Err(DefaultError::InvalidValue.into())
Err(Box::new(DefaultError::InvalidValue))
}
}

Expand Down
12 changes: 9 additions & 3 deletions src/kernel/src/shm/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use thiserror::Error;
use crate::{
errno::{Errno, EINVAL},
fs::{
check_access, Access, DefaultError, FileBackend, IoCmd, Mode, OpenFlags, Stat,
check_access, Access, AccessError, DefaultError, FileBackend, IoCmd, Mode, OpenFlags, Stat,
TruncateLength, Uio, UioMut, VFile, VFileFlags, VPathBuf,
},
memory::MemoryManager,
Expand All @@ -14,6 +14,7 @@ use crate::{
};
use std::{convert::Infallible, sync::Arc};

#[allow(dead_code)] // TODO: remove when used.
pub struct SharedMemoryManager {
mm: Arc<MemoryManager>,
}
Expand Down Expand Up @@ -50,14 +51,15 @@ impl SharedMemoryManager {

let filedesc = td.proc().files();

#[allow(unused_variables)] // TODO: remove when implementing.
let mode = mode & filedesc.cmask() & 0o7777;

let fd = filedesc.alloc_without_budget::<Infallible>(
|_| match path {
ShmPath::Anon => {
todo!()
}
ShmPath::Path(path) => {
ShmPath::Path(_) => {
todo!()
}
},
Expand All @@ -67,6 +69,7 @@ impl SharedMemoryManager {
Ok(fd.into())
}

#[allow(unused_variables)] // TODO: remove when implementing.
fn sys_shm_unlink(self: &Arc<Self>, td: &VThread, i: &SysIn) -> Result<SysOut, SysErr> {
todo!("sys_shm_unlink")
}
Expand All @@ -78,6 +81,7 @@ pub enum ShmPath {
}

#[derive(Debug)]
#[allow(unused_variables)] // TODO: remove when used.
pub struct Shm {
uid: Uid,
gid: Gid,
Expand All @@ -86,12 +90,14 @@ pub struct Shm {

impl Shm {
/// See `shm_do_truncate` on the PS4 for a reference.
#[allow(unused_variables)] // TODO: remove when implementing.
fn do_truncate(&self, length: TruncateLength) -> Result<(), TruncateError> {
todo!()
}

/// See `shm_access` on the PS4 for a reference.
fn access(&self, cred: &Ucred, flags: VFileFlags) -> Result<(), Box<dyn Errno>> {
#[allow(dead_code)] // TODO: remove when used.
fn access(&self, cred: &Ucred, flags: VFileFlags) -> Result<(), AccessError> {
let mut access = Access::empty();

if flags.intersects(VFileFlags::READ) {
Expand Down

0 comments on commit 727cc08

Please sign in to comment.