diff options
Diffstat (limited to 'tvix/store/src/fuse/mod.rs')
-rw-r--r-- | tvix/store/src/fuse/mod.rs | 57 |
1 files changed, 55 insertions, 2 deletions
diff --git a/tvix/store/src/fuse/mod.rs b/tvix/store/src/fuse/mod.rs index 8b44f7db550e..0015abb9d557 100644 --- a/tvix/store/src/fuse/mod.rs +++ b/tvix/store/src/fuse/mod.rs @@ -66,6 +66,9 @@ pub struct FUSE { directory_service: Arc<dyn DirectoryService>, path_info_service: Arc<dyn PathInfoService>, + /// Whether to (try) listing elements in the root. + list_root: bool, + /// This maps a given StorePath to the inode we allocated for the root inode. store_paths: HashMap<StorePath, u64>, @@ -83,12 +86,15 @@ impl FUSE { blob_service: Arc<dyn BlobService>, directory_service: Arc<dyn DirectoryService>, path_info_service: Arc<dyn PathInfoService>, + list_root: bool, ) -> Self { Self { blob_service, directory_service, path_info_service, + list_root, + store_paths: HashMap::default(), inode_tracker: Default::default(), @@ -311,8 +317,55 @@ impl fuser::Filesystem for FUSE { debug!("readdir"); if ino == fuser::FUSE_ROOT_ID { - reply.error(libc::EPERM); // same error code as ipfs/kubo - return; + if !self.list_root { + reply.error(libc::EPERM); // same error code as ipfs/kubo + return; + } else { + for (i, path_info) in self + .path_info_service + .list() + .skip(offset as usize) + .enumerate() + { + let path_info = match path_info { + Err(e) => { + warn!("failed to retrieve pathinfo: {}", e); + reply.error(libc::EPERM); + return; + } + Ok(path_info) => path_info, + }; + + // We know the root node exists and the store_path can be parsed because clients MUST validate. + let root_node = path_info.node.unwrap().node.unwrap(); + let store_path = StorePath::from_bytes(root_node.get_name()).unwrap(); + + let ino = match self.store_paths.get(&store_path) { + Some(ino) => *ino, + None => { + // insert the (sparse) inode data and register in + // self.store_paths. + let ino = self.inode_tracker.put((&root_node).into()); + self.store_paths.insert(store_path.clone(), ino); + ino + } + }; + + let ty = match root_node { + Node::Directory(_) => fuser::FileType::Directory, + Node::File(_) => fuser::FileType::RegularFile, + Node::Symlink(_) => fuser::FileType::Symlink, + }; + + let full = + reply.add(ino, offset + i as i64 + 1_i64, ty, store_path.to_string()); + if full { + break; + } + } + reply.ok(); + return; + } } // lookup the inode data. |