From b795ee80c9a001a46b036740da30c0280851ecb7 Mon Sep 17 00:00:00 2001 From: Nilstrieb <48135649+Nilstrieb@users.noreply.github.com> Date: Wed, 4 Oct 2023 21:35:18 +0200 Subject: [PATCH] fopen and tests --- libuwuc/src/alloc.rs | 17 +++++++++++++++-- libuwuc/src/io/fd.rs | 1 + libuwuc/src/io/mod.rs | 14 ++++++++------ libuwuc/src/io/stream/file.rs | 13 ++++++++++++- libuwuc/src/io/stream/mod.rs | 20 ++++++++++++-------- rawc/src/stdio.rs | 4 +++- test_c.sh | 4 ++-- tests/c/argv.c | 9 +++++---- tests/c/fopen.c | 16 ++++++++++++++++ tests/c/getenv.c | 12 +++++------- tests/c/malloc.c | 5 ++++- tests/c/mem.c | 11 ++++++----- tests/c/simple_printf.c | 8 ++++---- tests/c/strtol.c | 8 ++++---- 14 files changed, 97 insertions(+), 45 deletions(-) create mode 100644 tests/c/fopen.c diff --git a/libuwuc/src/alloc.rs b/libuwuc/src/alloc.rs index 1c8b02b..11e33db 100644 --- a/libuwuc/src/alloc.rs +++ b/libuwuc/src/alloc.rs @@ -6,6 +6,15 @@ use core::{ use linked_list_allocator::LockedHeap; +pub fn boxed(value: T) -> *mut T { + let ptr = unsafe { alloc_zeroed(Layout::new::()) }.cast::(); + if ptr.is_null() { + return ptr; + } + unsafe { ptr.write(value) }; + ptr +} + static ALLOCATOR: LockedHeap = LockedHeap::empty(); const UNINIT: usize = 0; @@ -51,7 +60,7 @@ fn init() { } } -pub unsafe fn malloc_zeroed(size: usize, align: usize) -> *mut u8 { +pub unsafe fn alloc_zeroed(layout: Layout) -> *mut u8 { /* |start |align |offset |RETURN VALUE */ @@ -59,7 +68,7 @@ pub unsafe fn malloc_zeroed(size: usize, align: usize) -> *mut u8 { init(); let (layout, offset) = Layout::array::(3) .unwrap_unchecked() - .extend(Layout::from_size_align_unchecked(size, align)) + .extend(layout) .unwrap_unchecked(); let ptr = ALLOCATOR.alloc_zeroed(layout); @@ -75,6 +84,10 @@ pub unsafe fn malloc_zeroed(size: usize, align: usize) -> *mut u8 { ret_ptr } +pub unsafe fn malloc_zeroed(size: usize, align: usize) -> *mut u8 { + alloc_zeroed(Layout::from_size_align_unchecked(size, align)) +} + pub unsafe fn free(ptr: *mut u8) { init(); let offset = ptr.cast::().sub(1).read(); diff --git a/libuwuc/src/io/fd.rs b/libuwuc/src/io/fd.rs index be7d9cd..34c696c 100644 --- a/libuwuc/src/io/fd.rs +++ b/libuwuc/src/io/fd.rs @@ -3,6 +3,7 @@ use crate::{ utils::SharedThinCstr, }; +#[derive(Clone, Copy)] #[repr(transparent)] pub struct Fd(pub i32); diff --git a/libuwuc/src/io/mod.rs b/libuwuc/src/io/mod.rs index 1a45752..c3515ab 100644 --- a/libuwuc/src/io/mod.rs +++ b/libuwuc/src/io/mod.rs @@ -11,14 +11,14 @@ use crate::{ sys::syscall, }; -pub const STDIN: i32 = 0; -pub const STDOUT: i32 = 1; -pub const STDERR: i32 = 2; +pub const STDIN: Fd = Fd(0); +pub const STDOUT: Fd = Fd(1); +pub const STDERR: Fd = Fd(2); pub const EOF: i32 = -1; #[doc(hidden)] -pub struct Printer(pub i32); +pub struct Printer(pub Fd); impl core::fmt::Write for Printer { fn write_str(&mut self, s: &str) -> core::fmt::Result { @@ -37,13 +37,15 @@ macro_rules! println { } pub use println; +use self::fd::Fd; + pub unsafe fn sys_write(fd: i32, buf: &[u8]) -> Result { syscall::syscall!(syscall::SYS_WRITE, fd, buf.as_ptr(), buf.len()).syscall_resultify() } -pub unsafe fn write_all(fd: i32, mut buf: &[u8]) -> Result<(), Error> { +pub unsafe fn write_all(fd: Fd, mut buf: &[u8]) -> Result<(), Error> { while !buf.is_empty() { - let result = sys_write(fd, buf)?; + let result = sys_write(fd.0, buf)?; buf = &buf[result..]; } Ok(()) diff --git a/libuwuc/src/io/stream/file.rs b/libuwuc/src/io/stream/file.rs index 3b47bc8..ceee518 100644 --- a/libuwuc/src/io/stream/file.rs +++ b/libuwuc/src/io/stream/file.rs @@ -1,4 +1,4 @@ -use crate::utils::SharedThinCstr; +use crate::{io::fd, utils::SharedThinCstr}; #[derive(Debug, PartialEq)] pub enum OpenMode { @@ -11,6 +11,17 @@ pub enum OpenMode { } impl OpenMode { + pub fn flags(self) -> i32 { + match self { + OpenMode::R => fd::O_RDONLY, + OpenMode::RP => fd::O_RDWR, + OpenMode::W => fd::O_WRONLY | fd::O_CREAT | fd::O_TRUNC, + OpenMode::WP => fd::O_RDWR | fd::O_CREAT | fd::O_TRUNC, + OpenMode::A => fd::O_WRONLY | fd::O_CREAT | fd::O_APPEND, + OpenMode::AP => fd::O_RDWR | fd::O_CREAT | fd::O_APPEND, + } + } + pub fn parse(str: SharedThinCstr<'_>) -> Result { let mut buf = [0; 2]; let mut i = 0; diff --git a/libuwuc/src/io/stream/mod.rs b/libuwuc/src/io/stream/mod.rs index 988cb94..32281e3 100644 --- a/libuwuc/src/io/stream/mod.rs +++ b/libuwuc/src/io/stream/mod.rs @@ -1,19 +1,22 @@ pub mod file; -use core::ffi::c_int; +use crate::{ + alloc, + error::Error, + io::{fd, stream::file::OpenMode}, + utils::SharedThinCstr, +}; -use crate::{error::Error, io::stream::file::OpenMode, utils::SharedThinCstr}; - -use super::{IoWrite, EOF}; +use super::{fd::Fd, IoWrite, EOF}; /// A `FILE`. #[repr(C)] pub struct FileStream { - fd: c_int, + fd: Fd, } impl FileStream { - pub const fn from_raw_fd(fd: c_int) -> Self { + pub const fn from_raw_fd(fd: Fd) -> Self { Self { fd } } @@ -24,7 +27,7 @@ impl FileStream { impl IoWrite for &FileStream { fn write(&mut self, buf: &[u8]) -> Result { - unsafe { super::sys_write(self.fd, buf) } + unsafe { super::sys_write(self.fd.0, buf) } } } @@ -36,7 +39,8 @@ pub unsafe fn fopen<'a>( return Err(Error::INVAL); }; - todo!() + let fd = fd::open(pathname, mode.flags())?; + unsafe { Ok(&*alloc::boxed(FileStream { fd })) } } pub fn fputc(c: u8, stream: &FileStream) -> i32 { diff --git a/rawc/src/stdio.rs b/rawc/src/stdio.rs index 6c61bde..b2c8295 100644 --- a/rawc/src/stdio.rs +++ b/rawc/src/stdio.rs @@ -91,7 +91,9 @@ pub unsafe extern "C" fn fopen<'a>( pathname: SharedThinCstr, mode: SharedThinCstr, ) -> Option<&'a FileStream> { - todo!() + libuwuc::io::stream::fopen(pathname, mode) + .map_err(|err| libuwuc::error::set_errno(err.0)) + .ok() } #[no_mangle] diff --git a/test_c.sh b/test_c.sh index c590301..ef33428 100755 --- a/test_c.sh +++ b/test_c.sh @@ -10,7 +10,7 @@ clean() { rm -r "${test_dir}" } -for test in tests/c/*; do +for test in "$SCRIPT_DIR"/tests/c/*; do name=$(basename $test .c) printf "test $name " @@ -31,7 +31,7 @@ for test in tests/c/*; do exit 1 fi - + cd "$SCRIPT_DIR/tests" OUTPUT=$("$test_dir/$name") code="$?" if [ "$code" -ne "0" ]; then diff --git a/tests/c/argv.c b/tests/c/argv.c index 274d6bf..115aeef 100644 --- a/tests/c/argv.c +++ b/tests/c/argv.c @@ -1,9 +1,10 @@ #include +#include -int main(int argc, char *argv[]) { +int main(int argc, char *argv[]) +{ char *self = argv[0]; char first = self[0]; - if (first != '/') { - return 1; - } + + assert((first < 128) && "argv[0] is not ascii/utf-8"); } \ No newline at end of file diff --git a/tests/c/fopen.c b/tests/c/fopen.c new file mode 100644 index 0000000..dc728bc --- /dev/null +++ b/tests/c/fopen.c @@ -0,0 +1,16 @@ +#include +#include +#include + +int main(int argc, char *argv[]) { + FILE *file1 = fopen("./c/fopen.c", "r"); + assert(file1 && "failed to open file"); + + FILE *file2 = fopen("./c/fopen.c", "meow"); + assert(!file2 && "succeeded opening file despite invalid argument"); + assert((errno == EINVAL) && "wrong errno"); + + FILE *file3 = fopen("/this-does-absolutely-not-exist-at-all-edhjkefhew98", "r"); + assert(!file3 && "succeeded despite file not existing"); + assert((errno == ENOENT) && "wrong errno"); +} \ No newline at end of file diff --git a/tests/c/getenv.c b/tests/c/getenv.c index a4a348c..2a1adfa 100644 --- a/tests/c/getenv.c +++ b/tests/c/getenv.c @@ -1,14 +1,12 @@ #include +#include -int main(int argc, char *argv[]) { +int main(int argc, char *argv[]) +{ char *env = getenv("PATH"); - if (!env) { - return 1; - } + assert(env && "PATH doesnt exist"); char *env2 = getenv( "__some absolutely NONSENSE that no one would ever define please.."); - if (env2) { - return 1; - } + assert(!env2 && "nonsense environment variable found"); } diff --git a/tests/c/malloc.c b/tests/c/malloc.c index 818263b..1826258 100644 --- a/tests/c/malloc.c +++ b/tests/c/malloc.c @@ -1,7 +1,10 @@ #include +#include -int main(void) { +int main(void) +{ char *alloc = (char *)malloc(10); + assert(alloc && "allocation failed"); *alloc = 1; *(alloc + 9) = 2; free(alloc); diff --git a/tests/c/mem.c b/tests/c/mem.c index b231301..825accd 100644 --- a/tests/c/mem.c +++ b/tests/c/mem.c @@ -1,13 +1,14 @@ #include +#include -int main(void) { +int main(void) +{ char buf[10]; memset(buf, 34, sizeof(buf)); - for (int i = 0; i < 10; ++i) { - if (buf[i] != 34) { - return 1; - } + for (int i = 0; i < 10; ++i) + { + assert((buf[i] == 34) && "memset failed to write byte"); } } \ No newline at end of file diff --git a/tests/c/simple_printf.c b/tests/c/simple_printf.c index e56f7a5..b506304 100644 --- a/tests/c/simple_printf.c +++ b/tests/c/simple_printf.c @@ -1,8 +1,8 @@ #include +#include -int main(int argc, char *argv[]) { +int main(int argc, char *argv[]) +{ int result = printf("Hello, world!\n"); - if (result != 14) { - return 1; - } + assert((result == 14) && "printf returned wrong number of chars"); } diff --git a/tests/c/strtol.c b/tests/c/strtol.c index 11fbc04..3ab849f 100644 --- a/tests/c/strtol.c +++ b/tests/c/strtol.c @@ -1,9 +1,9 @@ #include +#include -int main(void) { +int main(void) +{ char *str = "12"; long value = strtol(str, NULL, 10); - if (value != 12) { - return 1; - } + assert((value == 12) && "value must be 12"); }