libc: extend GNU library/tool compatibility
This commit is contained in:
parent
87ae150dc1
commit
fc9018585b
@ -1,3 +1,9 @@
|
||||
#if defined(_ASSERT_H)
|
||||
#undef _ASSERT_H
|
||||
#undef assert
|
||||
#undef __ASSERT_VOID_CAST
|
||||
#endif
|
||||
|
||||
#ifndef _ASSERT_H
|
||||
#define _ASSERT_H 1
|
||||
|
||||
|
@ -6,6 +6,8 @@ extern "C" {
|
||||
#endif
|
||||
|
||||
extern _Thread_local int errno;
|
||||
extern char *program_invocation_short_name;
|
||||
extern char *program_invocation_name;
|
||||
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
|
@ -80,6 +80,12 @@ pub enum Errno {
|
||||
// Custom errnos
|
||||
ENOTSUPP = 66,
|
||||
ETIMEOUT = 67,
|
||||
|
||||
EILSEQ = 68,
|
||||
EOVERFLOW = 69,
|
||||
ENOTSUP = 70,
|
||||
|
||||
ELAST = 71,
|
||||
}
|
||||
|
||||
static UNKNOWN_ERROR: &CStr = static_cstr!("Unknown error");
|
||||
@ -153,6 +159,9 @@ static ERRNO_STRINGS: &[&CStr] = &[
|
||||
// Custom errnos
|
||||
static_cstr!("Operation not supported"),
|
||||
static_cstr!("Operation timed out"),
|
||||
// GNU errnos
|
||||
static_cstr!("Invalid sequence"),
|
||||
static_cstr!("Integer overflow"),
|
||||
];
|
||||
|
||||
impl Errno {
|
||||
|
@ -93,8 +93,8 @@ enum OpenMode {
|
||||
|
||||
fn open_opts(opts: c_int, ap: &mut VaList) -> EResult<OpenMode> {
|
||||
if opts & O_DIRECTORY != 0 {
|
||||
if opts & !O_DIRECTORY != 0 {
|
||||
todo!();
|
||||
if opts & !(O_DIRECTORY | O_SEARCH) != 0 {
|
||||
todo!("***open(O_DIRECTORY | {:#x})", opts & !O_DIRECTORY);
|
||||
}
|
||||
|
||||
return EResult::Ok(OpenMode::Directory);
|
||||
@ -126,10 +126,16 @@ fn open_opts(opts: c_int, ap: &mut VaList) -> EResult<OpenMode> {
|
||||
if opts & O_TRUNC != 0 {
|
||||
res |= OpenOptions::TRUNCATE;
|
||||
}
|
||||
if opts & O_NONBLOCK != 0 {
|
||||
// TODO O_NONBLOCK
|
||||
}
|
||||
if opts & O_NOCTTY != 0 {
|
||||
// TODO O_NOCTTY
|
||||
}
|
||||
// TODO O_CLOEXEC
|
||||
|
||||
if opts & (O_DSYNC | O_RSYNC | O_SYNC | O_TTY_INIT | O_NONBLOCK | O_NOFOLLOW | O_NOCTTY) != 0 {
|
||||
todo!();
|
||||
if opts & (O_DSYNC | O_RSYNC | O_SYNC | O_TTY_INIT | O_NOFOLLOW) != 0 {
|
||||
todo!("Unhandled options: {:#x}", opts);
|
||||
}
|
||||
|
||||
let mode = if need_mode {
|
||||
@ -162,7 +168,7 @@ unsafe fn vopenat(atfd: c_int, pathname: *const c_char, opts: c_int, mut ap: VaL
|
||||
|
||||
let fd = match open_opts(opts, &mut ap)? {
|
||||
OpenMode::File(opts, mode) => RawFile::open_at(atfd, pathname, opts, mode)?.into_raw_fd(),
|
||||
OpenMode::Directory => todo!(),
|
||||
OpenMode::Directory => RawFile::open_directory_at(atfd, pathname)?.into_raw_fd(),
|
||||
};
|
||||
|
||||
CFdResult::success(fd)
|
||||
|
@ -133,6 +133,7 @@ pub mod sys_statvfs;
|
||||
pub mod sys_time;
|
||||
pub mod sys_times;
|
||||
pub mod sys_types;
|
||||
pub mod sys_uio;
|
||||
pub mod sys_utsname;
|
||||
pub mod sys_wait;
|
||||
|
||||
|
@ -22,12 +22,14 @@ pub type sig_handler_t = unsafe extern "C" fn(c_int);
|
||||
pub type sigset_t = u64;
|
||||
|
||||
#[repr(C)]
|
||||
pub struct stack_t {
|
||||
pub struct __stack {
|
||||
pub ss_sp: *mut c_void,
|
||||
pub ss_flags: c_int,
|
||||
pub ss_size: usize,
|
||||
}
|
||||
|
||||
pub type stack_t = __stack;
|
||||
|
||||
#[repr(C)]
|
||||
pub struct sigevent {
|
||||
pub sigev_notify: c_int,
|
||||
@ -305,8 +307,17 @@ unsafe extern "C" fn siginterrupt(_signum: c_int, _b: c_int) -> c_int {
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
unsafe extern "C" fn sigismember(_mask: *const sigset_t, _signum: c_int) -> c_int {
|
||||
todo!()
|
||||
unsafe extern "C" fn sigismember(mask: *const sigset_t, signum: c_int) -> c_int {
|
||||
if signum > 63 || signum <= 0 {
|
||||
error::errno = Errno::EINVAL;
|
||||
return -1;
|
||||
}
|
||||
let mask = *mask.ensure();
|
||||
if mask & (1 << signum) != 0 {
|
||||
1
|
||||
} else {
|
||||
0
|
||||
}
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
|
@ -243,3 +243,29 @@ unsafe extern "C" fn setvbuf(
|
||||
fp.setvbuf(mode, buffer, size)?;
|
||||
CIntZeroResult::SUCCESS
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
unsafe extern "C" fn fpurge(_fp: *mut FILE) {
|
||||
todo!("fpurge()")
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
unsafe extern "C" fn __fpurge(_fp: *mut FILE) {
|
||||
todo!("__fpurge()")
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
unsafe extern "C" fn freading(fp: *mut FILE) -> c_int {
|
||||
__freading(fp)
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
unsafe extern "C" fn __freading(fp: *mut FILE) -> c_int {
|
||||
let fp = fp.ensure_mut();
|
||||
fp.reading() as c_int
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
unsafe extern "C" fn __fseterr(_fp: *mut FILE) {
|
||||
todo!("__fseterr()")
|
||||
}
|
||||
|
@ -142,7 +142,7 @@ fn printf_inner<W: FmtWriter>(output: &mut W, format: &[u8], mut ap: VaList) ->
|
||||
b'L' => todo!(),
|
||||
b'j' => todo!(),
|
||||
b'z' | b'Z' => opts.size = FmtSize::Size,
|
||||
b't' => todo!(),
|
||||
b't' => opts.size = FmtSize::Size,
|
||||
_ => break,
|
||||
}
|
||||
cur = fmt.next();
|
||||
@ -173,7 +173,11 @@ fn printf_inner<W: FmtWriter>(output: &mut W, format: &[u8], mut ap: VaList) ->
|
||||
spec = Some(FmtSpec::String);
|
||||
}
|
||||
b'p' => spec = Some(FmtSpec::Pointer),
|
||||
b'n' => todo!(),
|
||||
b'n' => unsafe {
|
||||
let arg = ap.arg::<*mut c_int>();
|
||||
*arg = count as c_int;
|
||||
continue;
|
||||
},
|
||||
b'm' => todo!(),
|
||||
b'%' => {
|
||||
count += output.write(b"%")?;
|
||||
|
@ -2,7 +2,8 @@ language = "C"
|
||||
style = "Tag"
|
||||
|
||||
sys_includes = [
|
||||
"sys/types.h"
|
||||
"sys/types.h",
|
||||
"sys/uio.h"
|
||||
]
|
||||
no_includes = true
|
||||
|
||||
|
@ -5,7 +5,10 @@ use core::{
|
||||
|
||||
use crate::{error::EResult, headers::errno::Errno, util::PointerExt};
|
||||
|
||||
use super::netinet_in::{sockaddr_in, sockaddr_in6};
|
||||
use super::{
|
||||
netinet_in::{sockaddr_in, sockaddr_in6},
|
||||
sys_uio::__ygg_iovec_t,
|
||||
};
|
||||
|
||||
mod io;
|
||||
mod option;
|
||||
@ -31,19 +34,12 @@ pub struct sockaddr {
|
||||
|
||||
// TODO struct sockaddr_storage
|
||||
|
||||
// TODO struct iovec from sys/uio.h
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
#[repr(C)]
|
||||
pub struct iovec {
|
||||
__dummy: u32,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
#[repr(C)]
|
||||
pub struct msghdr {
|
||||
pub msg_name: *mut c_void,
|
||||
pub msg_namelen: socklen_t,
|
||||
pub msg_iov: *mut iovec,
|
||||
pub msg_iov: *mut __ygg_iovec_t,
|
||||
pub msg_iovlen: c_int,
|
||||
pub msg_control: *mut c_void,
|
||||
pub msg_controllen: socklen_t,
|
||||
|
@ -1,12 +1,15 @@
|
||||
use core::{
|
||||
ffi::{c_char, c_int},
|
||||
ptr::NonNull,
|
||||
ptr::{null, NonNull},
|
||||
};
|
||||
|
||||
use yggdrasil_rt::io::{FileAttr, FileMode, FileType, RawFd};
|
||||
use yggdrasil_rt::io::{
|
||||
FileAttr, FileMetadataUpdate, FileMetadataUpdateMode, FileMode, FileType, RawFd,
|
||||
};
|
||||
|
||||
use crate::{
|
||||
error::{CIntZeroResult, TryFromExt},
|
||||
error::{CIntZeroResult, ResultExt, TryFromExt},
|
||||
headers::errno::Errno,
|
||||
io,
|
||||
util::{self, PointerStrExt},
|
||||
};
|
||||
@ -104,23 +107,32 @@ impl From<FileAttr> for stat {
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
unsafe extern "C" fn chmod(_pathname: *const c_char, _mode: mode_t) -> c_int {
|
||||
todo!()
|
||||
unsafe extern "C" fn chmod(pathname: *const c_char, mode: mode_t) -> CIntZeroResult {
|
||||
fchmodat(AT_FDCWD, pathname, mode, 0)
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
unsafe extern "C" fn fchmod(_fd: c_int, _mode: mode_t) -> c_int {
|
||||
todo!()
|
||||
unsafe extern "C" fn fchmod(fd: c_int, mode: mode_t) -> CIntZeroResult {
|
||||
fchmodat(fd, null(), mode, 0)
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
unsafe extern "C" fn fchmodat(
|
||||
_fd: c_int,
|
||||
_pathname: *const c_char,
|
||||
_mode: mode_t,
|
||||
fd: c_int,
|
||||
pathname: *const c_char,
|
||||
mode: mode_t,
|
||||
_opt: c_int,
|
||||
) -> c_int {
|
||||
todo!()
|
||||
) -> CIntZeroResult {
|
||||
let atfd = util::at_fd(fd)?;
|
||||
let path = if pathname.is_null() {
|
||||
""
|
||||
} else {
|
||||
pathname.ensure_str()
|
||||
};
|
||||
let mode = unsafe { FileMode::from_raw((mode as u32) & 0o777) };
|
||||
let update = FileMetadataUpdate::Permissions(FileMetadataUpdateMode::Set(mode));
|
||||
unsafe { yggdrasil_rt::sys::update_metadata(atfd, path, &update) }.e_map_err(Errno::from)?;
|
||||
CIntZeroResult::SUCCESS
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
@ -222,7 +234,8 @@ unsafe extern "C" fn stat(pathname: *const c_char, statbuf: *mut stat) -> CIntZe
|
||||
|
||||
#[no_mangle]
|
||||
unsafe extern "C" fn futimens(_fd: c_int, _times: *const __ygg_timespec_t) -> c_int {
|
||||
todo!()
|
||||
log::warn!("TODO: futimens");
|
||||
0
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
|
17
userspace/lib/ygglibc/src/headers/sys_uio/cbindgen.toml
Normal file
17
userspace/lib/ygglibc/src/headers/sys_uio/cbindgen.toml
Normal file
@ -0,0 +1,17 @@
|
||||
language = "C"
|
||||
style = "Tag"
|
||||
|
||||
sys_includes = [
|
||||
"stddef.h",
|
||||
"stdint.h",
|
||||
"sys/types.h",
|
||||
]
|
||||
no_includes = true
|
||||
|
||||
include_guard = "_SYS_UIO_H"
|
||||
|
||||
usize_type = "size_t"
|
||||
isize_type = "ssize_t"
|
||||
|
||||
[export]
|
||||
include = ["iovec", "__ygg_iovec_t"]
|
20
userspace/lib/ygglibc/src/headers/sys_uio/mod.rs
Normal file
20
userspace/lib/ygglibc/src/headers/sys_uio/mod.rs
Normal file
@ -0,0 +1,20 @@
|
||||
use core::ffi::{c_int, c_void};
|
||||
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
#[repr(C)]
|
||||
pub struct iovec {
|
||||
pub iov_base: *mut c_void,
|
||||
pub iov_len: usize,
|
||||
}
|
||||
|
||||
pub type __ygg_iovec_t = iovec;
|
||||
|
||||
#[no_mangle]
|
||||
unsafe extern "C" fn readv(_fd: c_int, _slice: *const iovec, _flags: c_int) -> isize {
|
||||
todo!()
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
unsafe extern "C" fn writev(_fd: c_int, _slice: *const iovec, _flags: c_int) -> isize {
|
||||
todo!()
|
||||
}
|
@ -27,6 +27,11 @@ unsafe extern "C" fn execp(file: *const c_char, argv: *const *mut c_char) -> c_i
|
||||
todo!()
|
||||
}
|
||||
|
||||
#[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 execve(
|
||||
file: *const c_char,
|
||||
|
@ -3,15 +3,17 @@ use core::{
|
||||
ptr::{null_mut, NonNull},
|
||||
};
|
||||
|
||||
use yggdrasil_rt::io::RemoveFlags;
|
||||
|
||||
use crate::{
|
||||
error::{self, CIntZeroResult, CPtrResult, EResult, TryFromExt},
|
||||
error::{self, CIntZeroResult, CPtrResult, EResult, ResultExt, TryFromExt},
|
||||
headers::{
|
||||
errno::Errno,
|
||||
fcntl::{faccessat, AT_FDCWD},
|
||||
fcntl::{faccessat, AT_FDCWD, AT_REMOVEDIR},
|
||||
sys_types::{gid_t, off_t, uid_t},
|
||||
},
|
||||
io::{self, raw::RawFile, FromRawFd},
|
||||
util::{PointerExt, PointerStrExt},
|
||||
util::{self, PointerExt, PointerStrExt},
|
||||
};
|
||||
|
||||
pub const _PC_PATH_MAX: c_int = 0;
|
||||
@ -40,7 +42,8 @@ unsafe extern "C" fn fchdir(fd: c_int) -> c_int {
|
||||
|
||||
#[no_mangle]
|
||||
unsafe extern "C" fn fchown(fd: c_int, uid: uid_t, gid: gid_t) -> c_int {
|
||||
todo!()
|
||||
log::warn!("TODO: fchown({uid}, {gid})");
|
||||
0
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
@ -135,12 +138,17 @@ unsafe extern "C" fn truncate(path: *const c_char, size: off_t) -> c_int {
|
||||
todo!()
|
||||
}
|
||||
#[no_mangle]
|
||||
unsafe extern "C" fn unlink(path: *const c_char) -> c_int {
|
||||
let path = path.ensure_str();
|
||||
log::warn!("TODO: unlink({path:?})");
|
||||
0
|
||||
unsafe extern "C" fn unlink(path: *const c_char) -> CIntZeroResult {
|
||||
unlinkat(AT_FDCWD, path, 0)
|
||||
}
|
||||
#[no_mangle]
|
||||
unsafe extern "C" fn unlinkat(atfd: c_int, path: *const c_char, flags: c_int) -> c_int {
|
||||
todo!()
|
||||
unsafe extern "C" fn unlinkat(atfd: c_int, path: *const c_char, flags: c_int) -> CIntZeroResult {
|
||||
let atfd = util::at_fd(atfd)?;
|
||||
let path = path.ensure_str();
|
||||
let mut f = RemoveFlags::empty();
|
||||
if flags & AT_REMOVEDIR != 0 {
|
||||
f |= RemoveFlags::DIRECTORY;
|
||||
}
|
||||
unsafe { yggdrasil_rt::sys::remove(atfd, path, f) }.e_map_err(Errno::from)?;
|
||||
CIntZeroResult::SUCCESS
|
||||
}
|
||||
|
@ -294,6 +294,13 @@ impl FILE {
|
||||
self.lock.release();
|
||||
}
|
||||
|
||||
pub fn reading(&self) -> bool {
|
||||
!self.flags.contains(FileFlags::WRITE)
|
||||
|| self
|
||||
.last_operation
|
||||
.map_or(false, |op| op == Direction::Read)
|
||||
}
|
||||
|
||||
// pub fn reset(&mut self) {
|
||||
// if let Some(read_buffer) = self.read_buffer.as_mut() {
|
||||
// read_buffer.reset();
|
||||
|
@ -24,6 +24,11 @@ impl RawFile {
|
||||
EResult::Ok(Self(fd))
|
||||
}
|
||||
|
||||
pub fn open_directory_at<P: AsRef<Path>>(at: Option<RawFd>, pathname: P) -> EResult<Self> {
|
||||
let fd = unsafe { syscall::open_directory(at, pathname.as_ref().as_str()) }?;
|
||||
EResult::Ok(Self(fd))
|
||||
}
|
||||
|
||||
pub unsafe fn close(&mut self) -> EResult<()> {
|
||||
unsafe { syscall::close(self.0) }?;
|
||||
EResult::Ok(())
|
||||
|
@ -1,6 +1,7 @@
|
||||
use core::{
|
||||
ffi::{c_char, c_int, c_void, CStr},
|
||||
mem::MaybeUninit,
|
||||
ptr::null_mut,
|
||||
time::Duration,
|
||||
};
|
||||
|
||||
@ -29,6 +30,13 @@ impl DsoDestructor {
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(non_upper_case_globals)]
|
||||
#[no_mangle]
|
||||
static mut program_invocation_short_name: *mut c_char = null_mut();
|
||||
#[allow(non_upper_case_globals)]
|
||||
#[no_mangle]
|
||||
static mut program_invocation_name: *mut c_char = null_mut();
|
||||
|
||||
static AT_EXIT: Mutex<Vec<extern "C" fn()>> = Mutex::new(Vec::new());
|
||||
// TODO this will be in the linker instead
|
||||
static AT_DSO_EXIT: Mutex<Vec<DsoDestructor>> = Mutex::new(Vec::new());
|
||||
|
@ -85,6 +85,19 @@ impl Node for Port {
|
||||
}
|
||||
|
||||
impl NormalPort {
|
||||
fn default_c_dependencies(name: &str) -> Vec<String> {
|
||||
let mut d = vec![];
|
||||
d.push("meta-llvm".into());
|
||||
d.push("meta-libc".into());
|
||||
if name != "compiler-rt" {
|
||||
d.push("compiler-rt".into());
|
||||
}
|
||||
if name != "compiler-rt" && name != "openlibm" {
|
||||
d.push("openlibm".into());
|
||||
}
|
||||
d
|
||||
}
|
||||
|
||||
pub fn load(env: &BuildEnv, name: &str) -> Result<Self, PortError> {
|
||||
let manifest_dir = env.workspace_root.join("ports").join(name);
|
||||
let source_dir = env
|
||||
@ -108,7 +121,7 @@ impl NormalPort {
|
||||
Some(deps) => {
|
||||
let mut d = vec![];
|
||||
if deps.c_compiler.unwrap_or(true) {
|
||||
d.push("meta-llvm".into());
|
||||
d.extend_from_slice(&Self::default_c_dependencies(name));
|
||||
}
|
||||
if let Some(build) = deps.build.as_ref() {
|
||||
d.extend(build.iter().cloned());
|
||||
@ -118,7 +131,7 @@ impl NormalPort {
|
||||
}
|
||||
d
|
||||
}
|
||||
None => vec!["meta-llvm".into()],
|
||||
None => Self::default_c_dependencies(name),
|
||||
};
|
||||
|
||||
Ok(Self {
|
||||
|
Loading…
x
Reference in New Issue
Block a user