1*004e86ffSlogin use core::any::Any; 2*004e86ffSlogin 3*004e86ffSlogin use alloc::{ 4*004e86ffSlogin collections::BTreeMap, 5*004e86ffSlogin string::String, 6*004e86ffSlogin sync::{Arc, Weak}, 7*004e86ffSlogin vec::Vec, 8*004e86ffSlogin }; 9*004e86ffSlogin 10*004e86ffSlogin use crate::{ 11*004e86ffSlogin filesystem::vfs::{core::generate_inode_id, FileType}, 12*004e86ffSlogin include::bindings::bindings::{ 13*004e86ffSlogin EEXIST, EINVAL, EISDIR, ENOBUFS, ENOENT, ENOTDIR, ENOTEMPTY, EPERM, 14*004e86ffSlogin }, 15*004e86ffSlogin libs::spinlock::{SpinLock, SpinLockGuard}, 16*004e86ffSlogin time::TimeSpec, 17*004e86ffSlogin }; 18*004e86ffSlogin 19*004e86ffSlogin use super::vfs::{ 20*004e86ffSlogin file::FilePrivateData, FileSystem, FsInfo, IndexNode, InodeId, Metadata, PollStatus, 21*004e86ffSlogin }; 22*004e86ffSlogin 23*004e86ffSlogin /// RamFS的inode名称的最大长度 24*004e86ffSlogin const RAMFS_MAX_NAMELEN: usize = 64; 25*004e86ffSlogin 26*004e86ffSlogin /// @brief 内存文件系统的Inode结构体 27*004e86ffSlogin #[derive(Debug)] 28*004e86ffSlogin struct LockedRamFSInode(SpinLock<RamFSInode>); 29*004e86ffSlogin 30*004e86ffSlogin /// @brief 内存文件系统结构体 31*004e86ffSlogin #[derive(Debug)] 32*004e86ffSlogin pub struct RamFS { 33*004e86ffSlogin /// RamFS的root inode 34*004e86ffSlogin root_inode: Arc<LockedRamFSInode>, 35*004e86ffSlogin } 36*004e86ffSlogin 37*004e86ffSlogin /// @brief 内存文件系统的Inode结构体(不包含锁) 38*004e86ffSlogin #[derive(Debug)] 39*004e86ffSlogin pub struct RamFSInode { 40*004e86ffSlogin // parent变量目前只在find函数中使用到 41*004e86ffSlogin // 所以只有当inode是文件夹的时候,parent才会生效 42*004e86ffSlogin // 对于文件来说,parent就没什么作用了 43*004e86ffSlogin // 关于parent的说明: 目录不允许有硬链接 44*004e86ffSlogin /// 指向父Inode的弱引用 45*004e86ffSlogin parent: Weak<LockedRamFSInode>, 46*004e86ffSlogin /// 指向自身的弱引用 47*004e86ffSlogin self_ref: Weak<LockedRamFSInode>, 48*004e86ffSlogin /// 子Inode的B树 49*004e86ffSlogin children: BTreeMap<String, Arc<LockedRamFSInode>>, 50*004e86ffSlogin /// 当前inode的数据部分 51*004e86ffSlogin data: Vec<u8>, 52*004e86ffSlogin /// 当前inode的元数据 53*004e86ffSlogin metadata: Metadata, 54*004e86ffSlogin /// 指向inode所在的文件系统对象的指针 55*004e86ffSlogin fs: Weak<RamFS>, 56*004e86ffSlogin } 57*004e86ffSlogin 58*004e86ffSlogin impl FileSystem for RamFS { 59*004e86ffSlogin fn root_inode(&self) -> Arc<dyn super::vfs::IndexNode> { 60*004e86ffSlogin return self.root_inode.clone(); 61*004e86ffSlogin } 62*004e86ffSlogin 63*004e86ffSlogin fn info(&self) -> FsInfo { 64*004e86ffSlogin return FsInfo { 65*004e86ffSlogin blk_dev_id: 0, 66*004e86ffSlogin max_name_len: RAMFS_MAX_NAMELEN, 67*004e86ffSlogin }; 68*004e86ffSlogin } 69*004e86ffSlogin 70*004e86ffSlogin /// @brief 本函数用于实现动态转换。 71*004e86ffSlogin /// 具体的文件系统在实现本函数时,最简单的方式就是:直接返回self 72*004e86ffSlogin fn as_any_ref(&self) -> &dyn Any { 73*004e86ffSlogin self 74*004e86ffSlogin } 75*004e86ffSlogin } 76*004e86ffSlogin 77*004e86ffSlogin impl RamFS { 78*004e86ffSlogin pub fn new() -> Arc<Self> { 79*004e86ffSlogin // 初始化root inode 80*004e86ffSlogin let root: Arc<LockedRamFSInode> = Arc::new(LockedRamFSInode(SpinLock::new(RamFSInode { 81*004e86ffSlogin parent: Weak::default(), 82*004e86ffSlogin self_ref: Weak::default(), 83*004e86ffSlogin children: BTreeMap::new(), 84*004e86ffSlogin data: Vec::new(), 85*004e86ffSlogin metadata: Metadata { 86*004e86ffSlogin dev_id: 0, 87*004e86ffSlogin inode_id: generate_inode_id(), 88*004e86ffSlogin size: 0, 89*004e86ffSlogin blk_size: 0, 90*004e86ffSlogin blocks: 0, 91*004e86ffSlogin atime: TimeSpec::default(), 92*004e86ffSlogin mtime: TimeSpec::default(), 93*004e86ffSlogin ctime: TimeSpec::default(), 94*004e86ffSlogin file_type: FileType::Dir, 95*004e86ffSlogin mode: 0o777, 96*004e86ffSlogin nlinks: 1, 97*004e86ffSlogin uid: 0, 98*004e86ffSlogin gid: 0, 99*004e86ffSlogin raw_dev: 0, 100*004e86ffSlogin }, 101*004e86ffSlogin fs: Weak::default(), 102*004e86ffSlogin }))); 103*004e86ffSlogin 104*004e86ffSlogin let result: Arc<RamFS> = Arc::new(RamFS { root_inode: root }); 105*004e86ffSlogin 106*004e86ffSlogin // 对root inode加锁,并继续完成初始化工作 107*004e86ffSlogin let mut root_guard: SpinLockGuard<RamFSInode> = result.root_inode.0.lock(); 108*004e86ffSlogin root_guard.parent = Arc::downgrade(&result.root_inode); 109*004e86ffSlogin root_guard.self_ref = Arc::downgrade(&result.root_inode); 110*004e86ffSlogin root_guard.fs = Arc::downgrade(&result); 111*004e86ffSlogin // 释放锁 112*004e86ffSlogin drop(root_guard); 113*004e86ffSlogin 114*004e86ffSlogin return result; 115*004e86ffSlogin } 116*004e86ffSlogin } 117*004e86ffSlogin 118*004e86ffSlogin impl IndexNode for LockedRamFSInode { 119*004e86ffSlogin fn read_at( 120*004e86ffSlogin &self, 121*004e86ffSlogin offset: usize, 122*004e86ffSlogin len: usize, 123*004e86ffSlogin buf: &mut [u8], 124*004e86ffSlogin _data: &mut FilePrivateData, 125*004e86ffSlogin ) -> Result<usize, i32> { 126*004e86ffSlogin if buf.len() < len { 127*004e86ffSlogin return Err(-(EINVAL as i32)); 128*004e86ffSlogin } 129*004e86ffSlogin // 加锁 130*004e86ffSlogin let inode: SpinLockGuard<RamFSInode> = self.0.lock(); 131*004e86ffSlogin 132*004e86ffSlogin // 检查当前inode是否为一个文件夹,如果是的话,就返回错误 133*004e86ffSlogin if inode.metadata.file_type == FileType::Dir { 134*004e86ffSlogin return Err(-(EISDIR as i32)); 135*004e86ffSlogin } 136*004e86ffSlogin 137*004e86ffSlogin let start = inode.data.len().min(offset); 138*004e86ffSlogin let end = inode.data.len().min(offset + len); 139*004e86ffSlogin 140*004e86ffSlogin // buffer空间不足 141*004e86ffSlogin if buf.len() < (end - start) { 142*004e86ffSlogin return Err(-(ENOBUFS as i32)); 143*004e86ffSlogin } 144*004e86ffSlogin 145*004e86ffSlogin // 拷贝数据 146*004e86ffSlogin let src = &inode.data[start..end]; 147*004e86ffSlogin buf[0..src.len()].copy_from_slice(src); 148*004e86ffSlogin return Ok(src.len()); 149*004e86ffSlogin } 150*004e86ffSlogin 151*004e86ffSlogin fn write_at( 152*004e86ffSlogin &self, 153*004e86ffSlogin offset: usize, 154*004e86ffSlogin len: usize, 155*004e86ffSlogin buf: &[u8], 156*004e86ffSlogin _data: &mut FilePrivateData, 157*004e86ffSlogin ) -> Result<usize, i32> { 158*004e86ffSlogin if buf.len() < len { 159*004e86ffSlogin return Err(-(EINVAL as i32)); 160*004e86ffSlogin } 161*004e86ffSlogin 162*004e86ffSlogin // 加锁 163*004e86ffSlogin let mut inode: SpinLockGuard<RamFSInode> = self.0.lock(); 164*004e86ffSlogin 165*004e86ffSlogin // 检查当前inode是否为一个文件夹,如果是的话,就返回错误 166*004e86ffSlogin if inode.metadata.file_type == FileType::Dir { 167*004e86ffSlogin return Err(-(EISDIR as i32)); 168*004e86ffSlogin } 169*004e86ffSlogin 170*004e86ffSlogin let data: &mut Vec<u8> = &mut inode.data; 171*004e86ffSlogin 172*004e86ffSlogin // 如果文件大小比原来的大,那就resize这个数组 173*004e86ffSlogin if offset + len > data.len() { 174*004e86ffSlogin data.resize(offset + len, 0); 175*004e86ffSlogin } 176*004e86ffSlogin 177*004e86ffSlogin let target = &mut data[offset..offset + len]; 178*004e86ffSlogin target.copy_from_slice(&buf[0..len]); 179*004e86ffSlogin return Ok(len); 180*004e86ffSlogin } 181*004e86ffSlogin 182*004e86ffSlogin fn poll(&self) -> Result<PollStatus, i32> { 183*004e86ffSlogin // 加锁 184*004e86ffSlogin let inode: SpinLockGuard<RamFSInode> = self.0.lock(); 185*004e86ffSlogin 186*004e86ffSlogin // 检查当前inode是否为一个文件夹,如果是的话,就返回错误 187*004e86ffSlogin if inode.metadata.file_type == FileType::Dir { 188*004e86ffSlogin return Err(-(EISDIR as i32)); 189*004e86ffSlogin } 190*004e86ffSlogin 191*004e86ffSlogin return Ok(PollStatus { 192*004e86ffSlogin flags: PollStatus::READ_MASK | PollStatus::WRITE_MASK, 193*004e86ffSlogin }); 194*004e86ffSlogin } 195*004e86ffSlogin 196*004e86ffSlogin fn fs(&self) -> Arc<dyn FileSystem> { 197*004e86ffSlogin return self.0.lock().fs.upgrade().unwrap(); 198*004e86ffSlogin } 199*004e86ffSlogin 200*004e86ffSlogin fn as_any_ref(&self) -> &dyn core::any::Any { 201*004e86ffSlogin self 202*004e86ffSlogin } 203*004e86ffSlogin 204*004e86ffSlogin fn metadata(&self) -> Result<Metadata, i32> { 205*004e86ffSlogin let inode = self.0.lock(); 206*004e86ffSlogin let mut metadata = inode.metadata.clone(); 207*004e86ffSlogin metadata.size = inode.data.len() as i64; 208*004e86ffSlogin 209*004e86ffSlogin return Ok(metadata); 210*004e86ffSlogin } 211*004e86ffSlogin 212*004e86ffSlogin fn set_metadata(&self, metadata: &Metadata) -> Result<(), i32> { 213*004e86ffSlogin let mut inode = self.0.lock(); 214*004e86ffSlogin inode.metadata.atime = metadata.atime; 215*004e86ffSlogin inode.metadata.mtime = metadata.mtime; 216*004e86ffSlogin inode.metadata.ctime = metadata.ctime; 217*004e86ffSlogin inode.metadata.mode = metadata.mode; 218*004e86ffSlogin inode.metadata.uid = metadata.uid; 219*004e86ffSlogin inode.metadata.gid = metadata.gid; 220*004e86ffSlogin 221*004e86ffSlogin return Ok(()); 222*004e86ffSlogin } 223*004e86ffSlogin 224*004e86ffSlogin fn resize(&self, len: usize) -> Result<(), i32> { 225*004e86ffSlogin let mut inode = self.0.lock(); 226*004e86ffSlogin if inode.metadata.file_type == FileType::File { 227*004e86ffSlogin inode.data.resize(len, 0); 228*004e86ffSlogin return Ok(()); 229*004e86ffSlogin } else { 230*004e86ffSlogin return Err(-(EINVAL as i32)); 231*004e86ffSlogin } 232*004e86ffSlogin } 233*004e86ffSlogin 234*004e86ffSlogin fn create_with_data( 235*004e86ffSlogin &self, 236*004e86ffSlogin name: &str, 237*004e86ffSlogin file_type: FileType, 238*004e86ffSlogin mode: u32, 239*004e86ffSlogin data: usize, 240*004e86ffSlogin ) -> Result<Arc<dyn IndexNode>, i32> { 241*004e86ffSlogin // 获取当前inode 242*004e86ffSlogin let mut inode = self.0.lock(); 243*004e86ffSlogin // 如果当前inode不是文件夹,则返回 244*004e86ffSlogin if inode.metadata.file_type != FileType::Dir { 245*004e86ffSlogin return Err(-(ENOTDIR as i32)); 246*004e86ffSlogin } 247*004e86ffSlogin // 如果有重名的,则返回 248*004e86ffSlogin if inode.children.contains_key(name) { 249*004e86ffSlogin return Err(-(EEXIST as i32)); 250*004e86ffSlogin } 251*004e86ffSlogin 252*004e86ffSlogin // 创建inode 253*004e86ffSlogin let result: Arc<LockedRamFSInode> = Arc::new(LockedRamFSInode(SpinLock::new(RamFSInode { 254*004e86ffSlogin parent: inode.self_ref.clone(), 255*004e86ffSlogin self_ref: Weak::default(), 256*004e86ffSlogin children: BTreeMap::new(), 257*004e86ffSlogin data: Vec::new(), 258*004e86ffSlogin metadata: Metadata { 259*004e86ffSlogin dev_id: 0, 260*004e86ffSlogin inode_id: generate_inode_id(), 261*004e86ffSlogin size: 0, 262*004e86ffSlogin blk_size: 0, 263*004e86ffSlogin blocks: 0, 264*004e86ffSlogin atime: TimeSpec::default(), 265*004e86ffSlogin mtime: TimeSpec::default(), 266*004e86ffSlogin ctime: TimeSpec::default(), 267*004e86ffSlogin file_type: file_type, 268*004e86ffSlogin mode: mode, 269*004e86ffSlogin nlinks: 1, 270*004e86ffSlogin uid: 0, 271*004e86ffSlogin gid: 0, 272*004e86ffSlogin raw_dev: data, 273*004e86ffSlogin }, 274*004e86ffSlogin fs: inode.fs.clone(), 275*004e86ffSlogin }))); 276*004e86ffSlogin 277*004e86ffSlogin // 初始化inode的自引用的weak指针 278*004e86ffSlogin result.0.lock().self_ref = Arc::downgrade(&result); 279*004e86ffSlogin 280*004e86ffSlogin // 将子inode插入父inode的B树中 281*004e86ffSlogin inode.children.insert(String::from(name), result.clone()); 282*004e86ffSlogin 283*004e86ffSlogin return Ok(result); 284*004e86ffSlogin } 285*004e86ffSlogin 286*004e86ffSlogin fn link(&self, name: &str, other: &Arc<dyn IndexNode>) -> Result<(), i32> { 287*004e86ffSlogin let other: &LockedRamFSInode = other 288*004e86ffSlogin .downcast_ref::<LockedRamFSInode>() 289*004e86ffSlogin .ok_or(-(EPERM as i32))?; 290*004e86ffSlogin let mut inode: SpinLockGuard<RamFSInode> = self.0.lock(); 291*004e86ffSlogin let mut other_locked: SpinLockGuard<RamFSInode> = other.0.lock(); 292*004e86ffSlogin 293*004e86ffSlogin // 如果当前inode不是文件夹,那么报错 294*004e86ffSlogin if inode.metadata.file_type != FileType::Dir { 295*004e86ffSlogin return Err(-(ENOTDIR as i32)); 296*004e86ffSlogin } 297*004e86ffSlogin 298*004e86ffSlogin // 如果另一个inode是文件夹,那么也报错 299*004e86ffSlogin if other_locked.metadata.file_type == FileType::Dir { 300*004e86ffSlogin return Err(-(EISDIR as i32)); 301*004e86ffSlogin } 302*004e86ffSlogin 303*004e86ffSlogin // 如果当前文件夹下已经有同名文件,也报错。 304*004e86ffSlogin if inode.children.contains_key(name) { 305*004e86ffSlogin return Err(-(EEXIST as i32)); 306*004e86ffSlogin } 307*004e86ffSlogin 308*004e86ffSlogin inode 309*004e86ffSlogin .children 310*004e86ffSlogin .insert(String::from(name), other_locked.self_ref.upgrade().unwrap()); 311*004e86ffSlogin 312*004e86ffSlogin // 增加硬链接计数 313*004e86ffSlogin other_locked.metadata.nlinks += 1; 314*004e86ffSlogin return Ok(()); 315*004e86ffSlogin } 316*004e86ffSlogin 317*004e86ffSlogin fn unlink(&self, name: &str) -> Result<(), i32> { 318*004e86ffSlogin let mut inode: SpinLockGuard<RamFSInode> = self.0.lock(); 319*004e86ffSlogin // 如果当前inode不是目录,那么也没有子目录/文件的概念了,因此要求当前inode的类型是目录 320*004e86ffSlogin if inode.metadata.file_type != FileType::Dir { 321*004e86ffSlogin return Err(-(ENOTDIR as i32)); 322*004e86ffSlogin } 323*004e86ffSlogin // 不允许删除当前文件夹,也不允许删除上一个目录 324*004e86ffSlogin if name == "." || name == ".." { 325*004e86ffSlogin return Err(-(ENOTEMPTY as i32)); 326*004e86ffSlogin } 327*004e86ffSlogin 328*004e86ffSlogin // 获得要删除的文件的inode 329*004e86ffSlogin let to_delete = inode.children.get(name).ok_or(-(ENOENT as i32))?; 330*004e86ffSlogin if to_delete.0.lock().metadata.file_type == FileType::Dir { 331*004e86ffSlogin return Err(-(EPERM as i32)); 332*004e86ffSlogin } 333*004e86ffSlogin // 减少硬链接计数 334*004e86ffSlogin to_delete.0.lock().metadata.nlinks -= 1; 335*004e86ffSlogin // 在当前目录中删除这个子目录项 336*004e86ffSlogin inode.children.remove(name); 337*004e86ffSlogin return Ok(()); 338*004e86ffSlogin } 339*004e86ffSlogin 340*004e86ffSlogin fn rmdir(&self, name: &str) -> Result<(), i32> { 341*004e86ffSlogin let mut inode: SpinLockGuard<RamFSInode> = self.0.lock(); 342*004e86ffSlogin // 如果当前inode不是目录,那么也没有子目录/文件的概念了,因此要求当前inode的类型是目录 343*004e86ffSlogin if inode.metadata.file_type != FileType::Dir { 344*004e86ffSlogin return Err(-(ENOTDIR as i32)); 345*004e86ffSlogin } 346*004e86ffSlogin // 获得要删除的文件夹的inode 347*004e86ffSlogin let to_delete = inode.children.get(name).ok_or(-(ENOENT as i32))?; 348*004e86ffSlogin if to_delete.0.lock().metadata.file_type != FileType::Dir { 349*004e86ffSlogin return Err(-(ENOTDIR as i32)); 350*004e86ffSlogin } 351*004e86ffSlogin 352*004e86ffSlogin to_delete.0.lock().metadata.nlinks -= 1; 353*004e86ffSlogin // 在当前目录中删除这个子目录项 354*004e86ffSlogin inode.children.remove(name); 355*004e86ffSlogin return Ok(()); 356*004e86ffSlogin } 357*004e86ffSlogin 358*004e86ffSlogin fn move_( 359*004e86ffSlogin &self, 360*004e86ffSlogin old_name: &str, 361*004e86ffSlogin target: &Arc<dyn IndexNode>, 362*004e86ffSlogin new_name: &str, 363*004e86ffSlogin ) -> Result<(), i32> { 364*004e86ffSlogin let old_inode: Arc<dyn IndexNode> = self.find(old_name)?; 365*004e86ffSlogin 366*004e86ffSlogin // 在新的目录下创建一个硬链接 367*004e86ffSlogin target.link(new_name, &old_inode)?; 368*004e86ffSlogin // 取消现有的目录下的这个硬链接 369*004e86ffSlogin if let Err(err) = self.unlink(old_name) { 370*004e86ffSlogin // 如果取消失败,那就取消新的目录下的硬链接 371*004e86ffSlogin target.unlink(new_name)?; 372*004e86ffSlogin return Err(err); 373*004e86ffSlogin } 374*004e86ffSlogin return Ok(()); 375*004e86ffSlogin } 376*004e86ffSlogin 377*004e86ffSlogin fn find(&self, name: &str) -> Result<Arc<dyn IndexNode>, i32> { 378*004e86ffSlogin let inode = self.0.lock(); 379*004e86ffSlogin 380*004e86ffSlogin if inode.metadata.file_type != FileType::Dir { 381*004e86ffSlogin return Err(-(ENOTDIR as i32)); 382*004e86ffSlogin } 383*004e86ffSlogin 384*004e86ffSlogin match name { 385*004e86ffSlogin "" | "." => { 386*004e86ffSlogin return Ok(inode.self_ref.upgrade().ok_or(-(ENOENT as i32))?); 387*004e86ffSlogin } 388*004e86ffSlogin 389*004e86ffSlogin ".." => { 390*004e86ffSlogin return Ok(inode.parent.upgrade().ok_or(-(ENOENT as i32))?); 391*004e86ffSlogin } 392*004e86ffSlogin name => { 393*004e86ffSlogin // 在子目录项中查找 394*004e86ffSlogin return Ok(inode.children.get(name).ok_or(-(ENOENT as i32))?.clone()); 395*004e86ffSlogin } 396*004e86ffSlogin } 397*004e86ffSlogin } 398*004e86ffSlogin 399*004e86ffSlogin fn get_entry_name(&self, ino: InodeId) -> Result<String, i32> { 400*004e86ffSlogin let inode: SpinLockGuard<RamFSInode> = self.0.lock(); 401*004e86ffSlogin if inode.metadata.file_type != FileType::Dir { 402*004e86ffSlogin return Err(-(ENOTDIR as i32)); 403*004e86ffSlogin } 404*004e86ffSlogin 405*004e86ffSlogin match ino { 406*004e86ffSlogin 0 => { 407*004e86ffSlogin return Ok(String::from(".")); 408*004e86ffSlogin } 409*004e86ffSlogin 1 => { 410*004e86ffSlogin return Ok(String::from("..")); 411*004e86ffSlogin } 412*004e86ffSlogin ino => { 413*004e86ffSlogin // 暴力遍历所有的children,判断inode id是否相同 414*004e86ffSlogin // TODO: 优化这里,这个地方性能很差! 415*004e86ffSlogin let mut key: Vec<String> = inode 416*004e86ffSlogin .children 417*004e86ffSlogin .keys() 418*004e86ffSlogin .filter(|k| inode.children.get(*k).unwrap().0.lock().metadata.inode_id == ino) 419*004e86ffSlogin .cloned() 420*004e86ffSlogin .collect(); 421*004e86ffSlogin 422*004e86ffSlogin match key.len() { 423*004e86ffSlogin 0=>{return Err(-(ENOENT as i32));} 424*004e86ffSlogin 1=>{return Ok(key.remove(0));} 425*004e86ffSlogin _ => panic!("Ramfs get_entry_name: key.len()={key_len}>1, current inode_id={inode_id}, to find={to_find}", key_len=key.len(), inode_id = inode.metadata.inode_id, to_find=ino) 426*004e86ffSlogin } 427*004e86ffSlogin } 428*004e86ffSlogin } 429*004e86ffSlogin } 430*004e86ffSlogin 431*004e86ffSlogin fn list(&self) -> Result<Vec<String>, i32> { 432*004e86ffSlogin let info = self.metadata()?; 433*004e86ffSlogin if info.file_type != FileType::Dir { 434*004e86ffSlogin return Err(-(ENOTDIR as i32)); 435*004e86ffSlogin } 436*004e86ffSlogin 437*004e86ffSlogin let mut keys: Vec<String> = Vec::new(); 438*004e86ffSlogin keys.push(String::from(".")); 439*004e86ffSlogin keys.push(String::from("..")); 440*004e86ffSlogin keys.append(&mut self.0.lock().children.keys().cloned().collect()); 441*004e86ffSlogin 442*004e86ffSlogin return Ok(keys); 443*004e86ffSlogin } 444*004e86ffSlogin } 445