diff --git a/src/filesystem.rs b/src/filesystem.rs index ed180bd618..2848b4c7b7 100644 --- a/src/filesystem.rs +++ b/src/filesystem.rs @@ -16,6 +16,7 @@ pub struct File { pub uid: u32, pub gid: u32, pub nlink: usize, + pub parent: Inode, pub open_handles: usize, @@ -76,6 +77,7 @@ impl Filesystem { gid: 0, data: FileData::Directory(IndexMap::new()), + parent: Inode(Self::ROOT_INODE), } } pub fn get_block_size(&self) -> Result { diff --git a/src/scheme.rs b/src/scheme.rs index c103abb74a..0318c009b9 100644 --- a/src/scheme.rs +++ b/src/scheme.rs @@ -1,4 +1,6 @@ use std::convert::{TryFrom, TryInto}; +use std::io::{Cursor, Seek}; +use std::iter; use std::os::unix::io::AsRawFd; use indexmap::IndexMap; @@ -191,6 +193,7 @@ impl SchemeMut for Scheme { nlink: 2, // parent entry, "." data: FileData::Directory(IndexMap::new()), open_handles: 1, + parent: Inode(parent_dir_inode), } } else { if mode & MODE_TYPE == 0 { @@ -211,6 +214,7 @@ impl SchemeMut for Scheme { nlink: 1, data: FileData::File(Vec::new()), open_handles: 1, + parent: Inode(parent_dir_inode), } }; let current_perm = current_perm(&new_inode, ctx.uid, ctx.gid); @@ -369,9 +373,40 @@ impl SchemeMut for Scheme { // TODO Err(Error::new(ENOSYS)) } - fn fpath(&mut self, _inode: usize, _buf: &mut [u8]) -> Result { - // TODO - Err(Error::new(ENOSYS)) + fn fpath(&mut self, mut current_inode: usize, buf: &mut [u8]) -> Result { + let mut chain = Vec::new(); + + let mut current_info = self + .filesystem + .files + .get(¤t_inode) + .ok_or(Error::new(EBADFD))?; + + while current_inode != Filesystem::ROOT_INODE { + let parent_info = self + .filesystem + .files + .get(¤t_info.parent.0) + .ok_or(Error::new(EBADFD))?; + + let FileData::Directory(ref dir) = parent_info.data else { + return Err(Error::new(EBADFD)); + }; + // TODO: error handling? + let (name, _) = dir.iter().find(|(_name, inode)| inode.0 == current_inode).ok_or(Error::new(ENOENT))?; + chain.push(&**name); + + current_inode = current_info.parent.0; + current_info = parent_info; + } + + let mut cursor = Cursor::new(buf); + for component in iter::once(self.scheme_name.trim_start_matches('/')).chain(chain.iter().copied().rev()) { + use std::io::Write; + + write!(cursor, "/{component}").unwrap(); + } + Ok(cursor.stream_position().unwrap() as usize) } fn frename(&mut self, _inode: usize, _path: &str, _uid: u32, _gid: u32) -> Result { // TODO