mirror of
https://github.com/Noratrieb/libuwuc.git
synced 2026-01-14 19:55:07 +01:00
fopen and tests
This commit is contained in:
parent
862ef8dc22
commit
b795ee80c9
14 changed files with 97 additions and 45 deletions
|
|
@ -6,6 +6,15 @@ use core::{
|
||||||
|
|
||||||
use linked_list_allocator::LockedHeap;
|
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();
|
static ALLOCATOR: LockedHeap = LockedHeap::empty();
|
||||||
|
|
||||||
const UNINIT: usize = 0;
|
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
|
|start |align |offset |RETURN VALUE
|
||||||
*/
|
*/
|
||||||
|
|
@ -59,7 +68,7 @@ pub unsafe fn malloc_zeroed(size: usize, align: usize) -> *mut u8 {
|
||||||
init();
|
init();
|
||||||
let (layout, offset) = Layout::array::<usize>(3)
|
let (layout, offset) = Layout::array::<usize>(3)
|
||||||
.unwrap_unchecked()
|
.unwrap_unchecked()
|
||||||
.extend(Layout::from_size_align_unchecked(size, align))
|
.extend(layout)
|
||||||
.unwrap_unchecked();
|
.unwrap_unchecked();
|
||||||
|
|
||||||
let ptr = ALLOCATOR.alloc_zeroed(layout);
|
let ptr = ALLOCATOR.alloc_zeroed(layout);
|
||||||
|
|
@ -75,6 +84,10 @@ pub unsafe fn malloc_zeroed(size: usize, align: usize) -> *mut u8 {
|
||||||
ret_ptr
|
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) {
|
pub unsafe fn free(ptr: *mut u8) {
|
||||||
init();
|
init();
|
||||||
let offset = ptr.cast::<usize>().sub(1).read();
|
let offset = ptr.cast::<usize>().sub(1).read();
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,7 @@ use crate::{
|
||||||
utils::SharedThinCstr,
|
utils::SharedThinCstr,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#[derive(Clone, Copy)]
|
||||||
#[repr(transparent)]
|
#[repr(transparent)]
|
||||||
pub struct Fd(pub i32);
|
pub struct Fd(pub i32);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -11,14 +11,14 @@ use crate::{
|
||||||
sys::syscall,
|
sys::syscall,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub const STDIN: i32 = 0;
|
pub const STDIN: Fd = Fd(0);
|
||||||
pub const STDOUT: i32 = 1;
|
pub const STDOUT: Fd = Fd(1);
|
||||||
pub const STDERR: i32 = 2;
|
pub const STDERR: Fd = Fd(2);
|
||||||
|
|
||||||
pub const EOF: i32 = -1;
|
pub const EOF: i32 = -1;
|
||||||
|
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
pub struct Printer(pub i32);
|
pub struct Printer(pub Fd);
|
||||||
|
|
||||||
impl core::fmt::Write for Printer {
|
impl core::fmt::Write for Printer {
|
||||||
fn write_str(&mut self, s: &str) -> core::fmt::Result {
|
fn write_str(&mut self, s: &str) -> core::fmt::Result {
|
||||||
|
|
@ -37,13 +37,15 @@ macro_rules! println {
|
||||||
}
|
}
|
||||||
pub use println;
|
pub use println;
|
||||||
|
|
||||||
|
use self::fd::Fd;
|
||||||
|
|
||||||
pub unsafe fn sys_write(fd: i32, buf: &[u8]) -> Result<usize, Error> {
|
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()
|
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() {
|
while !buf.is_empty() {
|
||||||
let result = sys_write(fd, buf)?;
|
let result = sys_write(fd.0, buf)?;
|
||||||
buf = &buf[result..];
|
buf = &buf[result..];
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
use crate::utils::SharedThinCstr;
|
use crate::{io::fd, utils::SharedThinCstr};
|
||||||
|
|
||||||
#[derive(Debug, PartialEq)]
|
#[derive(Debug, PartialEq)]
|
||||||
pub enum OpenMode {
|
pub enum OpenMode {
|
||||||
|
|
@ -11,6 +11,17 @@ pub enum OpenMode {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl 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> {
|
pub fn parse(str: SharedThinCstr<'_>) -> Result<OpenMode, &'static str> {
|
||||||
let mut buf = [0; 2];
|
let mut buf = [0; 2];
|
||||||
let mut i = 0;
|
let mut i = 0;
|
||||||
|
|
|
||||||
|
|
@ -1,19 +1,22 @@
|
||||||
pub mod file;
|
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::{fd::Fd, IoWrite, EOF};
|
||||||
|
|
||||||
use super::{IoWrite, EOF};
|
|
||||||
|
|
||||||
/// A `FILE`.
|
/// A `FILE`.
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
pub struct FileStream {
|
pub struct FileStream {
|
||||||
fd: c_int,
|
fd: Fd,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl FileStream {
|
impl FileStream {
|
||||||
pub const fn from_raw_fd(fd: c_int) -> Self {
|
pub const fn from_raw_fd(fd: Fd) -> Self {
|
||||||
Self { fd }
|
Self { fd }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -24,7 +27,7 @@ impl FileStream {
|
||||||
|
|
||||||
impl IoWrite for &FileStream {
|
impl IoWrite for &FileStream {
|
||||||
fn write(&mut self, buf: &[u8]) -> Result<usize, Error> {
|
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);
|
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 {
|
pub fn fputc(c: u8, stream: &FileStream) -> i32 {
|
||||||
|
|
|
||||||
|
|
@ -91,7 +91,9 @@ pub unsafe extern "C" fn fopen<'a>(
|
||||||
pathname: SharedThinCstr,
|
pathname: SharedThinCstr,
|
||||||
mode: SharedThinCstr,
|
mode: SharedThinCstr,
|
||||||
) -> Option<&'a FileStream> {
|
) -> Option<&'a FileStream> {
|
||||||
todo!()
|
libuwuc::io::stream::fopen(pathname, mode)
|
||||||
|
.map_err(|err| libuwuc::error::set_errno(err.0))
|
||||||
|
.ok()
|
||||||
}
|
}
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,7 @@ clean() {
|
||||||
rm -r "${test_dir}"
|
rm -r "${test_dir}"
|
||||||
}
|
}
|
||||||
|
|
||||||
for test in tests/c/*; do
|
for test in "$SCRIPT_DIR"/tests/c/*; do
|
||||||
name=$(basename $test .c)
|
name=$(basename $test .c)
|
||||||
printf "test $name "
|
printf "test $name "
|
||||||
|
|
||||||
|
|
@ -31,7 +31,7 @@ for test in tests/c/*; do
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
cd "$SCRIPT_DIR/tests"
|
||||||
OUTPUT=$("$test_dir/$name")
|
OUTPUT=$("$test_dir/$name")
|
||||||
code="$?"
|
code="$?"
|
||||||
if [ "$code" -ne "0" ]; then
|
if [ "$code" -ne "0" ]; then
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,10 @@
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
#include <assert.h>
|
||||||
|
|
||||||
int main(int argc, char *argv[]) {
|
int main(int argc, char *argv[])
|
||||||
|
{
|
||||||
char *self = argv[0];
|
char *self = argv[0];
|
||||||
char first = self[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
16
tests/c/fopen.c
Normal 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");
|
||||||
|
}
|
||||||
|
|
@ -1,14 +1,12 @@
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
#include <assert.h>
|
||||||
|
|
||||||
int main(int argc, char *argv[]) {
|
int main(int argc, char *argv[])
|
||||||
|
{
|
||||||
char *env = getenv("PATH");
|
char *env = getenv("PATH");
|
||||||
if (!env) {
|
assert(env && "PATH doesnt exist");
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
char *env2 = getenv(
|
char *env2 = getenv(
|
||||||
"__some absolutely NONSENSE that no one would ever define please..");
|
"__some absolutely NONSENSE that no one would ever define please..");
|
||||||
if (env2) {
|
assert(!env2 && "nonsense environment variable found");
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,10 @@
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
#include <assert.h>
|
||||||
|
|
||||||
int main(void) {
|
int main(void)
|
||||||
|
{
|
||||||
char *alloc = (char *)malloc(10);
|
char *alloc = (char *)malloc(10);
|
||||||
|
assert(alloc && "allocation failed");
|
||||||
*alloc = 1;
|
*alloc = 1;
|
||||||
*(alloc + 9) = 2;
|
*(alloc + 9) = 2;
|
||||||
free(alloc);
|
free(alloc);
|
||||||
|
|
|
||||||
|
|
@ -1,13 +1,14 @@
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <assert.h>
|
||||||
|
|
||||||
int main(void) {
|
int main(void)
|
||||||
|
{
|
||||||
char buf[10];
|
char buf[10];
|
||||||
|
|
||||||
memset(buf, 34, sizeof(buf));
|
memset(buf, 34, sizeof(buf));
|
||||||
|
|
||||||
for (int i = 0; i < 10; ++i) {
|
for (int i = 0; i < 10; ++i)
|
||||||
if (buf[i] != 34) {
|
{
|
||||||
return 1;
|
assert((buf[i] == 34) && "memset failed to write byte");
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1,8 +1,8 @@
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
#include <assert.h>
|
||||||
|
|
||||||
int main(int argc, char *argv[]) {
|
int main(int argc, char *argv[])
|
||||||
|
{
|
||||||
int result = printf("Hello, world!\n");
|
int result = printf("Hello, world!\n");
|
||||||
if (result != 14) {
|
assert((result == 14) && "printf returned wrong number of chars");
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,9 @@
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
#include <assert.h>
|
||||||
|
|
||||||
int main(void) {
|
int main(void)
|
||||||
|
{
|
||||||
char *str = "12";
|
char *str = "12";
|
||||||
long value = strtol(str, NULL, 10);
|
long value = strtol(str, NULL, 10);
|
||||||
if (value != 12) {
|
assert((value == 12) && "value must be 12");
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue