hermit/fs/
mem.rs

1// Copyright (c) 2019 Stefan Lankes, RWTH Aachen University
2//
3// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
4// http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
5// http://opensource.org/licenses/MIT>, at your option. This file may not be
6// copied, modified, or distributed except according to those terms.
7
8//! Implements basic functions to realize a simple in-memory file system
9
10#![allow(dead_code)]
11
12use alloc::boxed::Box;
13use alloc::collections::BTreeMap;
14use alloc::string::String;
15use alloc::sync::Arc;
16use alloc::vec::Vec;
17use core::mem::MaybeUninit;
18
19use async_lock::{Mutex, RwLock};
20use async_trait::async_trait;
21
22use crate::executor::block_on;
23use crate::fd::{AccessPermission, ObjectInterface, OpenOption, PollEvent};
24use crate::fs::{DirectoryEntry, FileAttr, NodeKind, SeekWhence, VfsNode};
25use crate::time::timespec;
26use crate::{arch, io};
27
28#[derive(Debug)]
29pub(crate) struct RomFileInner {
30	pub data: &'static [u8],
31	pub attr: FileAttr,
32}
33
34impl RomFileInner {
35	pub fn new(data: &'static [u8], attr: FileAttr) -> Self {
36		Self { data, attr }
37	}
38}
39
40#[derive(Debug, Clone)]
41struct RomFileInterface {
42	/// Position within the file
43	pos: Arc<Mutex<usize>>,
44	/// File content
45	inner: Arc<RwLock<RomFileInner>>,
46}
47
48#[async_trait]
49impl ObjectInterface for RomFileInterface {
50	async fn poll(&self, event: PollEvent) -> io::Result<PollEvent> {
51		let len = self.inner.read().await.data.len();
52		let pos = *self.pos.lock().await;
53
54		let ret = if pos < len {
55			event.intersection(PollEvent::POLLIN | PollEvent::POLLRDNORM | PollEvent::POLLRDBAND)
56		} else {
57			PollEvent::empty()
58		};
59
60		Ok(ret)
61	}
62
63	async fn read(&self, buf: &mut [MaybeUninit<u8>]) -> io::Result<usize> {
64		{
65			let microseconds = arch::kernel::systemtime::now_micros();
66			let t = timespec::from_usec(microseconds as i64);
67			let mut guard = self.inner.write().await;
68			guard.attr.st_atim = t;
69		}
70
71		let vec = self.inner.read().await.data;
72		let mut pos_guard = self.pos.lock().await;
73		let pos = *pos_guard;
74
75		if pos >= vec.len() {
76			return Ok(0);
77		}
78
79		let len = if vec.len() - pos < buf.len() {
80			vec.len() - pos
81		} else {
82			buf.len()
83		};
84
85		buf[..len].write_copy_of_slice(&vec[pos..pos + len]);
86		*pos_guard = pos + len;
87
88		Ok(len)
89	}
90
91	async fn lseek(&self, offset: isize, whence: SeekWhence) -> io::Result<isize> {
92		let guard = self.inner.read().await;
93		let mut pos_guard = self.pos.lock().await;
94
95		let new_pos: isize = if whence == SeekWhence::Set {
96			if offset < 0 {
97				return Err(io::Error::EINVAL);
98			}
99
100			offset
101		} else if whence == SeekWhence::End {
102			guard.data.len() as isize + offset
103		} else if whence == SeekWhence::Cur {
104			(*pos_guard as isize) + offset
105		} else {
106			return Err(io::Error::EINVAL);
107		};
108
109		if new_pos <= isize::try_from(guard.data.len()).unwrap() {
110			*pos_guard = new_pos.try_into().unwrap();
111			Ok(new_pos)
112		} else {
113			Err(io::Error::EBADF)
114		}
115	}
116
117	async fn fstat(&self) -> io::Result<FileAttr> {
118		let guard = self.inner.read().await;
119		Ok(guard.attr)
120	}
121}
122
123impl RomFileInterface {
124	pub fn new(inner: Arc<RwLock<RomFileInner>>) -> Self {
125		Self {
126			pos: Arc::new(Mutex::new(0)),
127			inner,
128		}
129	}
130
131	pub fn len(&self) -> usize {
132		block_on(async { Ok(self.inner.read().await.data.len()) }, None).unwrap()
133	}
134}
135
136#[derive(Debug)]
137pub(crate) struct RamFileInner {
138	pub data: Vec<u8>,
139	pub attr: FileAttr,
140}
141
142impl RamFileInner {
143	pub fn new(attr: FileAttr) -> Self {
144		Self {
145			data: Vec::new(),
146			attr,
147		}
148	}
149}
150
151#[derive(Debug, Clone)]
152pub struct RamFileInterface {
153	/// Position within the file
154	pos: Arc<Mutex<usize>>,
155	/// File content
156	inner: Arc<RwLock<RamFileInner>>,
157}
158
159#[async_trait]
160impl ObjectInterface for RamFileInterface {
161	async fn poll(&self, event: PollEvent) -> io::Result<PollEvent> {
162		let len = self.inner.read().await.data.len();
163		let pos = *self.pos.lock().await;
164
165		let mut available = PollEvent::POLLOUT | PollEvent::POLLWRNORM | PollEvent::POLLWRBAND;
166
167		if pos < len {
168			available.insert(PollEvent::POLLIN | PollEvent::POLLRDNORM | PollEvent::POLLRDBAND);
169		}
170
171		Ok(event & available)
172	}
173
174	async fn read(&self, buf: &mut [MaybeUninit<u8>]) -> io::Result<usize> {
175		{
176			let microseconds = arch::kernel::systemtime::now_micros();
177			let t = timespec::from_usec(microseconds as i64);
178			let mut guard = self.inner.write().await;
179			guard.attr.st_atim = t;
180		}
181
182		let guard = self.inner.read().await;
183		let mut pos_guard = self.pos.lock().await;
184		let pos = *pos_guard;
185
186		if pos >= guard.data.len() {
187			return Ok(0);
188		}
189
190		let len = if guard.data.len() - pos < buf.len() {
191			guard.data.len() - pos
192		} else {
193			buf.len()
194		};
195
196		buf[..len].write_copy_of_slice(&guard.data[pos..pos + len]);
197		*pos_guard = pos + len;
198
199		Ok(len)
200	}
201
202	async fn write(&self, buf: &[u8]) -> io::Result<usize> {
203		let microseconds = arch::kernel::systemtime::now_micros();
204		let t = timespec::from_usec(microseconds as i64);
205		let mut guard = self.inner.write().await;
206		let mut pos_guard = self.pos.lock().await;
207		let pos = *pos_guard;
208
209		if pos + buf.len() > guard.data.len() {
210			guard.data.resize(pos + buf.len(), 0);
211			guard.attr.st_size = guard.data.len().try_into().unwrap();
212		}
213
214		guard.attr.st_atim = t;
215		guard.attr.st_mtim = t;
216		guard.attr.st_ctim = t;
217
218		guard.data[pos..pos + buf.len()].copy_from_slice(buf);
219		*pos_guard = pos + buf.len();
220
221		Ok(buf.len())
222	}
223
224	async fn lseek(&self, offset: isize, whence: SeekWhence) -> io::Result<isize> {
225		let mut guard = self.inner.write().await;
226		let mut pos_guard = self.pos.lock().await;
227
228		let new_pos: isize = if whence == SeekWhence::Set {
229			if offset < 0 {
230				return Err(io::Error::EINVAL);
231			}
232
233			offset
234		} else if whence == SeekWhence::End {
235			guard.data.len() as isize + offset
236		} else if whence == SeekWhence::Cur {
237			(*pos_guard as isize) + offset
238		} else {
239			return Err(io::Error::EINVAL);
240		};
241
242		if new_pos > isize::try_from(guard.data.len()).unwrap() {
243			guard.data.resize(new_pos.try_into().unwrap(), 0);
244			guard.attr.st_size = guard.data.len().try_into().unwrap();
245		}
246		*pos_guard = new_pos.try_into().unwrap();
247
248		Ok(new_pos)
249	}
250
251	async fn fstat(&self) -> io::Result<FileAttr> {
252		let guard = self.inner.read().await;
253		Ok(guard.attr)
254	}
255}
256
257impl RamFileInterface {
258	pub fn new(inner: Arc<RwLock<RamFileInner>>) -> Self {
259		Self {
260			pos: Arc::new(Mutex::new(0)),
261			inner,
262		}
263	}
264
265	pub fn len(&self) -> usize {
266		block_on(async { Ok(self.inner.read().await.data.len()) }, None).unwrap()
267	}
268}
269
270#[derive(Debug)]
271pub(crate) struct RomFile {
272	data: Arc<RwLock<RomFileInner>>,
273}
274
275impl VfsNode for RomFile {
276	fn get_kind(&self) -> NodeKind {
277		NodeKind::File
278	}
279
280	fn get_object(&self) -> io::Result<Arc<dyn ObjectInterface>> {
281		Ok(Arc::new(RomFileInterface::new(self.data.clone())))
282	}
283
284	fn get_file_attributes(&self) -> io::Result<FileAttr> {
285		block_on(async { Ok(self.data.read().await.attr) }, None)
286	}
287
288	fn traverse_lstat(&self, components: &mut Vec<&str>) -> io::Result<FileAttr> {
289		if components.is_empty() {
290			self.get_file_attributes()
291		} else {
292			Err(io::Error::EBADF)
293		}
294	}
295
296	fn traverse_stat(&self, components: &mut Vec<&str>) -> io::Result<FileAttr> {
297		if components.is_empty() {
298			self.get_file_attributes()
299		} else {
300			Err(io::Error::EBADF)
301		}
302	}
303}
304
305impl RomFile {
306	pub fn new(data: &'static [u8], mode: AccessPermission) -> Self {
307		let microseconds = arch::kernel::systemtime::now_micros();
308		let t = timespec::from_usec(microseconds as i64);
309		let attr = FileAttr {
310			st_size: data.len().try_into().unwrap(),
311			st_mode: mode | AccessPermission::S_IFREG,
312			st_atim: t,
313			st_mtim: t,
314			st_ctim: t,
315			..Default::default()
316		};
317
318		Self {
319			data: Arc::new(RwLock::new(RomFileInner::new(data, attr))),
320		}
321	}
322}
323
324#[derive(Debug, Clone)]
325pub(crate) struct RamFile {
326	data: Arc<RwLock<RamFileInner>>,
327}
328
329impl VfsNode for RamFile {
330	fn get_kind(&self) -> NodeKind {
331		NodeKind::File
332	}
333
334	fn get_object(&self) -> io::Result<Arc<dyn ObjectInterface>> {
335		Ok(Arc::new(RamFileInterface::new(self.data.clone())))
336	}
337
338	fn get_file_attributes(&self) -> io::Result<FileAttr> {
339		block_on(async { Ok(self.data.read().await.attr) }, None)
340	}
341
342	fn traverse_lstat(&self, components: &mut Vec<&str>) -> io::Result<FileAttr> {
343		if components.is_empty() {
344			self.get_file_attributes()
345		} else {
346			Err(io::Error::EBADF)
347		}
348	}
349
350	fn traverse_stat(&self, components: &mut Vec<&str>) -> io::Result<FileAttr> {
351		if components.is_empty() {
352			self.get_file_attributes()
353		} else {
354			Err(io::Error::EBADF)
355		}
356	}
357}
358
359impl RamFile {
360	pub fn new(mode: AccessPermission) -> Self {
361		let microseconds = arch::kernel::systemtime::now_micros();
362		let t = timespec::from_usec(microseconds as i64);
363		let attr = FileAttr {
364			st_mode: mode | AccessPermission::S_IFREG,
365			st_atim: t,
366			st_mtim: t,
367			st_ctim: t,
368			..Default::default()
369		};
370
371		Self {
372			data: Arc::new(RwLock::new(RamFileInner::new(attr))),
373		}
374	}
375}
376
377#[derive(Debug, Clone)]
378pub struct MemDirectoryInterface {
379	/// Directory entries
380	inner:
381		Arc<RwLock<BTreeMap<String, Box<dyn VfsNode + core::marker::Send + core::marker::Sync>>>>,
382}
383
384impl MemDirectoryInterface {
385	pub fn new(
386		inner: Arc<
387			RwLock<BTreeMap<String, Box<dyn VfsNode + core::marker::Send + core::marker::Sync>>>,
388		>,
389	) -> Self {
390		Self { inner }
391	}
392}
393
394#[async_trait]
395impl ObjectInterface for MemDirectoryInterface {
396	async fn readdir(&self) -> io::Result<Vec<DirectoryEntry>> {
397		let mut entries: Vec<DirectoryEntry> = Vec::new();
398		for name in self.inner.read().await.keys() {
399			entries.push(DirectoryEntry::new(name.clone()));
400		}
401
402		Ok(entries)
403	}
404}
405
406#[derive(Debug)]
407pub(crate) struct MemDirectory {
408	inner:
409		Arc<RwLock<BTreeMap<String, Box<dyn VfsNode + core::marker::Send + core::marker::Sync>>>>,
410	attr: FileAttr,
411}
412
413impl MemDirectory {
414	pub fn new(mode: AccessPermission) -> Self {
415		let microseconds = arch::kernel::systemtime::now_micros();
416		let t = timespec::from_usec(microseconds as i64);
417
418		Self {
419			inner: Arc::new(RwLock::new(BTreeMap::new())),
420			attr: FileAttr {
421				st_mode: mode | AccessPermission::S_IFDIR,
422				st_atim: t,
423				st_mtim: t,
424				st_ctim: t,
425				..Default::default()
426			},
427		}
428	}
429
430	async fn async_traverse_open(
431		&self,
432		components: &mut Vec<&str>,
433		opt: OpenOption,
434		mode: AccessPermission,
435	) -> io::Result<Arc<dyn ObjectInterface>> {
436		if let Some(component) = components.pop() {
437			let node_name = String::from(component);
438
439			if components.is_empty() {
440				let mut guard = self.inner.write().await;
441				if let Some(file) = guard.get(&node_name) {
442					if opt.contains(OpenOption::O_DIRECTORY)
443						&& file.get_kind() != NodeKind::Directory
444					{
445						return Err(io::Error::ENOTDIR);
446					}
447
448					if file.get_kind() == NodeKind::File || file.get_kind() == NodeKind::Directory {
449						return file.get_object();
450					} else {
451						return Err(io::Error::ENOENT);
452					}
453				} else if opt.contains(OpenOption::O_CREAT) {
454					let file = Box::new(RamFile::new(mode));
455					guard.insert(node_name, file.clone());
456					return Ok(Arc::new(RamFileInterface::new(file.data.clone())));
457				} else {
458					return Err(io::Error::ENOENT);
459				}
460			}
461
462			if let Some(directory) = self.inner.read().await.get(&node_name) {
463				return directory.traverse_open(components, opt, mode);
464			}
465		}
466
467		Err(io::Error::ENOENT)
468	}
469}
470
471impl VfsNode for MemDirectory {
472	fn get_kind(&self) -> NodeKind {
473		NodeKind::Directory
474	}
475
476	fn get_object(&self) -> io::Result<Arc<dyn ObjectInterface>> {
477		Ok(Arc::new(MemDirectoryInterface::new(self.inner.clone())))
478	}
479
480	fn get_file_attributes(&self) -> io::Result<FileAttr> {
481		Ok(self.attr)
482	}
483
484	fn traverse_mkdir(&self, components: &mut Vec<&str>, mode: AccessPermission) -> io::Result<()> {
485		block_on(
486			async {
487				if let Some(component) = components.pop() {
488					let node_name = String::from(component);
489
490					if let Some(directory) = self.inner.read().await.get(&node_name) {
491						return directory.traverse_mkdir(components, mode);
492					}
493
494					if components.is_empty() {
495						self.inner
496							.write()
497							.await
498							.insert(node_name, Box::new(MemDirectory::new(mode)));
499						return Ok(());
500					}
501				}
502
503				Err(io::Error::EBADF)
504			},
505			None,
506		)
507	}
508
509	fn traverse_rmdir(&self, components: &mut Vec<&str>) -> io::Result<()> {
510		block_on(
511			async {
512				if let Some(component) = components.pop() {
513					let node_name = String::from(component);
514
515					if components.is_empty() {
516						let mut guard = self.inner.write().await;
517
518						let obj = guard.remove(&node_name).ok_or(io::Error::ENOENT)?;
519						if obj.get_kind() == NodeKind::Directory {
520							return Ok(());
521						} else {
522							guard.insert(node_name, obj);
523							return Err(io::Error::ENOTDIR);
524						}
525					} else if let Some(directory) = self.inner.read().await.get(&node_name) {
526						return directory.traverse_rmdir(components);
527					}
528				}
529
530				Err(io::Error::EBADF)
531			},
532			None,
533		)
534	}
535
536	fn traverse_unlink(&self, components: &mut Vec<&str>) -> io::Result<()> {
537		block_on(
538			async {
539				if let Some(component) = components.pop() {
540					let node_name = String::from(component);
541
542					if components.is_empty() {
543						let mut guard = self.inner.write().await;
544
545						let obj = guard.remove(&node_name).ok_or(io::Error::ENOENT)?;
546						if obj.get_kind() == NodeKind::File {
547							return Ok(());
548						} else {
549							guard.insert(node_name, obj);
550							return Err(io::Error::EISDIR);
551						}
552					} else if let Some(directory) = self.inner.read().await.get(&node_name) {
553						return directory.traverse_unlink(components);
554					}
555				}
556
557				Err(io::Error::EBADF)
558			},
559			None,
560		)
561	}
562
563	fn traverse_readdir(&self, components: &mut Vec<&str>) -> io::Result<Vec<DirectoryEntry>> {
564		block_on(
565			async {
566				if let Some(component) = components.pop() {
567					let node_name = String::from(component);
568
569					if let Some(directory) = self.inner.read().await.get(&node_name) {
570						directory.traverse_readdir(components)
571					} else {
572						Err(io::Error::EBADF)
573					}
574				} else {
575					let mut entries: Vec<DirectoryEntry> = Vec::new();
576					for name in self.inner.read().await.keys() {
577						entries.push(DirectoryEntry::new(name.clone()));
578					}
579
580					Ok(entries)
581				}
582			},
583			None,
584		)
585	}
586
587	fn traverse_lstat(&self, components: &mut Vec<&str>) -> io::Result<FileAttr> {
588		block_on(
589			async {
590				if let Some(component) = components.pop() {
591					let node_name = String::from(component);
592
593					if components.is_empty() {
594						if let Some(node) = self.inner.read().await.get(&node_name) {
595							return node.get_file_attributes();
596						}
597					}
598
599					if let Some(directory) = self.inner.read().await.get(&node_name) {
600						directory.traverse_lstat(components)
601					} else {
602						Err(io::Error::EBADF)
603					}
604				} else {
605					Err(io::Error::ENOSYS)
606				}
607			},
608			None,
609		)
610	}
611
612	fn traverse_stat(&self, components: &mut Vec<&str>) -> io::Result<FileAttr> {
613		block_on(
614			async {
615				if let Some(component) = components.pop() {
616					let node_name = String::from(component);
617
618					if components.is_empty() {
619						if let Some(node) = self.inner.read().await.get(&node_name) {
620							return node.get_file_attributes();
621						}
622					}
623
624					if let Some(directory) = self.inner.read().await.get(&node_name) {
625						directory.traverse_stat(components)
626					} else {
627						Err(io::Error::EBADF)
628					}
629				} else {
630					Err(io::Error::ENOSYS)
631				}
632			},
633			None,
634		)
635	}
636
637	fn traverse_mount(
638		&self,
639		components: &mut Vec<&str>,
640		obj: Box<dyn VfsNode + core::marker::Send + core::marker::Sync>,
641	) -> io::Result<()> {
642		block_on(
643			async {
644				if let Some(component) = components.pop() {
645					let node_name = String::from(component);
646
647					if let Some(directory) = self.inner.read().await.get(&node_name) {
648						return directory.traverse_mount(components, obj);
649					}
650
651					if components.is_empty() {
652						self.inner.write().await.insert(node_name, obj);
653						return Ok(());
654					}
655				}
656
657				Err(io::Error::EBADF)
658			},
659			None,
660		)
661	}
662
663	fn traverse_open(
664		&self,
665		components: &mut Vec<&str>,
666		opt: OpenOption,
667		mode: AccessPermission,
668	) -> io::Result<Arc<dyn ObjectInterface>> {
669		block_on(self.async_traverse_open(components, opt, mode), None)
670	}
671
672	fn traverse_create_file(
673		&self,
674		components: &mut Vec<&str>,
675		data: &'static [u8],
676		mode: AccessPermission,
677	) -> io::Result<()> {
678		block_on(
679			async {
680				if let Some(component) = components.pop() {
681					let name = String::from(component);
682
683					if components.is_empty() {
684						let file = RomFile::new(data, mode);
685						self.inner.write().await.insert(name, Box::new(file));
686						return Ok(());
687					}
688
689					if let Some(directory) = self.inner.read().await.get(&name) {
690						return directory.traverse_create_file(components, data, mode);
691					}
692				}
693
694				Err(io::Error::ENOENT)
695			},
696			None,
697		)
698	}
699}