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 storage_trace::duration!(
49 "storage",
50 "ErofsSymlink::get_attributes",
51 "nid" => self.node.nid()
52 );
53 let mtime = self.node.mtime_ns();
54 let content_size = self.target.len() as u64;
55 let selinux_context = self
56 .volume
57 .fs()
58 .get_xattr(&self.node, b"security.selinux")
59 .ok()
60 .flatten()
61 .map(fio::SelinuxContext::Data);
62 Ok(vfs::attributes!(
63 requested_attributes,
64 Mutable {
65 mode: self.node.mode() as u32,
66 uid: self.node.uid(),
67 gid: self.node.gid(),
68 creation_time: mtime,
69 modification_time: mtime,
70 access_time: mtime,
71 selinux_context: selinux_context,
72 },
73 Immutable {
74 protocols: fio::NodeProtocolKinds::SYMLINK,
75 abilities: fio::Operations::GET_ATTRIBUTES,
76 content_size: content_size,
77 storage_size: content_size,
78 id: self.node.nid(),
79 link_count: self.node.link_count() as u64,
80 change_time: mtime,
81 }
82 ))
83 }
84
85 async fn list_extended_attributes(&self) -> Result<Vec<Vec<u8>>, zx::Status> {
86 self.volume.fs().list_xattrs(&self.node).map_err(|e| e.to_status())
87 }
88
89 async fn get_extended_attribute(&self, name: Vec<u8>) -> Result<Vec<u8>, zx::Status> {
90 self.volume
91 .fs()
92 .get_xattr(&self.node, &name)
93 .map_err(|e| e.to_status())?
94 .ok_or(zx::Status::NOT_FOUND)
95 }
96}
97
98impl Symlink for ErofsSymlink {
99 async fn read_target(&self) -> Result<Vec<u8>, zx::Status> {
100 Ok(self.target.clone())
101 }
102}