starnix_core/vfs/
anon_node.rs1use 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 let fs = anon_fs(current_task.kernel());
54 let node = fs.create_node_with_flags(None, Anon {}, info, FsNodeFlags::empty());
55 security::fs_node_init_anon(current_task, &node, name)?;
56 let name = NamespaceNode::new_anonymous(DirEntry::new(node, None, name.into()));
57 FileObject::new(current_task, ops, name, flags)
58 }
59
60 pub fn new_file(
62 current_task: &CurrentTask,
63 ops: Box<dyn FileOps>,
64 flags: OpenFlags,
65 name: &'static str,
66 ) -> Result<FileHandle, Errno> {
67 Self::new_file_extended(
68 current_task,
69 ops,
70 flags,
71 name,
72 FsNodeInfo::new(FileMode::from_bits(0o600), current_task.current_fscred()),
73 )
74 }
75
76 pub fn new_private_file(
79 current_task: &CurrentTask,
80 ops: Box<dyn FileOps>,
81 flags: OpenFlags,
82 name: &'static str,
83 ) -> FileHandle {
84 let node = shared_private_node(current_task);
85 security::fs_node_init_anon(current_task, &node, name)
86 .expect("Private anon_inode creation cannot fail");
87 let name = NamespaceNode::new_anonymous(DirEntry::new(node, None, name.into()));
88 FileObject::new(current_task, ops, name, flags).unwrap()
89 }
90}
91
92struct AnonFs;
93impl FileSystemOps for AnonFs {
94 fn statfs(&self, _fs: &FileSystem, _current_task: &CurrentTask) -> Result<statfs, Errno> {
95 Ok(default_statfs(ANON_INODE_FS_MAGIC))
96 }
97 fn name(&self) -> &'static FsStr {
98 "anon_inodefs".into()
99 }
100}
101
102pub fn anon_fs(kernel: &Kernel) -> FileSystemHandle {
103 struct AnonFsHandle(FileSystemHandle);
104
105 kernel
106 .expando
107 .get_or_init(|| {
108 let fs =
109 FileSystem::new(kernel, CacheMode::Uncached, AnonFs, FileSystemOptions::default())
110 .expect("anonfs constructed with valid options");
111 AnonFsHandle(fs)
112 })
113 .0
114 .clone()
115}
116
117fn shared_private_node(current_task: &CurrentTask) -> FsNodeHandle {
118 struct CommonAnonFsNodeHandle(FsNodeHandle);
119
120 let fs = anon_fs(current_task.kernel());
121
122 current_task
123 .kernel()
124 .expando
125 .get_or_init(|| {
126 let info = FsNodeInfo::new(FileMode::from_bits(0o600), FsCred::root());
127 let node = fs.create_node_with_flags(None, Anon {}, info, FsNodeFlags::IS_PRIVATE);
128 CommonAnonFsNodeHandle(node)
129 })
130 .0
131 .clone()
132}