mirror of
https://github.com/Noratrieb/libuwuc.git
synced 2026-01-14 19:55:07 +01:00
implement more things
This commit is contained in:
parent
119d0f1443
commit
9e2cf38cd5
11 changed files with 177 additions and 12 deletions
|
|
@ -97,6 +97,50 @@ pub unsafe fn free(ptr: *mut u8) {
|
||||||
ALLOCATOR.dealloc(start, layout);
|
ALLOCATOR.dealloc(start, layout);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn array_size(nmemb: usize, size: usize) -> Option<usize> {
|
||||||
|
let total = nmemb.checked_mul(size)?;
|
||||||
|
if total > (isize::MAX as usize) {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
Some(total)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub unsafe fn malloc_zeroed_array(nmemb: usize, size: usize, align: usize) -> *mut u8 {
|
||||||
|
let Some(total) = nmemb.checked_mul(size) else {
|
||||||
|
return core::ptr::null_mut();
|
||||||
|
};
|
||||||
|
if total > (isize::MAX as usize) {
|
||||||
|
return core::ptr::null_mut();
|
||||||
|
}
|
||||||
|
malloc_zeroed(total, align)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub unsafe fn realloc(ptr: *mut u8, size: usize, align: usize) -> *mut u8 {
|
||||||
|
let new = malloc_zeroed(size, align);
|
||||||
|
if !new.is_null() {
|
||||||
|
core::ptr::copy_nonoverlapping(ptr, new, size);
|
||||||
|
}
|
||||||
|
free(ptr);
|
||||||
|
new
|
||||||
|
}
|
||||||
|
|
||||||
|
pub unsafe extern "C" fn reallocarray(
|
||||||
|
ptr: *mut u8,
|
||||||
|
nmemb: usize,
|
||||||
|
size: usize,
|
||||||
|
align: usize,
|
||||||
|
) -> *mut u8 {
|
||||||
|
let new = malloc_zeroed_array(size, size, align);
|
||||||
|
if !new.is_null() {
|
||||||
|
let Some(total) = array_size(nmemb, size) else {
|
||||||
|
return core::ptr::null_mut();
|
||||||
|
};
|
||||||
|
core::ptr::copy_nonoverlapping(ptr, new, total);
|
||||||
|
}
|
||||||
|
free(ptr);
|
||||||
|
new
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg_attr(miri, allow(unused_variables, unreachable_code))]
|
#[cfg_attr(miri, allow(unused_variables, unreachable_code))]
|
||||||
pub unsafe fn sys_mmap(
|
pub unsafe fn sys_mmap(
|
||||||
addr: *const u8,
|
addr: *const u8,
|
||||||
|
|
|
||||||
|
|
@ -273,8 +273,8 @@ impl super::Error {
|
||||||
pub const HWPOISON: Self = Self(EHWPOISON);
|
pub const HWPOISON: Self = Self(EHWPOISON);
|
||||||
pub const NOTSUP: Self = Self(ENOTSUP);
|
pub const NOTSUP: Self = Self(ENOTSUP);
|
||||||
|
|
||||||
pub fn simple_str(self) -> &'static str {
|
pub fn simple_str(self) -> Option<&'static str> {
|
||||||
match self {
|
Some(match self {
|
||||||
Self::PERM => "EPERM",
|
Self::PERM => "EPERM",
|
||||||
Self::NOENT => "ENOENT",
|
Self::NOENT => "ENOENT",
|
||||||
Self::SRCH => "ESRCH",
|
Self::SRCH => "ESRCH",
|
||||||
|
|
@ -406,7 +406,7 @@ impl super::Error {
|
||||||
Self::NOTRECOVERABLE => "ENOTRECOVERABLE",
|
Self::NOTRECOVERABLE => "ENOTRECOVERABLE",
|
||||||
Self::RFKILL => "ERFKILL",
|
Self::RFKILL => "ERFKILL",
|
||||||
Self::HWPOISON => "EHWPOISON",
|
Self::HWPOISON => "EHWPOISON",
|
||||||
_ => "<invalid error>",
|
_ => return None,
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -20,12 +20,17 @@ pub fn set_errno(errno: i32) {
|
||||||
unsafe { ERRNO.0.get().write(errno) }
|
unsafe { ERRNO.0.get().write(errno) }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn strerror(errnum: Error) -> Option<&'static str> {
|
||||||
|
errnum.simple_str()
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Copy, Clone, PartialEq, Eq)]
|
#[derive(Copy, Clone, PartialEq, Eq)]
|
||||||
|
#[repr(transparent)]
|
||||||
pub struct Error(pub i32);
|
pub struct Error(pub i32);
|
||||||
|
|
||||||
impl Debug for Error {
|
impl Debug for Error {
|
||||||
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
|
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
|
||||||
f.write_str(self.simple_str())
|
f.write_str(self.simple_str().unwrap_or("<error: invalid error>"))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -39,13 +39,17 @@ pub use println;
|
||||||
|
|
||||||
use self::fd::Fd;
|
use self::fd::Fd;
|
||||||
|
|
||||||
pub unsafe fn sys_write(fd: i32, buf: &[u8]) -> Result<usize, Error> {
|
pub unsafe fn sys_read(fd: Fd, buf: &mut [u8]) -> Result<usize, Error> {
|
||||||
syscall::syscall!(syscall::SYS_WRITE, fd, buf.as_ptr(), buf.len()).syscall_resultify()
|
syscall::syscall!(syscall::SYS_READ, fd.0, buf.as_ptr(), buf.len()).syscall_resultify()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub unsafe fn sys_write(fd: Fd, buf: &[u8]) -> Result<usize, Error> {
|
||||||
|
syscall::syscall!(syscall::SYS_WRITE, fd.0, buf.as_ptr(), buf.len()).syscall_resultify()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub unsafe fn write_all(fd: Fd, 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.0, buf)?;
|
let result = sys_write(fd, buf)?;
|
||||||
buf = &buf[result..];
|
buf = &buf[result..];
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|
|
||||||
|
|
@ -27,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.0, buf) }
|
unsafe { super::sys_write(self.fd, buf) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -16,6 +16,31 @@ pub unsafe fn memcpy(dest: *mut u8, src: *const u8, size: usize) -> *mut u8 {
|
||||||
dest
|
dest
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub unsafe fn memmove(dest: *mut u8, src: *const u8, size: usize) -> *mut u8 {
|
||||||
|
if dest as usize > src as usize {
|
||||||
|
// 1 2 3 4 5 6 7
|
||||||
|
// ^---- dest
|
||||||
|
// ^---- src
|
||||||
|
// We need to move backwards, first copying the 5 to 6, then 4 to 5 etc.
|
||||||
|
// Iterating fowards would overwrite 4 with 3 before we can copy 4.
|
||||||
|
for i in (0..size).rev() {
|
||||||
|
dest.add(i).write(src.add(i).read());
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// 1 2 3 4 5 6 7
|
||||||
|
// ^---- dest
|
||||||
|
// ^---- src
|
||||||
|
// We need to move forwards from src. This way we never overwrite values
|
||||||
|
// before we would need to read them.
|
||||||
|
for i in 0..size {
|
||||||
|
dest.add(i).write(src.add(i).read());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
dest
|
||||||
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub unsafe fn memcmp(s1: *const u8, s2: *const u8, size: usize) -> i32 {
|
pub unsafe fn memcmp(s1: *const u8, s2: *const u8, size: usize) -> i32 {
|
||||||
for i in 0..size {
|
for i in 0..size {
|
||||||
|
|
@ -56,6 +81,38 @@ mod tests {
|
||||||
assert_eq!(dest, src);
|
assert_eq!(dest, src);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn memmove_null() {
|
||||||
|
unsafe { super::memmove(std::ptr::null_mut(), std::ptr::null_mut(), 0) };
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn memmove_one_forwards() {
|
||||||
|
let mut arr = [1, 2, 3, 4, 5];
|
||||||
|
let src = arr.as_mut_ptr();
|
||||||
|
let dest = unsafe { src.add(1) };
|
||||||
|
unsafe { super::memmove(dest, src, 4) };
|
||||||
|
assert_eq!(arr, [1, 1, 2, 3, 4]);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn memmove_one_backwards() {
|
||||||
|
let mut arr = [1, 2, 3, 4, 5];
|
||||||
|
let src = unsafe { arr.as_mut_ptr().add(1) };
|
||||||
|
let dest = unsafe { src.sub(1) };
|
||||||
|
unsafe { super::memmove(dest, src, 4) };
|
||||||
|
assert_eq!(arr, [2, 3, 4, 5, 5]);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn memmove_full_overlap() {
|
||||||
|
let mut arr = [1, 2, 3, 4, 5];
|
||||||
|
let src = arr.as_mut_ptr();
|
||||||
|
let dest = src;
|
||||||
|
unsafe { super::memmove(src, dest, 4) };
|
||||||
|
assert_eq!(arr, [1, 2, 3, 4, 5]);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn memset_null() {
|
fn memset_null() {
|
||||||
unsafe { super::memset(std::ptr::null_mut(), 0, 0) };
|
unsafe { super::memset(std::ptr::null_mut(), 0, 0) };
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,7 @@ mod rt;
|
||||||
mod stdio;
|
mod stdio;
|
||||||
mod stdlib;
|
mod stdlib;
|
||||||
mod string;
|
mod string;
|
||||||
|
mod unistd;
|
||||||
|
|
||||||
// libcore seems to require this symbol, even though it's unused.
|
// libcore seems to require this symbol, even though it's unused.
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
|
|
|
||||||
|
|
@ -2,9 +2,13 @@ use core::ffi::{c_int, c_long};
|
||||||
|
|
||||||
use libuwuc::{error::IntoOkOrErrno, utils::SharedThinCstr};
|
use libuwuc::{error::IntoOkOrErrno, utils::SharedThinCstr};
|
||||||
|
|
||||||
|
// Allocation functions
|
||||||
|
|
||||||
|
const MAX_ALIGN: usize = 16;
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub unsafe extern "C" fn malloc(size: usize) -> *mut u8 {
|
pub unsafe extern "C" fn malloc(size: usize) -> *mut u8 {
|
||||||
libuwuc::alloc::malloc_zeroed(size, 16)
|
libuwuc::alloc::malloc_zeroed(size, MAX_ALIGN)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
|
|
@ -13,10 +17,22 @@ pub unsafe extern "C" fn free(ptr: *mut u8) {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub unsafe extern "C" fn exit(code: i32) -> ! {
|
pub unsafe extern "C" fn calloc(nmemb: usize, size: usize) -> *mut u8 {
|
||||||
libuwuc::start::sys_exit(code as i64 as _)
|
libuwuc::alloc::malloc_zeroed_array(nmemb, size, MAX_ALIGN)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
pub unsafe extern "C" fn realloc(ptr: *mut u8, size: usize) -> *mut u8 {
|
||||||
|
libuwuc::alloc::realloc(ptr, size, MAX_ALIGN)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
pub unsafe extern "C" fn reallocarray(ptr: *mut u8, nmemb: usize, size: usize) -> *mut u8 {
|
||||||
|
libuwuc::alloc::reallocarray(ptr, nmemb, size, MAX_ALIGN)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Integer parsing functions
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub unsafe extern "C" fn strtol(nptr: *const u8, endptr: *mut *const u8, base: c_int) -> c_long {
|
pub unsafe extern "C" fn strtol(nptr: *const u8, endptr: *mut *const u8, base: c_int) -> c_long {
|
||||||
let str = SharedThinCstr::from_raw(nptr);
|
let str = SharedThinCstr::from_raw(nptr);
|
||||||
|
|
@ -33,9 +49,16 @@ pub unsafe extern "C" fn strtoll(nptr: *const u8, endptr: *mut *const u8, base:
|
||||||
strtol(nptr, endptr, base)
|
strtol(nptr, endptr, base)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Other functions
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub unsafe extern "C" fn getenv(name: *const u8) -> *const u8 {
|
pub unsafe extern "C" fn getenv(name: *const u8) -> *const u8 {
|
||||||
libuwuc::env::getenv(SharedThinCstr::from_raw(name))
|
libuwuc::env::getenv(SharedThinCstr::from_raw(name))
|
||||||
.map(SharedThinCstr::as_raw)
|
.map(SharedThinCstr::as_raw)
|
||||||
.unwrap_or(core::ptr::null())
|
.unwrap_or(core::ptr::null())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
pub unsafe extern "C" fn exit(code: i32) -> ! {
|
||||||
|
libuwuc::start::sys_exit(code as i64 as _)
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,5 @@
|
||||||
|
use libuwuc::error::Error;
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub unsafe extern "C" fn memset(ptr: *mut u8, constant: u8, len: usize) {
|
pub unsafe extern "C" fn memset(ptr: *mut u8, constant: u8, len: usize) {
|
||||||
libuwuc::mem::memset(ptr, constant, len)
|
libuwuc::mem::memset(ptr, constant, len)
|
||||||
|
|
@ -8,6 +10,11 @@ pub unsafe extern "C" fn memcpy(dest: *mut u8, src: *const u8, size: usize) -> *
|
||||||
libuwuc::mem::memcpy(dest, src, size)
|
libuwuc::mem::memcpy(dest, src, size)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
pub unsafe extern "C" fn memmove(dest: *mut u8, src: *const u8, size: usize) -> *mut u8 {
|
||||||
|
libuwuc::mem::memmove(dest, src, size)
|
||||||
|
}
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub unsafe extern "C" fn memcmp(s1: *const u8, s2: *const u8, size: usize) -> i32 {
|
pub unsafe extern "C" fn memcmp(s1: *const u8, s2: *const u8, size: usize) -> i32 {
|
||||||
libuwuc::mem::memcmp(s1, s2, size)
|
libuwuc::mem::memcmp(s1, s2, size)
|
||||||
|
|
@ -22,3 +29,10 @@ pub unsafe extern "C" fn bcmp(s1: *const u8, s2: *const u8, size: usize) -> i32
|
||||||
pub unsafe extern "C" fn strlen(s: *const u8) -> usize {
|
pub unsafe extern "C" fn strlen(s: *const u8) -> usize {
|
||||||
libuwuc::mem::strlen(s)
|
libuwuc::mem::strlen(s)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
pub unsafe extern "C" fn strerror(errnum: Error) -> *const u8 {
|
||||||
|
libuwuc::error::strerror(errnum)
|
||||||
|
.map(str::as_ptr)
|
||||||
|
.unwrap_or(core::ptr::null())
|
||||||
|
}
|
||||||
|
|
|
||||||
16
rawc/src/unistd.rs
Normal file
16
rawc/src/unistd.rs
Normal file
|
|
@ -0,0 +1,16 @@
|
||||||
|
use libuwuc::error::IntoOkOrErrno;
|
||||||
|
use libuwuc::io::fd::Fd;
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
pub unsafe extern "C" fn read(fd: Fd, buf: *mut u8, count: usize) -> isize {
|
||||||
|
libuwuc::io::sys_read(fd, core::slice::from_raw_parts_mut(buf, count))
|
||||||
|
.map(|n| n as isize)
|
||||||
|
.into_ok_or_errno()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
pub unsafe extern "C" fn write(fd: Fd, buf: *const u8, count: usize) -> isize {
|
||||||
|
libuwuc::io::sys_write(fd, core::slice::from_raw_parts(buf, count))
|
||||||
|
.map(|n| n as isize)
|
||||||
|
.into_ok_or_errno()
|
||||||
|
}
|
||||||
|
|
@ -15,3 +15,4 @@ ensure_cloned() {
|
||||||
}
|
}
|
||||||
|
|
||||||
ensure_cloned "https://github.com/tsoding/noed.git" "tsoding_noed" "1c2bd182139080a8448a59589e8d457a7019d553"
|
ensure_cloned "https://github.com/tsoding/noed.git" "tsoding_noed" "1c2bd182139080a8448a59589e8d457a7019d553"
|
||||||
|
ensure_cloned "https://github.com/zesterer/tosh.git" "zest_tosh" "fa43ee9ec01a625f6a96cb48662f6c8911d8cc8c"
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue