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_types::vfs::default_statfs;
13use starnix_uapi::auth::FsCred;
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
21impl FsNodeOps for Anon {
22 fs_node_impl_not_dir!();
23
24 fn create_file_ops(
25 &self,
26 _node: &FsNode,
27 _current_task: &CurrentTask,
28 _flags: OpenFlags,
29 ) -> Result<Box<dyn FileOps>, Errno> {
30 error!(ENOSYS)
31 }
32}
33
34impl Anon {
35 pub fn new_for_binder_device() -> Self {
37 Self {}
38 }
39
40 pub fn new_for_socket() -> Self {
42 Self {}
43 }
44
45 pub fn new_file_extended(
47 current_task: &CurrentTask,
48 ops: Box<dyn FileOps>,
49 flags: OpenFlags,
50 name: &'static str,
51 info: FsNodeInfo,
52 ) -> Result<FileHandle, Errno> {
53 Self::new_file_internal(current_task, ops, flags, name, info, FsNodeFlags::empty())
54 }
55
56 pub fn new_file(
58 current_task: &CurrentTask,
59 ops: Box<dyn FileOps>,
60 flags: OpenFlags,
61 name: &'static str,
62 ) -> Result<FileHandle, Errno> {
63 Self::new_file_extended(
64 current_task,
65 ops,
66 flags,
67 name,
68 FsNodeInfo::new(FileMode::from_bits(0o600), current_task.current_fscred()),
69 )
70 }
71
72 pub fn new_private_file(
75 current_task: &CurrentTask,
76 ops: Box<dyn FileOps>,
77 flags: OpenFlags,
78 name: &'static str,
79 ) -> FileHandle {
80 let node = shared_private_node(current_task);
81 security::fs_node_init_anon(current_task, &node, name)
82 .expect("Private anon_inode creation cannot fail");
83 let name = NamespaceNode::new_anonymous(DirEntry::new(node, None, name.into()));
84 FileObject::new(current_task, ops, name, flags).unwrap()
85 }
86
87 pub fn new_private_file_extended(
90 current_task: &CurrentTask,
91 ops: Box<dyn FileOps>,
92 flags: OpenFlags,
93 name: &'static str,
94 info: FsNodeInfo,
95 ) -> FileHandle {
96 Self::new_file_internal(current_task, ops, flags, name, info, FsNodeFlags::IS_PRIVATE)
97 .expect("Private anon_inode creation cannot fail")
98 }
99
100 fn new_file_internal(
101 current_task: &CurrentTask,
102 ops: Box<dyn FileOps>,
103 flags: OpenFlags,
104 name: &'static str,
105 info: FsNodeInfo,
106 node_flags: FsNodeFlags,
107 ) -> Result<FileHandle, Errno> {
108 let fs = anon_fs(current_task.kernel());
109 let node = fs.create_node_with_flags(None, Anon {}, info, node_flags);
110 security::fs_node_init_anon(current_task, &node, name)?;
111 let name = NamespaceNode::new_anonymous(DirEntry::new(node, None, name.into()));
112 FileObject::new(current_task, ops, name, flags)
113 }
114}
115
116struct AnonFs;
117impl FileSystemOps for AnonFs {
118 fn statfs(&self, _fs: &FileSystem, _current_task: &CurrentTask) -> Result<statfs, Errno> {
119 Ok(default_statfs(ANON_INODE_FS_MAGIC))
120 }
121 fn name(&self) -> &'static FsStr {
122 "anon_inodefs".into()
123 }
124}
125
126pub fn anon_fs(kernel: &Kernel) -> FileSystemHandle {
127 struct AnonFsHandle(FileSystemHandle);
128
129 kernel
130 .expando
131 .get_or_init(|| {
132 let fs =
133 FileSystem::new(kernel, CacheMode::Uncached, AnonFs, FileSystemOptions::default())
134 .expect("anonfs constructed with valid options");
135 AnonFsHandle(fs)
136 })
137 .0
138 .clone()
139}
140
141fn shared_private_node(current_task: &CurrentTask) -> FsNodeHandle {
142 struct CommonAnonFsNodeHandle(FsNodeHandle);
143
144 let fs = anon_fs(current_task.kernel());
145
146 current_task
147 .kernel()
148 .expando
149 .get_or_init(|| {
150 let info = FsNodeInfo::new(FileMode::from_bits(0o600), FsCred::root());
151 let node = fs.create_node_with_flags(None, Anon {}, info, FsNodeFlags::IS_PRIVATE);
152 CommonAnonFsNodeHandle(node)
153 })
154 .0
155 .clone()
156}