Skip to main content

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_uapi::auth::FsCred;
11use starnix_uapi::errors::Errno;
12use starnix_uapi::file_mode::mode;
13
14/// A node that represents a symlink to another node.
15pub struct SymlinkNode {
16    /// The target of the symlink (the path to use to find the actual node).
17    target: FsString,
18    xattrs: MemoryXattrStorage,
19}
20
21impl SymlinkNode {
22    pub fn new(target: &FsStr, owner: FsCred) -> (Self, FsNodeInfo) {
23        let size = target.len();
24        let mut info = FsNodeInfo::new(mode!(IFLNK, 0o777), owner);
25        info.size = size;
26        (Self { target: target.to_owned(), xattrs: Default::default() }, info)
27    }
28}
29
30impl FsNodeOps for SymlinkNode {
31    fs_node_impl_symlink!();
32    fs_node_impl_xattr_delegate!(self, self.xattrs);
33
34    fn readlink(
35        &self,
36        _node: &FsNode,
37        _current_task: &CurrentTask,
38    ) -> Result<SymlinkTarget, Errno> {
39        Ok(SymlinkTarget::Path(self.target.clone()))
40    }
41}
42
43/// A SymlinkNode that uses a callback.
44pub struct CallbackSymlinkNode<F>
45where
46    F: Fn() -> Result<SymlinkTarget, Errno> + Send + Sync + 'static,
47{
48    callback: F,
49    xattrs: MemoryXattrStorage,
50}
51
52impl<F> CallbackSymlinkNode<F>
53where
54    F: Fn() -> Result<SymlinkTarget, Errno> + Send + Sync + 'static,
55{
56    pub fn new(callback: F) -> CallbackSymlinkNode<F> {
57        CallbackSymlinkNode { callback, xattrs: Default::default() }
58    }
59}
60
61impl<F> FsNodeOps for CallbackSymlinkNode<F>
62where
63    F: Fn() -> Result<SymlinkTarget, Errno> + Send + Sync + 'static,
64{
65    fs_node_impl_symlink!();
66    fs_node_impl_xattr_delegate!(self, self.xattrs);
67
68    fn readlink(
69        &self,
70        _node: &FsNode,
71        _current_task: &CurrentTask,
72    ) -> Result<SymlinkTarget, Errno> {
73        (self.callback)()
74    }
75}