1use crate::security;
6use crate::task::{CurrentTask, Kernel};
7use crate::vfs::{
8 CacheMode, DirEntry, FileHandle, FileObject, FileOps, FileSystem, FileSystemHandle,
9 FileSystemOps, FileSystemOptions, FsNode, FsNodeFlags, FsNodeHandle, FsNodeInfo, FsNodeOps,
10 FsStr, NamespaceNode, fs_node_impl_not_dir,
11};
12use starnix_sync::{FileOpsCore, LockEqualOrBefore, Locked};
13use starnix_types::vfs::default_statfs;
14use starnix_uapi::auth::FsCred;
15use starnix_uapi::errors::Errno;
16use starnix_uapi::file_mode::FileMode;
17use starnix_uapi::open_flags::OpenFlags;
18use starnix_uapi::{ANON_INODE_FS_MAGIC, error, statfs};
19
20pub struct Anon {}
21
22impl FsNodeOps for Anon {
23 fs_node_impl_not_dir!();
24
25 fn create_file_ops(
26 &self,
27 _locked: &mut Locked<FileOpsCore>,
28 _node: &FsNode,
29 _current_task: &CurrentTask,
30 _flags: OpenFlags,
31 ) -> Result<Box<dyn FileOps>, Errno> {
32 error!(ENOSYS)
33 }
34}
35
36impl Anon {
37 pub fn new_for_binder_device() -> Self {
39 Self {}
40 }
41
42 pub fn new_for_socket() -> Self {
44 Self {}
45 }
46
47 pub fn new_file_extended<L>(
49 locked: &mut Locked<L>,
50 current_task: &CurrentTask,
51 ops: Box<dyn FileOps>,
52 flags: OpenFlags,
53 name: &'static str,
54 info: FsNodeInfo,
55 ) -> Result<FileHandle, Errno>
56 where
57 L: LockEqualOrBefore<FileOpsCore>,
58 {
59 Self::new_file_internal(locked, current_task, ops, flags, name, info, FsNodeFlags::empty())
60 }
61
62 pub fn new_file<L>(
64 locked: &mut Locked<L>,
65 current_task: &CurrentTask,
66 ops: Box<dyn FileOps>,
67 flags: OpenFlags,
68 name: &'static str,
69 ) -> Result<FileHandle, Errno>
70 where
71 L: LockEqualOrBefore<FileOpsCore>,
72 {
73 Self::new_file_extended(
74 locked,
75 current_task,
76 ops,
77 flags,
78 name,
79 FsNodeInfo::new(FileMode::from_bits(0o600), current_task.current_fscred()),
80 )
81 }
82
83 pub fn new_private_file<L>(
86 locked: &mut Locked<L>,
87 current_task: &CurrentTask,
88 ops: Box<dyn FileOps>,
89 flags: OpenFlags,
90 name: &'static str,
91 ) -> FileHandle
92 where
93 L: LockEqualOrBefore<FileOpsCore>,
94 {
95 let node = shared_private_node(locked, current_task);
96 security::fs_node_init_anon(current_task, &node, name)
97 .expect("Private anon_inode creation cannot fail");
98 let name = NamespaceNode::new_anonymous(DirEntry::new(node, None, name.into()));
99 FileObject::new(locked, current_task, ops, name, flags).unwrap()
100 }
101
102 pub fn new_private_file_extended<L>(
105 locked: &mut Locked<L>,
106 current_task: &CurrentTask,
107 ops: Box<dyn FileOps>,
108 flags: OpenFlags,
109 name: &'static str,
110 info: FsNodeInfo,
111 ) -> FileHandle
112 where
113 L: LockEqualOrBefore<FileOpsCore>,
114 {
115 Self::new_file_internal(
116 locked,
117 current_task,
118 ops,
119 flags,
120 name,
121 info,
122 FsNodeFlags::IS_PRIVATE,
123 )
124 .expect("Private anon_inode creation cannot fail")
125 }
126
127 fn new_file_internal<L>(
128 locked: &mut Locked<L>,
129 current_task: &CurrentTask,
130 ops: Box<dyn FileOps>,
131 flags: OpenFlags,
132 name: &'static str,
133 info: FsNodeInfo,
134 node_flags: FsNodeFlags,
135 ) -> Result<FileHandle, Errno>
136 where
137 L: LockEqualOrBefore<FileOpsCore>,
138 {
139 let fs = anon_fs(locked, current_task.kernel());
140 let node = fs.create_node_with_flags(None, Anon {}, info, node_flags);
141 security::fs_node_init_anon(current_task, &node, name)?;
142 let name = NamespaceNode::new_anonymous(DirEntry::new(node, None, name.into()));
143 FileObject::new(locked, current_task, ops, name, flags)
144 }
145}
146
147struct AnonFs;
148impl FileSystemOps for AnonFs {
149 fn statfs(
150 &self,
151 _locked: &mut Locked<FileOpsCore>,
152 _fs: &FileSystem,
153 _current_task: &CurrentTask,
154 ) -> Result<statfs, Errno> {
155 Ok(default_statfs(ANON_INODE_FS_MAGIC))
156 }
157 fn name(&self) -> &'static FsStr {
158 "anon_inodefs".into()
159 }
160}
161
162pub fn anon_fs<L>(locked: &mut Locked<L>, kernel: &Kernel) -> FileSystemHandle
163where
164 L: LockEqualOrBefore<FileOpsCore>,
165{
166 struct AnonFsHandle(FileSystemHandle);
167
168 kernel
169 .expando
170 .get_or_init(|| {
171 let fs = FileSystem::new(
172 locked,
173 kernel,
174 CacheMode::Uncached,
175 AnonFs,
176 FileSystemOptions::default(),
177 )
178 .expect("anonfs constructed with valid options");
179 AnonFsHandle(fs)
180 })
181 .0
182 .clone()
183}
184
185fn shared_private_node<L>(locked: &mut Locked<L>, current_task: &CurrentTask) -> FsNodeHandle
186where
187 L: LockEqualOrBefore<FileOpsCore>,
188{
189 struct CommonAnonFsNodeHandle(FsNodeHandle);
190
191 let fs = anon_fs(locked, current_task.kernel());
192
193 current_task
194 .kernel()
195 .expando
196 .get_or_init(|| {
197 let info = FsNodeInfo::new(FileMode::from_bits(0o600), FsCred::root());
198 let node = fs.create_node_with_flags(None, Anon {}, info, FsNodeFlags::IS_PRIVATE);
199 CommonAnonFsNodeHandle(node)
200 })
201 .0
202 .clone()
203}