xref: /DragonOS/kernel/src/filesystem/sysfs/symlink.rs (revision c75089286e9d49cef8d039446bf570c1bd4d2550)
1 use alloc::{
2     borrow::ToOwned,
3     string::{String, ToString},
4     sync::Arc,
5 };
6 
7 use crate::{
8     driver::base::kobject::KObject, filesystem::kernfs::KernFSInode, syscall::SystemError,
9 };
10 
11 use super::SysFS;
12 
13 impl SysFS {
14     /// 在sysfs中创建一个符号链接
15     ///
16     /// ## 参数
17     ///
18     /// - `kobj`: object whose directory we're creating the link in. (符号链接所在目录)
19     ///    如果为None,则创建在sysfs的根目录下
20     /// - `target`: object we're pointing to.
21     /// - `name`: 符号链接的名称
22     ///
23     /// 参考:https://opengrok.ringotek.cn/xref/linux-6.1.9/fs/sysfs/symlink.c#89
24     pub fn create_link(
25         &self,
26         kobj: Option<&Arc<dyn KObject>>,
27         target: &Arc<dyn KObject>,
28         name: String,
29     ) -> Result<(), SystemError> {
30         return self.do_create_link(kobj, target, name, true);
31     }
32 
33     /// 在sysfs中删除一个符号链接
34     ///
35     /// ## 参数
36     ///
37     /// - `kobj`: 要删除符号链接的kobject(符号链接所在目录)
38     /// - `name`: 符号链接的名称
39     ///
40     ///
41     /// 参考:https://opengrok.ringotek.cn/xref/linux-6.1.9/fs/sysfs/symlink.c#143
42     pub fn remove_link(&self, _kobj: &Arc<dyn KObject>, _name: String) {
43         todo!("sysfs remove link")
44     }
45 
46     fn do_create_link(
47         &self,
48         kobj: Option<&Arc<dyn KObject>>,
49         target: &Arc<dyn KObject>,
50         name: String,
51         warn: bool,
52     ) -> Result<(), SystemError> {
53         let parent = if let Some(kobj) = kobj {
54             kobj.inode()
55         } else {
56             Some(self.root_inode().clone())
57         };
58 
59         // 没有parent,返回错误
60         let parent = parent.ok_or(SystemError::EFAULT)?;
61         return self.do_create_link_sd(&parent, target, name, warn);
62     }
63 
64     /// 参考 https://opengrok.ringotek.cn/xref/linux-6.1.9/fs/sysfs/symlink.c#20
65     fn do_create_link_sd(
66         &self,
67         inode: &Arc<KernFSInode>,
68         target: &Arc<dyn KObject>,
69         name: String,
70         warn: bool,
71     ) -> Result<(), SystemError> {
72         let target_inode = target.inode().ok_or(SystemError::ENOENT)?;
73 
74         let target_abs_path = "/sys".to_string() + &self.kernfs_path(&target_inode).to_owned();
75         // let current_path = self.kernfs_path(inode);
76         // kdebug!("sysfs: create link {} to {}", current_path, target_abs_path);
77 
78         let kn = inode.add_link(name.clone(), &target_inode, target_abs_path);
79         if kn.is_ok() {
80             return Ok(());
81         }
82         let err = kn.unwrap_err();
83         if warn && err == SystemError::EEXIST {
84             self.warn_duplicate(inode, &name);
85         }
86         return Err(err);
87     }
88 
89     /// sysfs_create_link_sd - create symlink to a given object.
90     ///
91     /// ## 参数
92     ///
93     /// - `inode`: 目录inode,在这个目录下创建符号链接
94     /// - `target`: object we're pointing to.
95     /// - `name`: 符号链接的名称
96     #[allow(dead_code)]
97     pub(super) fn create_link_sd(
98         &self,
99         inode: &Arc<KernFSInode>,
100         target: &Arc<dyn KObject>,
101         name: String,
102     ) -> Result<(), SystemError> {
103         return self.do_create_link_sd(inode, target, name, true);
104     }
105 }
106