patch: fix FUSE load file
Signed-off-by: ClSlaid <cailue@bupt.edu.cn>
This commit is contained in:
parent
d0dc22794e
commit
7fbb4045e2
@ -19,7 +19,7 @@
|
|||||||
//! - any write operations, hard links, and symbolic links on the FS should be denied
|
//! - any write operations, hard links, and symbolic links on the FS should be denied
|
||||||
|
|
||||||
use std::{
|
use std::{
|
||||||
collections::{BTreeMap, HashMap},
|
collections::{BTreeMap, HashMap, VecDeque},
|
||||||
ffi::OsString,
|
ffi::OsString,
|
||||||
path::{Path, PathBuf},
|
path::{Path, PathBuf},
|
||||||
sync::{
|
sync::{
|
||||||
@ -811,41 +811,69 @@ impl FuseNode {
|
|||||||
sub_root_map.insert(Path::new("/").to_path_buf(), FUSE_ROOT_ID);
|
sub_root_map.insert(Path::new("/").to_path_buf(), FUSE_ROOT_ID);
|
||||||
sub_root_map.insert(Path::new("").to_path_buf(), FUSE_ROOT_ID);
|
sub_root_map.insert(Path::new("").to_path_buf(), FUSE_ROOT_ID);
|
||||||
|
|
||||||
for (inode, mut file) in files
|
for file in files.into_iter() {
|
||||||
.into_iter()
|
let name = file.name.clone();
|
||||||
.enumerate()
|
let ancestors = name
|
||||||
.map(|(i, f)| (i as u64 + 2, f))
|
.ancestors()
|
||||||
{
|
.collect::<VecDeque<_>>()
|
||||||
let FileDescription { name, .. } = file.clone();
|
.into_iter()
|
||||||
|
.rev()
|
||||||
|
.chain([name.as_path()].into_iter());
|
||||||
|
|
||||||
let parent_inode = match name.parent() {
|
// build tree iteratively
|
||||||
Some(parent) => sub_root_map[parent],
|
// from root to self
|
||||||
None => {
|
for ancestor in ancestors {
|
||||||
// parent should be root
|
if sub_root_map.contains_key(ancestor) {
|
||||||
FUSE_ROOT_ID
|
continue;
|
||||||
}
|
}
|
||||||
};
|
|
||||||
|
|
||||||
tree_list[parent_inode as usize - 1].add_child(inode);
|
let inode = tree_list.len() as u64 + FUSE_ROOT_ID;
|
||||||
|
sub_root_map.insert(ancestor.to_path_buf(), inode);
|
||||||
|
let parent_inode = match ancestor.parent() {
|
||||||
|
Some(parent) => sub_root_map[parent],
|
||||||
|
None => {
|
||||||
|
// parent should be root
|
||||||
|
FUSE_ROOT_ID
|
||||||
|
}
|
||||||
|
};
|
||||||
|
tree_list[parent_inode as usize - 1].add_child(inode);
|
||||||
|
|
||||||
if file.kind == FileType::Directory {
|
let base_name = name.file_name().ok_or_else(|| {
|
||||||
sub_root_map.insert(name.clone(), inode);
|
let err = std::io::Error::new(
|
||||||
|
std::io::ErrorKind::InvalidData,
|
||||||
|
format!("invalid file name {}", file.name.display()),
|
||||||
|
);
|
||||||
|
CliprdrError::FileError {
|
||||||
|
path: file.name.clone(),
|
||||||
|
err,
|
||||||
|
}
|
||||||
|
})?;
|
||||||
|
|
||||||
|
let mut desc = if ancestor != &file.name {
|
||||||
|
FileDescription {
|
||||||
|
conn_id: 0,
|
||||||
|
name: ancestor.to_path_buf(),
|
||||||
|
kind: FileType::Directory,
|
||||||
|
atime: SystemTime::UNIX_EPOCH,
|
||||||
|
last_modified: SystemTime::UNIX_EPOCH,
|
||||||
|
last_metadata_changed: SystemTime::UNIX_EPOCH,
|
||||||
|
creation_time: SystemTime::UNIX_EPOCH,
|
||||||
|
size: 0,
|
||||||
|
perm: PERM_READ,
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
file.clone()
|
||||||
|
};
|
||||||
|
|
||||||
|
desc.name = Path::new(base_name).to_path_buf();
|
||||||
|
|
||||||
|
if desc.kind == FileType::Directory {
|
||||||
|
sub_root_map.insert(desc.name.clone(), inode);
|
||||||
|
}
|
||||||
|
let mut fuse_node = FuseNode::from_description(inode, desc);
|
||||||
|
fuse_node.parent = Some(parent_inode);
|
||||||
|
tree_list.push(fuse_node);
|
||||||
}
|
}
|
||||||
|
|
||||||
let f_name = name.clone();
|
|
||||||
let base_name = f_name.file_name().ok_or_else(|| {
|
|
||||||
let err = std::io::Error::new(
|
|
||||||
std::io::ErrorKind::InvalidData,
|
|
||||||
format!("invalid file name {}", name.display()),
|
|
||||||
);
|
|
||||||
CliprdrError::FileError { path: name, err }
|
|
||||||
})?;
|
|
||||||
file.name = Path::new(base_name).to_path_buf();
|
|
||||||
|
|
||||||
let mut fuse_node = FuseNode::from_description(inode, file);
|
|
||||||
fuse_node.parent = Some(parent_inode);
|
|
||||||
|
|
||||||
tree_list.push(fuse_node)
|
|
||||||
}
|
}
|
||||||
Ok(tree_list)
|
Ok(tree_list)
|
||||||
}
|
}
|
||||||
@ -1010,11 +1038,13 @@ impl FileHandles {
|
|||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod fuse_test {
|
mod fuse_test {
|
||||||
|
use std::str::FromStr;
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
// todo: more tests needed!
|
// todo: more tests needed!
|
||||||
|
|
||||||
fn generate_descriptions() -> Vec<FileDescription> {
|
fn generate_descriptions(prefix: &str) -> Vec<FileDescription> {
|
||||||
fn desc_gen(name: &str, kind: FileType) -> FileDescription {
|
fn desc_gen(name: &str, kind: FileType) -> FileDescription {
|
||||||
FileDescription {
|
FileDescription {
|
||||||
conn_id: 0,
|
conn_id: 0,
|
||||||
@ -1029,53 +1059,68 @@ mod fuse_test {
|
|||||||
perm: 0,
|
perm: 0,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let folder0 = desc_gen("folder0", FileType::Directory);
|
let (d0_path, f0_path, f1_path, d1_path, f2_path) = if prefix == "" {
|
||||||
let file0 = desc_gen("folder0/file0", FileType::File);
|
(
|
||||||
let file1 = desc_gen("folder0/file1", FileType::File);
|
"folder0".to_string(),
|
||||||
let folder1 = desc_gen("folder1", FileType::Directory);
|
"folder0/file0".to_string(),
|
||||||
let file2 = desc_gen("folder1/file2", FileType::File);
|
"folder0/file1".to_string(),
|
||||||
|
"folder1".to_string(),
|
||||||
|
"folder1/file2".to_string(),
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
(
|
||||||
|
format!("{}/folder0", prefix),
|
||||||
|
format!("{}/folder0/file0", prefix),
|
||||||
|
format!("{}/folder0/file1", prefix),
|
||||||
|
format!("{}/folder1", prefix),
|
||||||
|
format!("{}/folder1/file2", prefix),
|
||||||
|
)
|
||||||
|
};
|
||||||
|
let folder0 = desc_gen(&d0_path, FileType::Directory);
|
||||||
|
let file0 = desc_gen(&f0_path, FileType::File);
|
||||||
|
let file1 = desc_gen(&f1_path, FileType::File);
|
||||||
|
let folder1 = desc_gen(&d1_path, FileType::Directory);
|
||||||
|
let file2 = desc_gen(&f2_path, FileType::File);
|
||||||
|
|
||||||
vec![folder0, file0, file1, folder1, file2]
|
vec![folder0, file0, file1, folder1, file2]
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
fn build_tree(prefix: &str) {
|
||||||
fn build_tree() {
|
let source_list = generate_descriptions(prefix);
|
||||||
// Tree:
|
|
||||||
// - folder0
|
|
||||||
// - file0
|
|
||||||
// - file1
|
|
||||||
// - folder1
|
|
||||||
// - file2
|
|
||||||
let source_list = generate_descriptions();
|
|
||||||
|
|
||||||
let build_res = FuseNode::build_tree(source_list);
|
let build_res = FuseNode::build_tree(source_list);
|
||||||
assert!(build_res.is_ok());
|
assert!(build_res.is_ok());
|
||||||
// expected tree:
|
|
||||||
// - /
|
|
||||||
// - folder0
|
|
||||||
// - file0
|
|
||||||
// - file1
|
|
||||||
// - folder1
|
|
||||||
// - file2
|
|
||||||
let tree_list = build_res.unwrap();
|
let tree_list = build_res.unwrap();
|
||||||
assert_eq!(tree_list.len(), 6);
|
|
||||||
|
|
||||||
assert_eq!(tree_list[0].name, "/"); // inode 1
|
let extra_wrap = PathBuf::from_str(prefix.trim_matches('/')).unwrap();
|
||||||
assert_eq!(tree_list[0].children, vec![2, 5]);
|
let e = extra_wrap.components().count(); // extra component count
|
||||||
|
|
||||||
assert_eq!(tree_list[1].name, "folder0"); // inode 2
|
assert_eq!(tree_list.len(), 6 + e);
|
||||||
assert_eq!(tree_list[1].children, vec![3, 4]);
|
|
||||||
|
|
||||||
assert_eq!(tree_list[2].name, "file0"); // inode 3
|
assert_eq!(tree_list[0].name, "/");
|
||||||
assert!(tree_list[2].children.is_empty());
|
let strip_list = &tree_list[e..];
|
||||||
|
assert_eq!(strip_list[1].name, "folder0");
|
||||||
|
assert_eq!(strip_list[2].name, "file0");
|
||||||
|
assert_eq!(strip_list[3].name, "file1");
|
||||||
|
assert_eq!(strip_list[4].name, "folder1");
|
||||||
|
assert_eq!(strip_list[5].name, "file2");
|
||||||
|
|
||||||
assert_eq!(tree_list[3].name, "file1"); // inode 4
|
let e = e as u64;
|
||||||
assert!(tree_list[3].children.is_empty());
|
|
||||||
|
|
||||||
assert_eq!(tree_list[4].name, "folder1"); // inode 5
|
assert_eq!(strip_list[0].children, vec![e + 2, e + 5]);
|
||||||
assert_eq!(tree_list[4].children, vec![6]);
|
assert_eq!(strip_list[1].children, vec![e + 3, e + 4]);
|
||||||
|
assert!(strip_list[2].children.is_empty());
|
||||||
|
assert!(strip_list[3].children.is_empty());
|
||||||
|
assert_eq!(strip_list[4].children, vec![e + 6]);
|
||||||
|
assert!(strip_list[5].children.is_empty());
|
||||||
|
}
|
||||||
|
|
||||||
assert_eq!(tree_list[5].name, "file2"); // inode 6
|
#[test]
|
||||||
assert!(tree_list[5].children.is_empty());
|
fn test_parse_tree() {
|
||||||
|
build_tree("");
|
||||||
|
build_tree("/");
|
||||||
|
build_tree("test");
|
||||||
|
build_tree("/test");
|
||||||
|
build_tree("/test/test");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user