Fix warnings and make it enough to build binutils
This commit is contained in:
parent
85eb9a7c74
commit
af1b621042
@ -11,6 +11,7 @@ yggdrasil-rt = { git = "https://git.alnyan.me/yggdrasil/yggdrasil-rt.git" }
|
||||
libyalloc = { git = "https://git.alnyan.me/yggdrasil/libyalloc.git" }
|
||||
bitflags = { version = "2.4.1" }
|
||||
chrono = { version = "0.4.31", default-features = false }
|
||||
linked_list_allocator = { version = "0.10.5", default-features = false }
|
||||
|
||||
[build-dependencies]
|
||||
cbindgen = { git = "https://git.alnyan.me/yggdrasil/cbindgen.git", branch = "master" }
|
||||
|
@ -1,12 +1,10 @@
|
||||
#ifndef _ASSERT_H
|
||||
#define _ASSERT_H 1
|
||||
|
||||
#define assert(x) \
|
||||
do { \
|
||||
if (!(x)) { \
|
||||
__assert_fail(__FILE__, __LINE__, #x); \
|
||||
} \
|
||||
} while(0)
|
||||
#define __ASSERT_VOID_CAST (void)
|
||||
|
||||
#define assert(expr) \
|
||||
((expr) ? __ASSERT_VOID_CAST(0) : __assert_fail(__FILE__, __LINE__, #expr))
|
||||
|
||||
[[noreturn]] void __assert_fail(const char *file, int line, const char *message);
|
||||
|
||||
|
15
include/bits/signal.h
Normal file
15
include/bits/signal.h
Normal file
@ -0,0 +1,15 @@
|
||||
#ifndef _YGGDRASIL_SIGNAL_H
|
||||
#define _YGGDRASIL_SIGNAL_H 1
|
||||
#include <stdatomic.h>
|
||||
|
||||
typedef _Atomic int sig_atomic_t;
|
||||
|
||||
#define SIG_IGN __sig_ignore
|
||||
// TODO
|
||||
#define SIG_ERR __sig_terminate
|
||||
// TODO
|
||||
#define SIG_HOLD __sig_terminate
|
||||
|
||||
#define SIG_DFL ((sig_handler_t) 0)
|
||||
|
||||
#endif
|
@ -3,8 +3,8 @@
|
||||
|
||||
int printf(const char *format, ...);
|
||||
int fprintf(FILE *stream, const char *format, ...);
|
||||
int sprintf(FILE *stream, const char *format, ...);
|
||||
int snprintf(FILE *stream, size_t len, const char *format, ...);
|
||||
int sprintf(char *dst, const char *format, ...);
|
||||
int snprintf(char *dst, size_t len, const char *format, ...);
|
||||
int dprintf(int fd, const char *format, ...);
|
||||
|
||||
int scanf(const char *format, ...);
|
||||
|
7
include/bits/sys/param.h
Normal file
7
include/bits/sys/param.h
Normal file
@ -0,0 +1,7 @@
|
||||
#ifndef _YGGDRASIL_SYS_PARAM_H
|
||||
#define _YGGDRASIL_SYS_PARAM_H 1
|
||||
|
||||
#define MIN(a, b) (((a) < (b)) ? (a) : (b))
|
||||
#define MAX(a, b) (((a) > (b)) ? (a) : (b))
|
||||
|
||||
#endif
|
12
include/bits/sys/select.h
Normal file
12
include/bits/sys/select.h
Normal file
@ -0,0 +1,12 @@
|
||||
#ifndef _YGGDRASIL_SYS_SELECT_H
|
||||
#define _YGGDRASIL_SYS_SELECT_H 1
|
||||
|
||||
#define __FD_INDEX(fd) ((fd) / sizeof(uint64_t))
|
||||
#define __FD_BIT(fd) ((fd) % sizeof(uint64_t))
|
||||
|
||||
#define FD_CLR(fd, set) ((set)->bits[__FD_INDEX(fd)] &= ~(1 << __FD_BIT(fd)))
|
||||
#define FD_ISSET(fd, set) (((set)->bits[__FD_INDEX(fd)] & (1 << __FD_BIT(fd))) != 0)
|
||||
#define FD_SET(fd, set) ((set)->bits[__FD_INDEX(fd)] |= (1 << __FD_BIT(fd)))
|
||||
#define FD_ZERO(set) ((void) memset((set)->bits, 0, sizeof((set)->bits)))
|
||||
|
||||
#endif
|
@ -8,7 +8,7 @@
|
||||
#define S_ISBLK(m) (((m) & S_IFMT) == S_IFBLK)
|
||||
#define S_ISCHR(m) (((m) & S_IFMT) == S_IFCHR)
|
||||
#define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR)
|
||||
#define S_ISFIFO(m) (((m) & S_IFMT) == S_IFFIFO)
|
||||
#define S_ISFIFO(m) (((m) & S_IFMT) == S_IFIFO)
|
||||
#define S_ISREG(m) (((m) & S_IFMT) == S_IFREG)
|
||||
#define S_ISLNK(m) (((m) & S_IFMT) == S_IFLNK)
|
||||
#define S_ISSOCK(m) (((m) & S_IFMT) == S_IFSOCK)
|
||||
|
46
include/inttypes.h
Normal file
46
include/inttypes.h
Normal file
@ -0,0 +1,46 @@
|
||||
#ifndef _INTTYPES_H
|
||||
#define _INTTYPES_H 1
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#define PRIo64 "lo"
|
||||
#define PRId64 "ld"
|
||||
#define PRIu64 "lu"
|
||||
#define PRIx64 "lx"
|
||||
|
||||
#define PRIo32 "o"
|
||||
#define PRId32 "d"
|
||||
#define PRIu32 "u"
|
||||
#define PRIx32 "x"
|
||||
|
||||
#define PRIo16 "ho"
|
||||
#define PRId16 "hd"
|
||||
#define PRIu16 "hu"
|
||||
#define PRIx16 "hx"
|
||||
|
||||
#define PRIo8 "hho"
|
||||
#define PRId8 "hhd"
|
||||
#define PRIu8 "hhu"
|
||||
#define PRIx8 "hhx"
|
||||
|
||||
#define SCNo64 PRIo64
|
||||
#define SCNd64 PRId64
|
||||
#define SCNu64 PRIu64
|
||||
#define SCNx64 PRIx64
|
||||
|
||||
#define SCNo32 PRIo32
|
||||
#define SCNd32 PRId32
|
||||
#define SCNu32 PRIu32
|
||||
#define SCNx32 PRIx32
|
||||
|
||||
#define SCNo16 PRIo16
|
||||
#define SCNd16 PRId16
|
||||
#define SCNu16 PRIu16
|
||||
#define SCNx16 PRIx16
|
||||
|
||||
#define SCNo8 PRIo8
|
||||
#define SCNd8 PRId8
|
||||
#define SCNu8 PRIu8
|
||||
#define SCNx8 PRIx8
|
||||
|
||||
#endif
|
4
include/memory.h
Normal file
4
include/memory.h
Normal file
@ -0,0 +1,4 @@
|
||||
#ifndef _MEMORY_H
|
||||
#define _MEMORY_H 1
|
||||
#include <string.h>
|
||||
#endif
|
@ -1,4 +1,4 @@
|
||||
use libyalloc::GlobalAllocator;
|
||||
use libyalloc::global::GlobalAllocator;
|
||||
|
||||
#[global_allocator]
|
||||
pub static GLOBAL_ALLOCATOR: GlobalAllocator = GlobalAllocator;
|
||||
|
@ -96,7 +96,7 @@ impl<T> FromResidual<yggdrasil_rt::Error> for EResult<T> {
|
||||
}
|
||||
|
||||
impl<T> FromResidual<Result<Infallible, Errno>> for EResult<T> {
|
||||
fn from_residual(residual: Result<Infallible, Errno>) -> Self {
|
||||
fn from_residual(_residual: Result<Infallible, Errno>) -> Self {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
@ -109,11 +109,11 @@ impl<T> Try for EResult<T> {
|
||||
match self.into_set_errno() {
|
||||
Self::Ok(value) => ControlFlow::Continue(value),
|
||||
Self::Errno(e) => ControlFlow::Break(Err(e)),
|
||||
Self::Err(error) => unreachable!(),
|
||||
Self::Err(_error) => unreachable!(),
|
||||
}
|
||||
}
|
||||
|
||||
fn from_output(output: Self::Output) -> Self {
|
||||
fn from_output(_output: Self::Output) -> Self {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
162
src/file.rs
162
src/file.rs
@ -1,3 +1,8 @@
|
||||
use core::{
|
||||
ffi::c_int,
|
||||
ops::{Deref, DerefMut},
|
||||
};
|
||||
|
||||
use yggdrasil_rt::{
|
||||
io::{FileMode, OpenOptions, RawFd, SeekFrom},
|
||||
path::Path,
|
||||
@ -5,35 +10,27 @@ use yggdrasil_rt::{
|
||||
};
|
||||
|
||||
use crate::{
|
||||
error::EResult,
|
||||
header::errno::Errno,
|
||||
io::{Read, Seek, Write},
|
||||
error::{self, EResult},
|
||||
header::errno::{Errno, EBADF},
|
||||
io::{AsRawFd, AsRawFdOpt, FromRawFd, IntoRawFd, Read, Seek, Write},
|
||||
};
|
||||
|
||||
pub enum FileBacking {
|
||||
File(File),
|
||||
File(ManagedFile),
|
||||
}
|
||||
|
||||
pub struct File {
|
||||
pub struct RawFile {
|
||||
fd: RawFd,
|
||||
}
|
||||
|
||||
pub struct ManagedFile {
|
||||
inner: RawFile,
|
||||
reference: bool,
|
||||
}
|
||||
|
||||
impl File {
|
||||
pub unsafe fn new(fd: RawFd) -> Self {
|
||||
Self {
|
||||
fd,
|
||||
reference: false,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn from_raw(fd: RawFd) -> Self {
|
||||
Self {
|
||||
fd,
|
||||
reference: false,
|
||||
}
|
||||
}
|
||||
// RawFile
|
||||
|
||||
impl RawFile {
|
||||
pub fn open_at<P: AsRef<Path>>(
|
||||
at: Option<RawFd>,
|
||||
pathname: P,
|
||||
@ -42,26 +39,17 @@ impl File {
|
||||
) -> Result<Self, Errno> {
|
||||
let fd =
|
||||
EResult::from(unsafe { syscall::open(at, pathname.as_ref().as_str(), opts, mode) })?;
|
||||
Ok(Self {
|
||||
fd,
|
||||
reference: false,
|
||||
})
|
||||
Ok(Self { fd })
|
||||
}
|
||||
|
||||
pub unsafe fn close(&self) -> Result<(), Errno> {
|
||||
yggdrasil_rt::debug_trace!("Close fd {:?}", self.fd);
|
||||
pub unsafe fn close(self: &mut Self) -> Result<(), Errno> {
|
||||
EResult::from(unsafe { syscall::close(self.fd) })?;
|
||||
self.fd = RawFd::NONE;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn into_raw_fd(self) -> RawFd {
|
||||
let fd = self.fd;
|
||||
core::mem::forget(self);
|
||||
fd
|
||||
}
|
||||
}
|
||||
|
||||
impl Write for File {
|
||||
impl Write for RawFile {
|
||||
fn write(&mut self, data: &[u8]) -> Result<usize, Errno> {
|
||||
let count = EResult::from(unsafe { syscall::write(self.fd, data) })?;
|
||||
Ok(count)
|
||||
@ -73,21 +61,107 @@ impl Write for File {
|
||||
}
|
||||
}
|
||||
|
||||
impl Read for File {
|
||||
impl Read for RawFile {
|
||||
fn read(&mut self, data: &mut [u8]) -> Result<usize, Errno> {
|
||||
let count = EResult::from(unsafe { syscall::read(self.fd, data) })?;
|
||||
Ok(count)
|
||||
}
|
||||
}
|
||||
|
||||
impl Seek for File {
|
||||
impl Seek for RawFile {
|
||||
fn seek(&mut self, off: SeekFrom) -> Result<u64, Errno> {
|
||||
let pos = EResult::from(unsafe { syscall::seek(self.fd, off) })?;
|
||||
Ok(pos)
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for File {
|
||||
impl FromRawFd for RawFile {
|
||||
unsafe fn from_raw_fd(fd: RawFd) -> Self {
|
||||
Self { fd }
|
||||
}
|
||||
}
|
||||
|
||||
impl AsRawFd for RawFile {
|
||||
fn as_raw_fd(&self) -> RawFd {
|
||||
self.fd
|
||||
}
|
||||
}
|
||||
|
||||
impl IntoRawFd for RawFile {
|
||||
fn into_raw_fd(self) -> RawFd {
|
||||
self.fd
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<c_int> for RawFile {
|
||||
type Error = Errno;
|
||||
|
||||
fn try_from(value: c_int) -> Result<Self, Self::Error> {
|
||||
if value >= 0 {
|
||||
Ok(Self {
|
||||
fd: RawFd(value as _),
|
||||
})
|
||||
} else {
|
||||
error::set_errno_result(EBADF)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ManagedFile
|
||||
|
||||
impl ManagedFile {
|
||||
pub fn open_at<P: AsRef<Path>>(
|
||||
at: Option<RawFd>,
|
||||
pathname: P,
|
||||
opts: OpenOptions,
|
||||
mode: FileMode,
|
||||
) -> Result<Self, Errno> {
|
||||
let inner = RawFile::open_at(at, pathname, opts, mode)?;
|
||||
Ok(Self {
|
||||
inner,
|
||||
reference: false,
|
||||
})
|
||||
}
|
||||
|
||||
pub unsafe fn close(self: &mut Self) -> Result<(), Errno> {
|
||||
if self.reference {
|
||||
unreachable!("Cannot close a reference ManagedFile");
|
||||
}
|
||||
self.reference = true;
|
||||
RawFile::close(&mut self.inner)
|
||||
}
|
||||
}
|
||||
|
||||
impl FromRawFd for ManagedFile {
|
||||
unsafe fn from_raw_fd(fd: RawFd) -> Self {
|
||||
Self::from(RawFile::from_raw_fd(fd))
|
||||
}
|
||||
}
|
||||
|
||||
impl Deref for ManagedFile {
|
||||
type Target = RawFile;
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
&self.inner
|
||||
}
|
||||
}
|
||||
|
||||
impl DerefMut for ManagedFile {
|
||||
fn deref_mut(&mut self) -> &mut Self::Target {
|
||||
&mut self.inner
|
||||
}
|
||||
}
|
||||
|
||||
impl From<RawFile> for ManagedFile {
|
||||
fn from(value: RawFile) -> Self {
|
||||
Self {
|
||||
inner: value,
|
||||
reference: false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for ManagedFile {
|
||||
fn drop(&mut self) {
|
||||
if !self.reference {
|
||||
unsafe {
|
||||
@ -97,19 +171,29 @@ impl Drop for File {
|
||||
}
|
||||
}
|
||||
|
||||
// FileBacking
|
||||
|
||||
impl FileBacking {
|
||||
pub unsafe fn make_ref(&self) -> Self {
|
||||
match self {
|
||||
Self::File(file) => Self::File(File {
|
||||
fd: file.fd,
|
||||
Self::File(file) => Self::File(ManagedFile {
|
||||
inner: RawFile::from_raw_fd(file.inner.fd),
|
||||
reference: true,
|
||||
}),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn as_raw_fd(&self) -> EResult<RawFd> {
|
||||
pub unsafe fn close(self: &mut Self) -> Result<(), Errno> {
|
||||
match self {
|
||||
Self::File(file) => EResult::Ok(file.fd),
|
||||
Self::File(file) => ManagedFile::close(file),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl AsRawFdOpt for FileBacking {
|
||||
fn as_raw_fd_opt(&self) -> Option<RawFd> {
|
||||
match self {
|
||||
Self::File(file) => Some(file.as_raw_fd()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -9,7 +9,7 @@ use yggdrasil_rt::io::{DirectoryEntry, RawFd};
|
||||
|
||||
use crate::{error, io::dir::DirReader, util::Nullable};
|
||||
|
||||
use super::{errno::EBADF, limits::NAME_MAX, sys_types::ino_t};
|
||||
use super::{errno::EBADF, sys_types::ino_t};
|
||||
|
||||
#[derive(Debug)]
|
||||
#[repr(C)]
|
||||
@ -22,7 +22,7 @@ pub struct DIR {
|
||||
#[repr(C)]
|
||||
pub struct dirent {
|
||||
pub d_ino: ino_t,
|
||||
pub d_name: [c_char; NAME_MAX],
|
||||
pub d_name: [c_char; 256],
|
||||
}
|
||||
|
||||
pub type __scandir_filter_fn_t = extern "C" fn(*const dirent) -> c_int;
|
||||
@ -30,10 +30,10 @@ pub type __scandir_compar_fn_t = extern "C" fn(*mut *const dirent, *mut *const d
|
||||
|
||||
impl From<DirectoryEntry> for dirent {
|
||||
fn from(value: DirectoryEntry) -> Self {
|
||||
let mut d_name = [0; NAME_MAX];
|
||||
let mut d_name = [0; 256];
|
||||
let len = value.name.len();
|
||||
|
||||
if len + 1 >= NAME_MAX {
|
||||
if len >= 255 {
|
||||
todo!("Name too long");
|
||||
}
|
||||
|
||||
|
@ -47,6 +47,17 @@ pub const EMLINK: Errno = Errno(31);
|
||||
pub const EPIPE: Errno = Errno(32);
|
||||
pub const EDOM: Errno = Errno(33);
|
||||
pub const ERANGE: Errno = Errno(34);
|
||||
|
||||
pub const EDEADLK: Errno = Errno(35);
|
||||
pub const ENAMETOOLONG: Errno = Errno(36);
|
||||
|
||||
pub const ENOLCK: Errno = Errno(37);
|
||||
pub const ENOSYS: Errno = Errno(38);
|
||||
pub const ENOTEMPTY: Errno = Errno(39);
|
||||
pub const ELOOP: Errno = Errno(40);
|
||||
pub const EWOULDBLOCK: Errno = EAGAIN;
|
||||
pub const ENOMSG: Errno = Errno(42);
|
||||
|
||||
pub const MAX_ERROR: Errno = ERANGE;
|
||||
|
||||
static SUCCESS: &CStr = static_cstr!("Success");
|
||||
|
@ -1,11 +1,8 @@
|
||||
use core::ffi::{c_char, c_int, c_short, CStr, VaList};
|
||||
|
||||
use yggdrasil_rt::{
|
||||
io::{FileMode, OpenOptions, RawFd},
|
||||
path::Path,
|
||||
};
|
||||
use yggdrasil_rt::io::{FileMode, OpenOptions};
|
||||
|
||||
use crate::{error, file::File, header::errno::EINVAL, util::Nullable};
|
||||
use crate::{error, file::RawFile, header::errno::EINVAL, io::IntoRawFd, util::Nullable};
|
||||
|
||||
use super::{
|
||||
errno::Errno,
|
||||
@ -137,7 +134,15 @@ unsafe extern "C" fn creat(pathname: *const c_char, mode: mode_t) -> c_int {
|
||||
|
||||
#[no_mangle]
|
||||
unsafe extern "C" fn fcntl(fd: c_int, cmd: c_int, args: ...) -> c_int {
|
||||
todo!()
|
||||
let Ok(file) = RawFile::try_from(fd) else {
|
||||
return -1;
|
||||
};
|
||||
|
||||
match cmd {
|
||||
F_GETFD => 0,
|
||||
F_SETFD => 0,
|
||||
_ => todo!("fcntl({}, {}, ...)", fd, cmd),
|
||||
}
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
@ -148,7 +153,7 @@ unsafe extern "C" fn open(pathname: *const c_char, opts: c_int, mut args: ...) -
|
||||
|
||||
let result = match open_opts(opts, &mut args) {
|
||||
Ok(OpenMode::File(opts, mode)) => {
|
||||
File::open_at(None, pathname, opts, mode).map(File::into_raw_fd)
|
||||
RawFile::open_at(None, pathname, opts, mode).map(RawFile::into_raw_fd)
|
||||
}
|
||||
Ok(OpenMode::Directory) => {
|
||||
todo!();
|
||||
|
@ -1,19 +0,0 @@
|
||||
// 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;
|
@ -1,4 +1,7 @@
|
||||
use core::ffi::{c_char, c_int};
|
||||
use core::{
|
||||
ffi::{c_char, c_int},
|
||||
ptr::null_mut,
|
||||
};
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
#[repr(C)]
|
||||
@ -75,7 +78,8 @@ unsafe extern "C" fn newlocale(
|
||||
|
||||
#[no_mangle]
|
||||
unsafe extern "C" fn setlocale(category: c_int, locale: *const c_char) -> *mut c_char {
|
||||
todo!()
|
||||
// TODO
|
||||
null_mut()
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
|
@ -1,11 +1,10 @@
|
||||
language = "C"
|
||||
style = "Type"
|
||||
|
||||
sys_includes = []
|
||||
sys_includes = ["bits/math.h"]
|
||||
no_includes = true
|
||||
|
||||
include_guard = "_MATH_H"
|
||||
trailer = "#include <bits/math.h>"
|
||||
|
||||
usize_type = "size_t"
|
||||
isize_type = "ssize_t"
|
||||
|
@ -1 +1,13 @@
|
||||
use core::ffi::{c_double, c_float};
|
||||
|
||||
pub const NAN: f64 = f64::NAN;
|
||||
|
||||
#[no_mangle]
|
||||
unsafe extern "C" fn fabs(x: c_double) -> c_double {
|
||||
todo!()
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
unsafe extern "C" fn fabsf(x: c_float) -> c_float {
|
||||
todo!()
|
||||
}
|
||||
|
@ -2,6 +2,11 @@
|
||||
|
||||
// TODO limits.h is compiler-provided
|
||||
|
||||
pub mod sys_param;
|
||||
pub mod sys_resource;
|
||||
pub mod sys_select;
|
||||
pub mod sys_socket;
|
||||
pub mod sys_time;
|
||||
pub mod sys_types;
|
||||
pub mod sys_wait;
|
||||
|
||||
@ -9,16 +14,20 @@ pub mod ctype;
|
||||
pub mod dirent;
|
||||
pub mod errno;
|
||||
pub mod fcntl;
|
||||
pub mod limits;
|
||||
pub mod locale;
|
||||
pub mod math;
|
||||
pub mod pwd;
|
||||
pub mod setjmp;
|
||||
pub mod signal;
|
||||
pub mod stdio;
|
||||
pub mod stdlib;
|
||||
pub mod string;
|
||||
pub mod strings;
|
||||
pub mod sys_stat;
|
||||
pub mod termios;
|
||||
pub mod time;
|
||||
pub mod unistd;
|
||||
pub mod wchar;
|
||||
|
||||
/*
|
||||
Impl Check Name
|
||||
@ -95,7 +104,7 @@ PARTIAL sys/wait.h - declarations for waiting
|
||||
----- tar.h - extended tar definitions
|
||||
----- termios.h - define values for termios
|
||||
----- tgmath.h - type-generic macros
|
||||
----- time.h - time types
|
||||
MOSTLY time.h - time types
|
||||
OSSUP trace.h - tracing
|
||||
OSSUP ulimit.h - ulimit commands
|
||||
PARTIAL unistd.h - standard symbolic constants and types
|
||||
|
14
src/header/pwd/cbindgen.toml
Normal file
14
src/header/pwd/cbindgen.toml
Normal file
@ -0,0 +1,14 @@
|
||||
language = "C"
|
||||
style = "Tag"
|
||||
|
||||
sys_includes = ["stddef.h", "sys/types.h"]
|
||||
no_includes = true
|
||||
|
||||
include_guard = "_PWD_H"
|
||||
|
||||
usize_type = "size_t"
|
||||
isize_type = "ssize_t"
|
||||
|
||||
[export]
|
||||
include = ["passwd"]
|
||||
exclude = []
|
13
src/header/pwd/mod.rs
Normal file
13
src/header/pwd/mod.rs
Normal file
@ -0,0 +1,13 @@
|
||||
use core::ffi::c_char;
|
||||
|
||||
use super::sys_types::{gid_t, uid_t};
|
||||
|
||||
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
|
||||
#[repr(C)]
|
||||
pub struct passwd {
|
||||
pub pw_name: *mut c_char,
|
||||
pub pw_uid: uid_t,
|
||||
pub pw_gid: gid_t,
|
||||
pub pw_dir: *mut c_char,
|
||||
pub pw_shell: *mut c_char,
|
||||
}
|
@ -1,5 +1,3 @@
|
||||
use core::ffi::c_int;
|
||||
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
mod x86_64;
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
use core::{arch::global_asm, ffi::c_int};
|
||||
use core::arch::global_asm;
|
||||
|
||||
#[repr(C)]
|
||||
pub struct __jmp_buf {
|
||||
|
19
src/header/signal/cbindgen.toml
Normal file
19
src/header/signal/cbindgen.toml
Normal file
@ -0,0 +1,19 @@
|
||||
language = "C"
|
||||
style = "Type"
|
||||
|
||||
sys_includes = [
|
||||
"stddef.h",
|
||||
"stdint.h",
|
||||
"sys/types.h",
|
||||
"bits/signal.h"
|
||||
]
|
||||
no_includes = true
|
||||
|
||||
include_guard = "_SIGNAL_H"
|
||||
|
||||
usize_type = "size_t"
|
||||
isize_type = "ssize_t"
|
||||
|
||||
[export]
|
||||
include = ["sig_handler_t", "SIGABRT"]
|
||||
exclude = []
|
106
src/header/signal/mod.rs
Normal file
106
src/header/signal/mod.rs
Normal file
@ -0,0 +1,106 @@
|
||||
use core::ffi::c_int;
|
||||
|
||||
use yggdrasil_rt::process::Signal;
|
||||
|
||||
use crate::signal;
|
||||
|
||||
use super::sys_types::pid_t;
|
||||
|
||||
pub type sig_handler_t = unsafe extern "C" fn(SigNumber);
|
||||
|
||||
extern "C" {
|
||||
fn __sig_terminate(_: SigNumber);
|
||||
fn __sig_ignore(_: SigNumber);
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, PartialEq, Eq, Debug, Default)]
|
||||
#[repr(transparent)]
|
||||
pub struct SigNumber(pub c_int);
|
||||
|
||||
// TODO generate these based on the ABI
|
||||
pub const SIGSEGV: SigNumber = SigNumber(1);
|
||||
pub const SIGABRT: SigNumber = SigNumber(2);
|
||||
pub const SIGKILL: SigNumber = SigNumber(3);
|
||||
pub const SIGINT: SigNumber = SigNumber(4);
|
||||
|
||||
// TODO not yet defined signals
|
||||
pub const SIGALRM: SigNumber = SigNumber::INVALID;
|
||||
pub const SIGBUS: SigNumber = SigNumber::INVALID;
|
||||
pub const SIGCHLD: SigNumber = SigNumber::INVALID;
|
||||
pub const SIGCONT: SigNumber = SigNumber::INVALID;
|
||||
pub const SIGFPE: SigNumber = SigNumber::INVALID;
|
||||
pub const SIGHUP: SigNumber = SigNumber::INVALID;
|
||||
pub const SIGPIPE: SigNumber = SigNumber::INVALID;
|
||||
pub const SIGQUIT: SigNumber = SigNumber::INVALID;
|
||||
pub const SIGSTOP: SigNumber = SigNumber::INVALID;
|
||||
pub const SIGTERM: SigNumber = SigNumber::INVALID;
|
||||
pub const SIGTSTP: SigNumber = SigNumber::INVALID;
|
||||
pub const SIGTTIN: SigNumber = SigNumber::INVALID;
|
||||
pub const SIGTTOU: SigNumber = SigNumber::INVALID;
|
||||
pub const SIGUSR1: SigNumber = SigNumber::INVALID;
|
||||
pub const SIGUSR2: SigNumber = SigNumber::INVALID;
|
||||
pub const SIGPOLL: SigNumber = SigNumber::INVALID;
|
||||
pub const SIGPROF: SigNumber = SigNumber::INVALID;
|
||||
pub const SIGSYS: SigNumber = SigNumber::INVALID;
|
||||
pub const SIGTRAP: SigNumber = SigNumber::INVALID;
|
||||
pub const SIGURG: SigNumber = SigNumber::INVALID;
|
||||
pub const SIGVTALRM: SigNumber = SigNumber::INVALID;
|
||||
pub const SIGXCPU: SigNumber = SigNumber::INVALID;
|
||||
pub const SIGXFSZ: SigNumber = SigNumber::INVALID;
|
||||
|
||||
impl SigNumber {
|
||||
pub const INVALID: Self = Self(-65536);
|
||||
}
|
||||
|
||||
impl TryFrom<SigNumber> for Signal {
|
||||
type Error = ();
|
||||
|
||||
fn try_from(value: SigNumber) -> Result<Self, Self::Error> {
|
||||
match value {
|
||||
SIGSEGV => Ok(Signal::MemoryAccessViolation),
|
||||
SIGABRT => Ok(Signal::Aborted),
|
||||
SIGKILL => Ok(Signal::Killed),
|
||||
SIGINT => Ok(Signal::Interrupted),
|
||||
_ => Err(()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Signal> for SigNumber {
|
||||
fn from(value: Signal) -> Self {
|
||||
match value {
|
||||
Signal::Aborted => SIGABRT,
|
||||
Signal::Interrupted => SIGINT,
|
||||
Signal::Killed => SIGKILL,
|
||||
Signal::MemoryAccessViolation => SIGSEGV,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
unsafe extern "C" fn kill(pid: pid_t, signum: SigNumber) -> c_int {
|
||||
todo!()
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
unsafe extern "C" fn killpg(pid: pid_t, signum: SigNumber) -> c_int {
|
||||
todo!()
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
unsafe extern "C" fn raise(signum: SigNumber) -> c_int {
|
||||
todo!()
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
unsafe extern "C" fn signal(signum: SigNumber, handler: sig_handler_t) -> sig_handler_t {
|
||||
// NOTE handler might be NULL, so check that
|
||||
let Ok(signal) = Signal::try_from(signum) else {
|
||||
// Ignore
|
||||
return __sig_terminate;
|
||||
};
|
||||
let handler_ptr = handler as usize;
|
||||
let handler = (handler_ptr != 0).then_some(handler);
|
||||
|
||||
signal::set_handler(signal, handler)
|
||||
}
|
@ -10,9 +10,12 @@ use yggdrasil_rt::{
|
||||
};
|
||||
|
||||
use crate::{
|
||||
error::{CSizeResult, CZeroResult},
|
||||
header::{errno::Errno, sys_types::off_t},
|
||||
io::{Read, Seek, Write},
|
||||
error::{self, CSizeResult, CZeroResult},
|
||||
header::{
|
||||
errno::{Errno, EBADF},
|
||||
sys_types::off_t,
|
||||
},
|
||||
io::{AsRawFdOpt, Read, Seek, Write},
|
||||
};
|
||||
|
||||
use super::{
|
||||
@ -23,10 +26,16 @@ fn open_inner<O: FileOpenSource>(source: O, mode_str: &[u8]) -> Result<*mut FILE
|
||||
let opts = match mode_str {
|
||||
b"r" | b"rb" => OpenOptions::READ,
|
||||
b"r+" | b"rb+" => OpenOptions::READ | OpenOptions::WRITE,
|
||||
b"w" | b"wb" => OpenOptions::TRUNCATE | OpenOptions::WRITE,
|
||||
b"w+" | b"wb+" => OpenOptions::TRUNCATE | OpenOptions::READ | OpenOptions::WRITE,
|
||||
b"a" | b"ab" => OpenOptions::APPEND | OpenOptions::READ | OpenOptions::WRITE,
|
||||
b"a+" | b"ab+" => OpenOptions::APPEND | OpenOptions::READ | OpenOptions::WRITE,
|
||||
b"w" | b"wb" => OpenOptions::TRUNCATE | OpenOptions::WRITE | OpenOptions::CREATE,
|
||||
b"w+" | b"wb+" => {
|
||||
OpenOptions::TRUNCATE | OpenOptions::READ | OpenOptions::WRITE | OpenOptions::CREATE
|
||||
}
|
||||
b"a" | b"ab" => {
|
||||
OpenOptions::APPEND | OpenOptions::READ | OpenOptions::WRITE | OpenOptions::CREATE
|
||||
}
|
||||
b"a+" | b"ab+" => {
|
||||
OpenOptions::APPEND | OpenOptions::READ | OpenOptions::WRITE | OpenOptions::CREATE
|
||||
}
|
||||
// TODO: errno and fail
|
||||
_ => todo!(),
|
||||
};
|
||||
@ -57,7 +66,9 @@ 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);
|
||||
|
||||
open_inner(Path::from_str(pathname), mode.to_bytes()).unwrap_or(null_mut())
|
||||
let res = open_inner(Path::from_str(pathname), mode.to_bytes()).unwrap_or(null_mut());
|
||||
yggdrasil_rt::debug_trace!("fopen({:?}, {:?}) -> {:p}", pathname, mode, res);
|
||||
res
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
@ -113,9 +124,12 @@ pub unsafe extern "C" fn fclose(stream: *mut FILE) -> c_int {
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn fileno(stream: *mut FILE) -> c_int {
|
||||
let stream = stream.as_mut().unwrap();
|
||||
match stream.as_raw_fd() {
|
||||
Ok(RawFd(fd)) => fd as _,
|
||||
Err(_) => -1,
|
||||
match stream.as_raw_fd_opt() {
|
||||
Some(RawFd(fd)) => fd as _,
|
||||
None => {
|
||||
error::set_errno(EBADF);
|
||||
-1
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -5,13 +5,13 @@ use core::{
|
||||
|
||||
use crate::{
|
||||
error,
|
||||
header::{stdlib::realloc, string::strlen},
|
||||
header::stdlib::realloc,
|
||||
io::{Read, Write},
|
||||
};
|
||||
|
||||
use super::{
|
||||
stderr, stdin, stdout,
|
||||
unlocked::{flockfile, fputc_unlocked, fputs_unlocked, funlockfile, fwrite_unlocked},
|
||||
unlocked::{flockfile, fputc_unlocked, fputs_unlocked, funlockfile},
|
||||
EOF, FILE,
|
||||
};
|
||||
|
||||
|
@ -12,15 +12,15 @@ use yggdrasil_rt::{
|
||||
|
||||
use crate::{
|
||||
error::{EResult, TryFromExt},
|
||||
file::{File, FileBacking},
|
||||
file::{FileBacking, ManagedFile, RawFile},
|
||||
io::{
|
||||
buffered::{BufWriter, FileWriter, LineWriter, ReadBuffer, UnbufferedWriter},
|
||||
BufRead, Read, Seek, Write,
|
||||
AsRawFdOpt, BufRead, FromRawFd, Read, Seek, Write,
|
||||
},
|
||||
sync::{Mutex, RawMutex},
|
||||
};
|
||||
|
||||
use super::{errno::Errno, limits};
|
||||
use super::errno::Errno;
|
||||
|
||||
// TODO:
|
||||
// L_ctermid
|
||||
@ -86,16 +86,22 @@ pub struct FILE {
|
||||
}
|
||||
|
||||
impl FILE {
|
||||
pub unsafe fn from_c_file(file: File, flags: FileFlags) -> Self {
|
||||
assert!(!flags.contains(FileFlags::BUILTIN));
|
||||
let inner = FileBacking::File(file);
|
||||
// TODO run is_terminal on file and check for desired buffering mode
|
||||
unsafe fn from_backing(
|
||||
backing: FileBacking,
|
||||
flags: FileFlags,
|
||||
buffering: BufferingMode,
|
||||
) -> Self {
|
||||
let output = backing.make_ref();
|
||||
let output: Box<dyn FileWriter> = match buffering {
|
||||
BufferingMode::None => Box::new(UnbufferedWriter::new(output)),
|
||||
BufferingMode::Full => Box::new(BufWriter::with_capacity(output, BUFSIZ)),
|
||||
BufferingMode::Line => Box::new(LineWriter::with_capacity(output, BUFSIZ)),
|
||||
};
|
||||
Self {
|
||||
lock: RawMutex::new(),
|
||||
|
||||
output: Box::new(BufWriter::with_capacity(inner.make_ref(), BUFSIZ)),
|
||||
inner,
|
||||
read_buffer: Some(ReadBuffer::owned(BUFSIZ)),
|
||||
output,
|
||||
inner: backing,
|
||||
read_buffer: None, // Some(ReadBuffer::owned(BUFSIZ)),
|
||||
|
||||
flags,
|
||||
|
||||
@ -105,48 +111,39 @@ impl FILE {
|
||||
}
|
||||
}
|
||||
|
||||
pub unsafe fn new_builtin(fd: RawFd, flags: FileFlags, buffered: bool) -> Self {
|
||||
let inner = FileBacking::File(File::new(fd));
|
||||
Self {
|
||||
lock: RawMutex::new(),
|
||||
pub unsafe fn from_raw_file(file: RawFile, flags: FileFlags) -> Self {
|
||||
Self::from_managed_file(file.into(), flags)
|
||||
}
|
||||
|
||||
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)),
|
||||
pub unsafe fn from_managed_file(file: ManagedFile, flags: FileFlags) -> Self {
|
||||
assert!(!flags.contains(FileFlags::BUILTIN));
|
||||
let inner = FileBacking::File(file);
|
||||
Self::from_backing(inner, flags, BufferingMode::Full)
|
||||
}
|
||||
|
||||
flags: FileFlags::BUILTIN | flags,
|
||||
|
||||
ungetc: Vec::new(),
|
||||
|
||||
last_operation: None,
|
||||
}
|
||||
pub unsafe fn new_builtin(fd: RawFd, flags: FileFlags, buffering: BufferingMode) -> Self {
|
||||
let inner = FileBacking::File(ManagedFile::from_raw_fd(fd));
|
||||
Self::from_backing(inner, flags, buffering)
|
||||
}
|
||||
|
||||
pub unsafe fn close(self: *mut Self) -> Result<(), Errno> {
|
||||
// TODO lock needed?
|
||||
let r = self.as_mut().unwrap();
|
||||
r.flush()?;
|
||||
|
||||
if r.flags.contains(FileFlags::BUILTIN) {
|
||||
// NOTE The OS will close the file for us
|
||||
Ok(())
|
||||
todo!()
|
||||
} else {
|
||||
// Drop the file
|
||||
drop(Box::from_raw(self));
|
||||
Ok(())
|
||||
let mut this = Box::from_raw(self);
|
||||
let result = FileBacking::close(&mut this.inner);
|
||||
drop(this);
|
||||
result
|
||||
}
|
||||
}
|
||||
|
||||
pub unsafe fn as_raw_fd_unlocked(&mut self) -> Result<RawFd, Errno> {
|
||||
let fd = self.inner.as_raw_fd()?;
|
||||
Ok(fd)
|
||||
}
|
||||
|
||||
pub fn as_raw_fd(&mut self) -> Result<RawFd, Errno> {
|
||||
locked_op!(self, self.as_raw_fd_unlocked())
|
||||
pub unsafe fn as_raw_fd_opt_unlocked(&self) -> Option<RawFd> {
|
||||
self.inner.as_raw_fd_opt()
|
||||
}
|
||||
|
||||
pub unsafe fn clear_error_unlocked(&mut self) {
|
||||
@ -247,7 +244,7 @@ impl FILE {
|
||||
self.lock.release();
|
||||
}
|
||||
|
||||
fn reset(&mut self) {
|
||||
pub fn reset(&mut self) {
|
||||
if let Some(read_buffer) = self.read_buffer.as_mut() {
|
||||
read_buffer.reset();
|
||||
}
|
||||
@ -403,9 +400,15 @@ impl Seek for FILE {
|
||||
}
|
||||
}
|
||||
|
||||
impl AsRawFdOpt for FILE {
|
||||
fn as_raw_fd_opt(&self) -> Option<RawFd> {
|
||||
locked_op!(self, self.as_raw_fd_opt_unlocked())
|
||||
}
|
||||
}
|
||||
|
||||
impl FileOpenSource for &Path {
|
||||
fn open_with(self, opts: OpenOptions) -> Result<FILE, Errno> {
|
||||
let f = File::open_at(None, self, opts, FileMode::default_file())?;
|
||||
let f = ManagedFile::open_at(None, self, opts, FileMode::default_file())?;
|
||||
let mut flags = FileFlags::empty();
|
||||
if opts.contains(OpenOptions::READ) {
|
||||
flags |= FileFlags::READ;
|
||||
@ -413,13 +416,13 @@ impl FileOpenSource for &Path {
|
||||
if opts.contains(OpenOptions::WRITE) {
|
||||
flags |= FileFlags::WRITE;
|
||||
}
|
||||
Ok(unsafe { FILE::from_c_file(f, flags) })
|
||||
Ok(unsafe { FILE::from_managed_file(f, flags) })
|
||||
}
|
||||
}
|
||||
|
||||
impl FileOpenSource for RawFd {
|
||||
fn open_with(self, opts: OpenOptions) -> Result<FILE, Errno> {
|
||||
let f = File::from_raw(self);
|
||||
let f = unsafe { RawFile::from_raw_fd(self) };
|
||||
let mut flags = FileFlags::empty();
|
||||
if opts.contains(OpenOptions::READ) {
|
||||
flags |= FileFlags::READ;
|
||||
@ -427,7 +430,7 @@ impl FileOpenSource for RawFd {
|
||||
if opts.contains(OpenOptions::WRITE) {
|
||||
flags |= FileFlags::WRITE;
|
||||
}
|
||||
Ok(unsafe { FILE::from_c_file(f, flags) })
|
||||
Ok(unsafe { FILE::from_raw_file(f, flags) })
|
||||
}
|
||||
}
|
||||
|
||||
@ -481,17 +484,17 @@ pub unsafe fn setup_default_files() {
|
||||
let stdin_ = Box::into_raw(Box::new(FILE::new_builtin(
|
||||
RawFd::STDIN,
|
||||
FileFlags::READ,
|
||||
true,
|
||||
BufferingMode::Line,
|
||||
)));
|
||||
let stdout_ = Box::into_raw(Box::new(FILE::new_builtin(
|
||||
RawFd::STDOUT,
|
||||
FileFlags::WRITE,
|
||||
true,
|
||||
BufferingMode::Line,
|
||||
)));
|
||||
let stderr_ = Box::into_raw(Box::new(FILE::new_builtin(
|
||||
RawFd::STDERR,
|
||||
FileFlags::WRITE,
|
||||
false,
|
||||
BufferingMode::None,
|
||||
)));
|
||||
|
||||
stdin = stdin_;
|
||||
|
@ -57,7 +57,7 @@ fn fmt_float_exp<W: Write + fmt::Write>(
|
||||
}
|
||||
|
||||
fn fmt_float_string(val: c_double, precision: usize) -> String {
|
||||
let mut string = format!("{:.p$}", val, p = precision);
|
||||
let string = format!("{:.p$}", val, p = precision);
|
||||
// TODO trim
|
||||
string
|
||||
}
|
||||
|
@ -20,6 +20,7 @@ pub enum FmtSize {
|
||||
Long,
|
||||
LongLong,
|
||||
Size,
|
||||
#[allow(unused)]
|
||||
LongFloat,
|
||||
}
|
||||
|
||||
|
@ -194,6 +194,11 @@ unsafe extern "C" fn fprintf(stream: *mut FILE, format: *const c_char, mut args:
|
||||
vfprintf(stream, format, args.as_va_list())
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
unsafe extern "C" fn vprintf(format: *const c_char, ap: VaList) -> c_int {
|
||||
vfprintf(stdout, format, ap)
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
unsafe extern "C" fn vfprintf(stream: *mut FILE, format: *const c_char, ap: VaList) -> c_int {
|
||||
if format.is_null() {
|
||||
|
@ -1,4 +1,4 @@
|
||||
use core::ffi::{c_char, c_int, c_void, CStr, VaList};
|
||||
use core::ffi::{c_char, c_int, CStr, VaList};
|
||||
|
||||
use crate::header::errno::Errno;
|
||||
|
||||
|
@ -2,9 +2,12 @@ use core::ffi::{c_char, c_int, c_void, CStr};
|
||||
|
||||
use yggdrasil_rt::io::RawFd;
|
||||
|
||||
use crate::error::{CSizeResult, CZeroResult};
|
||||
use crate::{
|
||||
error::{self, CSizeResult, CZeroResult},
|
||||
header::errno::EBADF,
|
||||
};
|
||||
|
||||
use super::{FileFlags, EOF, FILE};
|
||||
use super::{stdin, stdout, FileFlags, EOF, FILE};
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn flockfile(stream: *mut FILE) {
|
||||
@ -48,9 +51,12 @@ pub unsafe extern "C" fn clearerr_unlocked(stream: *mut FILE) {
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn fileno_unlocked(stream: *mut FILE) -> c_int {
|
||||
let stream = stream.as_mut().unwrap();
|
||||
match stream.as_raw_fd_unlocked() {
|
||||
Ok(RawFd(fd)) => fd as _,
|
||||
Err(_) => -1,
|
||||
match stream.as_raw_fd_opt_unlocked() {
|
||||
Some(RawFd(fd)) => fd as _,
|
||||
None => {
|
||||
error::set_errno(EBADF);
|
||||
-1
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -97,22 +103,28 @@ pub unsafe extern "C" fn fflush_unlocked(stream: *mut FILE) -> c_int {
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn fgetc_unlocked(stream: *mut FILE) -> c_int {
|
||||
todo!()
|
||||
let stream = stream.as_mut().unwrap();
|
||||
let mut buf = [0];
|
||||
match stream.read_unlocked(&mut buf) {
|
||||
Ok(1) => buf[0] as c_int,
|
||||
Ok(_) => EOF,
|
||||
Err(_) => EOF,
|
||||
}
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn getc_unlocked(stream: *mut FILE) -> c_int {
|
||||
todo!()
|
||||
fgetc_unlocked(stream)
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn getchar_unlocked() -> c_int {
|
||||
todo!()
|
||||
fgetc_unlocked(stdin)
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn putchar_unlocked(c: c_char) -> c_int {
|
||||
todo!()
|
||||
pub unsafe extern "C" fn putchar_unlocked(c: c_int) -> c_int {
|
||||
fputc_unlocked(c, stdout)
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
|
@ -7,8 +7,9 @@ use core::{
|
||||
|
||||
use crate::{allocator::GLOBAL_ALLOCATOR, error, header::errno::ENOMEM};
|
||||
|
||||
unsafe fn alloc_inner(size: usize, offset: usize, align: usize) -> *mut c_void {
|
||||
let layout = Layout::from_size_align(size + offset, align).unwrap();
|
||||
unsafe fn alloc_inner(size: usize) -> *mut c_void {
|
||||
let size = (size + 15) & !15;
|
||||
let layout = Layout::from_size_align(size + 16, 16).unwrap();
|
||||
let ptr = GLOBAL_ALLOCATOR.alloc(layout);
|
||||
|
||||
if ptr.is_null() {
|
||||
@ -16,20 +17,19 @@ unsafe fn alloc_inner(size: usize, offset: usize, align: usize) -> *mut c_void {
|
||||
return ptr as *mut c_void;
|
||||
}
|
||||
|
||||
*(ptr as *mut u64) = (size + offset) as u64;
|
||||
*(ptr as *mut u64).add(1) = align as u64;
|
||||
*(ptr as *mut u64) = (size + 16) as u64;
|
||||
*(ptr as *mut u64).add(1) = 16 as u64;
|
||||
|
||||
ptr.add(offset) as *mut c_void
|
||||
ptr.add(16) as *mut c_void
|
||||
}
|
||||
|
||||
unsafe fn get_allocation(ptr: *mut c_void) -> (*mut u8, Layout) {
|
||||
let ptr = (ptr as *mut u64).offset(-2);
|
||||
let size = *ptr as usize;
|
||||
let align = *ptr.add(1) as usize;
|
||||
(
|
||||
ptr as *mut u8,
|
||||
Layout::from_size_align(size, align).unwrap(),
|
||||
)
|
||||
assert!(ptr as usize > 0x10);
|
||||
let base = (ptr as *mut u8).sub(16);
|
||||
let size = *(base as *mut u64);
|
||||
let align = *(base as *mut u64).add(1);
|
||||
let layout = Layout::from_size_align(size as _, align as _).unwrap();
|
||||
(base, layout)
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
@ -51,7 +51,7 @@ pub unsafe extern "C" fn calloc(nmemb: usize, size: usize) -> *mut c_void {
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn malloc(size: usize) -> *mut c_void {
|
||||
alloc_inner(size, 16, 8)
|
||||
alloc_inner(size)
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
@ -84,3 +84,15 @@ pub unsafe extern "C" fn free(ptr: *mut c_void) {
|
||||
let (allocation, layout) = get_allocation(ptr);
|
||||
GLOBAL_ALLOCATOR.dealloc(allocation, layout);
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
unsafe extern "C" fn ymalloc(size: usize) -> *mut c_void {
|
||||
let ptr = GLOBAL_ALLOCATOR.alloc(Layout::from_size_align(size, 8).unwrap());
|
||||
ptr as _
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
unsafe extern "C" fn yfree(ptr: *mut c_void, size: usize) {
|
||||
assert!(!ptr.is_null());
|
||||
GLOBAL_ALLOCATOR.dealloc(ptr as _, Layout::from_size_align(size, 8).unwrap());
|
||||
}
|
||||
|
@ -1,8 +1,4 @@
|
||||
use core::ffi::c_int;
|
||||
|
||||
use crate::{allocator::GLOBAL_ALLOCATOR, error};
|
||||
|
||||
use super::errno::ENOMEM;
|
||||
use core::ffi::{c_char, c_int};
|
||||
|
||||
mod malloc;
|
||||
mod number;
|
||||
@ -35,6 +31,34 @@ pub use malloc::{calloc, free, malloc, realloc};
|
||||
|
||||
pub const EXIT_SUCCESS: c_int = 0;
|
||||
pub const EXIT_FAILURE: c_int = 1;
|
||||
|
||||
pub const MB_CUR_MAX: c_int = 4;
|
||||
|
||||
// TODO RAND_MAX
|
||||
|
||||
// TODO MB_CUR_MAX
|
||||
|
||||
#[no_mangle]
|
||||
unsafe extern "C" fn mktemp(tstr: *mut c_char) -> *mut c_char {
|
||||
todo!()
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
unsafe extern "C" fn mkdtemp(tstr: *mut c_char) -> *mut c_char {
|
||||
todo!()
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
unsafe extern "C" fn mkstemp(temp: *mut c_char) -> c_int {
|
||||
todo!()
|
||||
}
|
||||
|
||||
// #[no_mangle]
|
||||
// unsafe extern "C" fn faccessat(fd: c_int, path: *const c_char, amode: c_int, flag: c_int) -> c_int {
|
||||
// todo!()
|
||||
// }
|
||||
|
||||
#[no_mangle]
|
||||
unsafe extern "C" fn getprogname() -> *const c_char {
|
||||
todo!()
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
use core::{
|
||||
ffi::{c_char, c_double, c_float, c_int, c_long, c_longlong, c_ulong, c_ulonglong, CStr},
|
||||
ffi::{c_char, c_double, c_float, c_int, c_long, c_longlong, c_ulong, c_ulonglong},
|
||||
ops::{AddAssign, MulAssign, Neg},
|
||||
ptr::null_mut,
|
||||
};
|
||||
@ -128,8 +128,6 @@ unsafe fn str_to_int_inner<F: Copy + Neg<Output = F> + MulAssign + AddAssign + F
|
||||
) -> F {
|
||||
string.ensure();
|
||||
|
||||
let mut matched = false;
|
||||
|
||||
// Skip whitespace
|
||||
while (*string as u8).is_ascii_whitespace() {
|
||||
string = string.add(1);
|
||||
@ -201,7 +199,6 @@ unsafe fn str_to_int_inner<F: Copy + Neg<Output = F> + MulAssign + AddAssign + F
|
||||
value *= mul;
|
||||
value += digit;
|
||||
|
||||
matched = true;
|
||||
string = string.add(1);
|
||||
}
|
||||
|
||||
|
@ -1,7 +1,6 @@
|
||||
use core::{
|
||||
ffi::{c_char, c_int, CStr},
|
||||
ptr::null_mut,
|
||||
slice::memchr,
|
||||
};
|
||||
|
||||
use crate::process;
|
||||
|
@ -1,3 +1,8 @@
|
||||
use core::{
|
||||
cmp::Ordering,
|
||||
ffi::{c_int, c_void},
|
||||
};
|
||||
|
||||
/*
|
||||
void *bsearch(const void *, const void *, size_t, size_t,
|
||||
int (*)(const void *, const void *));
|
||||
@ -6,3 +11,131 @@ int posix_memalign(void **, size_t, size_t);
|
||||
void qsort(void *, size_t, size_t, int (*)(const void *,
|
||||
const void *));
|
||||
*/
|
||||
|
||||
pub type qsort_compar_fn_t = extern "C" fn(*const c_void, *const c_void) -> c_int;
|
||||
pub type qsort_compar_r_fn_t = extern "C" fn(*const c_void, *const c_void, *mut c_void) -> c_int;
|
||||
|
||||
pub type bsearch_compar_fn_t = extern "C" fn(*const c_void, *const c_void) -> c_int;
|
||||
|
||||
struct Array {
|
||||
base: *mut c_void,
|
||||
size: usize,
|
||||
nmemb: usize,
|
||||
}
|
||||
|
||||
impl Array {
|
||||
unsafe fn new(base: *mut c_void, nmemb: usize, size: usize) -> Option<Self> {
|
||||
if nmemb == 0 || size == 0 || base.is_null() {
|
||||
return None;
|
||||
}
|
||||
Some(Self { base, nmemb, size })
|
||||
}
|
||||
|
||||
fn element(&mut self, i: usize) -> *mut c_void {
|
||||
if i >= self.nmemb {
|
||||
panic!("i = {}, nmemb = {}", i, self.nmemb);
|
||||
}
|
||||
unsafe { self.base.add(i * self.size) }
|
||||
}
|
||||
|
||||
fn partition<F: Fn(*mut c_void, *mut c_void) -> Ordering>(
|
||||
&mut self,
|
||||
lower: usize,
|
||||
upper: usize,
|
||||
cmp: &F,
|
||||
) -> usize {
|
||||
if lower >= upper {
|
||||
panic!()
|
||||
}
|
||||
let pivot_ptr = self.element(lower);
|
||||
let mut i = lower;
|
||||
let mut j = upper;
|
||||
|
||||
while i < j {
|
||||
while i <= upper - 1 && cmp(self.element(i), pivot_ptr).is_le() {
|
||||
i += 1;
|
||||
}
|
||||
while j >= lower + 1 && cmp(self.element(j), pivot_ptr).is_gt() {
|
||||
j -= 1;
|
||||
}
|
||||
|
||||
if i < j {
|
||||
self.swap(i, j);
|
||||
}
|
||||
}
|
||||
self.swap(lower, j);
|
||||
j
|
||||
}
|
||||
|
||||
fn swap(&mut self, i: usize, j: usize) {
|
||||
let el_i = self.element(i) as *mut u8;
|
||||
let el_j = self.element(j) as *mut u8;
|
||||
unsafe {
|
||||
for i in 0..self.size {
|
||||
core::ptr::swap(el_i.add(i), el_j.add(i));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn sort_inner<F: Fn(*mut c_void, *mut c_void) -> Ordering>(
|
||||
&mut self,
|
||||
lower: usize,
|
||||
upper: usize,
|
||||
cmp: &F,
|
||||
) {
|
||||
if lower < upper {
|
||||
let partition = self.partition(lower, upper, cmp);
|
||||
|
||||
if partition != 0 {
|
||||
self.sort_inner(lower, partition - 1, cmp);
|
||||
}
|
||||
self.sort_inner(partition + 1, upper, cmp);
|
||||
}
|
||||
}
|
||||
|
||||
fn sort<F: Fn(*mut c_void, *mut c_void) -> Ordering>(&mut self, cmp: &F) {
|
||||
if self.nmemb != 0 {
|
||||
self.sort_inner(0, self.nmemb - 1, cmp);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
unsafe extern "C" fn bsearch(
|
||||
key: *const c_void,
|
||||
base: *const c_void,
|
||||
nmemb: usize,
|
||||
size: usize,
|
||||
compar: bsearch_compar_fn_t,
|
||||
) -> *mut c_void {
|
||||
todo!()
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
unsafe extern "C" fn qsort(
|
||||
base: *mut c_void,
|
||||
nmemb: usize,
|
||||
size: usize,
|
||||
compar: qsort_compar_fn_t,
|
||||
) {
|
||||
let Some(mut array) = Array::new(base, nmemb, size) else {
|
||||
return;
|
||||
};
|
||||
|
||||
array.sort(&|a, b| compar(a, b).cmp(&0));
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
unsafe extern "C" fn qsort_r(
|
||||
base: *mut c_void,
|
||||
nmemb: usize,
|
||||
size: usize,
|
||||
compar: qsort_compar_r_fn_t,
|
||||
arg: *mut c_void,
|
||||
) {
|
||||
let Some(mut array) = Array::new(base, nmemb, size) else {
|
||||
return;
|
||||
};
|
||||
|
||||
array.sort(&|a, b| compar(a, b, arg).cmp(&0))
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
language = "C"
|
||||
style = "Type"
|
||||
|
||||
sys_includes = ["stddef.h", "locale.h"]
|
||||
sys_includes = ["stddef.h", "locale.h", "bits/string.h", "strings.h"]
|
||||
no_includes = true
|
||||
|
||||
include_guard = "_STRING_H"
|
||||
|
@ -4,17 +4,28 @@ use core::{
|
||||
ptr::null_mut,
|
||||
};
|
||||
|
||||
use crate::header::{
|
||||
errno::{self, Errno},
|
||||
locale::locale_t,
|
||||
string::strlen,
|
||||
use yggdrasil_rt::memcpy;
|
||||
|
||||
use crate::{
|
||||
header::{
|
||||
errno::{self, Errno},
|
||||
locale::locale_t,
|
||||
stdlib::malloc,
|
||||
string::strlen,
|
||||
},
|
||||
util::Nullable,
|
||||
};
|
||||
|
||||
use super::{mem::mempcpy, memset};
|
||||
|
||||
#[no_mangle]
|
||||
unsafe extern "C" fn stpcpy(dst: *mut c_char, src: *const c_char) -> *mut c_char {
|
||||
stpncpy(dst, src, usize::MAX)
|
||||
if dst.is_null() || src.is_null() {
|
||||
panic!();
|
||||
}
|
||||
let ptr = mempcpy(dst as _, src as _, strlen(src)) as *mut c_char;
|
||||
*ptr = 0;
|
||||
ptr
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
@ -28,7 +39,11 @@ unsafe extern "C" fn stpncpy(dst: *mut c_char, src: *const c_char, n: usize) ->
|
||||
|
||||
#[no_mangle]
|
||||
unsafe extern "C" fn strcat(dst: *mut c_char, src: *const c_char) -> *mut c_char {
|
||||
strncat(dst, src, usize::MAX)
|
||||
if dst.is_null() {
|
||||
panic!();
|
||||
}
|
||||
stpcpy(dst.add(strlen(dst)), src);
|
||||
dst
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
@ -59,7 +74,8 @@ unsafe extern "C" fn strcmp(a: *const c_char, b: *const c_char) -> c_int {
|
||||
|
||||
#[no_mangle]
|
||||
unsafe extern "C" fn strcpy(dst: *mut c_char, src: *const c_char) -> *mut c_char {
|
||||
strncpy(dst, src, usize::MAX)
|
||||
stpcpy(dst, src);
|
||||
dst
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
@ -80,7 +96,11 @@ unsafe extern "C" fn strcspn(mut s: *const c_char, reject: *const c_char) -> usi
|
||||
|
||||
#[no_mangle]
|
||||
unsafe extern "C" fn strdup(s: *const c_char) -> *mut c_char {
|
||||
strndup(s, usize::MAX)
|
||||
s.ensure();
|
||||
let len = strlen(s);
|
||||
let data = malloc(len + 1);
|
||||
memcpy(data as _, s as _, len + 1);
|
||||
data as _
|
||||
}
|
||||
|
||||
unsafe fn strerror_inner(e: c_int) -> *const c_char {
|
||||
@ -105,25 +125,29 @@ unsafe extern "C" fn strerror_r(e: c_int, buf: *mut c_char, n: usize) -> *mut c_
|
||||
|
||||
#[no_mangle]
|
||||
unsafe extern "C" fn strncat(dst: *mut c_char, src: *const c_char, n: usize) -> *mut c_char {
|
||||
if dst.is_null() {
|
||||
if dst.is_null() || src.is_null() {
|
||||
panic!();
|
||||
}
|
||||
let len = strnlen(src, n);
|
||||
let p = dst.add(strlen(dst));
|
||||
let p = mempcpy(p as _, src as _, len) as *mut c_char;
|
||||
*p = 0;
|
||||
let ptr = dst.add(strlen(dst));
|
||||
let ptr = mempcpy(ptr as _, src as _, len) as *mut c_char;
|
||||
*ptr = 0;
|
||||
|
||||
dst
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
unsafe extern "C" fn strncmp(mut a: *const c_char, mut b: *const c_char, mut n: usize) -> c_int {
|
||||
if a.is_null() || b.is_null() {
|
||||
if a.is_null() {
|
||||
panic!();
|
||||
}
|
||||
if b.is_null() {
|
||||
panic!();
|
||||
}
|
||||
if a == b {
|
||||
return 0;
|
||||
}
|
||||
|
||||
while n != 0 {
|
||||
match Ord::cmp(&*a, &*b) {
|
||||
Ordering::Less => return -1,
|
||||
|
@ -1,13 +1,13 @@
|
||||
language = "C"
|
||||
style = "Type"
|
||||
|
||||
sys_includes = ["stddef.h", "stdint.h"]
|
||||
sys_includes = ["stddef.h"]
|
||||
no_includes = true
|
||||
|
||||
include_guard = "_LIMITS_H"
|
||||
include_guard = "_STRINGS_H"
|
||||
|
||||
usize_type = "size_t"
|
||||
isize_type = "ssize_t"
|
||||
|
||||
[export]
|
||||
include = []
|
||||
exclude = []
|
29
src/header/strings/mod.rs
Normal file
29
src/header/strings/mod.rs
Normal file
@ -0,0 +1,29 @@
|
||||
use core::{
|
||||
cmp::Ordering,
|
||||
ffi::{c_char, c_int},
|
||||
};
|
||||
|
||||
#[no_mangle]
|
||||
unsafe extern "C" fn strcasecmp(s1: *const c_char, s2: *const c_char) -> c_int {
|
||||
strncasecmp(s1, s2, usize::MAX)
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
unsafe extern "C" fn strncasecmp(s1: *const c_char, s2: *const c_char, n: usize) -> c_int {
|
||||
for i in 0..n {
|
||||
let c0 = (*s1.add(i) as u8).to_ascii_lowercase();
|
||||
let c1 = (*s2.add(i) as u8).to_ascii_lowercase();
|
||||
|
||||
match c0.cmp(&c1) {
|
||||
Ordering::Less => return -1,
|
||||
Ordering::Equal => (),
|
||||
Ordering::Greater => return 1,
|
||||
}
|
||||
|
||||
if c0 == 0 {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
0
|
||||
}
|
20
src/header/sys_param/cbindgen.toml
Normal file
20
src/header/sys_param/cbindgen.toml
Normal file
@ -0,0 +1,20 @@
|
||||
language = "C"
|
||||
style = "Type"
|
||||
|
||||
sys_includes = [
|
||||
"stddef.h",
|
||||
"stdint.h",
|
||||
"sys/types.h",
|
||||
"limits.h",
|
||||
"signal.h",
|
||||
"bits/sys/param.h"
|
||||
]
|
||||
no_includes = true
|
||||
|
||||
include_guard = "_SYS_PARAM_H"
|
||||
|
||||
usize_type = "size_t"
|
||||
isize_type = "ssize_t"
|
||||
|
||||
[export]
|
||||
exclude = []
|
0
src/header/sys_param/mod.rs
Normal file
0
src/header/sys_param/mod.rs
Normal file
14
src/header/sys_resource/cbindgen.toml
Normal file
14
src/header/sys_resource/cbindgen.toml
Normal file
@ -0,0 +1,14 @@
|
||||
language = "C"
|
||||
style = "Tag"
|
||||
|
||||
sys_includes = ["stddef.h", "stdint.h", "sys/types.h"]
|
||||
no_includes = true
|
||||
|
||||
include_guard = "_SYS_RESOURCE_H"
|
||||
|
||||
usize_type = "size_t"
|
||||
isize_type = "ssize_t"
|
||||
|
||||
[export]
|
||||
include = ["rlimit"]
|
||||
exclude = []
|
22
src/header/sys_resource/mod.rs
Normal file
22
src/header/sys_resource/mod.rs
Normal file
@ -0,0 +1,22 @@
|
||||
use core::ffi::c_int;
|
||||
|
||||
pub type rlim_t = u64;
|
||||
|
||||
pub const RLIM_INFINITY: rlim_t = u64::MAX;
|
||||
pub const RLIM_SAVED_MAX: rlim_t = u64::MAX - 1;
|
||||
pub const RLIM_SAVED_CUR: rlim_t = u64::MAX - 2;
|
||||
|
||||
pub const RLIMIT_CORE: c_int = 1;
|
||||
pub const RLIMIT_CPU: c_int = 2;
|
||||
pub const RLIMIT_DATA: c_int = 3;
|
||||
pub const RLIMIT_FSIZE: c_int = 4;
|
||||
pub const RLIMIT_NOFILE: c_int = 5;
|
||||
pub const RLIMIT_STACK: c_int = 6;
|
||||
pub const RLIMIT_AS: c_int = 7;
|
||||
|
||||
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
|
||||
#[repr(C)]
|
||||
pub struct rlimit {
|
||||
rlim_cur: rlim_t,
|
||||
rlim_max: rlim_t,
|
||||
}
|
20
src/header/sys_select/cbindgen.toml
Normal file
20
src/header/sys_select/cbindgen.toml
Normal file
@ -0,0 +1,20 @@
|
||||
language = "C"
|
||||
style = "Tag"
|
||||
|
||||
sys_includes = [
|
||||
"stddef.h",
|
||||
"sys/types.h",
|
||||
"sys/time.h",
|
||||
"string.h",
|
||||
"bits/sys/select.h"
|
||||
]
|
||||
no_includes = true
|
||||
|
||||
include_guard = "_SYS_SOCKET_H"
|
||||
|
||||
usize_type = "size_t"
|
||||
isize_type = "ssize_t"
|
||||
|
||||
[export]
|
||||
include = ["sockaddr", "socklen_t"]
|
||||
exclude = []
|
24
src/header/sys_select/mod.rs
Normal file
24
src/header/sys_select/mod.rs
Normal file
@ -0,0 +1,24 @@
|
||||
use core::ffi::c_int;
|
||||
|
||||
use super::sys_time::__ygg_timeval_t;
|
||||
|
||||
#[derive(Clone, Copy, PartialEq, Eq, Debug, Default)]
|
||||
#[repr(C)]
|
||||
pub struct __fd_set {
|
||||
bits: [u64; 4],
|
||||
}
|
||||
|
||||
pub const FD_SETSIZE: usize = 64 * 4;
|
||||
|
||||
pub type fd_set = __fd_set;
|
||||
|
||||
#[no_mangle]
|
||||
unsafe extern "C" fn select(
|
||||
nfds: c_int,
|
||||
readfds: *mut fd_set,
|
||||
writefds: *mut fd_set,
|
||||
exceptfds: *mut fd_set,
|
||||
timeout: *mut __ygg_timeval_t,
|
||||
) -> c_int {
|
||||
todo!()
|
||||
}
|
14
src/header/sys_socket/cbindgen.toml
Normal file
14
src/header/sys_socket/cbindgen.toml
Normal file
@ -0,0 +1,14 @@
|
||||
language = "C"
|
||||
style = "Tag"
|
||||
|
||||
sys_includes = ["stddef.h", "stdint.h", "sys/types.h"]
|
||||
no_includes = true
|
||||
|
||||
include_guard = "_SYS_SOCKET_H"
|
||||
|
||||
usize_type = "size_t"
|
||||
isize_type = "ssize_t"
|
||||
|
||||
[export]
|
||||
include = ["sockaddr", "socklen_t"]
|
||||
exclude = []
|
10
src/header/sys_socket/mod.rs
Normal file
10
src/header/sys_socket/mod.rs
Normal file
@ -0,0 +1,10 @@
|
||||
pub type sa_family_t = u16;
|
||||
|
||||
pub type socklen_t = usize;
|
||||
|
||||
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
|
||||
#[repr(C)]
|
||||
pub struct sockaddr {
|
||||
pub sa_family: sa_family_t,
|
||||
pub sa_data: [u8; 30],
|
||||
}
|
@ -1,25 +1,18 @@
|
||||
use core::{
|
||||
ffi::{c_char, c_int, CStr},
|
||||
mem::MaybeUninit,
|
||||
};
|
||||
use core::ffi::{c_char, c_int, CStr};
|
||||
|
||||
use yggdrasil_rt::{
|
||||
io::{FileAttr, FileMode, FileType, RawFd},
|
||||
path::Path,
|
||||
sys as syscall,
|
||||
};
|
||||
use yggdrasil_rt::io::{FileAttr, FileMode, FileType, RawFd};
|
||||
|
||||
use crate::{
|
||||
error::{self, CZeroResult, EResult},
|
||||
error::{self, CZeroResult},
|
||||
io,
|
||||
util::Nullable,
|
||||
};
|
||||
|
||||
use super::{
|
||||
errno::{Errno, EBADF},
|
||||
errno::EBADF,
|
||||
fcntl::{AT_FDCWD, AT_SYMLINK_NOFOLLOW},
|
||||
sys_time::__ygg_timespec_t,
|
||||
sys_types::{blkcnt_t, blksize_t, dev_t, gid_t, ino_t, mode_t, nlink_t, off_t, uid_t},
|
||||
time::{__ygg_timespec_t, timespec},
|
||||
};
|
||||
|
||||
#[derive(Clone, Copy, PartialEq, Eq, Debug, Default)]
|
||||
|
14
src/header/sys_time/cbindgen.toml
Normal file
14
src/header/sys_time/cbindgen.toml
Normal file
@ -0,0 +1,14 @@
|
||||
language = "C"
|
||||
style = "Tag"
|
||||
|
||||
sys_includes = ["stdarg.h", "stddef.h", "stdint.h", "sys/types.h"]
|
||||
no_includes = true
|
||||
|
||||
include_guard = "_SYS_TIME_H"
|
||||
|
||||
usize_type = "size_t"
|
||||
isize_type = "ssize_t"
|
||||
|
||||
[export]
|
||||
include = ["timeval", "timespec", "__ygg_timeval_t", "__ygg_timespec_t"]
|
||||
exclude = []
|
20
src/header/sys_time/mod.rs
Normal file
20
src/header/sys_time/mod.rs
Normal file
@ -0,0 +1,20 @@
|
||||
use core::ffi::c_long;
|
||||
|
||||
use super::sys_types::{suseconds_t, time_t};
|
||||
|
||||
#[derive(Clone, Copy, PartialEq, Eq, Debug, Default)]
|
||||
#[repr(C)]
|
||||
pub struct timeval {
|
||||
pub tv_sec: time_t,
|
||||
pub tv_usec: suseconds_t,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, PartialEq, Eq, Debug, Default)]
|
||||
#[repr(C)]
|
||||
pub struct timespec {
|
||||
pub tv_sec: time_t,
|
||||
pub tv_nsec: c_long,
|
||||
}
|
||||
|
||||
pub type __ygg_timeval_t = timeval;
|
||||
pub type __ygg_timespec_t = timespec;
|
@ -27,12 +27,12 @@ pub type clock_t = u64;
|
||||
|
||||
#[derive(Clone, Copy, PartialEq, Eq, Debug, Default)]
|
||||
#[repr(transparent)]
|
||||
pub struct time_t(pub u64);
|
||||
pub struct time_t(pub i64);
|
||||
|
||||
pub type off_t = i64;
|
||||
|
||||
pub type suseconds_t = c_ulong;
|
||||
|
||||
impl time_t {
|
||||
pub const INVALID: Self = Self(u64::MAX);
|
||||
pub const INVALID: Self = Self(i64::MAX);
|
||||
}
|
||||
|
14
src/header/termios/cbindgen.toml
Normal file
14
src/header/termios/cbindgen.toml
Normal file
@ -0,0 +1,14 @@
|
||||
language = "C"
|
||||
style = "Tag"
|
||||
|
||||
sys_includes = ["stddef.h"]
|
||||
no_includes = true
|
||||
|
||||
include_guard = "_TERMIOS_H"
|
||||
|
||||
usize_type = "size_t"
|
||||
isize_type = "ssize_t"
|
||||
|
||||
[export]
|
||||
include = ["termios", "speed_t", "tcflag_t", "cc_t"]
|
||||
exclude = []
|
106
src/header/termios/mod.rs
Normal file
106
src/header/termios/mod.rs
Normal file
@ -0,0 +1,106 @@
|
||||
use core::ffi::{c_int, c_uchar, c_uint};
|
||||
|
||||
pub type cc_t = c_uchar;
|
||||
pub type speed_t = c_uint;
|
||||
pub type tcflag_t = c_uint;
|
||||
|
||||
// c_iflag
|
||||
pub const IGNBRK: tcflag_t = 1 << 0;
|
||||
pub const BRKINT: tcflag_t = 1 << 1;
|
||||
pub const IGNPAR: tcflag_t = 1 << 2;
|
||||
pub const PARMRK: tcflag_t = 1 << 3;
|
||||
pub const INPCK: tcflag_t = 1 << 4;
|
||||
pub const ISTRIP: tcflag_t = 1 << 5;
|
||||
pub const INLCR: tcflag_t = 1 << 6;
|
||||
pub const IGNCR: tcflag_t = 1 << 7;
|
||||
pub const ICRNL: tcflag_t = 1 << 8;
|
||||
pub const IXON: tcflag_t = 1 << 9;
|
||||
pub const IXANY: tcflag_t = 1 << 10;
|
||||
pub const IXOFF: tcflag_t = 1 << 11;
|
||||
|
||||
// c_oflag
|
||||
pub const OPOST: tcflag_t = 1 << 0;
|
||||
pub const ONLCR: tcflag_t = 1 << 1;
|
||||
pub const OCRNL: tcflag_t = 1 << 2;
|
||||
pub const ONOCR: tcflag_t = 1 << 3;
|
||||
pub const ONLRET: tcflag_t = 1 << 4;
|
||||
pub const OFILL: tcflag_t = 1 << 5;
|
||||
pub const OFDEL: tcflag_t = 1 << 6;
|
||||
|
||||
// c_cflag
|
||||
pub const CS5: tcflag_t = 0x0;
|
||||
pub const CS6: tcflag_t = 0x1;
|
||||
pub const CS7: tcflag_t = 0x2;
|
||||
pub const CS8: tcflag_t = 0x3;
|
||||
|
||||
pub const CSIZE: tcflag_t = 0x3;
|
||||
pub const CSTOPB: tcflag_t = 1 << 2;
|
||||
pub const CREAD: tcflag_t = 1 << 3;
|
||||
pub const PARENB: tcflag_t = 1 << 4;
|
||||
pub const PARODD: tcflag_t = 1 << 5;
|
||||
pub const HUPCL: tcflag_t = 1 << 6;
|
||||
pub const CLOCAL: tcflag_t = 1 << 7;
|
||||
|
||||
// c_lflag
|
||||
pub const ISIG: tcflag_t = 1 << 0;
|
||||
pub const ICANON: tcflag_t = 1 << 1;
|
||||
pub const ECHO: tcflag_t = 1 << 2;
|
||||
pub const ECHOE: tcflag_t = 1 << 3;
|
||||
pub const ECHOK: tcflag_t = 1 << 4;
|
||||
pub const ECHONL: tcflag_t = 1 << 5;
|
||||
pub const NOFLSH: tcflag_t = 1 << 6;
|
||||
pub const TOSTOP: tcflag_t = 1 << 7;
|
||||
pub const IEXTEN: tcflag_t = 1 << 8;
|
||||
|
||||
// c_cc
|
||||
pub const VEOF: usize = 0;
|
||||
pub const VEOL: usize = 1;
|
||||
pub const VERASE: usize = 2;
|
||||
pub const VINTR: usize = 3;
|
||||
pub const VKILL: usize = 4;
|
||||
pub const VQUIT: usize = 5;
|
||||
pub const VREPRINT: usize = 6;
|
||||
pub const VSTART: usize = 7;
|
||||
pub const VSTOP: usize = 8;
|
||||
pub const VSUSP: usize = 9;
|
||||
pub const VWERASE: usize = 10;
|
||||
|
||||
pub const TCSANOW: c_int = 0;
|
||||
pub const TCSADRAIN: c_int = 1;
|
||||
pub const TCSAFLUSH: c_int = 2;
|
||||
|
||||
pub const TCOOFF: c_int = 1;
|
||||
pub const TCOON: c_int = 2;
|
||||
pub const TCIOFF: c_int = 3;
|
||||
pub const TCION: c_int = 4;
|
||||
|
||||
pub const NCCS: usize = 16;
|
||||
|
||||
#[derive(Clone, Copy, PartialEq, Eq, Debug, Default)]
|
||||
#[repr(C)]
|
||||
pub struct termios {
|
||||
pub c_iflag: tcflag_t,
|
||||
pub c_oflag: tcflag_t,
|
||||
pub c_cflag: tcflag_t,
|
||||
pub c_lflag: tcflag_t,
|
||||
pub c_cc: [cc_t; NCCS],
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
unsafe extern "C" fn tcgetattr(fd: c_int, termios_p: *mut termios) -> c_int {
|
||||
todo!()
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
unsafe extern "C" fn tcsetattr(
|
||||
fd: c_int,
|
||||
optional_actions: c_int,
|
||||
termios_p: *const termios,
|
||||
) -> c_int {
|
||||
todo!()
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
unsafe extern "C" fn cfmakeraw(termios_p: *mut termios) {
|
||||
todo!()
|
||||
}
|
@ -6,7 +6,8 @@ sys_includes = [
|
||||
"stdint.h",
|
||||
"locale.h",
|
||||
"sys/types.h",
|
||||
"bits/time.h"
|
||||
"sys/time.h",
|
||||
"bits/time.h",
|
||||
]
|
||||
no_includes = true
|
||||
|
||||
@ -16,4 +17,4 @@ usize_type = "size_t"
|
||||
isize_type = "ssize_t"
|
||||
|
||||
[export]
|
||||
include = ["timespec", "tm", "itimerspec"]
|
||||
include = ["tm", "itimerspec"]
|
||||
|
@ -6,7 +6,7 @@ use core::{
|
||||
|
||||
use chrono::{DateTime, Datelike, NaiveDate, NaiveDateTime, NaiveTime, TimeZone, Timelike, Utc};
|
||||
|
||||
use super::sys_types::time_t;
|
||||
use super::{sys_time::__ygg_timespec_t, sys_types::time_t};
|
||||
|
||||
mod convert;
|
||||
mod string;
|
||||
@ -24,18 +24,11 @@ int timer_settime(timer_t, int, const struct itimerspec *restrict,
|
||||
struct itimerspec *restrict);
|
||||
*/
|
||||
|
||||
#[derive(Clone, Copy, PartialEq, Eq, Debug, Default)]
|
||||
#[repr(C)]
|
||||
pub struct timespec {
|
||||
pub tv_sec: time_t,
|
||||
pub tv_nsec: c_long,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, PartialEq, Eq, Debug, Default)]
|
||||
#[repr(C)]
|
||||
pub struct itimerspec {
|
||||
pub it_interval: timespec,
|
||||
pub it_value: timespec,
|
||||
pub it_interval: __ygg_timespec_t,
|
||||
pub it_value: __ygg_timespec_t,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, PartialEq, Eq, Debug, Default)]
|
||||
@ -52,8 +45,6 @@ pub struct tm {
|
||||
pub tm_isdst: c_int,
|
||||
}
|
||||
|
||||
pub type __ygg_timespec_t = timespec;
|
||||
|
||||
#[no_mangle]
|
||||
pub static mut daylight: c_int = 0;
|
||||
#[no_mangle]
|
||||
@ -71,11 +62,11 @@ pub trait CDateTime {
|
||||
|
||||
impl tm {
|
||||
pub fn naive_date(&self) -> Option<NaiveDate> {
|
||||
Some(NaiveDate::from_ymd(
|
||||
NaiveDate::from_ymd_opt(
|
||||
self.tm_year + 1900,
|
||||
u32::try_from(self.tm_mon).ok()? + 1,
|
||||
u32::try_from(self.tm_mday).ok()?,
|
||||
))
|
||||
)
|
||||
}
|
||||
|
||||
pub fn naive_time(&self) -> Option<NaiveTime> {
|
||||
@ -98,7 +89,7 @@ impl CDateTime for tm {
|
||||
|
||||
impl CDateTime for time_t {
|
||||
fn to_naive_datetime(&self) -> Option<NaiveDateTime> {
|
||||
NaiveDateTime::from_timestamp_opt(self.0.try_into().ok()?, 0)
|
||||
NaiveDateTime::from_timestamp_opt(self.0, 0)
|
||||
}
|
||||
}
|
||||
|
||||
@ -118,9 +109,12 @@ impl<T: Datelike + Timelike> From<T> for tm {
|
||||
}
|
||||
}
|
||||
|
||||
impl From<timespec> for Duration {
|
||||
fn from(value: timespec) -> Self {
|
||||
Self::new(value.tv_sec.0, value.tv_nsec.try_into().unwrap())
|
||||
impl From<__ygg_timespec_t> for Duration {
|
||||
fn from(value: __ygg_timespec_t) -> Self {
|
||||
Self::new(
|
||||
value.tv_sec.0.try_into().unwrap(),
|
||||
value.tv_nsec.try_into().unwrap(),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,12 +1,14 @@
|
||||
use core::ffi::c_int;
|
||||
|
||||
use crate::header::sys_types::{clock_t, clockid_t, pid_t};
|
||||
|
||||
use super::timespec;
|
||||
use crate::header::{
|
||||
sys_time::__ygg_timespec_t,
|
||||
sys_types::{clock_t, clockid_t, pid_t},
|
||||
};
|
||||
|
||||
#[no_mangle]
|
||||
unsafe extern "C" fn clock() -> clock_t {
|
||||
todo!()
|
||||
// TODO
|
||||
0
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
@ -15,17 +17,17 @@ unsafe extern "C" fn clock_getcpuclockid(pid: pid_t, clock_id_ptr: *mut clockid_
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
unsafe extern "C" fn clock_getres(clock_id: clockid_t, ts: *mut timespec) -> c_int {
|
||||
unsafe extern "C" fn clock_getres(clock_id: clockid_t, ts: *mut __ygg_timespec_t) -> c_int {
|
||||
todo!()
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
unsafe extern "C" fn clock_gettime(clock_id: clockid_t, ts: *mut timespec) -> c_int {
|
||||
unsafe extern "C" fn clock_gettime(clock_id: clockid_t, ts: *mut __ygg_timespec_t) -> c_int {
|
||||
todo!()
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
unsafe extern "C" fn clock_settime(clock_id: clockid_t, ts: *const timespec) -> c_int {
|
||||
unsafe extern "C" fn clock_settime(clock_id: clockid_t, ts: *const __ygg_timespec_t) -> c_int {
|
||||
todo!()
|
||||
}
|
||||
|
||||
@ -33,8 +35,8 @@ unsafe extern "C" fn clock_settime(clock_id: clockid_t, ts: *const timespec) ->
|
||||
unsafe extern "C" fn clock_nanosleep(
|
||||
clock_id: clockid_t,
|
||||
flags: c_int,
|
||||
rqtp: *const timespec,
|
||||
rmtp: *mut timespec,
|
||||
rqtp: *const __ygg_timespec_t,
|
||||
rmtp: *mut __ygg_timespec_t,
|
||||
) -> c_int {
|
||||
todo!()
|
||||
}
|
||||
|
@ -3,12 +3,16 @@ use core::{
|
||||
time::Duration,
|
||||
};
|
||||
|
||||
use crate::{header::sys_types::time_t, util};
|
||||
|
||||
use super::timespec;
|
||||
use crate::{
|
||||
header::{sys_time::__ygg_timespec_t, sys_types::time_t},
|
||||
util,
|
||||
};
|
||||
|
||||
#[no_mangle]
|
||||
unsafe extern "C" fn nanosleep(rqtp: *const timespec, rmtp: *mut timespec) -> c_int {
|
||||
unsafe extern "C" fn nanosleep(
|
||||
rqtp: *const __ygg_timespec_t,
|
||||
rmtp: *mut __ygg_timespec_t,
|
||||
) -> c_int {
|
||||
let rqtp = rqtp.as_ref().unwrap();
|
||||
|
||||
let amount = Duration::from(*rqtp);
|
||||
@ -17,7 +21,7 @@ unsafe extern "C" fn nanosleep(rqtp: *const timespec, rmtp: *mut timespec) -> c_
|
||||
Ok(()) => {
|
||||
if let Some(rmtp) = rmtp.as_mut() {
|
||||
// Zero
|
||||
*rmtp = timespec::default();
|
||||
*rmtp = __ygg_timespec_t::default();
|
||||
}
|
||||
|
||||
0
|
||||
|
@ -1,7 +1,13 @@
|
||||
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",
|
||||
"fcntl.h"
|
||||
]
|
||||
no_includes = true
|
||||
|
||||
include_guard = "_UNISTD_H"
|
||||
|
147
src/header/unistd/io.rs
Normal file
147
src/header/unistd/io.rs
Normal file
@ -0,0 +1,147 @@
|
||||
use core::ffi::{c_char, c_int, c_long, c_void};
|
||||
|
||||
use yggdrasil_rt::io::SeekFrom;
|
||||
|
||||
use crate::{
|
||||
error,
|
||||
file::RawFile,
|
||||
header::{
|
||||
errno::EINVAL,
|
||||
fcntl::{AT_FDCWD, AT_SYMLINK_NOFOLLOW},
|
||||
stdio::{SEEK_CUR, SEEK_END, SEEK_SET},
|
||||
sys_types::off_t,
|
||||
},
|
||||
io::{Read, Seek, Write},
|
||||
util::Nullable,
|
||||
};
|
||||
|
||||
pub const _PC_NAME_MAX: c_int = 1;
|
||||
pub const _PC_PATH_MAX: c_int = 2;
|
||||
|
||||
#[no_mangle]
|
||||
unsafe extern "C" fn getcwd(buf: *mut c_char, size: usize) -> *mut c_char {
|
||||
todo!()
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
unsafe extern "C" fn close(fd: c_int) -> c_int {
|
||||
let Ok(mut file) = RawFile::try_from(fd) else {
|
||||
return -1;
|
||||
};
|
||||
|
||||
match file.close() {
|
||||
Ok(()) => 0,
|
||||
Err(_) => -1,
|
||||
}
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
unsafe extern "C" fn unlink(pathname: *const c_char) -> c_int {
|
||||
unlinkat(AT_FDCWD, pathname, AT_SYMLINK_NOFOLLOW)
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
unsafe extern "C" fn unlinkat(atfd: c_int, pathname: *const c_char, flags: c_int) -> c_int {
|
||||
todo!()
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
unsafe extern "C" fn write(fd: c_int, buf: *const c_void, count: usize) -> isize {
|
||||
buf.ensure();
|
||||
|
||||
let Ok(mut file) = RawFile::try_from(fd) else {
|
||||
return -1;
|
||||
};
|
||||
let data = core::slice::from_raw_parts(buf as *const u8, count);
|
||||
|
||||
match file.write(data) {
|
||||
Ok(amount) => amount.try_into().unwrap(),
|
||||
Err(_) => -1,
|
||||
}
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
unsafe extern "C" fn read(fd: c_int, buf: *mut c_void, count: usize) -> isize {
|
||||
buf.ensure();
|
||||
|
||||
let Ok(mut file) = RawFile::try_from(fd) else {
|
||||
return -1;
|
||||
};
|
||||
let data = core::slice::from_raw_parts_mut(buf as *mut u8, count);
|
||||
|
||||
match file.read(data) {
|
||||
Ok(amount) => amount.try_into().unwrap(),
|
||||
Err(_) => -1,
|
||||
}
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
unsafe extern "C" fn lseek(fd: c_int, offset: off_t, whence: c_int) -> off_t {
|
||||
let Ok(mut file) = RawFile::try_from(fd) else {
|
||||
return -1;
|
||||
};
|
||||
let offset = match whence {
|
||||
SEEK_SET => SeekFrom::Start(offset.try_into().unwrap()),
|
||||
SEEK_CUR => SeekFrom::Current(offset),
|
||||
SEEK_END => SeekFrom::End(offset),
|
||||
_ => {
|
||||
error::set_errno(EINVAL);
|
||||
return -1;
|
||||
}
|
||||
};
|
||||
|
||||
match file.seek(offset) {
|
||||
Ok(pos) => pos.try_into().unwrap(),
|
||||
Err(_) => -1,
|
||||
}
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
unsafe extern "C" fn faccessat(
|
||||
fd: c_int,
|
||||
path: *const c_char,
|
||||
amode: c_int,
|
||||
flags: c_int,
|
||||
) -> c_int {
|
||||
todo!()
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
unsafe extern "C" fn access(path: *const c_char, amode: c_int) -> c_int {
|
||||
faccessat(AT_FDCWD, path, amode, 0)
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
unsafe extern "C" fn dup(fd: c_int) -> c_int {
|
||||
todo!()
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
unsafe extern "C" fn dup2(oldfd: c_int, newfd: c_int) -> c_int {
|
||||
todo!()
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
unsafe extern "C" fn isatty(fd: c_int) -> c_int {
|
||||
0
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
unsafe extern "C" fn rmdir(pathname: *const c_char) -> c_int {
|
||||
todo!()
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
unsafe extern "C" fn chdir(pathname: *const c_char) -> c_int {
|
||||
todo!()
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
unsafe extern "C" fn pipe(fds: *mut c_int) -> c_int {
|
||||
todo!()
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
unsafe extern "C" fn pathconf(pathname: *const c_char, name: c_int) -> c_long {
|
||||
todo!()
|
||||
}
|
@ -1,114 +1,77 @@
|
||||
use core::ffi::{c_char, c_int, CStr};
|
||||
|
||||
use crate::{
|
||||
error::{CZeroResult, EResult},
|
||||
util::{self, NullTerminated},
|
||||
use core::{
|
||||
ffi::{c_char, c_uint},
|
||||
time::Duration,
|
||||
};
|
||||
|
||||
use super::{errno::Errno, sys_types::pid_t};
|
||||
use crate::util;
|
||||
|
||||
use alloc::{vec, vec::Vec};
|
||||
use yggdrasil_rt::{path::Path, process::ExecveOptions, sys as syscall};
|
||||
/*
|
||||
unsigned alarm(unsigned);
|
||||
size_t confstr(int, char *, size_t);
|
||||
char *crypt(const char *, const char *);
|
||||
void encrypt(char [64], int);
|
||||
int fchdir(int);
|
||||
int fchown(int, uid_t, gid_t);
|
||||
int fchownat(int, const char *, uid_t, gid_t, int);
|
||||
int fdatasync(int);
|
||||
int fexecve(int, char *const [], char *const []);
|
||||
long fpathconf(int, int);
|
||||
int fsync(int);
|
||||
int ftruncate(int, off_t);
|
||||
gid_t getegid(void);
|
||||
uid_t geteuid(void);
|
||||
gid_t getgid(void);
|
||||
int getgroups(int, gid_t []);
|
||||
long gethostid(void);
|
||||
int gethostname(char *, size_t);
|
||||
char *getlogin(void);
|
||||
int getlogin_r(char *, size_t);
|
||||
int getopt(int, char * const [], const char *);
|
||||
pid_t getpgid(pid_t);
|
||||
pid_t getpgrp(void);
|
||||
pid_t getppid(void);
|
||||
pid_t getsid(pid_t);
|
||||
uid_t getuid(void);
|
||||
int lchown(const char *, uid_t, gid_t);
|
||||
int link(const char *, const char *);
|
||||
int linkat(int, const char *, int, const char *, int);
|
||||
int lockf(int, int, off_t);
|
||||
int nice(int);
|
||||
int pause(void);
|
||||
ssize_t pread(int, void *, size_t, off_t);
|
||||
ssize_t pwrite(int, const void *, size_t, off_t);
|
||||
ssize_t readlink(const char *restrict, char *restrict, size_t);
|
||||
ssize_t readlinkat(int, const char *restrict, char *restrict, size_t);
|
||||
int setegid(gid_t);
|
||||
int seteuid(uid_t);
|
||||
int setgid(gid_t);
|
||||
int setpgid(pid_t, pid_t);
|
||||
pid_t setpgrp(void);
|
||||
int setregid(gid_t, gid_t);
|
||||
int setreuid(uid_t, uid_t);
|
||||
pid_t setsid(void);
|
||||
int setuid(uid_t);
|
||||
unsigned sleep(unsigned);
|
||||
void swab(const void *restrict, void *restrict, ssize_t);
|
||||
int symlink(const char *, const char *);
|
||||
int symlinkat(const char *, int, const char *);
|
||||
void sync(void);
|
||||
long sysconf(int);
|
||||
pid_t tcgetpgrp(int);
|
||||
int tcsetpgrp(int, pid_t);
|
||||
int truncate(const char *, off_t);
|
||||
char *ttyname(int);
|
||||
int ttyname_r(int, char *, size_t);
|
||||
*/
|
||||
|
||||
unsafe fn fork_inner() -> Result<pid_t, Errno> {
|
||||
let result = EResult::from(syscall::fork())?;
|
||||
Ok(result as _)
|
||||
}
|
||||
|
||||
// TODO error reporting
|
||||
unsafe fn collect_execve_args<'a, 'e>(
|
||||
argv: *const *mut c_char,
|
||||
envp: *const *mut c_char,
|
||||
) -> Result<(Vec<&'a str>, Vec<&'e str>), Errno> {
|
||||
let mut arg_list = vec![];
|
||||
let mut env_list = vec![];
|
||||
|
||||
if let Some(argv) = NullTerminated::try_from_ptr(argv) {
|
||||
for &arg in argv {
|
||||
let arg = CStr::from_ptr(arg);
|
||||
arg_list.push(arg.to_str().unwrap());
|
||||
}
|
||||
}
|
||||
if let Some(envp) = NullTerminated::try_from_ptr(envp) {
|
||||
for &env in envp {
|
||||
let env = CStr::from_ptr(env);
|
||||
env_list.push(env.to_str().unwrap());
|
||||
}
|
||||
}
|
||||
|
||||
Ok((arg_list, env_list))
|
||||
}
|
||||
|
||||
unsafe fn execve_inner<P: AsRef<Path>>(
|
||||
pathname: P,
|
||||
argv: &[&str],
|
||||
envp: &[&str],
|
||||
) -> Result<(), Errno> {
|
||||
EResult::Err(yggdrasil_rt::Error::InvalidFile)?;
|
||||
let opts = ExecveOptions {
|
||||
program: pathname.as_ref().as_str(),
|
||||
arguments: argv,
|
||||
environment: envp,
|
||||
};
|
||||
let result = EResult::from(syscall::execve(&opts))?;
|
||||
Ok(result as _)
|
||||
}
|
||||
|
||||
unsafe fn execvpe_inner(file: &str, argv: &[&str], envp: &[&str]) -> Result<(), Errno> {
|
||||
let pathname = util::resolve_binary(file)?;
|
||||
execve_inner(&pathname, argv, envp)
|
||||
}
|
||||
pub mod io;
|
||||
pub mod process;
|
||||
|
||||
#[no_mangle]
|
||||
pub static mut environ: *mut *const c_char = core::ptr::null_mut();
|
||||
pub static mut environ: *mut *mut c_char = core::ptr::null_mut();
|
||||
|
||||
#[no_mangle]
|
||||
unsafe extern "C" fn fork() -> pid_t {
|
||||
match fork_inner() {
|
||||
Ok(pid) => pid,
|
||||
Err(_) => -1,
|
||||
}
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
unsafe extern "C" fn execve(
|
||||
pathname: *const c_char,
|
||||
argv: *const *mut c_char,
|
||||
envp: *const *mut c_char,
|
||||
) -> c_int {
|
||||
if pathname.is_null() {
|
||||
panic!();
|
||||
}
|
||||
let pathname = CStr::from_ptr(pathname);
|
||||
let pathname = pathname.to_str().unwrap();
|
||||
let (argv, envp) = match collect_execve_args(argv, envp) {
|
||||
Ok(r) => r,
|
||||
Err(_) => return -1,
|
||||
};
|
||||
|
||||
execve_inner(pathname, &argv, &envp).into_zero_status()
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
unsafe extern "C" fn execvp(file: *const c_char, argv: *const *mut c_char) -> c_int {
|
||||
todo!()
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
unsafe extern "C" fn execvpe(
|
||||
file: *const c_char,
|
||||
argv: *const *mut c_char,
|
||||
envp: *const *mut c_char,
|
||||
) -> c_int {
|
||||
if file.is_null() {
|
||||
panic!();
|
||||
}
|
||||
let file = CStr::from_ptr(file);
|
||||
let file = file.to_str().unwrap();
|
||||
let (argv, envp) = match collect_execve_args(argv, envp) {
|
||||
Ok(r) => r,
|
||||
Err(_) => return -1,
|
||||
};
|
||||
|
||||
execvpe_inner(file, &argv, &envp).into_zero_status()
|
||||
unsafe extern "C" fn sleep(seconds: c_uint) -> c_uint {
|
||||
util::nanosleep(Duration::from_secs(seconds as _), None).ok();
|
||||
0
|
||||
}
|
||||
|
128
src/header/unistd/process.rs
Normal file
128
src/header/unistd/process.rs
Normal file
@ -0,0 +1,128 @@
|
||||
use core::{
|
||||
ffi::{c_char, c_int, CStr},
|
||||
ptr::null,
|
||||
};
|
||||
|
||||
use alloc::{vec, vec::Vec};
|
||||
use yggdrasil_rt::{path::Path, process::ExecveOptions, sys as syscall};
|
||||
|
||||
use crate::{
|
||||
error::{CZeroResult, EResult},
|
||||
header::{errno::Errno, sys_types::pid_t},
|
||||
util::{self, NullTerminated},
|
||||
};
|
||||
|
||||
unsafe fn fork_inner() -> Result<pid_t, Errno> {
|
||||
let result = EResult::from(syscall::fork())?;
|
||||
Ok(result as _)
|
||||
}
|
||||
|
||||
// TODO error reporting
|
||||
unsafe fn collect_execve_args<'a, 'e>(
|
||||
argv: *const *mut c_char,
|
||||
envp: *const *mut c_char,
|
||||
) -> Result<(Vec<&'a str>, Vec<&'e str>), Errno> {
|
||||
let mut arg_list = vec![];
|
||||
let mut env_list = vec![];
|
||||
|
||||
if let Some(argv) = NullTerminated::try_from_ptr(argv) {
|
||||
for &arg in argv {
|
||||
let arg = CStr::from_ptr(arg);
|
||||
arg_list.push(arg.to_str().unwrap());
|
||||
}
|
||||
}
|
||||
if let Some(envp) = NullTerminated::try_from_ptr(envp) {
|
||||
for &env in envp {
|
||||
let env = CStr::from_ptr(env);
|
||||
env_list.push(env.to_str().unwrap());
|
||||
}
|
||||
}
|
||||
|
||||
Ok((arg_list, env_list))
|
||||
}
|
||||
|
||||
unsafe fn execve_inner<P: AsRef<Path>>(
|
||||
pathname: P,
|
||||
argv: &[&str],
|
||||
envp: &[&str],
|
||||
) -> Result<(), Errno> {
|
||||
let opts = ExecveOptions {
|
||||
program: pathname.as_ref().as_str(),
|
||||
arguments: argv,
|
||||
environment: envp,
|
||||
};
|
||||
let result = EResult::from(syscall::execve(&opts))?;
|
||||
Ok(result as _)
|
||||
}
|
||||
|
||||
unsafe fn execvpe_inner(file: &str, argv: &[&str], envp: &[&str]) -> Result<(), Errno> {
|
||||
let pathname = util::resolve_binary(file)?;
|
||||
execve_inner(&pathname, argv, envp)
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
unsafe extern "C" fn fork() -> pid_t {
|
||||
match fork_inner() {
|
||||
Ok(pid) => pid,
|
||||
Err(_) => -1,
|
||||
}
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
unsafe extern "C" fn execve(
|
||||
pathname: *const c_char,
|
||||
argv: *const *mut c_char,
|
||||
envp: *const *mut c_char,
|
||||
) -> c_int {
|
||||
if pathname.is_null() {
|
||||
panic!();
|
||||
}
|
||||
let pathname = CStr::from_ptr(pathname);
|
||||
let pathname = pathname.to_str().unwrap();
|
||||
let (argv, envp) = match collect_execve_args(argv, envp) {
|
||||
Ok(r) => r,
|
||||
Err(_) => return -1,
|
||||
};
|
||||
|
||||
execve_inner(pathname, &argv, &envp).into_zero_status()
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
unsafe extern "C" fn execv(pathname: *const c_char, argv: *const *mut c_char) -> c_int {
|
||||
execve(pathname, argv, null())
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
unsafe extern "C" fn execvp(file: *const c_char, argv: *const *mut c_char) -> c_int {
|
||||
execvpe(file, argv, null())
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
unsafe extern "C" fn execvpe(
|
||||
file: *const c_char,
|
||||
argv: *const *mut c_char,
|
||||
envp: *const *mut c_char,
|
||||
) -> c_int {
|
||||
if file.is_null() {
|
||||
panic!();
|
||||
}
|
||||
let file = CStr::from_ptr(file);
|
||||
let file = file.to_str().unwrap();
|
||||
let (argv, envp) = match collect_execve_args(argv, envp) {
|
||||
Ok(r) => r,
|
||||
Err(_) => return -1,
|
||||
};
|
||||
|
||||
execvpe_inner(file, &argv, &envp).into_zero_status()
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
unsafe extern "C" fn _exit(status: c_int) -> ! {
|
||||
todo!()
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
unsafe extern "C" fn getpid() -> pid_t {
|
||||
let pid = syscall::get_pid();
|
||||
pid.try_into().unwrap()
|
||||
}
|
20
src/header/wchar/cbindgen.toml
Normal file
20
src/header/wchar/cbindgen.toml
Normal file
@ -0,0 +1,20 @@
|
||||
language = "C"
|
||||
style = "Type"
|
||||
|
||||
sys_includes = [
|
||||
"stddef.h",
|
||||
"stdint.h",
|
||||
"stdarg.h",
|
||||
"locale.h",
|
||||
"string.h",
|
||||
"stdio.h",
|
||||
"time.h"
|
||||
]
|
||||
no_includes = true
|
||||
|
||||
include_guard = "_WCHAR_H"
|
||||
|
||||
usize_type = "size_t"
|
||||
isize_type = "ssize_t"
|
||||
|
||||
[export]
|
30
src/header/wchar/mod.rs
Normal file
30
src/header/wchar/mod.rs
Normal file
@ -0,0 +1,30 @@
|
||||
use core::ffi::c_uint;
|
||||
|
||||
mod multibyte;
|
||||
mod wcio;
|
||||
mod wcstring;
|
||||
mod wctype;
|
||||
|
||||
pub type wint_t = c_uint;
|
||||
|
||||
pub const WEOF: wint_t = -1i32 as wint_t;
|
||||
|
||||
/*
|
||||
wint_t btowc(int);
|
||||
size_t wcsftime(wchar_t *restrict, size_t,
|
||||
const wchar_t *restrict, const struct tm *restrict);
|
||||
double wcstod(const wchar_t *restrict, wchar_t **restrict);
|
||||
float wcstof(const wchar_t *restrict, wchar_t **restrict);
|
||||
long wcstol(const wchar_t *restrict, wchar_t **restrict, int);
|
||||
long double wcstold(const wchar_t *restrict, wchar_t **restrict);
|
||||
long long wcstoll(const wchar_t *restrict, wchar_t **restrict, int);
|
||||
unsigned long wcstoul(const wchar_t *restrict, wchar_t **restrict, int);
|
||||
unsigned long long
|
||||
wcstoull(const wchar_t *restrict, wchar_t **restrict, int);
|
||||
int wcswidth(const wchar_t *, size_t);
|
||||
int wctob(wint_t);
|
||||
wctype_t wctype(const char *);
|
||||
int wcwidth(wchar_t);
|
||||
int wprintf(const wchar_t *restrict, ...);
|
||||
int wscanf(const wchar_t *restrict, ...);
|
||||
*/
|
24
src/header/wchar/multibyte.rs
Normal file
24
src/header/wchar/multibyte.rs
Normal file
@ -0,0 +1,24 @@
|
||||
/*
|
||||
size_t mbrlen(const char *restrict, size_t, mbstate_t *restrict);
|
||||
size_t mbrtowc(wchar_t *restrict, const char *restrict, size_t,
|
||||
mbstate_t *restrict);
|
||||
int mbsinit(const mbstate_t *);
|
||||
size_t mbsnrtowcs(wchar_t *restrict, const char **restrict,
|
||||
size_t, size_t, mbstate_t *restrict);
|
||||
size_t mbsrtowcs(wchar_t *restrict, const char **restrict, size_t,
|
||||
mbstate_t *restrict);
|
||||
size_t wcrtomb(char *restrict, wchar_t, mbstate_t *restrict);
|
||||
size_t wcsnrtombs(char *restrict, const wchar_t **restrict, size_t,
|
||||
size_t, mbstate_t *restrict);
|
||||
size_t wcsrtombs(char *restrict, const wchar_t **restrict,
|
||||
size_t, mbstate_t *restrict);
|
||||
*/
|
||||
|
||||
use core::ffi::c_char;
|
||||
|
||||
use crate::types::wchar_t;
|
||||
|
||||
#[no_mangle]
|
||||
unsafe extern "C" fn mbstowcs(dest: *mut wchar_t, src: *const c_char, n: usize) -> usize {
|
||||
todo!()
|
||||
}
|
27
src/header/wchar/wcio.rs
Normal file
27
src/header/wchar/wcio.rs
Normal file
@ -0,0 +1,27 @@
|
||||
/*
|
||||
wint_t fgetwc(FILE *);
|
||||
wchar_t *fgetws(wchar_t *restrict, int, FILE *restrict);
|
||||
wint_t fputwc(wchar_t, FILE *);
|
||||
int fputws(const wchar_t *restrict, FILE *restrict);
|
||||
int fwide(FILE *, int);
|
||||
int fwprintf(FILE *restrict, const wchar_t *restrict, ...);
|
||||
int fwscanf(FILE *restrict, const wchar_t *restrict, ...);
|
||||
wint_t getwc(FILE *);
|
||||
wint_t getwchar(void);
|
||||
FILE *open_wmemstream(wchar_t **, size_t *);
|
||||
wint_t putwc(wchar_t, FILE *);
|
||||
wint_t putwchar(wchar_t);
|
||||
int swprintf(wchar_t *restrict, size_t,
|
||||
const wchar_t *restrict, ...);
|
||||
int swscanf(const wchar_t *restrict,
|
||||
const wchar_t *restrict, ...);
|
||||
wint_t ungetwc(wint_t, FILE *);
|
||||
int vfwprintf(FILE *restrict, const wchar_t *restrict, va_list);
|
||||
int vfwscanf(FILE *restrict, const wchar_t *restrict, va_list);
|
||||
int vswprintf(wchar_t *restrict, size_t,
|
||||
const wchar_t *restrict, va_list);
|
||||
int vswscanf(const wchar_t *restrict, const wchar_t *restrict,
|
||||
va_list);
|
||||
int vwprintf(const wchar_t *restrict, va_list);
|
||||
int vwscanf(const wchar_t *restrict, va_list);
|
||||
*/
|
36
src/header/wchar/wcstring.rs
Normal file
36
src/header/wchar/wcstring.rs
Normal file
@ -0,0 +1,36 @@
|
||||
/*
|
||||
wchar_t *wcpcpy(wchar_t *restrict, const wchar_t *restrict);
|
||||
wchar_t *wcpncpy(wchar_t *restrict, const wchar_t *restrict, size_t);
|
||||
int wcscasecmp(const wchar_t *, const wchar_t *);
|
||||
int wcscasecmp_l(const wchar_t *, const wchar_t *, locale_t);
|
||||
wchar_t *wcscat(wchar_t *restrict, const wchar_t *restrict);
|
||||
wchar_t *wcschr(const wchar_t *, wchar_t);
|
||||
int wcscmp(const wchar_t *, const wchar_t *);
|
||||
int wcscoll(const wchar_t *, const wchar_t *);
|
||||
int wcscoll_l(const wchar_t *, const wchar_t *, locale_t);
|
||||
wchar_t *wcscpy(wchar_t *restrict, const wchar_t *restrict);
|
||||
size_t wcscspn(const wchar_t *, const wchar_t *);
|
||||
wchar_t *wcsdup(const wchar_t *);
|
||||
size_t wcslen(const wchar_t *);
|
||||
int wcsncasecmp(const wchar_t *, const wchar_t *, size_t);
|
||||
int wcsncasecmp_l(const wchar_t *, const wchar_t *, size_t,
|
||||
locale_t);
|
||||
wchar_t *wcsncat(wchar_t *restrict, const wchar_t *restrict, size_t);
|
||||
int wcsncmp(const wchar_t *, const wchar_t *, size_t);
|
||||
wchar_t *wcsncpy(wchar_t *restrict, const wchar_t *restrict, size_t);
|
||||
size_t wcsnlen(const wchar_t *, size_t);
|
||||
wchar_t *wcspbrk(const wchar_t *, const wchar_t *);
|
||||
wchar_t *wcsrchr(const wchar_t *, wchar_t);
|
||||
size_t wcsspn(const wchar_t *, const wchar_t *);
|
||||
wchar_t *wcsstr(const wchar_t *restrict, const wchar_t *restrict);
|
||||
wchar_t *wcstok(wchar_t *restrict, const wchar_t *restrict,
|
||||
wchar_t **restrict);
|
||||
size_t wcsxfrm(wchar_t *restrict, const wchar_t *restrict, size_t);
|
||||
size_t wcsxfrm_l(wchar_t *restrict, const wchar_t *restrict,
|
||||
size_t, locale_t);
|
||||
wchar_t *wmemchr(const wchar_t *, wchar_t, size_t);
|
||||
int wmemcmp(const wchar_t *, const wchar_t *, size_t);
|
||||
wchar_t *wmemcpy(wchar_t *restrict, const wchar_t *restrict, size_t);
|
||||
wchar_t *wmemmove(wchar_t *, const wchar_t *, size_t);
|
||||
wchar_t *wmemset(wchar_t *, wchar_t, size_t);
|
||||
*/
|
16
src/header/wchar/wctype.rs
Normal file
16
src/header/wchar/wctype.rs
Normal file
@ -0,0 +1,16 @@
|
||||
/*
|
||||
int iswalnum(wint_t);
|
||||
int iswalpha(wint_t);
|
||||
int iswcntrl(wint_t);
|
||||
int iswctype(wint_t, wctype_t);
|
||||
int iswdigit(wint_t);
|
||||
int iswgraph(wint_t);
|
||||
int iswlower(wint_t);
|
||||
int iswprint(wint_t);
|
||||
int iswpunct(wint_t);
|
||||
int iswspace(wint_t);
|
||||
int iswupper(wint_t);
|
||||
int iswxdigit(wint_t);
|
||||
wint_t towlower(wint_t);
|
||||
wint_t towupper(wint_t);
|
||||
*/
|
@ -148,7 +148,7 @@ impl<W: Write> Write for UnbufferedWriter<W> {
|
||||
|
||||
impl<W: Write> Write for BufWriter<W> {
|
||||
fn write(&mut self, mut data: &[u8]) -> Result<usize, Errno> {
|
||||
if data.len() + self.buffer.len() > self.buffer.capacity() {
|
||||
if data.len() + self.buffer.len() >= self.buffer.capacity() {
|
||||
self.flush()?;
|
||||
}
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
use core::mem::MaybeUninit;
|
||||
|
||||
use alloc::{boxed::Box, vec::Vec};
|
||||
use alloc::boxed::Box;
|
||||
use yggdrasil_rt::{
|
||||
io::{DirectoryEntry, RawFd},
|
||||
path::Path,
|
||||
@ -26,7 +26,7 @@ impl DirReader {
|
||||
const BUFFER_SIZE: usize = 16;
|
||||
|
||||
pub fn open_at<P: AsRef<Path>>(at: Option<RawFd>, path: P) -> Result<Self, Errno> {
|
||||
let fd = EResult::from(unsafe { syscall::open_directory(None, path.as_ref().as_str()) })?;
|
||||
let fd = EResult::from(unsafe { syscall::open_directory(at, path.as_ref().as_str()) })?;
|
||||
Ok(unsafe { Self::from_raw_fd(fd) })
|
||||
}
|
||||
|
||||
|
@ -60,6 +60,22 @@ pub trait Seek {
|
||||
}
|
||||
}
|
||||
|
||||
pub trait FromRawFd {
|
||||
unsafe fn from_raw_fd(fd: RawFd) -> Self;
|
||||
}
|
||||
|
||||
pub trait AsRawFdOpt {
|
||||
fn as_raw_fd_opt(&self) -> Option<RawFd>;
|
||||
}
|
||||
|
||||
pub trait AsRawFd {
|
||||
fn as_raw_fd(&self) -> RawFd;
|
||||
}
|
||||
|
||||
pub trait IntoRawFd {
|
||||
fn into_raw_fd(self) -> RawFd;
|
||||
}
|
||||
|
||||
pub fn get_metadata<P: AsRef<Path>>(
|
||||
at: Option<RawFd>,
|
||||
path: P,
|
||||
|
32
src/lib.rs
32
src/lib.rs
@ -7,17 +7,18 @@
|
||||
arbitrary_self_types,
|
||||
new_uninit,
|
||||
maybe_uninit_slice,
|
||||
inline_const
|
||||
inline_const,
|
||||
vec_into_raw_parts
|
||||
)]
|
||||
#![allow(internal_features)]
|
||||
#![no_std]
|
||||
|
||||
use core::ffi::{c_char, c_int, CStr};
|
||||
use core::{
|
||||
ffi::{c_char, c_int, CStr},
|
||||
ptr::null,
|
||||
};
|
||||
|
||||
use alloc::{ffi::CString, vec::Vec};
|
||||
use header::unistd::environ;
|
||||
use alloc::vec::Vec;
|
||||
use util::Nullable;
|
||||
use yggdrasil_rt::process::{ExitCode, ProgramArgumentInner};
|
||||
|
||||
use crate::header::stdio::{self, stderr};
|
||||
|
||||
@ -32,6 +33,7 @@ pub mod file;
|
||||
pub mod io;
|
||||
pub mod path;
|
||||
pub mod process;
|
||||
pub mod signal;
|
||||
pub mod sync;
|
||||
pub mod types;
|
||||
pub mod util;
|
||||
@ -42,14 +44,17 @@ unsafe extern "C" fn _start(arg: usize) -> ! {
|
||||
fn main(argc: c_int, argv: *const *const c_char) -> c_int;
|
||||
}
|
||||
|
||||
signal::init();
|
||||
|
||||
let args = process::setup_env(arg);
|
||||
let c_args = args.iter().map(|s| s.as_ptr()).collect::<Vec<_>>();
|
||||
let mut c_args = args.iter().map(|s| s.as_ptr()).collect::<Vec<_>>();
|
||||
// Terminate argv with NULL
|
||||
let argc = c_args.len();
|
||||
c_args.push(null());
|
||||
|
||||
stdio::setup_default_files();
|
||||
|
||||
// TODO setup signals, allocator, etc.
|
||||
|
||||
let code = main(c_args.len().try_into().unwrap(), c_args.as_ptr());
|
||||
let code = main(argc.try_into().unwrap(), c_args.as_ptr());
|
||||
|
||||
process::exit(code)
|
||||
}
|
||||
@ -59,7 +64,8 @@ fn panic_handler(pi: &core::panic::PanicInfo) -> ! {
|
||||
yggdrasil_rt::debug_trace!("--- C PROGRAM PANICKED ---");
|
||||
yggdrasil_rt::debug_trace!("{:?}", pi);
|
||||
yggdrasil_rt::debug_trace!("--- END PANIC ---");
|
||||
process::exit(ExitCode::Exited(1));
|
||||
|
||||
process::abort();
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
@ -75,7 +81,7 @@ unsafe extern "C" fn __assert_fail(file: *const c_char, line: c_int, expr: *cons
|
||||
let expr = CStr::from_ptr(expr).to_str().unwrap();
|
||||
|
||||
// These should not be NULL, but check nevertheless
|
||||
writeln!(err, "Assertion failed: {:?} at {}:{}", expr, file, line);
|
||||
writeln!(err, "Assertion failed: '{}' at {}:{}", expr, file, line).ok();
|
||||
|
||||
panic!("TODO: abort()");
|
||||
process::abort();
|
||||
}
|
||||
|
@ -1,23 +1,19 @@
|
||||
use core::{
|
||||
ffi::c_char,
|
||||
ptr::{null, null_mut},
|
||||
slice::memchr,
|
||||
};
|
||||
use core::{ffi::c_char, ptr::null_mut, slice::memchr};
|
||||
|
||||
use alloc::{ffi::CString, vec::Vec};
|
||||
use yggdrasil_rt::{
|
||||
process::{ExitCode, ProgramArgumentInner},
|
||||
process::{ExitCode, ProgramArgumentInner, Signal},
|
||||
sys as syscall,
|
||||
};
|
||||
|
||||
use crate::{
|
||||
error,
|
||||
header::{
|
||||
errno::{Errno, EINVAL, ENOENT, ENOMEM, ESUCCESS},
|
||||
limits::ATEXIT_MAX,
|
||||
errno::{Errno, EINVAL, ENOMEM, ESUCCESS},
|
||||
stdio,
|
||||
unistd::environ,
|
||||
},
|
||||
signal,
|
||||
sync::Mutex,
|
||||
};
|
||||
|
||||
@ -39,6 +35,8 @@ impl ToExitCode for ExitCode {
|
||||
|
||||
// Exit
|
||||
|
||||
const ATEXIT_MAX: usize = 32;
|
||||
|
||||
static ATEXIT: Mutex<[Option<extern "C" fn()>; ATEXIT_MAX]> =
|
||||
Mutex::new([const { None }; ATEXIT_MAX]);
|
||||
|
||||
@ -71,25 +69,36 @@ unsafe fn pre_exit() {
|
||||
stdio::cleanup();
|
||||
}
|
||||
|
||||
pub fn current_pid() -> u32 {
|
||||
unsafe { syscall::get_pid() }
|
||||
}
|
||||
|
||||
pub fn abort() -> ! {
|
||||
unsafe {
|
||||
signal::send(current_pid(), Signal::Aborted).unwrap();
|
||||
unreachable!();
|
||||
}
|
||||
}
|
||||
|
||||
// Env
|
||||
|
||||
static mut ENVS: Vec<CString> = Vec::new();
|
||||
static mut C_ENVS: Vec<*const c_char> = Vec::new();
|
||||
static mut C_ENVS: Vec<*mut c_char> = Vec::new();
|
||||
|
||||
pub unsafe fn setup_env(arg: usize) -> Vec<CString> {
|
||||
let arg = &*(arg as *const ProgramArgumentInner<'static>);
|
||||
let mut args = Vec::new();
|
||||
|
||||
for (i, &arg) in arg.args.into_iter().enumerate() {
|
||||
for &arg in arg.args {
|
||||
args.push(CString::new(arg).unwrap());
|
||||
}
|
||||
|
||||
for (i, &env) in arg.env.into_iter().enumerate() {
|
||||
ENVS.push(CString::new(env).unwrap());
|
||||
C_ENVS.push(ENVS[i].as_ptr());
|
||||
C_ENVS.push(ENVS[i].as_ptr() as *mut _);
|
||||
}
|
||||
// Terminate the environ with null
|
||||
C_ENVS.push(null());
|
||||
C_ENVS.push(null_mut());
|
||||
|
||||
environ = C_ENVS.as_mut_ptr();
|
||||
|
||||
@ -168,8 +177,8 @@ pub unsafe fn setenv_raw(key: &[u8], value: Option<&[u8]>, overwrite: bool) -> R
|
||||
|
||||
ENVS.push(new_var);
|
||||
// Replace the null with the variable
|
||||
C_ENVS[new_index] = ENVS[new_index].as_ptr();
|
||||
C_ENVS.push(null());
|
||||
C_ENVS[new_index] = ENVS[new_index].as_ptr() as _;
|
||||
C_ENVS.push(null_mut());
|
||||
}
|
||||
|
||||
Ok(())
|
||||
|
72
src/signal.rs
Normal file
72
src/signal.rs
Normal file
@ -0,0 +1,72 @@
|
||||
use core::sync::atomic::{AtomicUsize, Ordering};
|
||||
|
||||
use alloc::vec;
|
||||
use yggdrasil_rt::{
|
||||
process::{ExitCode, Signal, SignalEntryData},
|
||||
sys as syscall,
|
||||
};
|
||||
|
||||
use crate::{
|
||||
error::EResult,
|
||||
header::{
|
||||
errno::Errno,
|
||||
signal::{sig_handler_t, SigNumber},
|
||||
},
|
||||
process,
|
||||
};
|
||||
|
||||
const SIGNAL_STACK_SIZE: usize = 65536;
|
||||
const MAX_SIGNAL: usize = 32;
|
||||
|
||||
static SIGNAL_TABLE: [AtomicUsize; MAX_SIGNAL] = [const { AtomicUsize::new(0) }; MAX_SIGNAL];
|
||||
|
||||
#[no_mangle]
|
||||
extern "C" fn __sig_ignore(_: SigNumber) {}
|
||||
|
||||
#[no_mangle]
|
||||
extern "C" fn __sig_terminate(c: SigNumber) {
|
||||
// Convert signal back to Signal
|
||||
let signal = Signal::try_from(c).unwrap();
|
||||
unsafe {
|
||||
process::raw_exit(ExitCode::BySignal(signal));
|
||||
}
|
||||
}
|
||||
|
||||
unsafe extern "C" fn signal_entry(data: &SignalEntryData) -> ! {
|
||||
let signum = data.signal as u32 as usize;
|
||||
|
||||
if let Some(handler_ptr) = SIGNAL_TABLE.get(signum) {
|
||||
let handler: sig_handler_t = core::mem::transmute(handler_ptr.load(Ordering::Acquire));
|
||||
|
||||
handler(data.signal.into());
|
||||
|
||||
syscall::exit_signal(data)
|
||||
} else {
|
||||
todo!("Signal out of range?");
|
||||
}
|
||||
}
|
||||
|
||||
pub unsafe fn set_handler(signal: Signal, handler: Option<sig_handler_t>) -> sig_handler_t {
|
||||
let signum = signal as u32 as usize;
|
||||
let handler_ptr = handler.unwrap_or(__sig_terminate) as usize;
|
||||
let old_handler_ptr = SIGNAL_TABLE[signum].swap(handler_ptr, Ordering::SeqCst);
|
||||
|
||||
// Not null
|
||||
core::mem::transmute(old_handler_ptr)
|
||||
}
|
||||
|
||||
pub unsafe fn send(target: u32, signal: Signal) -> Result<(), Errno> {
|
||||
EResult::from(syscall::send_signal(target, signal))?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub unsafe fn init() {
|
||||
let (signal_stack, _, _) = vec![0u8; SIGNAL_STACK_SIZE].into_raw_parts();
|
||||
let signal_stack_ptr = signal_stack.add(SIGNAL_STACK_SIZE);
|
||||
|
||||
for entry in SIGNAL_TABLE.iter() {
|
||||
entry.store(__sig_terminate as usize, Ordering::Release);
|
||||
}
|
||||
|
||||
syscall::set_signal_entry(signal_entry as usize, signal_stack_ptr as usize);
|
||||
}
|
@ -1,3 +1,5 @@
|
||||
#![allow(non_camel_case_types)]
|
||||
|
||||
pub type wchar_t = i32;
|
||||
use core::ffi::c_int;
|
||||
|
||||
pub type wchar_t = c_int;
|
||||
|
@ -1,10 +1,4 @@
|
||||
use core::{
|
||||
ffi::c_char,
|
||||
fmt,
|
||||
marker::PhantomData,
|
||||
ptr::{null_mut, NonNull},
|
||||
time::Duration,
|
||||
};
|
||||
use core::{ffi::c_char, fmt, marker::PhantomData, ptr::NonNull, time::Duration};
|
||||
|
||||
use yggdrasil_rt::{path::Path, sys as syscall};
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user