diff --git a/include/bits/stdio.h b/include/bits/stdio.h index 0103f3e..b07c035 100644 --- a/include/bits/stdio.h +++ b/include/bits/stdio.h @@ -11,4 +11,9 @@ int scanf(const char *format, ...); int sscanf(const char *str, const char *format, ...); int fscanf(FILE *stream, const char *format, ...); +#define P_tmpdir "/tmp" + +#define FILENAME_MAX PATH_MAX +#define FOPEN_MAX OPEN_MAX + #endif diff --git a/src/header/limits/cbindgen.toml b/src/header/limits/cbindgen.toml new file mode 100644 index 0000000..266c02a --- /dev/null +++ b/src/header/limits/cbindgen.toml @@ -0,0 +1,13 @@ +language = "C" +style = "Type" + +sys_includes = ["stddef.h", "stdint.h"] +no_includes = true + +include_guard = "_LIMITS_H" + +usize_type = "size_t" +isize_type = "ssize_t" + +[export] +include = [] diff --git a/src/header/limits/mod.rs b/src/header/limits/mod.rs new file mode 100644 index 0000000..304e4a4 --- /dev/null +++ b/src/header/limits/mod.rs @@ -0,0 +1,19 @@ +// TODO take from yggdrasil-abi + +pub const FILESIZEBITS: usize = 64; +pub const MAX_CANON: usize = 64; +pub const LINK_MAX: usize = 4096; +pub const NAME_MAX: usize = 255; +pub const PATH_MAX: usize = 4096; + +pub const SYMLINK_MAX: usize = 4096; + +pub const PIPE_BUF: usize = 4096; + +pub const OPEN_MAX: u32 = u32::MAX - 1; +pub const STREAM_MAX: u32 = OPEN_MAX; + +pub const PAGESIZE: usize = 4096; +pub const PAGE_SIZE: usize = PAGESIZE; + +pub const ATEXIT_MAX: usize = 32; diff --git a/src/header/mod.rs b/src/header/mod.rs index 6c9bbeb..68052e0 100644 --- a/src/header/mod.rs +++ b/src/header/mod.rs @@ -4,6 +4,7 @@ pub mod sys_types; pub mod sys_wait; pub mod errno; +pub mod limits; pub mod locale; pub mod math; pub mod stdio; diff --git a/src/header/stdio/cbindgen.toml b/src/header/stdio/cbindgen.toml index bc66c65..d6a494f 100644 --- a/src/header/stdio/cbindgen.toml +++ b/src/header/stdio/cbindgen.toml @@ -1,7 +1,7 @@ language = "C" style = "Type" -sys_includes = ["stdarg.h", "stddef.h", "stdint.h", "sys/types.h"] +sys_includes = ["stdarg.h", "stddef.h", "stdint.h", "sys/types.h", "limits.h"] no_includes = true include_guard = "_STDIO_H" diff --git a/src/header/stdio/file.rs b/src/header/stdio/file.rs index 700ac71..b2fdc6e 100644 --- a/src/header/stdio/file.rs +++ b/src/header/stdio/file.rs @@ -43,6 +43,11 @@ fn open_inner(source: O, mode_str: &[u8]) -> Result<*mut FILE } } +#[no_mangle] +pub unsafe extern "C" fn ctermid(buffer: *mut c_char) -> *mut c_char { + todo!() +} + #[no_mangle] pub unsafe extern "C" fn fopen(pathname: *const c_char, mode: *const c_char) -> *mut FILE { if pathname.is_null() || mode.is_null() { @@ -52,10 +57,26 @@ pub unsafe extern "C" fn fopen(pathname: *const c_char, mode: *const c_char) -> let pathname = pathname.to_str().unwrap(); let mode = CStr::from_ptr(mode); - match open_inner(Path::from_str(pathname), mode.to_bytes()) { - Ok(file) => file, - Err(_) => null_mut(), + open_inner(Path::from_str(pathname), mode.to_bytes()).unwrap_or(null_mut()) +} + +#[no_mangle] +pub unsafe extern "C" fn fdopen(fd: c_int, mode: *const c_char) -> *mut FILE { + if fd < 0 || mode.is_null() { + panic!(); } + let mode = CStr::from_ptr(mode); + + open_inner(RawFd(fd as u32), mode.to_bytes()).unwrap_or(null_mut()) +} + +#[no_mangle] +unsafe extern "C" fn freopen( + pathname: *const c_char, + mode: *const c_char, + stream: *mut FILE, +) -> *mut FILE { + todo!() } #[no_mangle] @@ -229,3 +250,53 @@ pub unsafe extern "C" fn setbuffer(stream: *mut FILE, buf: *mut c_char, size: us pub unsafe extern "C" fn setlinebuf(stream: *mut FILE) { setvbuf(stream, null_mut(), _IOLBF, 0); } + +#[no_mangle] +unsafe extern "C" fn fmemopen(buffer: *mut c_void, size: usize, mode: *mut c_char) -> *mut FILE { + todo!() +} + +#[no_mangle] +unsafe extern "C" fn open_memstream(bufptr: *mut *mut c_char, sizeptr: *mut usize) -> *mut FILE { + todo!() +} + +#[no_mangle] +unsafe extern "C" fn popen(command: *const c_char, mode: *const c_char) -> *mut FILE { + todo!() +} + +#[no_mangle] +unsafe extern "C" fn pclose(stream: *mut FILE) -> c_int { + todo!() +} + +#[no_mangle] +unsafe extern "C" fn remove(pathname: *const c_char) -> c_int { + todo!() +} + +#[no_mangle] +unsafe extern "C" fn rename(oldname: *const c_char, newname: *const c_char) -> c_int { + todo!() +} + +#[no_mangle] +unsafe extern "C" fn renameat(fd: c_int, oldname: *const c_char, newname: *const c_char) -> c_int { + todo!() +} + +#[no_mangle] +unsafe extern "C" fn tempnam(dir: *const c_char, pfx: *const c_char) -> *mut c_char { + todo!() +} + +#[no_mangle] +unsafe extern "C" fn tmpfile() -> *mut FILE { + todo!() +} + +#[no_mangle] +unsafe extern "C" fn tmpnam(template: *mut c_char) -> *mut c_char { + todo!() +} diff --git a/src/header/stdio/get_put.rs b/src/header/stdio/get_put.rs index 52d228c..0513c05 100644 --- a/src/header/stdio/get_put.rs +++ b/src/header/stdio/get_put.rs @@ -4,11 +4,32 @@ use core::{ }; use crate::{ - header::stdlib::realloc, + error, + header::{stdlib::realloc, string::strlen}, io::{Read, Write}, }; -use super::{stdin, stdout, EOF, FILE}; +use super::{ + stderr, stdin, stdout, + unlocked::{flockfile, fputc_unlocked, fputs_unlocked, funlockfile, fwrite_unlocked}, + EOF, FILE, +}; + +#[no_mangle] +unsafe extern "C" fn perror(msg: *const c_char) { + flockfile(stderr); + + if !msg.is_null() { + fputs_unlocked(msg, stderr); + fputc_unlocked(b':' as _, stderr); + fputc_unlocked(b' ' as _, stderr); + } + + fputs_unlocked(error::errno.to_c_str(), stderr); + fputc_unlocked(b'\n' as _, stderr); + + funlockfile(stderr); +} // Chars diff --git a/src/header/stdio/mod.rs b/src/header/stdio/mod.rs index fb59d08..00b7c1e 100644 --- a/src/header/stdio/mod.rs +++ b/src/header/stdio/mod.rs @@ -20,45 +20,11 @@ use crate::{ sync::{Mutex, RawMutex}, }; -use super::errno::Errno; +use super::{errno::Errno, limits}; // TODO: // L_ctermid // L_tmpnam -// -// SEEK_CUR -// SEEK_END -// SEEK_SET -// -// FILENAME_MAX -// FOPEN_MAX -// TMP_MAX -// -// EOF -// -// P_tmpdir - -/* -char *ctermid(char *); -FILE *fdopen(int, const char *); -void flockfile(FILE *); -FILE *fmemopen(void *restrict, size_t, const char *restrict); -FILE *freopen(const char *restrict, const char *restrict, - FILE *restrict); -int ftrylockfile(FILE *); -void funlockfile(FILE *); -FILE *open_memstream(char **, size_t *); -int pclose(FILE *); -void perror(const char *); -FILE *popen(const char *, const char *); -int remove(const char *); -int rename(const char *, const char *); -int renameat(int, const char *, int, const char *); -char *tempnam(const char *, const char *); -FILE *tmpfile(void); -char *tmpnam(char *); - -*/ macro_rules! locked_op { ($self:expr, $op:expr) => {{ @@ -139,12 +105,16 @@ impl FILE { } } - pub unsafe fn new_builtin(fd: RawFd, flags: FileFlags) -> Self { + pub unsafe fn new_builtin(fd: RawFd, flags: FileFlags, buffered: bool) -> Self { let inner = FileBacking::File(File::new(fd)); Self { lock: RawMutex::new(), - output: Box::new(LineWriter::with_capacity(inner.make_ref(), BUFSIZ)), + output: if buffered { + Box::new(LineWriter::with_capacity(inner.make_ref(), BUFSIZ)) + } else { + Box::new(UnbufferedWriter::new(inner.make_ref())) + }, inner, read_buffer: Some(ReadBuffer::owned(BUFSIZ)), @@ -261,22 +231,22 @@ impl FILE { } } - unsafe fn ungetc_unlocked(&mut self, ch: u8) -> bool { - // ungetc() for write doesn't make any sense - if self.set_direction(Direction::Read).is_err() { - return false; - } - if self.ungetc.len() == UNGETC_MAX { - return false; - } - self.ungetc.push(ch); - true - } - pub fn ungetc(&mut self, ch: u8) -> bool { locked_op!(self, self.ungetc_unlocked(ch)) } + pub fn lock(&mut self) { + self.lock.lock(); + } + + pub fn try_lock(&mut self) -> bool { + self.lock.try_lock() + } + + pub unsafe fn unlock(&mut self) { + self.lock.release(); + } + fn reset(&mut self) { if let Some(read_buffer) = self.read_buffer.as_mut() { read_buffer.reset(); @@ -367,6 +337,18 @@ impl FILE { _ => Ok(()), } } + + unsafe fn ungetc_unlocked(&mut self, ch: u8) -> bool { + // ungetc() for write doesn't make any sense + if self.set_direction(Direction::Read).is_err() { + return false; + } + if self.ungetc.len() == UNGETC_MAX { + return false; + } + self.ungetc.push(ch); + true + } } impl fmt::Write for FILE { @@ -475,6 +457,8 @@ pub const SEEK_SET: c_int = 0; pub const SEEK_CUR: c_int = 1; pub const SEEK_END: c_int = 2; +pub const TMP_MAX: usize = 216000; + pub const EOF: c_int = -1; pub type fpos_t = u64; @@ -494,9 +478,21 @@ pub unsafe fn deregister_file(file: *mut FILE) -> bool { } pub unsafe fn setup_default_files() { - let stdin_ = Box::into_raw(Box::new(FILE::new_builtin(RawFd::STDIN, FileFlags::READ))); - let stdout_ = Box::into_raw(Box::new(FILE::new_builtin(RawFd::STDOUT, FileFlags::WRITE))); - let stderr_ = Box::into_raw(Box::new(FILE::new_builtin(RawFd::STDERR, FileFlags::WRITE))); + let stdin_ = Box::into_raw(Box::new(FILE::new_builtin( + RawFd::STDIN, + FileFlags::READ, + true, + ))); + let stdout_ = Box::into_raw(Box::new(FILE::new_builtin( + RawFd::STDOUT, + FileFlags::WRITE, + true, + ))); + let stderr_ = Box::into_raw(Box::new(FILE::new_builtin( + RawFd::STDERR, + FileFlags::WRITE, + false, + ))); stdin = stdin_; stdout = stdout_; diff --git a/src/header/stdio/unlocked.rs b/src/header/stdio/unlocked.rs index d57b8b6..1abbf79 100644 --- a/src/header/stdio/unlocked.rs +++ b/src/header/stdio/unlocked.rs @@ -1,10 +1,31 @@ -use core::ffi::{c_int, c_void}; +use core::ffi::{c_char, c_int, c_void, CStr}; use yggdrasil_rt::io::RawFd; use crate::error::{CSizeResult, CZeroResult}; -use super::{FileFlags, FILE}; +use super::{FileFlags, EOF, FILE}; + +#[no_mangle] +pub unsafe extern "C" fn flockfile(stream: *mut FILE) { + let stream = stream.as_mut().unwrap(); + stream.lock(); +} + +#[no_mangle] +pub unsafe extern "C" fn ftrylockfile(stream: *mut FILE) -> c_int { + let stream = stream.as_mut().unwrap(); + match stream.try_lock() { + true => 0, + false => -1, + } +} + +#[no_mangle] +pub unsafe extern "C" fn funlockfile(stream: *mut FILE) { + let stream = stream.as_mut().unwrap(); + stream.unlock(); +} #[no_mangle] pub unsafe extern "C" fn feof_unlocked(stream: *mut FILE) -> c_int { @@ -74,17 +95,46 @@ pub unsafe extern "C" fn fflush_unlocked(stream: *mut FILE) -> c_int { } } -/* -int getc_unlocked(FILE *stream); -int getchar_unlocked(void); -int putc_unlocked(int c, FILE *stream); -int putchar_unlocked(int c); - -int fgetc_unlocked(FILE *stream); -int fputc_unlocked(int c, FILE *stream); -*/ +#[no_mangle] +pub unsafe extern "C" fn fgetc_unlocked(stream: *mut FILE) -> c_int { + todo!() +} #[no_mangle] pub unsafe extern "C" fn getc_unlocked(stream: *mut FILE) -> c_int { todo!() } + +#[no_mangle] +pub unsafe extern "C" fn getchar_unlocked() -> c_int { + todo!() +} + +#[no_mangle] +pub unsafe extern "C" fn putchar_unlocked(c: c_char) -> c_int { + todo!() +} + +#[no_mangle] +pub unsafe fn fputc_unlocked(c: c_int, stream: *mut FILE) -> c_int { + let stream = stream.as_mut().unwrap(); + + match stream.write_unlocked(&[c as u8]) { + Ok(_) => c, + Err(_) => EOF, + } +} + +pub unsafe fn fputs_unlocked(s: *const c_char, stream: *mut FILE) -> c_int { + if s.is_null() { + panic!(); + } + + let s = CStr::from_ptr(s); + let stream = stream.as_mut().unwrap(); + + match stream.write_unlocked(s.to_bytes()) { + Ok(_) => 0, + Err(_) => EOF, + } +} diff --git a/src/header/string/mod.rs b/src/header/string/mod.rs index b9264b7..f5923cc 100644 --- a/src/header/string/mod.rs +++ b/src/header/string/mod.rs @@ -4,6 +4,6 @@ pub mod mem; pub mod str; extern "C" { - fn strlen(s: *const c_char) -> usize; - fn memset(a: *mut c_void, c: c_int, n: usize) -> *mut c_void; + pub fn strlen(s: *const c_char) -> usize; + pub fn memset(a: *mut c_void, c: c_int, n: usize) -> *mut c_void; } diff --git a/src/sync.rs b/src/sync.rs index dd78b57..7b58ad8 100644 --- a/src/sync.rs +++ b/src/sync.rs @@ -29,7 +29,7 @@ impl RawMutex { } } - fn try_lock(&self) -> bool { + pub fn try_lock(&self) -> bool { self.value .compare_exchange( Self::UNLOCKED,