erofs_component/
symlink.rs1use crate::volume::ErofsVolume;
6use erofs::SymlinkNode;
7use fidl_fuchsia_io as fio;
8use std::sync::Arc;
9use vfs::directory::entry::{DirectoryEntry, EntryInfo, GetEntryInfo, OpenRequest};
10use vfs::node::Node;
11use vfs::symlink::Symlink;
12
13pub struct ErofsSymlink {
15 volume: Arc<ErofsVolume>,
16 node: SymlinkNode,
17 target: Vec<u8>,
18}
19
20impl ErofsSymlink {
21 pub fn new(volume: Arc<ErofsVolume>, node: SymlinkNode) -> Result<Arc<Self>, zx::Status> {
22 let target = volume.fs().read_symlink(&node).map_err(|e| e.to_status())?;
23 Ok(Arc::new(Self { volume, node, target }))
24 }
25
26 pub fn node(&self) -> &SymlinkNode {
27 &self.node
28 }
29}
30
31impl GetEntryInfo for ErofsSymlink {
32 fn entry_info(&self) -> EntryInfo {
33 EntryInfo::new(self.node.nid(), fio::DirentType::Symlink)
34 }
35}
36
37impl DirectoryEntry for ErofsSymlink {
38 fn open_entry(self: Arc<Self>, request: OpenRequest<'_>) -> Result<(), zx::Status> {
39 request.open_symlink(self)
40 }
41}
42
43impl Node for ErofsSymlink {
44 async fn get_attributes(
45 &self,
46 requested_attributes: fio::NodeAttributesQuery,
47 ) -> Result<fio::NodeAttributes2, zx::Status> {
48 let mtime = self.node.mtime_ns();
49 let content_size = self.target.len() as u64;
50 let selinux_context = self
51 .volume
52 .fs()
53 .get_xattr(&self.node, b"security.selinux")
54 .ok()
55 .flatten()
56 .map(fio::SelinuxContext::Data);
57 Ok(vfs::attributes!(
58 requested_attributes,
59 Mutable {
60 mode: self.node.mode() as u32,
61 uid: self.node.uid(),
62 gid: self.node.gid(),
63 creation_time: mtime,
64 modification_time: mtime,
65 access_time: mtime,
66 selinux_context: selinux_context,
67 },
68 Immutable {
69 protocols: fio::NodeProtocolKinds::SYMLINK,
70 abilities: fio::Operations::GET_ATTRIBUTES,
71 content_size: content_size,
72 storage_size: content_size,
73 id: self.node.nid(),
74 link_count: self.node.link_count() as u64,
75 change_time: mtime,
76 }
77 ))
78 }
79
80 async fn list_extended_attributes(&self) -> Result<Vec<Vec<u8>>, zx::Status> {
81 self.volume.fs().list_xattrs(&self.node).map_err(|e| e.to_status())
82 }
83
84 async fn get_extended_attribute(&self, name: Vec<u8>) -> Result<Vec<u8>, zx::Status> {
85 self.volume
86 .fs()
87 .get_xattr(&self.node, &name)
88 .map_err(|e| e.to_status())?
89 .ok_or(zx::Status::NOT_FOUND)
90 }
91}
92
93impl Symlink for ErofsSymlink {
94 async fn read_target(&self) -> Result<Vec<u8>, zx::Status> {
95 Ok(self.target.clone())
96 }
97}