fopen and tests

This commit is contained in:
nora 2023-10-04 21:35:18 +02:00
parent 862ef8dc22
commit b795ee80c9
14 changed files with 97 additions and 45 deletions

View file

@ -6,6 +6,15 @@ use core::{
use linked_list_allocator::LockedHeap;
pub fn boxed<T>(value: T) -> *mut T {
let ptr = unsafe { alloc_zeroed(Layout::new::<T>()) }.cast::<T>();
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::<usize>(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::<usize>().sub(1).read();

View file

@ -3,6 +3,7 @@ use crate::{
utils::SharedThinCstr,
};
#[derive(Clone, Copy)]
#[repr(transparent)]
pub struct Fd(pub i32);

View file

@ -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<usize, Error> {
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(())

View file

@ -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<OpenMode, &'static str> {
let mut buf = [0; 2];
let mut i = 0;

View file

@ -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<usize, Error> {
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 {

View file

@ -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]

View file

@ -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

View file

@ -1,9 +1,10 @@
#include <stdio.h>
#include <assert.h>
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");
}

16
tests/c/fopen.c Normal file
View file

@ -0,0 +1,16 @@
#include <stdio.h>
#include <errno.h>
#include <assert.h>
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");
}

View file

@ -1,14 +1,12 @@
#include <stdlib.h>
#include <assert.h>
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");
}

View file

@ -1,7 +1,10 @@
#include <stdlib.h>
#include <assert.h>
int main(void) {
int main(void)
{
char *alloc = (char *)malloc(10);
assert(alloc && "allocation failed");
*alloc = 1;
*(alloc + 9) = 2;
free(alloc);

View file

@ -1,13 +1,14 @@
#include <string.h>
#include <assert.h>
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");
}
}

View file

@ -1,8 +1,8 @@
#include <stdio.h>
#include <assert.h>
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");
}

View file

@ -1,9 +1,9 @@
#include <stdlib.h>
#include <assert.h>
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");
}