1use axerrno::{AxError, AxResult, ax_err, ax_err_type};
4use axfs_vfs::{VfsError, VfsNodeRef};
5use axio::SeekFrom;
6use cap_access::{Cap, WithCap};
7use core::fmt;
8
9#[cfg(feature = "myfs")]
10pub use crate::dev::Disk;
11#[cfg(feature = "myfs")]
12pub use crate::fs::myfs::MyFileSystemIf;
13
14pub type FileType = axfs_vfs::VfsNodeType;
16pub type DirEntry = axfs_vfs::VfsDirEntry;
18pub type FileAttr = axfs_vfs::VfsNodeAttr;
20pub type FilePerm = axfs_vfs::VfsNodePerm;
22
23pub struct File {
25 node: WithCap<VfsNodeRef>,
26 is_append: bool,
27 offset: u64,
28}
29
30pub struct Directory {
33 node: WithCap<VfsNodeRef>,
34 entry_idx: usize,
35}
36
37#[derive(Default, Clone)]
39pub struct OpenOptions {
40 read: bool,
42 write: bool,
43 execute: bool,
44 append: bool,
45 truncate: bool,
46 create: bool,
47 create_new: bool,
48 directory: bool,
49 _custom_flags: i32,
51 _mode: u32,
52}
53
54impl OpenOptions {
55 pub const fn new() -> Self {
57 Self {
58 read: false,
60 write: false,
61 execute: false,
62 append: false,
63 truncate: false,
64 create: false,
65 create_new: false,
66 directory: false,
67 _custom_flags: 0,
69 _mode: 0o666,
70 }
71 }
72 pub fn read(&mut self, read: bool) {
74 self.read = read;
75 }
76 pub fn write(&mut self, write: bool) {
78 self.write = write;
79 }
80 pub fn execute(&mut self, execute: bool) {
82 self.execute = execute;
83 }
84 pub fn append(&mut self, append: bool) {
86 self.append = append;
87 }
88 pub fn truncate(&mut self, truncate: bool) {
90 self.truncate = truncate;
91 }
92 pub fn create(&mut self, create: bool) {
94 self.create = create;
95 }
96 pub fn create_new(&mut self, create_new: bool) {
98 self.create_new = create_new;
99 }
100 pub fn directory(&mut self, directory: bool) {
102 self.directory = directory;
103 }
104 pub fn has_directory(&self) -> bool {
106 self.directory
107 }
108
109 pub fn set_create(mut self, create: bool, create_new: bool) -> Self {
111 self.create = create;
112 self.create_new = create_new;
113 self
114 }
115
116 pub fn set_read(mut self, read: bool) -> Self {
118 self.read = read;
119 self
120 }
121
122 pub fn set_write(mut self, write: bool) -> Self {
124 self.write = write;
125 self
126 }
127
128 const fn is_valid(&self) -> bool {
129 if !self.read && !self.write && !self.append && !self.directory {
130 return false;
131 }
132 match (self.write, self.append) {
133 (true, false) => {}
134 (false, false) => {
135 if self.truncate || self.create || self.create_new {
136 return false;
137 }
138 }
139 (_, true) => {
140 if self.truncate && !self.create_new {
141 return false;
142 }
143 }
144 }
145 true
146 }
147}
148
149impl File {
150 fn access_node(&self, cap: Cap) -> AxResult<&VfsNodeRef> {
151 self.node.access_or_err(cap, AxError::PermissionDenied)
152 }
153
154 fn _open_at(dir: Option<&VfsNodeRef>, path: &str, opts: &OpenOptions) -> AxResult<Self> {
155 debug!("open file: {} {:?}", path, opts);
156 if !opts.is_valid() {
157 return ax_err!(InvalidInput);
158 }
159
160 let node_option = crate::root::lookup(dir, path);
161 let node = if opts.create || opts.create_new {
162 match node_option {
163 Ok(node) => {
164 if opts.create_new {
166 return ax_err!(AlreadyExists);
167 }
168 node
169 }
170 Err(VfsError::NotFound) => crate::root::create_file(dir, path)?,
172 Err(e) => return Err(e),
173 }
174 } else {
175 node_option?
177 };
178
179 let attr = node.get_attr()?;
180 if attr.is_dir() {
181 return ax_err!(IsADirectory);
182 }
183 let access_cap = opts.into();
184 if !perm_to_cap(attr.perm()).contains(access_cap) {
185 return ax_err!(PermissionDenied);
186 }
187
188 node.open()?;
189 if opts.truncate {
190 node.truncate(0)?;
191 }
192 Ok(Self {
193 node: WithCap::new(node, access_cap),
194 is_append: opts.append,
195 offset: 0,
196 })
197 }
198
199 pub fn open(path: &str, opts: &OpenOptions) -> AxResult<Self> {
202 Self::_open_at(None, path, opts)
203 }
204
205 pub fn truncate(&self, size: u64) -> AxResult {
207 self.access_node(Cap::WRITE)?.truncate(size)?;
208 Ok(())
209 }
210
211 pub fn read(&mut self, buf: &mut [u8]) -> AxResult<usize> {
216 let node = self.access_node(Cap::READ)?;
217 let read_len = node.read_at(self.offset, buf)?;
218 self.offset += read_len as u64;
219 Ok(read_len)
220 }
221
222 pub fn read_at(&self, offset: u64, buf: &mut [u8]) -> AxResult<usize> {
226 let node = self.access_node(Cap::READ)?;
227 let read_len = node.read_at(offset, buf)?;
228 Ok(read_len)
229 }
230
231 pub fn write(&mut self, buf: &[u8]) -> AxResult<usize> {
237 let offset = if self.is_append {
238 self.get_attr()?.size()
239 } else {
240 self.offset
241 };
242 let node = self.access_node(Cap::WRITE)?;
243 let write_len = node.write_at(offset, buf)?;
244 self.offset = offset + write_len as u64;
245 Ok(write_len)
246 }
247
248 pub fn write_at(&self, offset: u64, buf: &[u8]) -> AxResult<usize> {
253 let node = self.access_node(Cap::WRITE)?;
254 let write_len = node.write_at(offset, buf)?;
255 Ok(write_len)
256 }
257
258 pub fn flush(&self) -> AxResult {
260 self.access_node(Cap::WRITE)?.fsync()?;
261 Ok(())
262 }
263
264 pub fn seek(&mut self, pos: SeekFrom) -> AxResult<u64> {
267 let size = self.get_attr()?.size();
268 let new_offset = match pos {
269 SeekFrom::Start(pos) => Some(pos),
270 SeekFrom::Current(off) => self.offset.checked_add_signed(off),
271 SeekFrom::End(off) => size.checked_add_signed(off),
272 }
273 .ok_or_else(|| ax_err_type!(InvalidInput))?;
274 self.offset = new_offset;
275 Ok(new_offset)
276 }
277
278 pub fn get_attr(&self) -> AxResult<FileAttr> {
280 self.access_node(Cap::empty())?.get_attr()
281 }
282}
283
284impl Directory {
285 fn access_node(&self, cap: Cap) -> AxResult<&VfsNodeRef> {
286 self.node.access_or_err(cap, AxError::PermissionDenied)
287 }
288
289 fn _open_dir_at(dir: Option<&VfsNodeRef>, path: &str, opts: &OpenOptions) -> AxResult<Self> {
290 debug!("open dir: {}", path);
291 if !opts.read {
292 return ax_err!(InvalidInput);
293 }
294 if opts.create || opts.create_new || opts.write || opts.append || opts.truncate {
295 return ax_err!(InvalidInput);
296 }
297
298 let node = crate::root::lookup(dir, path)?;
299 let attr = node.get_attr()?;
300 if !attr.is_dir() {
301 return ax_err!(NotADirectory);
302 }
303 let access_cap = opts.into();
304 let cap = perm_to_cap(attr.perm());
305 if !cap.contains(access_cap) {
306 return ax_err!(PermissionDenied);
307 }
308
309 node.open()?;
310 Ok(Self {
311 node: WithCap::new(node, cap),
315 entry_idx: 0,
316 })
317 }
318
319 fn access_at(&self, path: &str) -> AxResult<Option<&VfsNodeRef>> {
320 if path.starts_with('/') {
321 Ok(None)
322 } else {
323 Ok(Some(self.access_node(Cap::EXECUTE)?))
324 }
325 }
326
327 pub fn open_dir(path: &str, opts: &OpenOptions) -> AxResult<Self> {
330 Self::_open_dir_at(None, path, opts)
331 }
332
333 pub fn open_dir_at(&self, path: &str, opts: &OpenOptions) -> AxResult<Self> {
336 Self::_open_dir_at(self.access_at(path)?, path, opts)
337 }
338
339 pub fn open_file_at(&self, path: &str, opts: &OpenOptions) -> AxResult<File> {
342 File::_open_at(self.access_at(path)?, path, opts)
343 }
344
345 pub fn create_file(&self, path: &str) -> AxResult<VfsNodeRef> {
347 crate::root::create_file(self.access_at(path)?, path)
348 }
349
350 pub fn create_dir(&self, path: &str) -> AxResult {
352 crate::root::create_dir(self.access_at(path)?, path)
353 }
354
355 pub fn remove_file(&self, path: &str) -> AxResult {
357 crate::root::remove_file(self.access_at(path)?, path)
358 }
359
360 pub fn remove_dir(&self, path: &str) -> AxResult {
362 crate::root::remove_dir(self.access_at(path)?, path)
363 }
364
365 pub fn read_dir(&mut self, dirents: &mut [DirEntry]) -> AxResult<usize> {
371 let n = self
372 .access_node(Cap::READ)?
373 .read_dir(self.entry_idx, dirents)?;
374 self.entry_idx += n;
375 Ok(n)
376 }
377
378 pub fn rename(&self, old: &str, new: &str) -> AxResult {
383 crate::root::rename(old, new)
384 }
385}
386
387impl Drop for File {
388 fn drop(&mut self) {
389 unsafe { self.node.access_unchecked().release().ok() };
390 }
391}
392
393impl Drop for Directory {
394 fn drop(&mut self) {
395 unsafe { self.node.access_unchecked().release().ok() };
396 }
397}
398
399impl fmt::Debug for OpenOptions {
400 #[allow(unused_assignments)]
401 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
402 let mut written = false;
403 macro_rules! fmt_opt {
404 ($field: ident, $label: literal) => {
405 if self.$field {
406 if written {
407 write!(f, " | ")?;
408 }
409 write!(f, $label)?;
410 written = true;
411 }
412 };
413 }
414 fmt_opt!(read, "READ");
415 fmt_opt!(write, "WRITE");
416 fmt_opt!(append, "APPEND");
417 fmt_opt!(truncate, "TRUNC");
418 fmt_opt!(create, "CREATE");
419 fmt_opt!(create_new, "CREATE_NEW");
420 Ok(())
421 }
422}
423
424impl From<&OpenOptions> for Cap {
425 fn from(opts: &OpenOptions) -> Cap {
426 let mut cap = Cap::empty();
427 if opts.read {
428 cap |= Cap::READ;
429 }
430 if opts.write | opts.append {
431 cap |= Cap::WRITE;
432 }
433 if opts.execute {
434 cap |= Cap::EXECUTE;
435 }
436 cap
437 }
438}
439
440fn perm_to_cap(perm: FilePerm) -> Cap {
441 let mut cap = Cap::empty();
442 if perm.owner_readable() {
443 cap |= Cap::READ;
444 }
445 if perm.owner_writable() {
446 cap |= Cap::WRITE;
447 }
448 if perm.owner_executable() {
449 cap |= Cap::EXECUTE;
450 }
451 cap
452}