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