diff options
author | Florian Klink <flokli@flokli.de> | 2023-09-03T14·10+0300 |
---|---|---|
committer | clbot <clbot@tvl.fyi> | 2023-09-05T21·13+0000 |
commit | f9b5fc49b123cb4db3941ee2ae9b891f5262deef (patch) | |
tree | 47aa3496ad69b7b4c6010956b90f454da12947c4 /tvix/store/src/fuse/mod.rs | |
parent | da9d706e0a5e4e37087e4841a8fc8edf0da35e77 (diff) |
feat(tvix/store/fuse): allow listing r/6556
This provides an additional configuration flag to the tvix-store mount subcommand, and logic in the fuse module to request listing for the root of the mountpoint. Change-Id: I05a8bc11f7991b574696f27a30afe0f4e718a58c Reviewed-on: https://cl.tvl.fyi/c/depot/+/9217 Autosubmit: flokli <flokli@flokli.de> Reviewed-by: adisbladis <adisbladis@gmail.com> Tested-by: BuildkiteCI
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. |