xref: /DragonOS/kernel/src/filesystem/sysfs/dir.rs (revision fae6e9ade46a52976ad5d099643d51cc20876448)
1 #![allow(dead_code)]
2 use alloc::{
3     string::{String, ToString},
4     sync::{Arc, Weak},
5     vec::Vec,
6 };
7 use system_error::SystemError;
8 
9 use crate::{
10     driver::base::kobject::KObject,
11     filesystem::{
12         kernfs::{callback::KernInodePrivateData, KernFSInode},
13         vfs::syscall::ModeType,
14     },
15 };
16 
17 use super::{SysFS, SysFSKernPrivateData};
18 
19 #[derive(Debug)]
20 pub struct SysKernDirPriv {
21     /// 该目录对应的kobject
22     /// use weak reference to avoid cyclic reference
23     kobj: Weak<dyn KObject>,
24     // attribute_group: Option<&'static dyn AttributeGroup>,
25 }
26 
27 impl SysKernDirPriv {
28     pub fn new(kobj: Arc<dyn KObject>) -> Self {
29         // let attribute_group = kobj.kobj_type().map(|kobj_type| kobj_type.attribute_groups()).flatten();
30         Self {
31             kobj: Arc::downgrade(&kobj),
32             // attribute_group,
33         }
34     }
35 
36     pub fn kobj(&self) -> Option<Arc<dyn KObject>> {
37         self.kobj.upgrade()
38     }
39 
40     // pub fn attribute_group(&self) -> Option<&'static dyn AttributeGroup> {
41     //     self.attribute_group
42     // }
43 }
44 
45 impl SysFS {
46     /// 在sysfs中创建一个目录
47     ///
48     /// 如果kobj的parent为None,则会在根目录下创建一个目录。
49     ///
50     /// ## 参数
51     ///
52     /// - `kobj`: 要创建的目录对应的kobject
53     ///
54     /// ## 返回
55     ///
56     /// 返回创建的目录对应的inode
57     pub fn create_dir(&self, kobj: Arc<dyn KObject>) -> Result<Arc<KernFSInode>, SystemError> {
58         // 如果kobj的parent为None,则会在/sys目录下创建一个目录。
59         let parent = kobj
60             .parent()
61             .map(|p| p.upgrade().unwrap().inode())
62             .unwrap_or_else(|| Some(self.root_inode.clone()))
63             .ok_or(SystemError::ENOENT)?;
64 
65         let sysfs_dir_priv = SysFSKernPrivateData::Dir(SysKernDirPriv::new(kobj.clone()));
66         // 在kernfs里面创建一个目录
67         let dir: Arc<KernFSInode> = parent.add_dir(
68             kobj.name(),
69             ModeType::from_bits_truncate(0o755),
70             Some(KernInodePrivateData::SysFS(sysfs_dir_priv)),
71             None,
72         )?;
73 
74         kobj.set_inode(Some(dir.clone()));
75 
76         return Ok(dir);
77     }
78 
79     /// 获取指定的kernfs inode在sysfs中的路径(不包含`/sys`)
80     ///
81     /// ## 参数
82     ///
83     /// - `parent`: inode的父目录
84     /// - `name`: inode的名称
85     ///
86     /// ## 返回
87     ///
88     /// 返回inode在sysfs中的路径
89     pub(super) fn kernfs_path(&self, parent: &Arc<KernFSInode>) -> String {
90         let mut p = parent.clone();
91         let mut parts = Vec::new();
92         let sys_root_inode = self.root_inode();
93         let mut not_reach_sys_root = false;
94         while !Arc::ptr_eq(&p, sys_root_inode) {
95             parts.push(p.name().to_string());
96             if let Some(parent) = p.parent() {
97                 p = parent;
98             } else {
99                 not_reach_sys_root = true;
100                 break;
101             }
102         }
103 
104         let mut path = String::new();
105         if not_reach_sys_root {
106             path.push_str("(null)");
107         };
108 
109         for part in parts.iter().rev() {
110             path.push('/');
111             path.push_str(part);
112         }
113 
114         return path;
115     }
116 
117     /// 从sysfs中删除一个kobject对应的目录(包括目录自身以及目录下的所有文件、文件夹)
118     pub fn remove_dir(&self, kobj: &Arc<dyn KObject>) {
119         let kobj_inode = kobj.inode();
120         kobj.set_inode(None);
121 
122         if let Some(inode) = kobj_inode {
123             let parent = inode.parent().unwrap();
124             parent.remove_recursive()
125         }
126     }
127 }
128