Skip to content

Commit

Permalink
add basic support of file attributes
Browse files Browse the repository at this point in the history
  • Loading branch information
stlankes committed Jan 4, 2024
1 parent 64823b9 commit 2d8b489
Show file tree
Hide file tree
Showing 6 changed files with 150 additions and 54 deletions.
12 changes: 9 additions & 3 deletions src/fd/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -81,8 +81,8 @@ bitflags! {
}

bitflags! {
#[derive(Debug, Copy, Clone, Default)]
pub(crate) struct AccessPermission: i32 {
#[derive(Debug, Copy, Clone)]
pub struct AccessPermission: u32 {
const S_IRUSR = 0o400;
const S_IWUSR = 0o200;
const S_IXUSR = 0o100;
Expand All @@ -98,6 +98,12 @@ bitflags! {
}
}

impl Default for AccessPermission {
fn default() -> Self {
AccessPermission::from_bits(0o666).unwrap()
}
}

#[repr(C)]
#[derive(Debug, Copy, Clone, Default)]
pub struct Dirent {
Expand Down Expand Up @@ -242,7 +248,7 @@ pub(crate) trait ObjectInterface: Sync + Send + core::fmt::Debug + DynClone {
fn close(&self) {}
}

pub(crate) fn open(name: &str, flags: i32, mode: i32) -> Result<FileDescriptor, IoError> {
pub(crate) fn open(name: &str, flags: i32, mode: u32) -> Result<FileDescriptor, IoError> {
// mode is 0x777 (0b0111_0111_0111), when flags | O_CREAT, else 0
// flags is bitmask of O_DEC_* defined above.
// (taken from rust stdlib/sys hermit target )
Expand Down
43 changes: 21 additions & 22 deletions src/fs/fuse.rs
Original file line number Diff line number Diff line change
Expand Up @@ -204,24 +204,24 @@ struct fuse_attr {
pub padding: u32,
}

impl fuse_attr {
fn to_stat(&self) -> FileAttr {
impl From<fuse_attr> for FileAttr {
fn from(attr: fuse_attr) -> FileAttr {
FileAttr {
st_ino: self.ino,
st_nlink: self.nlink as u64,
st_mode: self.mode,
st_uid: self.uid,
st_gid: self.gid,
st_rdev: self.rdev as u64,
st_size: self.size.try_into().unwrap(),
st_blksize: self.blksize as i64,
st_blocks: self.blocks.try_into().unwrap(),
st_atime: self.atime.try_into().unwrap(),
st_atime_nsec: self.atimensec as i64,
st_mtime: self.mtime.try_into().unwrap(),
st_mtime_nsec: self.atimensec as i64,
st_ctime: self.ctime.try_into().unwrap(),
st_ctime_nsec: self.ctimensec as i64,
st_ino: attr.ino,
st_nlink: attr.nlink as u64,
st_mode: AccessPermission::from_bits(attr.mode).unwrap(),
st_uid: attr.uid,
st_gid: attr.gid,
st_rdev: attr.rdev as u64,
st_size: attr.size.try_into().unwrap(),
st_blksize: attr.blksize as i64,
st_blocks: attr.blocks.try_into().unwrap(),
st_atime: attr.atime.try_into().unwrap(),
st_atime_nsec: attr.atimensec as i64,
st_mtime: attr.mtime.try_into().unwrap(),
st_mtime_nsec: attr.atimensec as i64,
st_ctime: attr.ctime.try_into().unwrap(),
st_ctime_nsec: attr.ctimensec as i64,
..Default::default()
}
}
Expand Down Expand Up @@ -1498,7 +1498,7 @@ impl VfsNode for FuseDirectory {
let attr = rsp.attr;

if attr.mode & S_IFMT != S_IFLNK {
Ok(attr.to_stat())
Ok(FileAttr::from(attr))
} else {
let path = readlink(rsp.nodeid)?;
let mut components: Vec<&str> = path.split('/').collect();
Expand All @@ -1522,7 +1522,7 @@ impl VfsNode for FuseDirectory {
.send_command(cmd.as_ref(), rsp.as_mut());

let attr = unsafe { rsp.rsp.assume_init().attr };
Ok(attr.to_stat())
Ok(FileAttr::from(attr))
}

fn traverse_open(
Expand Down Expand Up @@ -1568,8 +1568,7 @@ impl VfsNode for FuseDirectory {
let (cmd, mut rsp) = create_create(
&path,
opt.bits().try_into().unwrap(),
mode.bits().try_into().unwrap(),
);
mode.bits());
get_filesystem_driver()
.ok_or(IoError::ENOSYS)?
.lock()
Expand Down Expand Up @@ -1629,7 +1628,7 @@ impl VfsNode for FuseDirectory {
} else {
components.iter().map(|v| "/".to_owned() + v).collect()
};
let (cmd, mut rsp) = create_mkdir(&path, mode.bits().try_into().unwrap());
let (cmd, mut rsp) = create_mkdir(&path, mode.bits());

get_filesystem_driver()
.ok_or(IoError::ENOSYS)?
Expand Down
117 changes: 101 additions & 16 deletions src/fs/mem.rs
Original file line number Diff line number Diff line change
Expand Up @@ -151,42 +151,100 @@ impl Clone for RamFileInterface {
}

#[derive(Debug, Clone)]
pub(crate) struct RomFile(Arc<RwSpinLock<&'static [u8]>>);
pub(crate) struct RomFile {
data: Arc<RwSpinLock<&'static [u8]>>,
attr: FileAttr,
}

impl VfsNode for RomFile {
fn get_kind(&self) -> NodeKind {
NodeKind::File
}

fn get_object(&self) -> Result<Arc<dyn ObjectInterface>, IoError> {
Ok(Arc::new(RomFileInterface::new(self.0.clone())))
Ok(Arc::new(RomFileInterface::new(self.data.clone())))
}

fn get_file_attributes(&self) -> Result<FileAttr, IoError> {
Ok(self.attr)
}

fn traverse_lstat(&self, components: &mut Vec<&str>) -> Result<FileAttr, IoError> {
if components.is_empty() {
Ok(self.attr)
} else {
Err(IoError::EBADF)
}
}

fn traverse_stat(&self, components: &mut Vec<&str>) -> Result<FileAttr, IoError> {
if components.is_empty() {
Ok(self.attr)
} else {
Err(IoError::EBADF)
}
}
}

impl RomFile {
pub unsafe fn new(ptr: *const u8, length: usize) -> Self {
Self(Arc::new(RwSpinLock::new(unsafe {
slice::from_raw_parts(ptr, length)
})))
pub unsafe fn new(ptr: *const u8, length: usize, mode: AccessPermission) -> Self {
Self {
data: Arc::new(RwSpinLock::new(unsafe {
slice::from_raw_parts(ptr, length)
})),
attr: FileAttr {
st_mode: mode,
..Default::default()
},
}
}
}

#[derive(Debug, Clone)]
pub(crate) struct RamFile(Arc<RwSpinLock<Vec<u8>>>);
pub(crate) struct RamFile {
data: Arc<RwSpinLock<Vec<u8>>>,
attr: FileAttr,
}

impl VfsNode for RamFile {
fn get_kind(&self) -> NodeKind {
NodeKind::File
}

fn get_object(&self) -> Result<Arc<dyn ObjectInterface>, IoError> {
Ok(Arc::new(RamFileInterface::new(self.0.clone())))
Ok(Arc::new(RamFileInterface::new(self.data.clone())))
}

fn get_file_attributes(&self) -> Result<FileAttr, IoError> {
Ok(self.attr)
}

fn traverse_lstat(&self, components: &mut Vec<&str>) -> Result<FileAttr, IoError> {
if components.is_empty() {
Ok(self.attr)
} else {
Err(IoError::EBADF)
}
}

fn traverse_stat(&self, components: &mut Vec<&str>) -> Result<FileAttr, IoError> {
if components.is_empty() {
Ok(self.attr)
} else {
Err(IoError::EBADF)
}
}
}

impl RamFile {
pub fn new() -> Self {
Self(Arc::new(RwSpinLock::new(Vec::new())))
pub fn new(mode: AccessPermission) -> Self {
Self {
data: Arc::new(RwSpinLock::new(Vec::new())),
attr: FileAttr {
st_mode: mode,
..Default::default()
},
}
}
}

Expand Down Expand Up @@ -308,19 +366,30 @@ pub(crate) struct MemDirectory {
inner: Arc<
RwSpinLock<BTreeMap<String, Box<dyn VfsNode + core::marker::Send + core::marker::Sync>>>,
>,
attr: FileAttr,
}

impl MemDirectory {
pub fn new() -> Self {
pub fn new(mode: AccessPermission) -> Self {
Self {
inner: Arc::new(RwSpinLock::new(BTreeMap::new())),
attr: FileAttr {
st_mode: mode,
..Default::default()
},
}
}

pub fn create_file(&self, name: &str, ptr: *const u8, length: usize) -> Result<(), IoError> {
pub fn create_file(
&self,
name: &str,
ptr: *const u8,
length: usize,
mode: AccessPermission,
) -> Result<(), IoError> {
let name = name.trim();
if name.find('/').is_none() {
let file = unsafe { RomFile::new(ptr, length) };
let file = unsafe { RomFile::new(ptr, length, mode) };
self.inner.write().insert(name.to_string(), Box::new(file));
Ok(())
} else {
Expand All @@ -334,6 +403,10 @@ impl VfsNode for MemDirectory {
NodeKind::Directory
}

fn get_file_attributes(&self) -> Result<FileAttr, IoError> {
Ok(self.attr)
}

fn traverse_mkdir(
&self,
components: &mut Vec<&str>,
Expand All @@ -349,7 +422,7 @@ impl VfsNode for MemDirectory {
if components.is_empty() {
self.inner
.write()
.insert(node_name, Box::new(MemDirectory::new()));
.insert(node_name, Box::new(MemDirectory::new(mode)));
return Ok(());
}
}
Expand Down Expand Up @@ -426,6 +499,12 @@ impl VfsNode for MemDirectory {
if let Some(component) = components.pop() {
let node_name = String::from(component);

if components.is_empty() {
if let Some(node) = self.inner.read().get(&node_name) {
node.get_file_attributes()?;
}
}

if let Some(directory) = self.inner.read().get(&node_name) {
directory.traverse_lstat(components)
} else {
Expand All @@ -440,6 +519,12 @@ impl VfsNode for MemDirectory {
if let Some(component) = components.pop() {
let node_name = String::from(component);

if components.is_empty() {
if let Some(node) = self.inner.read().get(&node_name) {
node.get_file_attributes()?;
}
}

if let Some(directory) = self.inner.read().get(&node_name) {
directory.traverse_stat(components)
} else {
Expand Down Expand Up @@ -486,9 +571,9 @@ impl VfsNode for MemDirectory {
if guard.get(&node_name).is_some() {
return Err(IoError::EEXIST);
} else {
let file = Box::new(RamFile::new());
let file = Box::new(RamFile::new(mode));
guard.insert(node_name, file.clone());
return Ok(Arc::new(RamFileInterface::new(file.0.clone())));
return Ok(Arc::new(RamFileInterface::new(file.data.clone())));
}
} else if let Some(file) = guard.get(&node_name) {
if file.get_kind() == NodeKind::File {
Expand Down
20 changes: 13 additions & 7 deletions src/fs/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,11 @@ pub(crate) trait VfsNode: core::fmt::Debug {
/// Determines the current node type
fn get_kind(&self) -> NodeKind;

/// determines the current file attribute
fn get_file_attributes(&self) -> Result<FileAttr, IoError> {
Err(IoError::ENOSYS)
}

/// Determine the syscall interface
fn get_object(&self) -> Result<Arc<dyn ObjectInterface>, IoError> {
Err(IoError::ENOSYS)
Expand Down Expand Up @@ -98,7 +103,7 @@ pub(crate) struct Filesystem {
impl Filesystem {
pub fn new() -> Self {
Self {
root: MemDirectory::new(),
root: MemDirectory::new(AccessPermission::from_bits(0o777).unwrap()),
}
}

Expand Down Expand Up @@ -210,8 +215,9 @@ impl Filesystem {
name: &str,
ptr: *const u8,
length: usize,
mode: AccessPermission,
) -> Result<(), IoError> {
self.root.create_file(name, ptr, length)
self.root.create_file(name, ptr, length, mode)
}
}

Expand All @@ -221,7 +227,7 @@ pub struct FileAttr {
pub st_dev: u64,
pub st_ino: u64,
pub st_nlink: u64,
pub st_mode: u32,
pub st_mode: AccessPermission,
pub st_uid: u32,
pub st_gid: u32,
pub st_rdev: u64,
Expand Down Expand Up @@ -275,15 +281,15 @@ pub(crate) fn init() {
if let Ok(fd) = FILESYSTEM.get().unwrap().open(
"/etc/hostname",
OpenOption::O_CREAT | OpenOption::O_RDWR,
AccessPermission::from_bits(0o666).unwrap(),
AccessPermission::from_bits(0o644).unwrap(),
) {
let _ret = fd.write(b"Hermit");
fd.close();
}
if let Ok(fd) = FILESYSTEM.get().unwrap().open(
"/etc/version",
OpenOption::O_CREAT | OpenOption::O_RDWR,
AccessPermission::from_bits(0o666).unwrap(),
AccessPermission::from_bits(0o644).unwrap(),
) {
let _ret = fd.write(VERSION.as_bytes());
fd.close();
Expand All @@ -294,12 +300,12 @@ pub(crate) fn init() {
uhyve::init();
}

pub unsafe fn create_file(name: &str, ptr: *const u8, length: usize) {
pub unsafe fn create_file(name: &str, ptr: *const u8, length: usize, mode: AccessPermission) {
unsafe {
FILESYSTEM
.get()
.unwrap()
.create_file(name, ptr, length)
.create_file(name, ptr, length, mode)
.expect("Unable to create file from ROM")
}
}
Loading

0 comments on commit 2d8b489

Please sign in to comment.