libc/colors: non-blocking local socket + fixed string bugs in libc

This commit is contained in:
Mark Poliakov 2025-02-26 11:52:05 +02:00
parent 7fdc57fd9f
commit 43acdb9e13
43 changed files with 459 additions and 115 deletions

View File

@ -129,7 +129,7 @@ impl SocketWrapper {
non_blocking: bool, non_blocking: bool,
) -> Result<usize, Error> { ) -> Result<usize, Error> {
if non_blocking { if non_blocking {
todo!() self.inner.clone().send_nonblocking(message)
} else { } else {
let timeout = self.options.read().send_timeout; let timeout = self.options.read().send_timeout;
block!(self.inner.clone().send_message(message, timeout).await)? block!(self.inner.clone().send_message(message, timeout).await)?

View File

@ -102,3 +102,7 @@ pub fn set_file_option_with<'de, T: OptionValue<'de>>(
let len = T::store(value, buffer)?; let len = T::store(value, buffer)?;
unsafe { crate::sys::set_file_option(fd, T::VARIANT.into(), &buffer[..len]) } unsafe { crate::sys::set_file_option(fd, T::VARIANT.into(), &buffer[..len]) }
} }
pub fn set_nonblocking(fd: RawFd, nonblocking: bool) -> Result<(), Error> {
set_file_option::<options::NonBlocking>(fd, &nonblocking)
}

16
test.c
View File

@ -1,16 +1,12 @@
#include <string.h>
#include <dlfcn.h> #include <dlfcn.h>
#include <stdio.h> #include <stdio.h>
int main(int argc, char **argv) { int main(int argc, char **argv) {
struct Dl_info dl0, dl1; char buffer[9] = {1, 2, 3, 4, 5, 6, 7, 8, 9};
strncpy(buffer, "abcdefghijkl", sizeof(buffer));
dladdr(main, &dl0); for (int i = 0; i < sizeof(buffer); ++i) {
dladdr(printf, &dl1); printf("[%d] 0x%hhx\n", i, buffer[i]);
printf("%s: %p\n", dl1.dli_sname, dl1.dli_saddr); }
printf("%s @ %p\n", dl1.dli_fname, dl1.dli_fbase);
printf("%s: %p\n", dl0.dli_sname, dl0.dli_saddr);
printf("%s @ %p\n", dl0.dli_fname, dl0.dli_fbase);
return 0; return 0;
} }

View File

@ -43,6 +43,8 @@ impl InputState {
b'.' => b'>', b'.' => b'>',
b'`' => b'~', b'`' => b'~',
b'\\' => b'|', b'\\' => b'|',
b'[' => b'{',
b']' => b'}',
_ => ch, _ => ch,
} }
} }

View File

@ -11,7 +11,7 @@ use std::{
use cross::mem::SharedMemory; use cross::mem::SharedMemory;
use input::InputState; use input::InputState;
use libcolors::{ use libcolors::{
event::{EventData, KeyModifiers, KeyboardKeyEvent, WindowEvent, WindowInfo}, event::{EventData, KeyEvent, KeyModifiers, KeyboardKeyEvent, WindowEvent, WindowInfo},
input::Key, input::Key,
message::{ClientMessage, CreateWindowInfo, WindowType}, message::{ClientMessage, CreateWindowInfo, WindowType},
}; };
@ -67,7 +67,7 @@ impl<'a> Server<'a> {
surface: &mut DisplaySurface, surface: &mut DisplaySurface,
tx: &mut ServerSender, tx: &mut ServerSender,
peer: &PeerAddress, peer: &PeerAddress,
info: CreateWindowInfo info: CreateWindowInfo,
) -> Result<(WindowInfo, RawFd), Error> { ) -> Result<(WindowInfo, RawFd), Error> {
let wid = self.last_window_id; let wid = self.last_window_id;
self.last_window_id += 1; self.last_window_id += 1;
@ -152,7 +152,12 @@ impl<'a> Server<'a> {
} }
} }
fn move_window(&mut self, surface: &mut DisplaySurface, tx: &mut ServerSender, direction: Direction) { fn move_window(
&mut self,
surface: &mut DisplaySurface,
tx: &mut ServerSender,
direction: Direction,
) {
if self.workspace.move_window(direction) { if self.workspace.move_window(direction) {
surface.fill(self.background); surface.fill(self.background);
self.flush_dirty_frames(tx); self.flush_dirty_frames(tx);
@ -192,7 +197,8 @@ impl<'a> Server<'a> {
impl WindowServer for Server<'_> { impl WindowServer for Server<'_> {
fn handle_initial(&mut self, mut surface: DisplaySurface) { fn handle_initial(&mut self, mut surface: DisplaySurface) {
self.workspace.resize(surface.width() as u32, surface.height() as u32); self.workspace
.resize(surface.width() as u32, surface.height() as u32);
surface.fill(self.background); surface.fill(self.background);
surface.present(); surface.present();
@ -285,9 +291,9 @@ impl WindowServer for Server<'_> {
) { ) {
self.input_state.update(event.key, event.state); self.input_state.update(event.key, event.state);
if event.state {
let input = self.input_state.make_input(event.key); let input = self.input_state.make_input(event.key);
if event.state {
// Non-window keys // Non-window keys
#[allow(clippy::single_match)] #[allow(clippy::single_match)]
match (input.modifiers, input.key) { match (input.modifiers, input.key) {
@ -299,11 +305,6 @@ impl WindowServer for Server<'_> {
_ => (), _ => (),
} }
let focus = self.workspace.focused_window().and_then(|wid| {
let window = self.windows.get(&wid)?;
Some((wid, window))
});
match (input.modifiers, input.key) { match (input.modifiers, input.key) {
(KeyModifiers::ALT, Key::Char(b'l')) => { (KeyModifiers::ALT, Key::Char(b'l')) => {
self.move_focus(tx, Direction::Right); self.move_focus(tx, Direction::Right);
@ -344,14 +345,6 @@ impl WindowServer for Server<'_> {
_ => (), _ => (),
} }
if let Some((wid, window)) = focus {
// Deliver event to the window
tx.send_event(
EventData::WindowEvent(wid, WindowEvent::KeyInput(input)),
&window.peer,
);
}
// // Window keys // // Window keys
// if let Some((row, col)) = self.focused_frame { // if let Some((row, col)) = self.focused_frame {
// let row_len = self.rows[row].frames.len(); // let row_len = self.rows[row].frames.len();
@ -361,6 +354,42 @@ impl WindowServer for Server<'_> {
// self.focused_frame = None; // self.focused_frame = None;
// } // }
} }
let focus = self.workspace.focused_window().and_then(|wid| {
let window = self.windows.get(&wid)?;
Some((wid, window))
});
if let Some((wid, window)) = focus {
if event.state {
tx.send_event(
EventData::WindowEvent(
wid,
WindowEvent::KeyPressed(KeyEvent {
key: event.key,
modifiers: input.modifiers,
}),
),
&window.peer,
);
// Deliver event to the window
tx.send_event(
EventData::WindowEvent(wid, WindowEvent::KeyInput(input)),
&window.peer,
);
} else {
tx.send_event(
EventData::WindowEvent(
wid,
WindowEvent::KeyReleased(KeyEvent {
key: event.key,
modifiers: input.modifiers,
}),
),
&window.peer,
);
}
}
} }
} }

View File

@ -8,7 +8,7 @@
)] )]
#![allow(clippy::new_without_default, clippy::missing_transmute_annotations)] #![allow(clippy::new_without_default, clippy::missing_transmute_annotations)]
use std::{mem::MaybeUninit, process::ExitCode}; use std::{fs, mem::MaybeUninit, os::yggdrasil::real_binary_path, path::Path, process::ExitCode};
use error::Error; use error::Error;
use object::Object; use object::Object;
@ -27,7 +27,8 @@ pub mod thread_local;
static mut OBJECTS: MaybeUninit<ObjectSet> = MaybeUninit::uninit(); static mut OBJECTS: MaybeUninit<ObjectSet> = MaybeUninit::uninit();
fn run(binary: &str, args: &[String]) -> Result<!, Error> { fn run(binary: &Path, args: &[String]) -> Result<!, Error> {
log::info!("dyn-loader {binary:?}");
// Open root and its dependencies // Open root and its dependencies
let root = Object::open(binary, true)?; let root = Object::open(binary, true)?;
let mut objects = ObjectSet::new(root); let mut objects = ObjectSet::new(root);
@ -139,6 +140,13 @@ unsafe fn enter(entry: extern "C" fn(usize), argument: usize) -> ! {
} }
} }
fn real_binary(arg0: &str) -> &Path {
if fs::exists(arg0).unwrap_or(false) {
return arg0.as_ref();
}
real_binary_path()
}
fn main() -> ExitCode { fn main() -> ExitCode {
logsink::setup_logging(false); logsink::setup_logging(false);
let args: Vec<String> = std::env::args().skip(1).collect(); let args: Vec<String> = std::env::args().skip(1).collect();
@ -148,7 +156,9 @@ fn main() -> ExitCode {
todo!() todo!()
} }
let Err(error) = run(&args[0], &args); let real_binary = real_binary(&args[0]);
let Err(error) = run(real_binary, &args);
eprintln!("Error: {error}"); eprintln!("Error: {error}");
ExitCode::FAILURE ExitCode::FAILURE
} }

View File

@ -1,5 +1,13 @@
use std::{ use std::{
cmp, collections::HashMap, ffi::{CStr, CString}, fs::File, io::{BufReader, Read, Seek, SeekFrom}, mem, ops::Range, path::{Path, PathBuf}, ptr, rc::Rc cmp,
ffi::{CStr, CString},
fs::File,
io::{BufReader, Read, Seek, SeekFrom},
mem,
ops::Range,
path::{Path, PathBuf},
ptr,
rc::Rc,
}; };
use elf::{ use elf::{

View File

@ -42,7 +42,7 @@ impl Relocation for Rela {
R_X86_64_TPOFF64 => { R_X86_64_TPOFF64 => {
// Need to extract fixed global offset // Need to extract fixed global offset
let tls_layout = state.tls_layout.as_ref().unwrap(); let tls_layout = state.tls_layout.as_ref().unwrap();
log::info!("TPOFF64: module_id={}", tls.module_id); log::info!("TPOFF64: {name} -> module_id={}", tls.module_id);
// Offset from TLS start // Offset from TLS start
let offset = tls_layout.offset(tls.module_id, tls.offset).unwrap(); let offset = tls_layout.offset(tls.module_id, tls.offset).unwrap();
let offset_from_tp = -((tls_layout.tp_offset - offset) as i64); let offset_from_tp = -((tls_layout.tp_offset - offset) as i64);

View File

@ -1 +1 @@
export PATH=/bin:/sbin export PATH=/mnt/bin:/bin:/sbin

View File

@ -1,4 +1,6 @@
.section .text .section .text
.global _start .global _start
_start: _start:
jmp . mov $12, %rax
mov $123, %rdi
syscall

View File

@ -1,3 +1,10 @@
void _start(void) { #include <stdlib.h>
#include <stdio.h>
int main(int argc, char **argv) {
printf("Argument count: %d\n", argc);
for (int i = 0; i < argc; ++i) {
printf("Argument %d is %s\n", i, argv[i]);
}
return EXIT_SUCCESS;
} }

6
userspace/etc/test.cpp Normal file
View File

@ -0,0 +1,6 @@
#include <iostream>
int main(int argc, char **argv) {
std::cout << "Test!!!" << std::endl;
return 0;
}

View File

@ -1,4 +1,7 @@
#!/bin/sh #!/bin/sh
/sbin/mount -t ext2 /dev/vb0p1 /mnt
/mnt/bin/clang -cc1as -filetype obj -main-file-name test.S -target-cpu x86-64 -mrelocation-model pic -triple x86_64-unknown-yggdrasil -o /test.o /etc/test.S /mnt/bin/clang -cc1as -filetype obj -main-file-name test.S -target-cpu x86-64 -mrelocation-model pic -triple x86_64-unknown-yggdrasil -o /test.o /etc/test.S
/mnt/bin/ld.lld -nostdlib -o /test /test.o
/bin/ls -lh / /bin/ls -lh /

View File

@ -32,6 +32,10 @@ impl LocalPacketSocket {
sys::LocalPacketSocketImpl::bind(path).map(Self) sys::LocalPacketSocketImpl::bind(path).map(Self)
} }
pub fn set_nonblocking(&self, nb: bool) -> io::Result<()> {
self.0.set_nonblocking(nb)
}
pub fn receive(&self, buffer: &mut [u8]) -> io::Result<usize> { pub fn receive(&self, buffer: &mut [u8]) -> io::Result<usize> {
self.0.receive(buffer) self.0.receive(buffer)
} }

View File

@ -70,6 +70,8 @@ pub(crate) trait LocalPacketSocket: AsRawFd + Sized {
fn bind<P: AsRef<Path>>(path: P) -> io::Result<Self>; fn bind<P: AsRef<Path>>(path: P) -> io::Result<Self>;
fn connect<P: AsRef<Path>>(path: P) -> io::Result<Self>; fn connect<P: AsRef<Path>>(path: P) -> io::Result<Self>;
fn set_nonblocking(&self, nb: bool) -> io::Result<()>;
fn receive(&self, data: &mut [u8]) -> io::Result<usize>; fn receive(&self, data: &mut [u8]) -> io::Result<usize>;
fn receive_from(&self, data: &mut [u8]) -> io::Result<(usize, Self::OwnedAddress)>; fn receive_from(&self, data: &mut [u8]) -> io::Result<(usize, Self::OwnedAddress)>;
fn receive_with_ancillary(&self, data: &mut [u8]) -> io::Result<(usize, Option<OwnedFd>)>; fn receive_with_ancillary(&self, data: &mut [u8]) -> io::Result<(usize, Option<OwnedFd>)>;

View File

@ -111,6 +111,11 @@ impl LocalPacketSocket for LocalPacketSocketImpl {
Ok(this) Ok(this)
} }
fn set_nonblocking(&self, nb: bool) -> io::Result<()> {
runtime::rt::io::set_nonblocking(self.as_raw_fd(), nb)?;
Ok(())
}
fn receive(&self, data: &mut [u8]) -> io::Result<usize> { fn receive(&self, data: &mut [u8]) -> io::Result<usize> {
let len = yggdrasil_rt::net::socket::receive(self.as_raw_fd(), data)?; let len = yggdrasil_rt::net::socket::receive(self.as_raw_fd(), data)?;
Ok(len) Ok(len)

View File

@ -25,6 +25,7 @@ pub struct Connection {
impl Connection { impl Connection {
pub fn new() -> Result<Self, Error> { pub fn new() -> Result<Self, Error> {
let channel = Channel::connect(crate::CHANNEL_NAME)?; let channel = Channel::connect(crate::CHANNEL_NAME)?;
channel.set_nonblocking(true)?;
let (sender, receiver) = channel.split(); let (sender, receiver) = channel.split();
let timeout = Duration::from_secs(1); let timeout = Duration::from_secs(1);
let mut poll = Poll::new()?; let mut poll = Poll::new()?;
@ -63,6 +64,21 @@ impl Connection {
} }
} }
pub fn poll_event(&mut self) -> Result<Option<Event>, Error> {
if let Some(event) = self.event_queue.pop_front() {
return Ok(Some(event));
}
match self.receiver.receive_with_file_from() {
Ok((data, file, _)) => {
let ServerMessage::Event(data) = data;
Ok(Some(Event { data, file }))
}
Err(error) if error.is_would_block() => Ok(None),
Err(error) => Err(error.into())
}
}
pub fn receive_event(&mut self) -> Result<Event, Error> { pub fn receive_event(&mut self) -> Result<Event, Error> {
if let Some(event) = self.event_queue.pop_front() { if let Some(event) = self.event_queue.pop_front() {
return Ok(event); return Ok(event);

View File

@ -52,7 +52,7 @@ impl<'a> Application<'a> {
fn run_inner(mut self) -> Result<ExitCode, Error> { fn run_inner(mut self) -> Result<ExitCode, Error> {
while self.is_running() { while self.is_running() {
self.poll_events()?; self.wait_events()?;
} }
Ok(ExitCode::SUCCESS) Ok(ExitCode::SUCCESS)
} }
@ -77,7 +77,7 @@ impl<'a> Application<'a> {
Ok(()) Ok(())
} }
pub fn poll_events(&mut self) -> Result<(), Error> { pub fn wait_events(&mut self) -> Result<(), Error> {
let event = { let event = {
let mut connection = self.connection.lock().unwrap(); let mut connection = self.connection.lock().unwrap();
connection.receive_event()? connection.receive_event()?
@ -86,6 +86,22 @@ impl<'a> Application<'a> {
self.handle_event(event) self.handle_event(event)
} }
pub fn poll_events(&mut self) -> Result<(), Error> {
loop {
let event = {
let mut connection = self.connection.lock().unwrap();
match connection.poll_event() {
Ok(Some(event)) => event,
Ok(None) => break,
Err(error) => return Err(error),
}
};
self.handle_event(event)?;
}
Ok(())
}
pub fn run(self) -> ExitCode { pub fn run(self) -> ExitCode {
match self.run_inner() { match self.run_inner() {
Ok(exit) => exit, Ok(exit) => exit,

View File

@ -4,7 +4,7 @@ use cross::mem::FileMapping;
use crate::{ use crate::{
error::Error, error::Error,
event::{EventData, KeyInput, WindowEvent}, event::{EventData, KeyEvent, KeyInput, WindowEvent},
message::{ClientMessage, CreateWindowInfo}, message::{ClientMessage, CreateWindowInfo},
}; };
@ -14,6 +14,8 @@ pub trait OnCloseRequested = Fn() -> EventOutcome;
pub trait OnKeyInput = Fn(KeyInput) -> EventOutcome; pub trait OnKeyInput = Fn(KeyInput) -> EventOutcome;
pub trait OnResized = Fn(u32, u32) -> EventOutcome; pub trait OnResized = Fn(u32, u32) -> EventOutcome;
pub trait OnFocusChanged = Fn(bool) -> EventOutcome; pub trait OnFocusChanged = Fn(bool) -> EventOutcome;
pub trait OnKeyPressed = Fn(KeyEvent) -> EventOutcome;
pub trait OnKeyReleased = Fn(KeyEvent) -> EventOutcome;
pub trait OnRedrawRequested = Fn(&mut [u32], u32, u32); pub trait OnRedrawRequested = Fn(&mut [u32], u32, u32);
@ -38,6 +40,8 @@ pub struct Window<'a> {
on_key_input: Box<dyn OnKeyInput>, on_key_input: Box<dyn OnKeyInput>,
on_resized: Box<dyn OnResized>, on_resized: Box<dyn OnResized>,
on_focus_changed: Box<dyn OnFocusChanged>, on_focus_changed: Box<dyn OnFocusChanged>,
on_key_pressed: Box<dyn OnKeyPressed>,
on_key_released: Box<dyn OnKeyReleased>,
} }
impl<'a> Window<'a> { impl<'a> Window<'a> {
@ -64,6 +68,8 @@ impl<'a> Window<'a> {
) )
}; };
log::info!("Created window: #{}", create_info.window_id);
Ok(Self { Ok(Self {
connection: application.connection.clone(), connection: application.connection.clone(),
window_id: create_info.window_id, window_id: create_info.window_id,
@ -82,6 +88,8 @@ impl<'a> Window<'a> {
dt.fill(0xFF888888); dt.fill(0xFF888888);
}), }),
on_key_input: Box::new(|_ev| EventOutcome::None), on_key_input: Box::new(|_ev| EventOutcome::None),
on_key_pressed: Box::new(|_| EventOutcome::None),
on_key_released: Box::new(|_| EventOutcome::None),
on_resized: Box::new(|_w, _h| EventOutcome::Redraw), on_resized: Box::new(|_w, _h| EventOutcome::Redraw),
on_focus_changed: Box::new(|_| EventOutcome::None), on_focus_changed: Box::new(|_| EventOutcome::None),
}) })
@ -99,6 +107,14 @@ impl<'a> Window<'a> {
self.on_key_input = Box::new(handler); self.on_key_input = Box::new(handler);
} }
pub fn set_on_key_pressed<H: OnKeyPressed + 'static>(&mut self, handler: H) {
self.on_key_pressed = Box::new(handler);
}
pub fn set_on_key_released<H: OnKeyReleased + 'static>(&mut self, handler: H) {
self.on_key_released = Box::new(handler);
}
pub fn set_on_resized<H: OnResized + 'static>(&mut self, handler: H) { pub fn set_on_resized<H: OnResized + 'static>(&mut self, handler: H) {
self.on_resized = Box::new(handler); self.on_resized = Box::new(handler);
} }
@ -147,6 +163,8 @@ impl<'a> Window<'a> {
(self.on_resized)(width, height) (self.on_resized)(width, height)
} }
WindowEvent::KeyPressed(key) => (self.on_key_pressed)(key),
WindowEvent::KeyReleased(key) => (self.on_key_released)(key),
WindowEvent::KeyInput(input) => (self.on_key_input)(input), WindowEvent::KeyInput(input) => (self.on_key_input)(input),
WindowEvent::FocusChanged(focused) => { WindowEvent::FocusChanged(focused) => {
self.focused = focused; self.focused = focused;

View File

@ -33,6 +33,15 @@ pub struct Receiver<T> {
_pd: PhantomData<T>, _pd: PhantomData<T>,
} }
impl Error {
pub fn is_would_block(&self) -> bool {
match self {
Self::Io(error) if error.kind() == io::ErrorKind::WouldBlock => true,
_ => false
}
}
}
#[repr(transparent)] #[repr(transparent)]
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct PeerAddress(OwnedLocalAddress); pub struct PeerAddress(OwnedLocalAddress);
@ -48,6 +57,11 @@ impl Channel {
Ok(Self(socket)) Ok(Self(socket))
} }
pub fn set_nonblocking(&self, nb: bool) -> Result<(), Error> {
self.0.set_nonblocking(nb)?;
Ok(())
}
pub fn split<T: Serialize, U: DeserializeOwned>(self) -> (Sender<T>, Receiver<U>) { pub fn split<T: Serialize, U: DeserializeOwned>(self) -> (Sender<T>, Receiver<U>) {
let this = Arc::new(self); let this = Arc::new(self);
let sender = Sender { let sender = Sender {

View File

@ -1,6 +1,8 @@
#ifndef _YGGDRASIL_SYS_WAIT_H #ifndef _YGGDRASIL_SYS_WAIT_H
#define _YGGDRASIL_SYS_WAIT_H 1 #define _YGGDRASIL_SYS_WAIT_H 1
// see headers/sys_wait/mod.rs
#define WEXITSTATUS(c) ((int) ((c) & 0xFF)) #define WEXITSTATUS(c) ((int) ((c) & 0xFF))
// TODO // TODO

View File

@ -1,6 +1,6 @@
use core::ffi::{c_int, c_void}; use core::ffi::c_void;
use crate::{error::CIntZeroResult, process}; use crate::{error::CIntZeroResult, process, thread::Thread};
#[no_mangle] #[no_mangle]
unsafe extern "C" fn __cxa_atexit( unsafe extern "C" fn __cxa_atexit(
@ -14,9 +14,10 @@ unsafe extern "C" fn __cxa_atexit(
#[no_mangle] #[no_mangle]
unsafe extern "C" fn __cxa_thread_atexit( unsafe extern "C" fn __cxa_thread_atexit(
_destructor: extern "C" fn(*mut c_void), destructor: extern "C" fn(*mut c_void),
_arg: *mut c_void, arg: *mut c_void,
_dso_handle: *mut c_void, dso_handle: *mut c_void,
) -> c_int { ) -> CIntZeroResult {
todo!() Thread::at_thread_exit(destructor, arg, dso_handle);
CIntZeroResult::SUCCESS
} }

View File

@ -43,6 +43,7 @@ pub trait CResult {
} }
#[must_use = "EResult must be converted into its output type with proper errno set"] #[must_use = "EResult must be converted into its output type with proper errno set"]
#[derive(Debug)]
pub enum EResult<T> { pub enum EResult<T> {
Ok(T), Ok(T),
Err(Errno), Err(Errno),

View File

@ -191,13 +191,16 @@ pub(crate) unsafe extern "C" fn faccessat(
) -> CIntZeroResult { ) -> CIntZeroResult {
let atfd = util::at_fd(atfd)?; let atfd = util::at_fd(atfd)?;
let path = path.ensure_str(); let path = path.ensure_str();
let access = match mode { let mut access = AccessMode::empty();
0 => AccessMode::empty(), if mode & R_OK != 0 {
R_OK => AccessMode::READ, access |= AccessMode::READ;
W_OK => AccessMode::WRITE, }
X_OK => AccessMode::EXEC, if mode & W_OK != 0 {
_ => todo!("{mode:#x}"), access |= AccessMode::WRITE;
}; }
if mode & X_OK != 0 {
access |= AccessMode::EXEC;
}
syscall::check_access(atfd, path, access).e_map_err(Errno::from)?; syscall::check_access(atfd, path, access).e_map_err(Errno::from)?;
CIntZeroResult::SUCCESS CIntZeroResult::SUCCESS

View File

@ -119,7 +119,7 @@ unsafe extern "C" fn pthread_mutex_consistent(_mutex: *mut pthread_mutex_t) -> c
#[no_mangle] #[no_mangle]
unsafe extern "C" fn pthread_mutex_destroy(_mutex: *mut pthread_mutex_t) -> c_int { unsafe extern "C" fn pthread_mutex_destroy(_mutex: *mut pthread_mutex_t) -> c_int {
log::error!("TODO: pthread_mutex_destroy()"); log::debug!("TODO: pthread_mutex_destroy()");
0 0
} }

View File

@ -1,14 +1,18 @@
use core::ffi::{c_char, c_int, c_short, c_void}; use core::ffi::{c_char, c_int, c_short, c_void};
use alloc::vec::Vec; use alloc::vec::Vec;
use yggdrasil_rt::{io::RawFd, process::{SpawnFlags, SpawnOption, SpawnOptions}, sys as syscall}; use yggdrasil_rt::{
io::RawFd,
process::{SpawnFlags, SpawnOption, SpawnOptions},
sys as syscall,
};
use super::{ use super::{
sched::__ygg_sched_param_t, sched::__ygg_sched_param_t,
sys_types::{mode_t, pid_t}, sys_types::{mode_t, pid_t},
}; };
use crate::{ use crate::{
error::{CIntCountResult, CIntZeroResult, ResultExt}, error::{CIntZeroResult, ResultExt},
headers::errno::Errno, headers::errno::Errno,
util::{NullTerminatedArrayIter, PointerStrExt}, util::{NullTerminatedArrayIter, PointerStrExt},
}; };
@ -49,9 +53,18 @@ unsafe extern "C" fn posix_spawn(
environment: &[], environment: &[],
directory: None, directory: None,
optional: &[ optional: &[
SpawnOption::CopyFile { source: RawFd::STDIN, child: RawFd::STDIN }, SpawnOption::CopyFile {
SpawnOption::CopyFile { source: RawFd::STDOUT, child: RawFd::STDOUT }, source: RawFd::STDIN,
SpawnOption::CopyFile { source: RawFd::STDERR, child: RawFd::STDERR }, child: RawFd::STDIN,
},
SpawnOption::CopyFile {
source: RawFd::STDOUT,
child: RawFd::STDOUT,
},
SpawnOption::CopyFile {
source: RawFd::STDERR,
child: RawFd::STDERR,
},
], ],
flags: SpawnFlags::empty(), flags: SpawnFlags::empty(),
}; };

View File

@ -56,6 +56,12 @@ impl StringWriter {
position: 0, position: 0,
} }
} }
fn finish(&mut self) {
if self.position < self.capacity {
unsafe { self.buffer.add(self.position).write(0) };
}
}
} }
impl fmt::Write for StringWriter { impl fmt::Write for StringWriter {
@ -272,5 +278,6 @@ unsafe extern "C" fn vsnprintf(
let mut writer = StringWriter::new(buffer, capacity); let mut writer = StringWriter::new(buffer, capacity);
let fmt = fmt.ensure_cstr(); let fmt = fmt.ensure_cstr();
let count = printf_inner(&mut writer, fmt.to_bytes(), args)?; let count = printf_inner(&mut writer, fmt.to_bytes(), args)?;
writer.finish();
CIntCountResult::success(count.try_into().unwrap()) CIntCountResult::success(count.try_into().unwrap())
} }

View File

@ -66,8 +66,10 @@ unsafe extern "C" fn setkey(_key: *const c_char) {
} }
#[no_mangle] #[no_mangle]
unsafe extern "C" fn system(_command: *const c_char) -> CIntZeroResult { unsafe extern "C" fn system(command: *const c_char) -> CIntZeroResult {
todo!() let command = command.ensure_str();
log::warn!("system({command:?})");
CIntZeroResult::ERROR
} }
#[no_mangle] #[no_mangle]

View File

@ -27,8 +27,9 @@ unsafe extern "C" fn stpncpy(dst: *mut c_char, src: *const c_char, n: usize) ->
if dst.is_null() || src.is_null() { if dst.is_null() || src.is_null() {
panic!(); panic!();
} }
memset(dst.cast(), 0, n); let dlen = strnlen(src.cast(), n);
mempcpy(dst.cast(), src.cast(), strnlen(src, n)).cast() let r = mempcpy(dst.cast(), src.cast(), n);
memset(r.cast(), 0, n - dlen).cast()
} }
#[no_mangle] #[no_mangle]
@ -164,8 +165,21 @@ unsafe extern "C" fn strncmp(mut a: *const c_char, mut b: *const c_char, mut n:
#[no_mangle] #[no_mangle]
unsafe extern "C" fn strncpy(dst: *mut c_char, src: *const c_char, n: usize) -> *mut c_char { unsafe extern "C" fn strncpy(dst: *mut c_char, src: *const c_char, n: usize) -> *mut c_char {
stpncpy(dst, src, n); if dst.is_null() || src.is_null() {
panic!();
}
let mut i = 0;
while i != n {
let c = *src.add(i);
*dst.add(i) = c;
if c == 0 {
break;
}
i += 1;
}
dst dst
// stpncpy(dst, src, n);
// dst
} }
#[no_mangle] #[no_mangle]

View File

@ -1,6 +1,6 @@
use core::{ use core::{
cmp::Ordering, cmp::Ordering,
ffi::{c_char, c_int}, ffi::{c_char, c_int, CStr},
}; };
use super::locale::locale_t; use super::locale::locale_t;
@ -26,6 +26,16 @@ unsafe extern "C" fn strcasecmp_l(
#[no_mangle] #[no_mangle]
unsafe extern "C" fn strncasecmp(s1: *const c_char, s2: *const c_char, n: usize) -> c_int { unsafe extern "C" fn strncasecmp(s1: *const c_char, s2: *const c_char, n: usize) -> c_int {
if s1.is_null() {
if s2.is_null() {
return 0;
} else {
return 1;
}
} else if s2.is_null() {
return -1;
}
for i in 0..n { for i in 0..n {
let c0 = (*s1.add(i) as u8).to_ascii_lowercase(); let c0 = (*s1.add(i) as u8).to_ascii_lowercase();
let c1 = (*s2.add(i) as u8).to_ascii_lowercase(); let c1 = (*s2.add(i) as u8).to_ascii_lowercase();

View File

@ -10,7 +10,7 @@ use yggdrasil_rt::{
}; };
use crate::{ use crate::{
error::{self, EResult, ResultExt, TryFromExt}, error::{self, CIntZeroResult, CResult, EResult, ResultExt, TryFromExt},
headers::errno::Errno, headers::errno::Errno,
}; };
@ -51,7 +51,7 @@ unsafe fn mmap_inner(
hint: *mut c_void, hint: *mut c_void,
len: usize, len: usize,
prot: c_int, prot: c_int,
flags: c_int, _flags: c_int,
fd: c_int, fd: c_int,
offset: off_t, offset: off_t,
) -> EResult<NonNull<c_void>> { ) -> EResult<NonNull<c_void>> {
@ -73,9 +73,9 @@ unsafe fn mmap_inner(
if prot & PROT_WRITE != 0 { if prot & PROT_WRITE != 0 {
mapping_flags |= MappingFlags::WRITE; mapping_flags |= MappingFlags::WRITE;
} }
if flags != MAP_PRIVATE { // if flags != MAP_PRIVATE {
todo!("Non-private mappings via mmap(2) are not yet supported"); // todo!("Non-private mappings via mmap(2) are not yet supported");
} // }
let address = syscall::map_memory(hint, len, mapping_flags, &source).e_map_err(Errno::from)?; let address = syscall::map_memory(hint, len, mapping_flags, &source).e_map_err(Errno::from)?;
assert_ne!(address, 0); assert_ne!(address, 0);
@ -143,8 +143,14 @@ unsafe extern "C" fn mmap(
} }
#[no_mangle] #[no_mangle]
unsafe extern "C" fn munmap(_ptr: *mut c_void, _len: usize) -> c_int { unsafe extern "C" fn munmap(ptr: *mut c_void, len: usize) -> CIntZeroResult {
todo!() let address = ptr.addr();
if address == 0 || address == usize::MAX || len == 0 {
error::errno = Errno::EINVAL;
return CIntZeroResult::ERROR;
}
syscall::unmap_memory(address, len).e_map_err(Errno::from)?;
CIntZeroResult::SUCCESS
} }
// posix_*** // posix_***

View File

@ -10,4 +10,4 @@ usize_type = "size_t"
isize_type = "ssize_t" isize_type = "ssize_t"
[export] [export]
include = ["rlimit", "rusage"] include = ["rlimit", "rusage", "__ygg_rusage_t"]

View File

@ -4,6 +4,8 @@ use super::{sys_time::__ygg_timeval_t, sys_types::id_t};
pub type rlim_t = u64; pub type rlim_t = u64;
pub type __ygg_rusage_t = rusage;
pub const PRIO_PROCESS: c_int = 0; pub const PRIO_PROCESS: c_int = 0;
pub const PRIO_PGRP: c_int = 1; pub const PRIO_PGRP: c_int = 1;
pub const PRIO_USER: c_int = 2; pub const PRIO_USER: c_int = 2;

View File

@ -73,8 +73,9 @@ impl From<FileAttr> for stat {
let st_uid = u32::from(value.uid).try_into().unwrap(); let st_uid = u32::from(value.uid).try_into().unwrap();
let st_gid = u32::from(value.gid).try_into().unwrap(); let st_gid = u32::from(value.gid).try_into().unwrap();
// TODO // TODO
let st_blksize = 512; let st_blksize = value.block_size as _;
let st_blocks = st_size.div_ceil(st_blksize as _).try_into().unwrap(); let st_blocks = st_size.div_ceil(st_blksize as _).try_into().unwrap();
let st_ino = value.inode.unwrap_or(0) as u64;
Self { Self {
st_mode, st_mode,
@ -83,6 +84,7 @@ impl From<FileAttr> for stat {
st_gid, st_gid,
st_blksize, st_blksize,
st_blocks, st_blocks,
st_ino,
..Default::default() ..Default::default()
} }
} }
@ -125,14 +127,13 @@ unsafe extern "C" fn mkdir(pathname: *const c_char, mode: mode_t) -> CIntZeroRes
#[no_mangle] #[no_mangle]
unsafe extern "C" fn mkdirat(atfd: c_int, pathname: *const c_char, mode: mode_t) -> CIntZeroResult { unsafe extern "C" fn mkdirat(atfd: c_int, pathname: *const c_char, mode: mode_t) -> CIntZeroResult {
let _pathname = pathname.ensure_str(); let pathname = pathname.ensure_str();
let _atfd = util::at_fd(atfd)?; let atfd = util::at_fd(atfd)?;
let _mode = FileMode::new((mode & 0o777) as u32); let mode = FileMode::new((mode & 0o777) as u32);
todo!() io::create_directory(atfd, pathname, mode)?;
// io::create_directory(atfd, pathname, mode)?;
// CIntZeroResult::OK CIntZeroResult::SUCCESS
} }
#[no_mangle] #[no_mangle]

View File

@ -7,6 +7,7 @@ sys_includes = [
"stdint.h", "stdint.h",
"signal.h", "signal.h",
"sys/types.h", "sys/types.h",
"sys/resource.h",
"bits/sys/wait.h" "bits/sys/wait.h"
] ]
no_includes = true no_includes = true

View File

@ -1,6 +1,18 @@
use core::ffi::{c_int, c_void}; use core::ffi::{c_int, c_void};
use super::sys_types::{id_t, pid_t}; use yggdrasil_rt::{
process::{ExitCode, ProcessGroupId, ProcessId, ProcessWait, WaitFlags},
sys as syscall,
};
use crate::error::{self, EResult, ResultExt};
use super::{
errno::Errno,
sys_resource::__ygg_rusage_t,
sys_time::timeval,
sys_types::{id_t, pid_t},
};
pub const WCONTINUED: c_int = 1 << 0; pub const WCONTINUED: c_int = 1 << 0;
pub const WNOHANG: c_int = 1 << 1; pub const WNOHANG: c_int = 1 << 1;
@ -16,6 +28,45 @@ pub const P_ALL: idtype_t = 0;
pub const P_PGID: idtype_t = 1; pub const P_PGID: idtype_t = 1;
pub const P_PID: idtype_t = 2; pub const P_PID: idtype_t = 2;
pub struct WaitResult {
pid: ProcessId,
status: ExitCode,
}
fn wait_inner(what: ProcessWait, nonblocking: bool) -> EResult<WaitResult> {
let mut status = ExitCode::Exited(0);
let mut flags = WaitFlags::empty();
if nonblocking {
flags |= WaitFlags::NON_BLOCKING;
}
let pid = unsafe { syscall::wait_process(&what, &mut status, flags) }.e_map_err(Errno::from)?;
EResult::Ok(WaitResult { pid, status })
}
fn convert_wait_pid(pid: pid_t) -> ProcessWait {
// TODO "any child whose process group ID is equal to that of the calling process"
if pid > 0 {
ProcessWait::Process(unsafe { ProcessId::from_raw(pid as _) })
} else if pid == -1 || pid == 0 {
ProcessWait::AnyChild
} else {
let pgrp = (-pid) as u32;
ProcessWait::Group(unsafe { ProcessGroupId::from_raw(pgrp) })
}
}
fn encode_exit_status(code: ExitCode) -> c_int {
match code {
ExitCode::Exited(status) => status & 0xFF,
ExitCode::BySignal(Ok(sig)) => {
let signum = sig as u32;
(signum + 0x100) as c_int
}
ExitCode::BySignal(Err(signum)) => (signum + 0x100) as c_int,
}
}
#[no_mangle] #[no_mangle]
unsafe extern "C" fn wait(_status: *mut c_int) -> pid_t { unsafe extern "C" fn wait(_status: *mut c_int) -> pid_t {
todo!() todo!()
@ -36,3 +87,29 @@ unsafe extern "C" fn waitid(
unsafe extern "C" fn waitpid(_pid: pid_t, _status: *mut c_int, _options: c_int) -> pid_t { unsafe extern "C" fn waitpid(_pid: pid_t, _status: *mut c_int, _options: c_int) -> pid_t {
todo!() todo!()
} }
#[no_mangle]
unsafe extern "C" fn wait4(
pid: pid_t,
wstatus: *mut c_int,
options: c_int,
rusage: *mut __ygg_rusage_t,
) -> pid_t {
let pid = convert_wait_pid(pid);
let result = match wait_inner(pid, options & WNOHANG != 0) {
EResult::Ok(result) => result,
EResult::Err(err) => {
error::errno = err;
return -1;
}
};
if let Some(wstatus) = wstatus.as_mut() {
*wstatus = encode_exit_status(result.status);
}
if let Some(rusage) = rusage.as_mut() {
// TODO not implemented on the kernel level
rusage.ru_utime = timeval::zero();
rusage.ru_stime = timeval::zero();
}
result.pid.bits() as pid_t
}

View File

@ -1,7 +1,7 @@
use core::{ffi::c_int, mem::MaybeUninit}; use core::{ffi::c_int, mem::MaybeUninit};
use yggdrasil_rt::{ use yggdrasil_rt::{
io::{FileAttr, RawFd, SeekFrom}, path::{Path, PathBuf}, sys as syscall io::{FileAttr, FileMode, RawFd, SeekFrom}, path::{Path, PathBuf}, sys as syscall
}; };
use crate::{ use crate::{
@ -127,6 +127,11 @@ pub fn get_metadata(at: Option<RawFd>, path: &str, follow: bool) -> EResult<File
EResult::Ok(unsafe { metadata.assume_init() }) EResult::Ok(unsafe { metadata.assume_init() })
} }
pub fn create_directory(at: Option<RawFd>, path: &str, mode: FileMode) -> EResult<()> {
unsafe { syscall::create_directory(at, path, mode) }?;
EResult::Ok(())
}
pub fn realpath<P: AsRef<Path>>(path: P) -> EResult<PathBuf> { pub fn realpath<P: AsRef<Path>>(path: P) -> EResult<PathBuf> {
// Cases: // Cases:
// * /a/b/c -> /a/b/c // * /a/b/c -> /a/b/c

View File

@ -34,6 +34,7 @@ use core::{
use alloc::vec::Vec; use alloc::vec::Vec;
use env::environ; use env::environ;
use thread::Thread;
extern crate alloc; extern crate alloc;
@ -71,6 +72,13 @@ unsafe extern "C" fn __ygglibc_entry(
signal::init(true); signal::init(true);
init::init(); init::init();
let sp = unsafe {
let sp: usize;
core::arch::asm!("mov %rsp, {0}", out(reg) sp, options(att_syntax));
sp
};
log::info!("sp = {sp:#x}");
// Setup args // Setup args
let args = env::handle_kernel_argument(arg); let args = env::handle_kernel_argument(arg);
let mut c_args = Vec::new(); let mut c_args = Vec::new();
@ -86,5 +94,8 @@ unsafe extern "C" fn __ygglibc_entry(
environ.cast(), environ.cast(),
); );
// Call main thread dtors
Thread::call_thread_dtors();
process::c_exit(status) process::c_exit(status)
} }

View File

@ -1,6 +1,6 @@
use core::{ffi::c_void, ptr::null_mut}; use core::{cell::RefCell, ffi::c_void, ptr::null_mut};
use alloc::{boxed::Box, collections::BTreeMap}; use alloc::{boxed::Box, collections::BTreeMap, vec::Vec};
use yggdrasil_rt::{ use yggdrasil_rt::{
process::{ process::{
thread::{self as rt, ThreadCreateInfo}, thread::{self as rt, ThreadCreateInfo},
@ -12,13 +12,21 @@ use yggdrasil_rt::{
use crate::{ use crate::{
error::{EResult, OptionExt}, error::{EResult, OptionExt},
headers::{ headers::{
errno::Errno, sys_types::{pthread_attr_t, pthread_t} errno::Errno,
sys_types::{pthread_attr_t, pthread_t},
}, },
}; };
pub mod tls; pub mod tls;
pub struct ThreadDestructor {
pub destructor: extern "C" fn(*mut c_void),
pub argument: *mut c_void,
}
static THREADS: Mutex<BTreeMap<pthread_t, Thread>> = Mutex::new(BTreeMap::new()); static THREADS: Mutex<BTreeMap<pthread_t, Thread>> = Mutex::new(BTreeMap::new());
#[thread_local]
static THREAD_LOCAL_DTORS: RefCell<Vec<ThreadDestructor>> = RefCell::new(Vec::new());
pub const DEFAULT_STACK_SIZE: usize = 4096 * 16; pub const DEFAULT_STACK_SIZE: usize = 4096 * 16;
pub const DEFAULT_SIGNAL_STACK_SIZE: usize = 4096 * 8; pub const DEFAULT_SIGNAL_STACK_SIZE: usize = 4096 * 8;
@ -49,7 +57,7 @@ impl Thread {
signal_stack: rt::ThreadSignalStack::Allocate(DEFAULT_SIGNAL_STACK_SIZE), signal_stack: rt::ThreadSignalStack::Allocate(DEFAULT_SIGNAL_STACK_SIZE),
stack, stack,
#[allow(clippy::redundant_closure)] #[allow(clippy::redundant_closure)]
entry: rt::ThreadFunction::Closure(Box::new(move |arg| entry(arg))), entry: rt::ThreadFunction::Closure(Box::new(move |arg| Self::thread_main(entry, arg))),
tls_image: tls::TLS_IMAGE.get().as_ref(), tls_image: tls::TLS_IMAGE.get().as_ref(),
}; };
let handle = rt::Thread::spawn(info, argument, true)?; let handle = rt::Thread::spawn(info, argument, true)?;
@ -68,6 +76,32 @@ impl Thread {
pub fn this() -> EResult<pthread_t> { pub fn this() -> EResult<pthread_t> {
EResult::Ok(unsafe { rt::Thread::<*mut c_void>::current().id() }) EResult::Ok(unsafe { rt::Thread::<*mut c_void>::current().id() })
} }
fn thread_main(
entry: extern "C" fn(*mut c_void) -> *mut c_void,
arg: *mut c_void,
) -> *mut c_void {
let ret = entry(arg);
unsafe { Self::call_thread_dtors() };
ret
}
pub fn at_thread_exit(
destructor: extern "C" fn(*mut c_void),
argument: *mut c_void,
_dso_handle: *mut c_void,
) {
THREAD_LOCAL_DTORS.borrow_mut().push(ThreadDestructor {
destructor,
argument,
});
}
pub unsafe fn call_thread_dtors() {
for dtor in THREAD_LOCAL_DTORS.borrow().iter() {
(dtor.destructor)(dtor.argument);
}
}
} }
pub fn init_main_thread(arg: &ProgramArgumentInner) { pub fn init_main_thread(arg: &ProgramArgumentInner) {

View File

@ -141,7 +141,7 @@ fn lex_identifier(i: &str) -> IResult<&str, &str> {
recognize(many1_count(alt((alphanumeric1, is_a("-_")))))(i) recognize(many1_count(alt((alphanumeric1, is_a("-_")))))(i)
} }
fn lex_filename(i: &str) -> IResult<&str, &str> { fn lex_filename(i: &str) -> IResult<&str, &str> {
recognize(many1_count(alt((alphanumeric1, is_a("./-_:")))))(i) recognize(many1_count(alt((alphanumeric1, is_a("./-_:+")))))(i)
} }
fn lex_braced_var(i: &str) -> IResult<&str, &str> { fn lex_braced_var(i: &str) -> IResult<&str, &str> {

View File

@ -1,12 +1,14 @@
use std::{io::{stdout, Write}, process::Command}; #![feature(seek_stream_len)]
use std::{fs::File, io::{stdout, Seek, Write}};
use cross::mem::FileMapping;
fn main() { fn main() {
let output = Command::new("/bin/ls").output().unwrap(); let mut file = File::open("/etc/test.txt").unwrap();
println!("status = {:?}", output.status); let size = file.stream_len().unwrap();
println!("stdout:"); let mapping = FileMapping::map(file, size as usize).unwrap();
stdout().write_all(&output.stdout).ok(); let mut data = vec![0; size as usize];
println!(); data.copy_from_slice(&mapping[..]);
println!("stderr:"); stdout().write_all(&data).unwrap();
stdout().write_all(&output.stderr).ok();
println!();
} }

View File

@ -362,6 +362,7 @@ impl Terminal<'_> {
static ABORT: AtomicBool = AtomicBool::new(false); static ABORT: AtomicBool = AtomicBool::new(false);
fn main() -> ExitCode { fn main() -> ExitCode {
logsink::setup_logging(false);
let font = PcScreenFont::default(); let font = PcScreenFont::default();
let term = Terminal::new(font).unwrap(); let term = Terminal::new(font).unwrap();

View File

@ -1,3 +1,4 @@
#![allow(unused)]
use std::{ use std::{
fs, fs,
path::{Path, PathBuf}, path::{Path, PathBuf},
@ -126,19 +127,25 @@ fn build_test_c_program(
fn install_ygglibc(env: &BuildEnv, ygglibc: &Ygglibc) -> Result<(), Error> { fn install_ygglibc(env: &BuildEnv, ygglibc: &Ygglibc) -> Result<(), Error> {
log::info!("Installing ygglibc into LLVM sysroot"); log::info!("Installing ygglibc into LLVM sysroot");
let dst_lib_dir = env.llvm_sysroot.join("lib"); // let dst_lib_dir = env.llvm_sysroot.join("lib");
let dst_include_dir = env.llvm_sysroot.join("usr/include"); // let dst_include_dir = env.llvm_sysroot.join("usr/include");
let _ = env;
let _ = ygglibc.crt0_file;
fs::create_dir_all(&dst_lib_dir)?; // fs::create_dir_all(&dst_lib_dir)?;
fs::create_dir_all(&dst_include_dir)?; // fs::create_dir_all(&dst_include_dir)?;
fs::copy(&ygglibc.static_lib_file, dst_lib_dir.join("libygglibc.a"))?; // fs::copy(&ygglibc.static_lib_file, dst_lib_dir.join("libygglibc.a"))?;
fs::copy(&ygglibc.shared_lib_file, dst_lib_dir.join("libygglibc.so"))?; // fs::copy(&ygglibc.shared_lib_file, dst_lib_dir.join("libygglibc.so"))?;
fs::copy(&ygglibc.crt0_file, dst_lib_dir.join("crt0.o"))?; // fs::copy(&ygglibc.crt0_file, dst_lib_dir.join("crt0.o"))?;
for path in ygglibc.include_paths.iter() { let _ = ygglibc.static_lib_file;
util::copy_dir_recursive(path, &dst_include_dir)?; let _ = ygglibc.shared_lib_file;
} let _ = ygglibc.include_paths;
// for path in ygglibc.include_paths.iter() {
// util::copy_dir_recursive(path, &dst_include_dir)?;
// }
Ok(()) Ok(())
} }
@ -212,7 +219,8 @@ fn install_openlibm(env: &BuildEnv, libm: &Openlibm) -> Result<(), Error> {
fs::copy(&libm.static_lib_file, env.llvm_sysroot.join("lib/libm.a"))?; fs::copy(&libm.static_lib_file, env.llvm_sysroot.join("lib/libm.a"))?;
fs::copy(&libm.shared_lib_file, env.llvm_sysroot.join("lib/libm.so"))?; fs::copy(&libm.shared_lib_file, env.llvm_sysroot.join("lib/libm.so"))?;
util::copy_dir_recursive(&libm.include_path, env.llvm_sysroot.join("usr/include"))?; let _ = libm.include_path;
// util::copy_dir_recursive(&libm.include_path, env.llvm_sysroot.join("usr/include"))?;
Ok(()) Ok(())
} }
@ -241,6 +249,7 @@ pub fn build_c(env: &BuildEnv, install: &mut Vec<(PathBuf, PathBuf)>) -> Result<
"lib/libc++.so".into(), "lib/libc++.so".into(),
)); ));
} }
install.push((ygglibc.crt0_file, "lib/crt0.o".into()));
install.push((ygglibc.shared_lib_file, "lib/libygglibc.so".into())); install.push((ygglibc.shared_lib_file, "lib/libygglibc.so".into()));
install.push((libm.shared_lib_file, "lib/libopenlibm.so.4".into())); install.push((libm.shared_lib_file, "lib/libopenlibm.so.4".into()));