feature(fs): O_CREAT option
This commit is contained in:
Generated
+3
@@ -211,6 +211,9 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "syscall"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tock-registers"
|
||||
|
||||
+15
-6
@@ -1,10 +1,13 @@
|
||||
use vfs::{VnodeImpl, VnodeKind, VnodeRef, Vnode, Stat};
|
||||
use crate::{BlockAllocator, Bvec, FileInode};
|
||||
use alloc::boxed::Box;
|
||||
use error::Errno;
|
||||
use vfs::{OpenFlags, Stat, Vnode, VnodeImpl, VnodeKind, VnodeRef};
|
||||
|
||||
pub struct DirInode;
|
||||
pub struct DirInode<A: BlockAllocator + Copy + 'static> {
|
||||
alloc: A,
|
||||
}
|
||||
|
||||
impl VnodeImpl for DirInode {
|
||||
impl<A: BlockAllocator + Copy + 'static> VnodeImpl for DirInode<A> {
|
||||
fn create(
|
||||
&mut self,
|
||||
_parent: VnodeRef,
|
||||
@@ -13,8 +16,9 @@ impl VnodeImpl for DirInode {
|
||||
) -> Result<VnodeRef, Errno> {
|
||||
let vnode = Vnode::new(name, kind, Vnode::SEEKABLE);
|
||||
match kind {
|
||||
VnodeKind::Directory => vnode.set_data(Box::new(DirInode {})),
|
||||
_ => todo!()
|
||||
VnodeKind::Directory => vnode.set_data(Box::new(DirInode { alloc: self.alloc })),
|
||||
VnodeKind::Regular => vnode.set_data(Box::new(FileInode::new(Bvec::new(self.alloc)))),
|
||||
_ => todo!(),
|
||||
}
|
||||
Ok(vnode)
|
||||
}
|
||||
@@ -27,7 +31,7 @@ impl VnodeImpl for DirInode {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn open(&mut self, _node: VnodeRef) -> Result<usize, Errno> {
|
||||
fn open(&mut self, _node: VnodeRef, _flags: OpenFlags) -> Result<usize, Errno> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
@@ -56,3 +60,8 @@ impl VnodeImpl for DirInode {
|
||||
}
|
||||
}
|
||||
|
||||
impl<A: BlockAllocator + Copy + 'static> DirInode<A> {
|
||||
pub const fn new(alloc: A) -> Self {
|
||||
Self { alloc }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
use vfs::{VnodeImpl, VnodeKind, VnodeRef, Stat};
|
||||
use vfs::{VnodeImpl, VnodeKind, VnodeRef, Stat, OpenFlags};
|
||||
use error::Errno;
|
||||
use crate::{BlockAllocator, Bvec};
|
||||
|
||||
@@ -6,12 +6,6 @@ pub struct FileInode<'a, A: BlockAllocator + Copy + 'static> {
|
||||
data: Bvec<'a, A>,
|
||||
}
|
||||
|
||||
impl<'a, A: BlockAllocator + Copy + 'static> FileInode<'a, A> {
|
||||
pub fn new(data: Bvec<'a, A>) -> Self {
|
||||
Self { data }
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, A: BlockAllocator + Copy + 'static> VnodeImpl for FileInode<'a, A> {
|
||||
fn create(
|
||||
&mut self,
|
||||
@@ -30,7 +24,7 @@ impl<'a, A: BlockAllocator + Copy + 'static> VnodeImpl for FileInode<'a, A> {
|
||||
panic!()
|
||||
}
|
||||
|
||||
fn open(&mut self, _node: VnodeRef) -> Result<usize, Errno> {
|
||||
fn open(&mut self, _node: VnodeRef, _mode: OpenFlags) -> Result<usize, Errno> {
|
||||
Ok(0)
|
||||
}
|
||||
|
||||
@@ -61,3 +55,9 @@ impl<'a, A: BlockAllocator + Copy + 'static> VnodeImpl for FileInode<'a, A> {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, A: BlockAllocator + Copy + 'static> FileInode<'a, A> {
|
||||
pub fn new(data: Bvec<'a, A>) -> Self {
|
||||
Self { data }
|
||||
}
|
||||
}
|
||||
|
||||
+2
-2
@@ -62,7 +62,7 @@ impl<A: BlockAllocator + Copy + 'static> Ramfs<A> {
|
||||
let node = Vnode::new(name, kind, Vnode::SEEKABLE);
|
||||
node.set_fs(self.clone());
|
||||
match kind {
|
||||
VnodeKind::Directory => node.set_data(Box::new(DirInode {})),
|
||||
VnodeKind::Directory => node.set_data(Box::new(DirInode::new(self.alloc))),
|
||||
VnodeKind::Regular => {}
|
||||
VnodeKind::Char => todo!(),
|
||||
VnodeKind::Block => todo!(),
|
||||
@@ -90,7 +90,7 @@ impl<A: BlockAllocator + Copy + 'static> Ramfs<A> {
|
||||
return Err(Errno::DoesNotExist);
|
||||
}
|
||||
// TODO file modes
|
||||
let node = at.mkdir(element, FileMode::default_dir())?;
|
||||
let node = at.create(element, FileMode::default_dir(), VnodeKind::Directory)?;
|
||||
node
|
||||
}
|
||||
};
|
||||
|
||||
+2
-2
@@ -1,4 +1,4 @@
|
||||
use crate::{VnodeImpl, VnodeKind, VnodeRef, Stat};
|
||||
use crate::{VnodeImpl, VnodeKind, VnodeRef, Stat, OpenFlags};
|
||||
use error::Errno;
|
||||
|
||||
/// Generic character device trait
|
||||
@@ -36,7 +36,7 @@ impl VnodeImpl for CharDeviceWrapper {
|
||||
panic!();
|
||||
}
|
||||
|
||||
fn open(&mut self, _node: VnodeRef) -> Result<usize, Errno> {
|
||||
fn open(&mut self, _node: VnodeRef, _opts: OpenFlags) -> Result<usize, Errno> {
|
||||
Ok(0)
|
||||
}
|
||||
|
||||
|
||||
+47
-8
@@ -1,4 +1,4 @@
|
||||
use crate::{FileMode, VnodeRef, VnodeKind};
|
||||
use crate::{FileMode, VnodeKind, VnodeRef, OpenFlags, File};
|
||||
use error::Errno;
|
||||
use libcommon::{path_component_left, path_component_right};
|
||||
|
||||
@@ -83,7 +83,28 @@ impl Ioctx {
|
||||
mode: FileMode,
|
||||
) -> Result<VnodeRef, Errno> {
|
||||
let (parent, name) = path_component_right(path);
|
||||
self.find(at, parent, true)?.mkdir(name.trim_start_matches('/'), mode)
|
||||
self.find(at, parent, true)?
|
||||
.create(name.trim_start_matches('/'), mode, VnodeKind::Directory)
|
||||
}
|
||||
|
||||
///
|
||||
pub fn open(
|
||||
&self,
|
||||
at: Option<VnodeRef>,
|
||||
path: &str,
|
||||
mode: FileMode,
|
||||
opts: OpenFlags,
|
||||
) -> Result<File, Errno> {
|
||||
let node = match self.find(at.clone(), path, true) {
|
||||
Err(Errno::DoesNotExist) => {
|
||||
let (parent, name) = path_component_right(path);
|
||||
let at = self.find(at, parent, true)?;
|
||||
at.create(name, mode, VnodeKind::Regular)
|
||||
},
|
||||
o => o
|
||||
}?;
|
||||
|
||||
node.open(opts)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -271,14 +292,32 @@ mod tests {
|
||||
|
||||
let ioctx = Ioctx::new(root_outer.clone());
|
||||
|
||||
assert_eq!(ioctx.find(None, "/dir0/dir1", false).unwrap_err(), Errno::DoesNotExist);
|
||||
assert_eq!(
|
||||
ioctx.find(None, "/dir0/dir1", false).unwrap_err(),
|
||||
Errno::DoesNotExist
|
||||
);
|
||||
|
||||
dir0.mount(root_inner.clone()).unwrap();
|
||||
|
||||
assert!(Rc::ptr_eq(&root_inner, &ioctx.find(None, "/dir0", false).unwrap()));
|
||||
assert!(Rc::ptr_eq(&dir1, &ioctx.find(None, "/dir0/dir1", false).unwrap()));
|
||||
assert!(Rc::ptr_eq(&root_inner, &ioctx.find(None, "/dir0/dir1/..", false).unwrap()));
|
||||
assert!(Rc::ptr_eq(&dir0, &ioctx.find(None, "/dir0/dir1/../..", false).unwrap()));
|
||||
assert!(Rc::ptr_eq(&root_outer, &ioctx.find(None, "/dir0/dir1/../../..", false).unwrap()));
|
||||
assert!(Rc::ptr_eq(
|
||||
&root_inner,
|
||||
&ioctx.find(None, "/dir0", false).unwrap()
|
||||
));
|
||||
assert!(Rc::ptr_eq(
|
||||
&dir1,
|
||||
&ioctx.find(None, "/dir0/dir1", false).unwrap()
|
||||
));
|
||||
assert!(Rc::ptr_eq(
|
||||
&root_inner,
|
||||
&ioctx.find(None, "/dir0/dir1/..", false).unwrap()
|
||||
));
|
||||
assert!(Rc::ptr_eq(
|
||||
&dir0,
|
||||
&ioctx.find(None, "/dir0/dir1/../..", false).unwrap()
|
||||
));
|
||||
assert!(Rc::ptr_eq(
|
||||
&root_outer,
|
||||
&ioctx.find(None, "/dir0/dir1/../../..", false).unwrap()
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
+1
-3
@@ -9,14 +9,12 @@ extern crate std;
|
||||
|
||||
extern crate alloc;
|
||||
|
||||
pub use syscall::stat::Stat;
|
||||
pub use syscall::stat::{Stat, OpenFlags, FileMode};
|
||||
|
||||
mod block;
|
||||
pub use block::BlockDevice;
|
||||
mod fs;
|
||||
pub use fs::Filesystem;
|
||||
mod stat;
|
||||
pub use stat::FileMode;
|
||||
mod node;
|
||||
pub use node::{Vnode, VnodeImpl, VnodeKind, VnodeRef};
|
||||
mod ioctx;
|
||||
|
||||
+7
-7
@@ -1,4 +1,4 @@
|
||||
use crate::{File, FileMode, Filesystem, Stat};
|
||||
use crate::{File, FileMode, Filesystem, Stat, OpenFlags};
|
||||
use alloc::{borrow::ToOwned, boxed::Box, rc::Rc, string::String, vec::Vec};
|
||||
use core::cell::{RefCell, RefMut};
|
||||
use core::fmt;
|
||||
@@ -58,7 +58,7 @@ pub trait VnodeImpl {
|
||||
fn lookup(&mut self, at: VnodeRef, name: &str) -> Result<VnodeRef, Errno>;
|
||||
|
||||
/// Opens a vnode for access. Returns initial file position.
|
||||
fn open(&mut self, node: VnodeRef /* TODO open mode */) -> Result<usize, Errno>;
|
||||
fn open(&mut self, node: VnodeRef, opts: OpenFlags) -> Result<usize, Errno>;
|
||||
/// Closes a vnode
|
||||
fn close(&mut self, node: VnodeRef) -> Result<(), Errno>;
|
||||
|
||||
@@ -234,8 +234,8 @@ impl Vnode {
|
||||
}
|
||||
}
|
||||
|
||||
/// Creates a new directory `name` in `self`
|
||||
pub fn mkdir(self: &VnodeRef, name: &str, mode: FileMode) -> Result<VnodeRef, Errno> {
|
||||
/// Creates a new node `name` in `self`
|
||||
pub fn create(self: &VnodeRef, name: &str, mode: FileMode, kind: VnodeKind) -> Result<VnodeRef, Errno> {
|
||||
if self.kind != VnodeKind::Directory {
|
||||
return Err(Errno::NotADirectory);
|
||||
}
|
||||
@@ -250,7 +250,7 @@ impl Vnode {
|
||||
};
|
||||
|
||||
if let Some(ref mut data) = *self.data() {
|
||||
let vnode = data.create(self.clone(), name, VnodeKind::Directory)?;
|
||||
let vnode = data.create(self.clone(), name, kind)?;
|
||||
if let Some(fs) = self.fs() {
|
||||
vnode.set_fs(fs);
|
||||
}
|
||||
@@ -282,13 +282,13 @@ impl Vnode {
|
||||
}
|
||||
|
||||
/// Opens a vnode for access
|
||||
pub fn open(self: &VnodeRef) -> Result<File, Errno> {
|
||||
pub fn open(self: &VnodeRef, flags: OpenFlags) -> Result<File, Errno> {
|
||||
if self.kind == VnodeKind::Directory {
|
||||
return Err(Errno::IsADirectory);
|
||||
}
|
||||
|
||||
if let Some(ref mut data) = *self.data() {
|
||||
let pos = data.open(self.clone())?;
|
||||
let pos = data.open(self.clone(), flags)?;
|
||||
Ok(File::normal(self.clone(), pos))
|
||||
} else {
|
||||
Err(Errno::NotImplemented)
|
||||
|
||||
@@ -1,99 +0,0 @@
|
||||
use core::fmt;
|
||||
|
||||
/// Wrapper type for file mode/permissions
|
||||
#[derive(Clone, Copy, PartialEq)]
|
||||
#[repr(transparent)]
|
||||
pub struct FileMode(u16);
|
||||
|
||||
impl FileMode {
|
||||
/// File is user-readable
|
||||
pub const USER_READ: u16 = 1 << 8;
|
||||
/// File is user-writeable
|
||||
pub const USER_WRITE: u16 = 1 << 7;
|
||||
/// File is user-executable
|
||||
pub const USER_EXEC: u16 = 1 << 6;
|
||||
/// File is group-readable
|
||||
pub const GROUP_READ: u16 = 1 << 5;
|
||||
/// File is group-writeable
|
||||
pub const GROUP_WRITE: u16 = 1 << 4;
|
||||
/// File is group-executable
|
||||
pub const GROUP_EXEC: u16 = 1 << 3;
|
||||
/// File is readable by anyone
|
||||
pub const OTHER_READ: u16 = 1 << 2;
|
||||
/// File is writable by anyone
|
||||
pub const OTHER_WRITE: u16 = 1 << 1;
|
||||
/// File is executable by anyone
|
||||
pub const OTHER_EXEC: u16 = 1 << 0;
|
||||
|
||||
/// Returns an empty permission set
|
||||
pub const fn empty() -> Self {
|
||||
Self(0)
|
||||
}
|
||||
|
||||
/// Returns default permission set for directories
|
||||
pub const fn default_dir() -> Self {
|
||||
Self(0o755)
|
||||
}
|
||||
|
||||
/// Returns default permission set for regular files
|
||||
pub const fn default_reg() -> Self {
|
||||
Self(0o644)
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Debug for FileMode {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(f, "FileMode (")?;
|
||||
|
||||
if self.0 & Self::USER_READ != 0 {
|
||||
write!(f, "r")?;
|
||||
} else {
|
||||
write!(f, "-")?;
|
||||
}
|
||||
if self.0 & Self::USER_WRITE != 0 {
|
||||
write!(f, "w")?;
|
||||
} else {
|
||||
write!(f, "-")?;
|
||||
}
|
||||
if self.0 & Self::USER_EXEC != 0 {
|
||||
write!(f, "x")?;
|
||||
} else {
|
||||
write!(f, "-")?;
|
||||
}
|
||||
|
||||
if self.0 & Self::GROUP_READ != 0 {
|
||||
write!(f, "r")?;
|
||||
} else {
|
||||
write!(f, "-")?;
|
||||
}
|
||||
if self.0 & Self::GROUP_WRITE != 0 {
|
||||
write!(f, "w")?;
|
||||
} else {
|
||||
write!(f, "-")?;
|
||||
}
|
||||
if self.0 & Self::GROUP_EXEC != 0 {
|
||||
write!(f, "x")?;
|
||||
} else {
|
||||
write!(f, "-")?;
|
||||
}
|
||||
|
||||
if self.0 & Self::OTHER_READ != 0 {
|
||||
write!(f, "r")?;
|
||||
} else {
|
||||
write!(f, "-")?;
|
||||
}
|
||||
if self.0 & Self::OTHER_WRITE != 0 {
|
||||
write!(f, "w")?;
|
||||
} else {
|
||||
write!(f, "-")?;
|
||||
}
|
||||
if self.0 & Self::OTHER_EXEC != 0 {
|
||||
write!(f, "x")?;
|
||||
} else {
|
||||
write!(f, "-")?;
|
||||
}
|
||||
|
||||
write!(f, ")")?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
+1
-3
@@ -5,18 +5,16 @@
|
||||
#[macro_use]
|
||||
extern crate libusr;
|
||||
|
||||
use libusr::sys::{OpenFlags, AT_FDCWD};
|
||||
use libusr::io;
|
||||
|
||||
#[no_mangle]
|
||||
fn main() -> i32 {
|
||||
let mut buf = [0; 128];
|
||||
let stat = io::stat("/test.txt").unwrap();
|
||||
|
||||
print!("\x1B[2J\x1B[1;1H");
|
||||
println!("Hello!");
|
||||
|
||||
println!("test.txt: {:?}", stat);
|
||||
|
||||
loop {
|
||||
print!("> ");
|
||||
|
||||
|
||||
+3
-3
@@ -3,7 +3,7 @@ use crate::fs::{devfs, MemfsBlockAlloc};
|
||||
use crate::mem;
|
||||
use crate::proc::{elf, Process};
|
||||
use memfs::Ramfs;
|
||||
use vfs::{FileMode, Filesystem, Ioctx};
|
||||
use vfs::{FileMode, Filesystem, Ioctx, OpenFlags};
|
||||
|
||||
#[inline(never)]
|
||||
pub extern "C" fn init_fn(_arg: usize) -> ! {
|
||||
@@ -28,7 +28,7 @@ pub extern "C" fn init_fn(_arg: usize) -> ! {
|
||||
let ioctx = Ioctx::new(root);
|
||||
|
||||
let node = ioctx.find(None, "/init", true).unwrap();
|
||||
let mut file = node.open().unwrap();
|
||||
let mut file = node.open(OpenFlags::O_RDONLY).unwrap();
|
||||
|
||||
proc.set_ioctx(ioctx);
|
||||
|
||||
@@ -43,7 +43,7 @@ pub extern "C" fn init_fn(_arg: usize) -> ! {
|
||||
|
||||
let mut io = proc.io.lock();
|
||||
// TODO fd cloning?
|
||||
io.place_file(tty_node.open().unwrap()).unwrap();
|
||||
io.place_file(tty_node.open(OpenFlags::O_RDWR).unwrap()).unwrap();
|
||||
}
|
||||
|
||||
drop(cfg);
|
||||
|
||||
@@ -161,6 +161,17 @@ impl ProcessIo {
|
||||
Err(Errno::TooManyDescriptors)
|
||||
}
|
||||
|
||||
///
|
||||
pub fn close_file(&mut self, idx: usize) -> Result<(), Errno> {
|
||||
if self.file_bitmap & (1 << idx) == 0 {
|
||||
return Err(Errno::InvalidFile);
|
||||
}
|
||||
|
||||
let res = self.files.remove(&idx);
|
||||
assert!(res.is_some());
|
||||
Ok(())
|
||||
}
|
||||
|
||||
///
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
|
||||
+24
-12
@@ -5,10 +5,8 @@ use core::mem::size_of;
|
||||
use core::time::Duration;
|
||||
use error::Errno;
|
||||
use libcommon::{Read, Write};
|
||||
use syscall::{
|
||||
abi,
|
||||
stat::{Stat, AT_FDCWD},
|
||||
};
|
||||
use syscall::{abi, stat::AT_FDCWD};
|
||||
use vfs::{FileMode, OpenFlags, Stat};
|
||||
|
||||
fn translate(virt: usize) -> Option<usize> {
|
||||
let mut res: usize;
|
||||
@@ -24,9 +22,7 @@ fn translate(virt: usize) -> Option<usize> {
|
||||
|
||||
fn validate_user_ptr_struct<'a, T>(base: usize) -> Result<&'a mut T, Errno> {
|
||||
let bytes = validate_user_ptr(base, size_of::<T>())?;
|
||||
Ok(unsafe {
|
||||
&mut *(bytes.as_mut_ptr() as *mut T)
|
||||
})
|
||||
Ok(unsafe { &mut *(bytes.as_mut_ptr() as *mut T) })
|
||||
}
|
||||
|
||||
fn validate_user_ptr<'a>(base: usize, len: usize) -> Result<&'a mut [u8], Errno> {
|
||||
@@ -119,15 +115,23 @@ pub unsafe fn syscall(num: usize, args: &[usize]) -> Result<usize, Errno> {
|
||||
}
|
||||
|
||||
// I/O system calls
|
||||
abi::SYS_OPEN => {
|
||||
let path = validate_user_str(args[0], 256)?;
|
||||
abi::SYS_OPENAT => {
|
||||
let at_fd = args[0];
|
||||
let path = validate_user_str(args[1], 256)?;
|
||||
let mode = FileMode::from_bits(args[2] as u32).ok_or(Errno::InvalidArgument)?;
|
||||
let opts = OpenFlags::from_bits(args[3] as u32).ok_or(Errno::InvalidArgument)?;
|
||||
|
||||
let at = if at_fd as i32 == AT_FDCWD {
|
||||
None
|
||||
} else {
|
||||
todo!();
|
||||
};
|
||||
|
||||
let proc = Process::current();
|
||||
let mut io = proc.io.lock();
|
||||
|
||||
let node = io.ioctx().find(None, path, true)?;
|
||||
// TODO check access
|
||||
io.place_file(node.open()?)
|
||||
let file = io.ioctx().open(at, path, mode, opts)?;
|
||||
io.place_file(file)
|
||||
}
|
||||
abi::SYS_READ => {
|
||||
let proc = Process::current();
|
||||
@@ -160,6 +164,14 @@ pub unsafe fn syscall(num: usize, args: &[usize]) -> Result<usize, Errno> {
|
||||
node.stat(buf)?;
|
||||
Ok(0)
|
||||
}
|
||||
abi::SYS_CLOSE => {
|
||||
let proc = Process::current();
|
||||
let mut io = proc.io.lock();
|
||||
let fd = args[0];
|
||||
|
||||
io.close_file(fd)?;
|
||||
Ok(0)
|
||||
}
|
||||
|
||||
// Extra system calls
|
||||
abi::SYS_EX_DEBUG_TRACE => {
|
||||
|
||||
+1
-1
@@ -9,7 +9,7 @@ pub mod io;
|
||||
|
||||
pub mod sys {
|
||||
pub use syscall::calls::*;
|
||||
pub use syscall::stat::Stat;
|
||||
pub use syscall::stat::{AT_FDCWD, Stat, OpenFlags};
|
||||
}
|
||||
|
||||
#[link_section = ".text._start"]
|
||||
|
||||
@@ -6,6 +6,7 @@ edition = "2021"
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
bitflags = "^1.3.0"
|
||||
|
||||
[features]
|
||||
user = []
|
||||
|
||||
+2
-1
@@ -6,5 +6,6 @@ pub const SYS_EX_NANOSLEEP: usize = 129;
|
||||
pub const SYS_EXIT: usize = 1;
|
||||
pub const SYS_READ: usize = 2;
|
||||
pub const SYS_WRITE: usize = 3;
|
||||
pub const SYS_OPEN: usize = 4;
|
||||
pub const SYS_OPENAT: usize = 4;
|
||||
pub const SYS_FSTATAT: usize = 5;
|
||||
pub const SYS_CLOSE: usize = 6;
|
||||
|
||||
@@ -38,6 +38,11 @@ pub unsafe fn sys_exit(status: i32) -> ! {
|
||||
loop {}
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub unsafe fn sys_close(fd: i32) -> i32 {
|
||||
syscall!(abi::SYS_CLOSE, fd as usize) as i32
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub unsafe fn sys_ex_nanosleep(ns: u64, rem: *mut [u64; 2]) -> i32 {
|
||||
syscall!(abi::SYS_EX_NANOSLEEP, ns as usize, rem as usize) as i32
|
||||
@@ -49,9 +54,10 @@ pub unsafe fn sys_ex_debug_trace(msg: *const u8, len: usize) -> usize {
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub unsafe fn sys_open(pathname: *const u8, mode: u32, flags: u32) -> i32 {
|
||||
pub unsafe fn sys_openat(at: i32, pathname: *const u8, mode: u32, flags: u32) -> i32 {
|
||||
syscall!(
|
||||
abi::SYS_OPEN,
|
||||
abi::SYS_OPENAT,
|
||||
at as usize,
|
||||
pathname as usize,
|
||||
mode as usize,
|
||||
flags as usize
|
||||
|
||||
+3
-1
@@ -4,8 +4,10 @@
|
||||
#[cfg(feature = "linux_compat")]
|
||||
compile_error!("Not yet implemented");
|
||||
|
||||
pub mod abi;
|
||||
#[macro_use]
|
||||
extern crate bitflags;
|
||||
|
||||
pub mod abi;
|
||||
pub mod stat;
|
||||
|
||||
#[cfg(feature = "user")]
|
||||
|
||||
@@ -1,5 +1,32 @@
|
||||
use core::fmt;
|
||||
|
||||
pub const AT_FDCWD: i32 = -2;
|
||||
|
||||
bitflags! {
|
||||
pub struct OpenFlags: u32 {
|
||||
const O_RDONLY = 1 << 0;
|
||||
const O_WRONLY = 2 << 0;
|
||||
const O_RDWR = 3 << 0;
|
||||
const O_ACCESS = 0xF;
|
||||
|
||||
const O_CREAT = 1 << 4;
|
||||
}
|
||||
}
|
||||
|
||||
bitflags! {
|
||||
pub struct FileMode: u32 {
|
||||
const USER_READ = 1 << 8;
|
||||
const USER_WRITE = 1 << 7;
|
||||
const USER_EXEC = 1 << 6;
|
||||
const GROUP_READ = 1 << 5;
|
||||
const GROUP_WRITE = 1 << 4;
|
||||
const GROUP_EXEC = 1 << 3;
|
||||
const OTHER_READ = 1 << 2;
|
||||
const OTHER_WRITE = 1 << 1;
|
||||
const OTHER_EXEC = 1 << 0;
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
#[repr(C)]
|
||||
pub struct Stat {
|
||||
@@ -7,3 +34,19 @@ pub struct Stat {
|
||||
pub size: u64,
|
||||
pub blksize: u32,
|
||||
}
|
||||
|
||||
impl FileMode {
|
||||
/// Returns default permission set for directories
|
||||
pub const fn default_dir() -> Self {
|
||||
unsafe {
|
||||
Self::from_bits_unchecked(0o755)
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns default permission set for regular files
|
||||
pub const fn default_reg() -> Self {
|
||||
unsafe {
|
||||
Self::from_bits_unchecked(0o644)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user