diff --git a/rcore-fs-sfs/src/lib.rs b/rcore-fs-sfs/src/lib.rs index f586273..286ec6b 100644 --- a/rcore-fs-sfs/src/lib.rs +++ b/rcore-fs-sfs/src/lib.rs @@ -308,7 +308,7 @@ impl vfs::INode for INodeImpl { }) } - fn chmod(&self, mode: u16) -> vfs::Result<()> { + fn chmod(&self, _mode: u16) -> vfs::Result<()> { // No-op for sfs Ok(()) } diff --git a/rcore-fs-sfs/src/tests.rs b/rcore-fs-sfs/src/tests.rs index 9fef478..e9b08b4 100644 --- a/rcore-fs-sfs/src/tests.rs +++ b/rcore-fs-sfs/src/tests.rs @@ -119,9 +119,57 @@ fn create_then_lookup() -> Result<()> { .expect("failed to create dir1"); let file2 = dir1.create("file2", FileType::File, 0o777) .expect("failed to create /dir1/file2"); - assert!(Arc::ptr_eq(&root.lookup("dir1/file2")?, &file2), "failed to find dir1/file1"); + assert!(Arc::ptr_eq(&root.lookup("dir1/file2")?, &file2), "failed to find dir1/file2"); assert!(Arc::ptr_eq(&dir1.lookup("..")?, &root), "failed to find .. from dir1"); + assert!(Arc::ptr_eq(&dir1.lookup("../dir1/file2")?, &file2), "failed to find dir1/file2 by relative"); + assert!(Arc::ptr_eq(&dir1.lookup("/dir1/file2")?, &file2), "failed to find dir1/file2 by absolute"); + assert!(Arc::ptr_eq(&dir1.lookup("/dir1/../dir1/file2")?, &file2), "failed to find dir1/file2 by absolute"); + assert!(Arc::ptr_eq(&dir1.lookup("../../..//dir1/../dir1/file2")?, &file2), "failed to find dir1/file2 by more than one .."); + assert!(Arc::ptr_eq(&dir1.lookup("..//dir1/file2")?, &file2), "failed to find dir1/file2 by weird relative"); + + sfs.sync()?; + Ok(()) +} + +#[test] +fn test_symlinks() -> Result<()> { + let sfs = _create_new_sfs(); + let root = sfs.root_inode(); + + let file1 = root.create("file1", FileType::File, 0o777) + .expect("failed to create file1"); + assert!(Arc::ptr_eq(&root.lookup("file1")?, &file1), "failed to find file1"); + + let link1 = root.create("link1", FileType::SymLink, 0o777) + .expect("failed to create link1"); + let data = "file1".as_bytes(); + link1.resize(data.len())?; + link1.write_at(0, data)?; + + let link2 = root.create("link2", FileType::SymLink, 0o777) + .expect("failed to create link2"); + let data = "link1".as_bytes(); + link2.resize(data.len())?; + link2.write_at(0, data)?; + + assert!(Arc::ptr_eq(&root.lookup("link1")?, &link1), "failed to find link1 by relative"); + assert!(Arc::ptr_eq(&root.lookup_follow("link1", 1)?, &file1), "failed to find file1 by link1"); + assert!(Arc::ptr_eq(&root.lookup_follow("link2", 0)?, &link2), "failed to find link2 by link2"); + assert!(Arc::ptr_eq(&root.lookup_follow("link2", 1)?, &link1), "failed to find link1 by link2"); + assert!(Arc::ptr_eq(&root.lookup_follow("link2", 2)?, &file1), "failed to find file1 by link2"); + + let link3 = root.create("link3", FileType::SymLink, 0o777) + .expect("failed to create link3"); + let data = "/link2".as_bytes(); + link3.resize(data.len())?; + link3.write_at(0, data)?; + + assert!(Arc::ptr_eq(&root.lookup_follow("link3", 0)?, &link3), "failed to find link3 by link3"); + assert!(Arc::ptr_eq(&root.lookup_follow("link3", 1)?, &link2), "failed to find link2 by link3"); + assert!(Arc::ptr_eq(&root.lookup_follow("link3", 2)?, &link1), "failed to find link1 by link3"); + assert!(Arc::ptr_eq(&root.lookup_follow("link3", 3)?, &file1), "failed to find file1 by link2"); + sfs.sync()?; Ok(()) } diff --git a/rcore-fs/src/vfs.rs b/rcore-fs/src/vfs.rs index 0d95695..36a09b1 100644 --- a/rcore-fs/src/vfs.rs +++ b/rcore-fs/src/vfs.rs @@ -58,12 +58,17 @@ impl INode { if self.metadata()?.type_ != FileType::Dir { return Err(FsError::NotDir); } + let mut result = self.find(".")?; let mut rest_path = String::from(path); while rest_path != "" { - if result.metadata()?.type_!= FileType::Dir { + if result.metadata()?.type_ != FileType::Dir { return Err(FsError::NotDir); } + // handle absolute path + if let Some('/') = rest_path.chars().next() { + return self.fs().root_inode().lookup_follow(&path[1..], follow_times); + } let name; match rest_path.find('/') { None => { @@ -86,8 +91,7 @@ impl INode { if let Ok(path) = str::from_utf8(&content[..len]) { if let Some('/') = path.chars().next() { // absolute link - result = result.fs().root_inode(); - rest_path = String::from(&path[1..]); + return result.fs().root_inode().lookup_follow(&path[1..], follow_times); } else { // relative link // result remains unchanged