1use crate::security;
6use crate::task::{CurrentTask, Kernel};
7use crate::vfs::{
8 CacheMode, FileHandle, FileObject, FileOps, FileSystem, FileSystemHandle, FileSystemOps,
9 FileSystemOptions, FsNode, FsNodeInfo, FsNodeOps, FsStr, FsString, fs_node_impl_not_dir,
10};
11use starnix_sync::{FileOpsCore, LockEqualOrBefore, Locked};
12use starnix_types::vfs::default_statfs;
13use starnix_uapi::errors::Errno;
14use starnix_uapi::file_mode::FileMode;
15use starnix_uapi::open_flags::OpenFlags;
16use starnix_uapi::{ANON_INODE_FS_MAGIC, error, statfs};
17
18pub struct Anon {
19 name: Option<&'static str>,
22
23 is_private: bool,
24}
25
26impl FsNodeOps for Anon {
27 fs_node_impl_not_dir!();
28
29 fn create_file_ops(
30 &self,
31 _locked: &mut Locked<FileOpsCore>,
32 _node: &FsNode,
33 _current_task: &CurrentTask,
34 _flags: OpenFlags,
35 ) -> Result<Box<dyn FileOps>, Errno> {
36 error!(ENOSYS)
37 }
38
39 fn internal_name(&self, _node: &FsNode) -> Option<FsString> {
40 self.name.map(|name| format!("anon_inode:{}", name).into())
41 }
42}
43
44impl Anon {
45 pub fn new_for_binder_device() -> Self {
47 Self { name: None, is_private: false }
48 }
49
50 pub fn new_for_socket(kernel_private: bool) -> Self {
52 Self { name: None, is_private: kernel_private }
53 }
54
55 pub fn new_file_extended<L>(
57 locked: &mut Locked<L>,
58 current_task: &CurrentTask,
59 ops: Box<dyn FileOps>,
60 flags: OpenFlags,
61 name: &'static str,
62 info: FsNodeInfo,
63 ) -> Result<FileHandle, Errno>
64 where
65 L: LockEqualOrBefore<FileOpsCore>,
66 {
67 let fs = anon_fs(locked, current_task.kernel());
68 let node =
69 fs.create_node_and_allocate_node_id(Anon { name: Some(name), is_private: false }, info);
70 security::fs_node_init_anon(current_task, &node, name)?;
71 Ok(FileObject::new_anonymous(locked, current_task, ops, node, flags))
72 }
73
74 pub fn new_file<L>(
76 locked: &mut Locked<L>,
77 current_task: &CurrentTask,
78 ops: Box<dyn FileOps>,
79 flags: OpenFlags,
80 name: &'static str,
81 ) -> Result<FileHandle, Errno>
82 where
83 L: LockEqualOrBefore<FileOpsCore>,
84 {
85 Self::new_file_extended(
86 locked,
87 current_task,
88 ops,
89 flags,
90 name,
91 FsNodeInfo::new(FileMode::from_bits(0o600), current_task.current_fscred()),
92 )
93 }
94
95 pub fn new_private_file<L>(
98 locked: &mut Locked<L>,
99 current_task: &CurrentTask,
100 ops: Box<dyn FileOps>,
101 flags: OpenFlags,
102 name: &'static str,
103 ) -> FileHandle
104 where
105 L: LockEqualOrBefore<FileOpsCore>,
106 {
107 Self::new_private_file_extended(
108 locked,
109 current_task,
110 ops,
111 flags,
112 name,
113 FsNodeInfo::new(FileMode::from_bits(0o600), current_task.current_fscred()),
114 )
115 }
116
117 pub fn new_private_file_extended<L>(
119 locked: &mut Locked<L>,
120 current_task: &CurrentTask,
121 ops: Box<dyn FileOps>,
122 flags: OpenFlags,
123 name: &'static str,
124 info: FsNodeInfo,
125 ) -> FileHandle
126 where
127 L: LockEqualOrBefore<FileOpsCore>,
128 {
129 let fs = anon_fs(locked, current_task.kernel());
130 let node =
131 fs.create_node_and_allocate_node_id(Anon { name: Some(name), is_private: true }, info);
132 security::fs_node_init_anon(current_task, &node, name)
133 .expect("Private anon_inode creation cannot fail");
134 FileObject::new_anonymous(locked, current_task, ops, node, flags)
135 }
136
137 pub fn is_private(fs_node: &FsNode) -> bool {
141 fs_node.downcast_ops::<Anon>().map(|anon| anon.is_private).unwrap_or(false)
142 }
143}
144
145struct AnonFs;
146impl FileSystemOps for AnonFs {
147 fn statfs(
148 &self,
149 _locked: &mut Locked<FileOpsCore>,
150 _fs: &FileSystem,
151 _current_task: &CurrentTask,
152 ) -> Result<statfs, Errno> {
153 Ok(default_statfs(ANON_INODE_FS_MAGIC))
154 }
155 fn name(&self) -> &'static FsStr {
156 "anon_inodefs".into()
157 }
158}
159pub fn anon_fs<L>(locked: &mut Locked<L>, kernel: &Kernel) -> FileSystemHandle
160where
161 L: LockEqualOrBefore<FileOpsCore>,
162{
163 struct AnonFsHandle(FileSystemHandle);
164
165 kernel
166 .expando
167 .get_or_init(|| {
168 let fs = FileSystem::new(
169 locked,
170 kernel,
171 CacheMode::Uncached,
172 AnonFs,
173 FileSystemOptions::default(),
174 )
175 .expect("anonfs constructed with valid options");
176 AnonFsHandle(fs)
177 })
178 .0
179 .clone()
180}