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