1#[non_exhaustive]
5pub struct FileSystemInfo;
6
7#[allow(dead_code)]
9#[derive(Debug, Clone, Copy)]
10pub struct VfsNodeAttr {
11 mode: VfsNodePerm,
13 ty: VfsNodeType,
15 size: u64,
17 blocks: u64,
19}
20
21bitflags::bitflags! {
22 #[derive(Debug, Clone, Copy)]
24 pub struct VfsNodePerm: u16 {
25 const OWNER_READ = 0o400;
27 const OWNER_WRITE = 0o200;
29 const OWNER_EXEC = 0o100;
31
32 const GROUP_READ = 0o40;
34 const GROUP_WRITE = 0o20;
36 const GROUP_EXEC = 0o10;
38
39 const OTHER_READ = 0o4;
41 const OTHER_WRITE = 0o2;
43 const OTHER_EXEC = 0o1;
45 }
46}
47
48#[repr(u8)]
50#[derive(Debug, Clone, Copy, Eq, PartialEq)]
51pub enum VfsNodeType {
52 Fifo = 0o1,
54 CharDevice = 0o2,
56 Dir = 0o4,
58 BlockDevice = 0o6,
60 File = 0o10,
62 SymLink = 0o12,
64 Socket = 0o14,
66}
67
68pub struct VfsDirEntry {
70 d_type: VfsNodeType,
71 d_name: [u8; 63],
72}
73
74impl VfsNodePerm {
75 pub const fn default_file() -> Self {
79 Self::from_bits_truncate(0o666)
80 }
81
82 pub const fn default_dir() -> Self {
87 Self::from_bits_truncate(0o755)
88 }
89
90 pub const fn mode(&self) -> u32 {
93 self.bits() as u32
94 }
95
96 pub const fn rwx_buf(&self) -> [u8; 9] {
100 let mut perm = [b'-'; 9];
101 if self.contains(Self::OWNER_READ) {
102 perm[0] = b'r';
103 }
104 if self.contains(Self::OWNER_WRITE) {
105 perm[1] = b'w';
106 }
107 if self.contains(Self::OWNER_EXEC) {
108 perm[2] = b'x';
109 }
110 if self.contains(Self::GROUP_READ) {
111 perm[3] = b'r';
112 }
113 if self.contains(Self::GROUP_WRITE) {
114 perm[4] = b'w';
115 }
116 if self.contains(Self::GROUP_EXEC) {
117 perm[5] = b'x';
118 }
119 if self.contains(Self::OTHER_READ) {
120 perm[6] = b'r';
121 }
122 if self.contains(Self::OTHER_WRITE) {
123 perm[7] = b'w';
124 }
125 if self.contains(Self::OTHER_EXEC) {
126 perm[8] = b'x';
127 }
128 perm
129 }
130
131 pub const fn owner_readable(&self) -> bool {
133 self.contains(Self::OWNER_READ)
134 }
135
136 pub const fn owner_writable(&self) -> bool {
138 self.contains(Self::OWNER_WRITE)
139 }
140
141 pub const fn owner_executable(&self) -> bool {
143 self.contains(Self::OWNER_EXEC)
144 }
145}
146
147impl VfsNodeType {
148 pub const fn is_file(self) -> bool {
150 matches!(self, Self::File)
151 }
152
153 pub const fn is_dir(self) -> bool {
155 matches!(self, Self::Dir)
156 }
157
158 pub const fn is_symlink(self) -> bool {
160 matches!(self, Self::SymLink)
161 }
162
163 pub const fn is_block_device(self) -> bool {
165 matches!(self, Self::BlockDevice)
166 }
167
168 pub const fn is_char_device(self) -> bool {
170 matches!(self, Self::CharDevice)
171 }
172
173 pub const fn is_fifo(self) -> bool {
175 matches!(self, Self::Fifo)
176 }
177
178 pub const fn is_socket(self) -> bool {
180 matches!(self, Self::Socket)
181 }
182
183 pub const fn as_char(self) -> char {
187 match self {
188 Self::Fifo => 'p',
189 Self::CharDevice => 'c',
190 Self::Dir => 'd',
191 Self::BlockDevice => 'b',
192 Self::File => '-',
193 Self::SymLink => 'l',
194 Self::Socket => 's',
195 }
196 }
197}
198
199impl VfsNodeAttr {
200 pub const fn new(mode: VfsNodePerm, ty: VfsNodeType, size: u64, blocks: u64) -> Self {
203 Self {
204 mode,
205 ty,
206 size,
207 blocks,
208 }
209 }
210
211 pub const fn new_file(size: u64, blocks: u64) -> Self {
213 Self {
214 mode: VfsNodePerm::default_file(),
215 ty: VfsNodeType::File,
216 size,
217 blocks,
218 }
219 }
220
221 pub const fn new_dir(size: u64, blocks: u64) -> Self {
224 Self {
225 mode: VfsNodePerm::default_dir(),
226 ty: VfsNodeType::Dir,
227 size,
228 blocks,
229 }
230 }
231
232 pub const fn size(&self) -> u64 {
234 self.size
235 }
236
237 pub const fn blocks(&self) -> u64 {
239 self.blocks
240 }
241
242 pub const fn perm(&self) -> VfsNodePerm {
244 self.mode
245 }
246
247 pub fn set_perm(&mut self, perm: VfsNodePerm) {
249 self.mode = perm
250 }
251
252 pub const fn file_type(&self) -> VfsNodeType {
254 self.ty
255 }
256
257 pub const fn is_file(&self) -> bool {
259 self.ty.is_file()
260 }
261
262 pub const fn is_dir(&self) -> bool {
264 self.ty.is_dir()
265 }
266}
267
268impl VfsDirEntry {
269 pub const fn default() -> Self {
271 Self {
272 d_type: VfsNodeType::File,
273 d_name: [0; 63],
274 }
275 }
276
277 pub fn new(name: &str, ty: VfsNodeType) -> Self {
279 let mut d_name = [0; 63];
280 if name.len() > d_name.len() {
281 log::warn!(
282 "directory entry name too long: {} > {}",
283 name.len(),
284 d_name.len()
285 );
286 }
287 d_name[..name.len()].copy_from_slice(name.as_bytes());
288 Self { d_type: ty, d_name }
289 }
290
291 pub fn entry_type(&self) -> VfsNodeType {
293 self.d_type
294 }
295
296 pub fn name_as_bytes(&self) -> &[u8] {
298 let len = self
299 .d_name
300 .iter()
301 .position(|&c| c == 0)
302 .unwrap_or(self.d_name.len());
303 &self.d_name[..len]
304 }
305}