Skip to content

Commit 87bea3f

Browse files
sys_stat: initial implementation
* add checking methods in VirtAddr * impl sys_stat * add method to read sizeof(T) bytes and get a mutable reference to T in VirtAddr Signed-off-by: Andy-Python-Programmer <[email protected]>
1 parent a727fec commit 87bea3f

File tree

8 files changed

+210
-6
lines changed

8 files changed

+210
-6
lines changed

patches/mlibc/mlibc.patch

Lines changed: 80 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,100 @@
1-
From 8917c56f1216c079d9a3560b03d4cc30c96920c5 Mon Sep 17 00:00:00 2001
1+
From d1583428ad4f44bb2ca458e06e3a0c60f2c45737 Mon Sep 17 00:00:00 2001
22
From: Andy-Python-Programmer <[email protected]>
33
Date: Thu, 10 Feb 2022 19:12:25 +1100
44
Subject: [PATCH] yes
55

66
Signed-off-by: Andy-Python-Programmer <[email protected]>
77
---
8-
sysdeps/aero/generic/filesystem.cpp | 1 -
9-
1 file changed, 1 deletion(-)
8+
.gitignore | 7 +++++++
9+
sysdeps/aero/generic/filesystem.cpp | 28 +++++++++++++++++++++-------
10+
sysdeps/aero/include/aero/syscall.h | 5 +++++
11+
3 files changed, 33 insertions(+), 7 deletions(-)
1012

13+
diff --git a/.gitignore b/.gitignore
14+
index dbb35e8b..384b3395 100644
15+
--- a/.gitignore
16+
+++ b/.gitignore
17+
@@ -8,3 +8,10 @@ subprojects/cxxshim
18+
subprojects/frigg
19+
.vscode
20+
.clang-format
21+
+
22+
+# clangd files
23+
+#
24+
+# * The compile commands json is usually generated by the build system
25+
+# if not, it can be constructed manually and should be in the root of
26+
+# of the project directory.
27+
+compile_commands.json
1128
diff --git a/sysdeps/aero/generic/filesystem.cpp b/sysdeps/aero/generic/filesystem.cpp
12-
index 0e73b63..54252ba 100644
29+
index 6a13f19c..ec81503c 100644
1330
--- a/sysdeps/aero/generic/filesystem.cpp
1431
+++ b/sysdeps/aero/generic/filesystem.cpp
15-
@@ -256,7 +256,6 @@ int sys_pselect(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds,
32+
@@ -84,9 +84,24 @@ int sys_access(const char *filename, int mode) {
33+
34+
int sys_stat(fsfd_target fsfdt, int fd, const char *path, int flags,
35+
struct stat *statbuf) {
36+
- mlibc::infoLogger() << "sys_stat() is unimplemented" << frg::endlog;
37+
+ auto result = 0;
38+
+
39+
+ switch (fsfdt) {
40+
+ case fsfd_target::path: {
41+
+ result = syscall(SYS_STAT, path, strlen(path), statbuf);
42+
+ break;
43+
+ }
44+
+
45+
+ default: {
46+
+ mlibc::infoLogger() << "mlibc warning: sys_stat: unsupported fsfd target" << frg::endlog;
47+
+ return EINVAL;
48+
+ }
49+
+ }
50+
+
51+
+ if (result < 0) {
52+
+ return -result;
53+
+ }
54+
55+
- memset(statbuf, 0, sizeof(struct stat));
56+
return 0;
57+
}
58+
59+
@@ -192,10 +207,10 @@ int sys_read_entries(int handle, void *buffer, size_t max_size,
60+
auto entry = (struct aero_dir_entry *)buffer;
61+
62+
struct dirent dirent = {
63+
- .d_ino = entry->inode,
64+
- .d_off = entry->offset,
65+
- .d_reclen = entry->reclen,
66+
- .d_type = entry->filetyp,
67+
+ .d_ino = static_cast<ino_t>(entry->inode),
68+
+ .d_off = static_cast<off_t>(entry->offset),
69+
+ .d_reclen = static_cast<unsigned short>(entry->reclen),
70+
+ .d_type = static_cast<unsigned char>(entry->filetyp),
71+
};
72+
73+
// The reclen is the size of the dirent struct, plus the size of the name.
74+
@@ -252,7 +267,6 @@ int sys_pselect(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds,
1675
const struct timespec *timeout, const sigset_t *sigmask,
1776
int *num_events) {
1877
mlibc::infoLogger() << "sys_pselect() is not implemented" << frg::endlog;
1978
- *num_events = 10;
2079
return 0;
2180
}
2281

82+
diff --git a/sysdeps/aero/include/aero/syscall.h b/sysdeps/aero/include/aero/syscall.h
83+
index 07b1b51b..1e3178d2 100644
84+
--- a/sysdeps/aero/include/aero/syscall.h
85+
+++ b/sysdeps/aero/include/aero/syscall.h
86+
@@ -49,6 +49,11 @@
87+
#define SYS_DUP 42
88+
#define SYS_FCNTL 43
89+
#define SYS_DUP2 44
90+
+#define SYS_IPC_SEND 45
91+
+#define SYS_IPC_RECV 46
92+
+#define SYS_DISCOVER_ROOT 47
93+
+#define SYS_BECOME_ROOT 48
94+
+#define SYS_STAT 49
95+
96+
// Invalid syscall used to trigger a log error in the kernel (as a hint)
97+
// so, that we can implement the syscall in the kernel.
2398
--
2499
2.25.1
25100

src/aero_kernel/src/fs/inode.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,9 @@ pub trait INodeInterface: Send + Sync + Downcastable {
7979
Err(FileSystemError::NotSupported)
8080
}
8181

82+
fn stat(&self) -> Result<aero_syscall::Stat> {
83+
Err(FileSystemError::NotSupported)
84+
}
8285
/// Creates a new dev inode with the provided `name` and the device `marker` in
8386
/// the filesystem.
8487
///

src/aero_kernel/src/fs/ramfs.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,12 @@ impl LockedRamINode {
114114
}
115115

116116
impl INodeInterface for LockedRamINode {
117+
fn stat(&self) -> Result<aero_syscall::Stat> {
118+
// todo(andy): implement `stat` for ramfs files. This is a workaround
119+
// to make not programs crash when they try to stat a ramfs file.
120+
Ok(aero_syscall::Stat::default())
121+
}
122+
117123
fn touch(&self, parent: DirCacheItem, name: &str) -> Result<DirCacheItem> {
118124
Ok(DirEntry::new(
119125
parent,

src/aero_kernel/src/mem/paging/addr.rs

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,39 @@ impl VirtAddr {
9494
self.as_ptr::<T>() as *mut T
9595
}
9696

97+
/// If the virtual address is a valid userland address, the [`Some`] varient is returned
98+
/// contaning the address, else the [`None`] variant is returned.
99+
///
100+
/// ## Example
101+
/// ```no_run
102+
/// let address: VirtAddr = VirtAddr::new(stat)
103+
/// .validate_user()
104+
/// .ok_or(AeroSyscallError::EFAULT)?;
105+
/// ```
106+
pub fn validate_user(self) -> Option<Self> {
107+
if self <= crate::arch::task::userland_last_address() {
108+
Some(self)
109+
} else {
110+
None
111+
}
112+
}
113+
114+
/// Reads `sizeof(T)` bytes from the virtual address and returns a mutable reference
115+
/// to the value (`&mut T`).
116+
///
117+
/// ## Example
118+
/// ```no_run
119+
/// let address: SomeStruct = VirtAddr::new(0xcafebabe)
120+
/// .read_mut::<SomeStruct>();
121+
/// ```
122+
///
123+
/// ## Safety
124+
/// * The virtual address must be valid.
125+
/// * It must be safe to read `sizeof(T)` bytes from the virtual address.
126+
pub unsafe fn read_mut<'struc, T>(&self) -> &'struc mut T {
127+
&mut *(self.as_mut_ptr() as *mut T)
128+
}
129+
97130
/// Aligns the virtual address downwards to the given alignment.
98131
///
99132
/// See the `align_down` function for more information.

src/aero_kernel/src/syscall/fs.rs

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ use aero_syscall::{AeroSyscallError, OpenFlags};
2323
use crate::fs::inode::DirEntry;
2424
use crate::fs::pipe::Pipe;
2525
use crate::fs::{self, lookup_path, LookupMode};
26+
use crate::mem::paging::VirtAddr;
2627
use crate::userland::scheduler;
2728

2829
use crate::fs::Path;
@@ -362,3 +363,22 @@ pub fn fcntl(fd: usize, command: usize, arg: usize) -> Result<usize, AeroSyscall
362363
_ => unimplemented!(),
363364
}
364365
}
366+
367+
pub fn stat(path: usize, path_size: usize, stat_struct: usize) -> Result<usize, AeroSyscallError> {
368+
let stat_struct = VirtAddr::new(stat_struct as _)
369+
.validate_user()
370+
.ok_or(AeroSyscallError::EFAULT)?;
371+
372+
// SAFETY: The user provided address is validated above.
373+
let stat_struct = unsafe { stat_struct.read_mut::<aero_syscall::Stat>() };
374+
375+
let path = validate_str(path as *mut u8, path_size).ok_or(AeroSyscallError::EINVAL)?;
376+
log::debug!("sys_stat: {path}");
377+
378+
let path = Path::new(path);
379+
380+
let file = fs::lookup_path(path)?;
381+
*stat_struct = file.inode().stat()?;
382+
383+
Ok(0)
384+
}

src/aero_kernel/src/syscall/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -184,6 +184,7 @@ pub fn generic_do_syscall(
184184
SYS_DUP => fs::dup(b, c),
185185
SYS_DUP2 => fs::dup2(b, c, d),
186186
SYS_FCNTL => fs::fcntl(b, c, d),
187+
SYS_STAT => fs::stat(b, c, d),
187188

188189
SYS_SOCKET => net::socket(b, c, d),
189190
SYS_BIND => net::bind(b, c, d),

src/aero_syscall/src/consts.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@ pub const SYS_IPC_SEND: usize = 45;
6767
pub const SYS_IPC_RECV: usize = 46;
6868
pub const SYS_IPC_DISCOVER_ROOT: usize = 47;
6969
pub const SYS_IPC_BECOME_ROOT: usize = 48;
70+
pub const SYS_STAT: usize = 49;
7071

7172
// fcntl constants:
7273
pub const F_GETFD: usize = 3;

src/aero_syscall/src/lib.rs

Lines changed: 66 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -284,7 +284,7 @@ impl Default for Utsname {
284284
}
285285
}
286286

287-
#[derive(Default, Clone)]
287+
#[derive(Default, Clone, Debug)]
288288
#[repr(C)]
289289
pub struct TimeSpec {
290290
pub tv_sec: isize,
@@ -874,3 +874,68 @@ pub fn sys_ipc_become_root() -> Result<(), AeroSyscallError> {
874874
let value = syscall0(prelude::SYS_IPC_BECOME_ROOT);
875875
isize_as_syscall_result(value as _).map(|_| ())
876876
}
877+
878+
// sysdeps/aero/include/abi-bits/stat.h
879+
bitflags::bitflags! {
880+
#[derive(Default)]
881+
pub struct Mode: u32 {
882+
const S_IFMT = 0x0F000;
883+
const S_IFBLK = 0x06000;
884+
const S_IFCHR = 0x02000;
885+
const S_IFIFO = 0x01000;
886+
const S_IFREG = 0x08000;
887+
const S_IFDIR = 0x04000;
888+
const S_IFLNK = 0x0A000;
889+
const S_IFSOCK = 0x0C000;
890+
891+
const S_IRWXU = 0700;
892+
const S_IRUSR = 0400;
893+
const S_IWUSR = 0200;
894+
const S_IXUSR = 0100;
895+
const S_IRWXG = 070;
896+
const S_IRGRP = 040;
897+
const S_IWGRP = 020;
898+
const S_IXGRP = 010;
899+
const S_IRWXO = 07;
900+
const S_IROTH = 04;
901+
const S_IWOTH = 02;
902+
const S_IXOTH = 01;
903+
const S_ISUID = 04000;
904+
const S_ISGID = 02000;
905+
const S_ISVTX = 01000;
906+
907+
const S_IREAD = Self::S_IRUSR.bits();
908+
const S_IWRITE = Self::S_IWUSR.bits();
909+
const S_IEXEC = Self::S_IXUSR.bits();
910+
}
911+
}
912+
913+
// sysdeps/aero/include/abi-bits/stat.h
914+
#[repr(C)]
915+
#[derive(Debug, Default)]
916+
pub struct Stat {
917+
pub st_dev: u64,
918+
pub st_ino: u64,
919+
pub st_mode: Mode,
920+
pub st_nlink: u32,
921+
pub st_uid: u32,
922+
pub st_gid: u32,
923+
pub st_rdev: u64,
924+
pub st_size: i64,
925+
pub st_atim: TimeSpec,
926+
pub st_mtim: TimeSpec,
927+
pub st_ctim: TimeSpec,
928+
pub st_blksize: u64,
929+
pub st_blocks: u64,
930+
}
931+
932+
pub fn sys_stat(path: &str, stat: &mut Stat) -> Result<usize, AeroSyscallError> {
933+
let value = syscall3(
934+
prelude::SYS_STAT,
935+
path.as_ptr() as usize,
936+
path.len(),
937+
stat as *mut Stat as usize,
938+
);
939+
940+
isize_as_syscall_result(value as _)
941+
}

0 commit comments

Comments
 (0)