starnix_core/vfs/
symlink_node.rs

1// Copyright 2021 The Fuchsia Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5use crate::task::CurrentTask;
6use crate::vfs::{
7    FsNode, FsNodeInfo, FsNodeOps, FsStr, FsString, MemoryXattrStorage, SymlinkTarget,
8    XattrStorage as _, fs_node_impl_symlink, fs_node_impl_xattr_delegate,
9};
10use starnix_sync::{FileOpsCore, Locked};
11use starnix_uapi::auth::FsCred;
12use starnix_uapi::errors::Errno;
13use starnix_uapi::file_mode::mode;
14
15/// A node that represents a symlink to another node.
16pub struct SymlinkNode {
17    /// The target of the symlink (the path to use to find the actual node).
18    target: FsString,
19    xattrs: MemoryXattrStorage,
20}
21
22impl SymlinkNode {
23    pub fn new(target: &FsStr, owner: FsCred) -> (Self, FsNodeInfo) {
24        let size = target.len();
25        let mut info = FsNodeInfo::new(mode!(IFLNK, 0o777), owner);
26        info.size = size;
27        (Self { target: target.to_owned(), xattrs: Default::default() }, info)
28    }
29}
30
31impl FsNodeOps for SymlinkNode {
32    fs_node_impl_symlink!();
33    fs_node_impl_xattr_delegate!(self, self.xattrs);
34
35    fn readlink(
36        &self,
37        _locked: &mut Locked<FileOpsCore>,
38        _node: &FsNode,
39        _current_task: &CurrentTask,
40    ) -> Result<SymlinkTarget, Errno> {
41        Ok(SymlinkTarget::Path(self.target.clone()))
42    }
43}
44
45/// A SymlinkNode that uses a callback.
46pub struct CallbackSymlinkNode<F>
47where
48    F: Fn() -> Result<SymlinkTarget, Errno> + Send + Sync + 'static,
49{
50    callback: F,
51    xattrs: MemoryXattrStorage,
52}
53
54impl<F> CallbackSymlinkNode<F>
55where
56    F: Fn() -> Result<SymlinkTarget, Errno> + Send + Sync + 'static,
57{
58    pub fn new(callback: F) -> CallbackSymlinkNode<F> {
59        CallbackSymlinkNode { callback, xattrs: Default::default() }
60    }
61}
62
63impl<F> FsNodeOps for CallbackSymlinkNode<F>
64where
65    F: Fn() -> Result<SymlinkTarget, Errno> + Send + Sync + 'static,
66{
67    fs_node_impl_symlink!();
68    fs_node_impl_xattr_delegate!(self, self.xattrs);
69
70    fn readlink(
71        &self,
72        _locked: &mut Locked<FileOpsCore>,
73        _node: &FsNode,
74        _current_task: &CurrentTask,
75    ) -> Result<SymlinkTarget, Errno> {
76        (self.callback)()
77    }
78}