1use crate::{
4 error::{Errno, ResultExt},
5 io::{self, Read, Write},
6 raw_cell::RawCell,
7};
8use alloc::{boxed::Box, vec::Vec};
9use core::{cell::Cell, fmt, ptr};
10
11pub use self::allocator::*;
12
13mod allocator;
14
15pub mod logger;
16
17pub use self::pal::{Pal, PalEpoll, PalPtrace, PalSignal, PalSocket};
18
19mod pal;
20
21pub use self::sys::Sys;
22
23#[cfg(target_os = "linux")]
24#[path = "linux/mod.rs"]
25pub(crate) mod sys;
26
27#[cfg(target_os = "redox")]
28#[path = "redox/mod.rs"]
29pub(crate) mod sys;
30
31pub use self::rlb::{Line, RawLineBuffer};
32pub mod rlb;
33
34#[cfg(target_os = "linux")]
35pub mod auxv_defs;
36
37#[cfg(target_os = "redox")]
38pub use redox_rt::auxv_defs;
39
40use self::types::*;
41pub mod types;
42
43#[thread_local]
45pub static ERRNO: Cell<c_int> = Cell::new(0);
46
47#[allow(non_upper_case_globals)]
49pub static mut argv: *mut *mut c_char = ptr::null_mut();
50#[allow(non_upper_case_globals)]
51pub static inner_argv: RawCell<Vec<*mut c_char>> = RawCell::new(Vec::new());
52#[allow(non_upper_case_globals)]
53pub static mut program_invocation_name: *mut c_char = ptr::null_mut();
54#[allow(non_upper_case_globals)]
55pub static mut program_invocation_short_name: *mut c_char = ptr::null_mut();
56
57#[allow(non_upper_case_globals)]
58#[unsafe(no_mangle)]
59pub static mut environ: *mut *mut c_char = ptr::null_mut();
60
61pub static OUR_ENVIRON: RawCell<Vec<*mut c_char>> = RawCell::new(Vec::new());
62
63pub fn environ_iter() -> impl Iterator<Item = *mut c_char> + 'static {
64 unsafe {
65 let mut ptrs = environ;
66
67 core::iter::from_fn(move || {
68 if ptrs.is_null() {
69 None
70 } else {
71 let ptr = ptrs.read();
72 if ptr.is_null() {
73 None
74 } else {
75 ptrs = ptrs.add(1);
76 Some(ptr)
77 }
78 }
79 })
80 }
81}
82
83pub trait WriteByte: fmt::Write {
84 fn write_u8(&mut self, byte: u8) -> fmt::Result;
85}
86
87impl<W: WriteByte> WriteByte for &mut W {
88 fn write_u8(&mut self, byte: u8) -> fmt::Result {
89 (**self).write_u8(byte)
90 }
91}
92
93pub struct FileWriter(pub c_int, Option<Errno>);
95
96impl FileWriter {
97 pub fn new(fd: c_int) -> Self {
98 Self(fd, None)
99 }
100
101 pub fn write(&mut self, buf: &[u8]) -> fmt::Result {
102 let _ = Sys::write(self.0, buf).map_err(|err| {
103 self.1 = Some(err);
104 fmt::Error
105 })?;
106 Ok(())
107 }
108}
109
110impl fmt::Write for FileWriter {
111 fn write_str(&mut self, s: &str) -> fmt::Result {
112 if let Ok(()) = self.write(s.as_bytes()) {}; Ok(())
114 }
115}
116
117impl WriteByte for FileWriter {
118 fn write_u8(&mut self, byte: u8) -> fmt::Result {
119 if let Ok(()) = self.write(&[byte]) {}; Ok(())
121 }
122}
123
124pub struct FileReader(pub c_int);
126
127impl FileReader {
128 pub fn read(&mut self, buf: &mut [u8]) -> isize {
130 Sys::read(self.0, buf)
131 .map(|u| u as isize)
132 .or_minus_one_errno()
133 }
134}
135
136impl Read for FileReader {
137 fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
138 let i = Sys::read(self.0, buf)
139 .map(|u| u as isize)
140 .or_minus_one_errno(); if i >= 0 {
142 Ok(i as usize)
143 } else {
144 Err(io::Error::from_raw_os_error(-i as i32))
145 }
146 }
147}
148
149pub struct StringWriter(pub *mut c_char, pub usize);
151impl Write for StringWriter {
152 fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
153 if self.1 > 1 {
154 let copy_size = buf.len().min(self.1 - 1);
155 unsafe {
156 ptr::copy_nonoverlapping(buf.as_ptr().cast(), self.0, copy_size);
157 self.1 -= copy_size;
158
159 self.0 = self.0.add(copy_size);
160 *self.0 = 0;
161 }
162 }
163
164 Ok(buf.len())
170 }
171 fn flush(&mut self) -> io::Result<()> {
172 Ok(())
173 }
174}
175impl fmt::Write for StringWriter {
176 fn write_str(&mut self, s: &str) -> fmt::Result {
177 self.write(s.as_bytes()).unwrap();
179 Ok(())
180 }
181}
182impl WriteByte for StringWriter {
183 fn write_u8(&mut self, byte: u8) -> fmt::Result {
184 self.write(&[byte]).unwrap();
186 Ok(())
187 }
188}
189
190pub struct UnsafeStringWriter(pub *mut u8);
193impl Write for UnsafeStringWriter {
194 fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
195 unsafe {
196 ptr::copy_nonoverlapping(buf.as_ptr(), self.0, buf.len());
197 self.0 = self.0.add(buf.len());
198 *self.0 = b'\0';
199 }
200 Ok(buf.len())
201 }
202 fn flush(&mut self) -> io::Result<()> {
203 Ok(())
204 }
205}
206impl fmt::Write for UnsafeStringWriter {
207 fn write_str(&mut self, s: &str) -> fmt::Result {
208 self.write(s.as_bytes()).unwrap();
210 Ok(())
211 }
212}
213impl WriteByte for UnsafeStringWriter {
214 fn write_u8(&mut self, byte: u8) -> fmt::Result {
215 self.write(&[byte]).unwrap();
217 Ok(())
218 }
219}
220
221pub struct UnsafeStringReader(pub *const u8);
224impl Read for UnsafeStringReader {
225 fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
226 unsafe {
227 for (i, inner) in buf.iter_mut().enumerate() {
228 if *self.0 == 0 {
229 return Ok(i);
230 }
231
232 *inner = *self.0;
233 self.0 = self.0.offset(1);
234 }
235 Ok(buf.len())
236 }
237 }
238}
239
240pub struct CountingWriter<T> {
243 pub inner: T,
244 pub written: usize,
245}
246impl<T> CountingWriter<T> {
247 pub fn new(writer: T) -> Self {
248 Self {
249 inner: writer,
250 written: 0,
251 }
252 }
253}
254impl<T: fmt::Write> fmt::Write for CountingWriter<T> {
255 fn write_str(&mut self, s: &str) -> fmt::Result {
256 self.written += s.len();
257 self.inner.write_str(s)
258 }
259}
260impl<T: WriteByte> WriteByte for CountingWriter<T> {
261 fn write_u8(&mut self, byte: u8) -> fmt::Result {
262 self.written += 1;
263 self.inner.write_u8(byte)
264 }
265}
266impl<T: Write> Write for CountingWriter<T> {
267 fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
268 let res = self.inner.write(buf);
269 if let Ok(written) = res {
270 self.written += written;
271 }
272 res
273 }
274 fn write_all(&mut self, buf: &[u8]) -> io::Result<()> {
275 match self.inner.write_all(buf) {
276 Ok(()) => (),
277 Err(ref err) if err.kind() == io::ErrorKind::WriteZero => (),
278 Err(err) => return Err(err),
279 }
280 self.written += buf.len();
281 Ok(())
282 }
283 fn flush(&mut self) -> io::Result<()> {
284 self.inner.flush()
285 }
286}
287
288#[cold]
292pub unsafe fn auxv_iter<'a>(ptr: *const usize) -> impl Iterator<Item = [usize; 2]> + 'a {
293 struct St(*const usize);
294 impl Iterator for St {
295 type Item = [usize; 2];
296
297 fn next(&mut self) -> Option<Self::Item> {
298 unsafe {
299 if *self.0 == self::auxv_defs::AT_NULL {
300 return None;
301 }
302 let kind = *self.0;
303 let value = *self.0.add(1);
304 self.0 = self.0.add(2);
305
306 Some([kind, value])
307 }
308 }
309 }
310 St(ptr)
311}
312
313#[cold]
314pub unsafe fn get_auxvs(ptr: *const usize) -> Box<[[usize; 2]]> {
315 let mut auxvs = unsafe { auxv_iter(ptr) }.collect::<Vec<_>>();
317
318 auxvs.sort_unstable_by_key(|[kind, _]| *kind);
319 auxvs.into_boxed_slice()
320}
321#[cold]
323pub unsafe fn get_auxv_raw(ptr: *const usize, requested_kind: usize) -> Option<usize> {
324 unsafe { auxv_iter(ptr) }
325 .find_map(|[kind, value]| Some(value).filter(|_| kind == requested_kind))
326}
327pub fn get_auxv(auxvs: &[[usize; 2]], key: usize) -> Option<usize> {
328 auxvs
329 .binary_search_by_key(&key, |[entry_key, _]| *entry_key)
330 .ok()
331 .map(|idx| auxvs[idx][1])
332}
333
334#[cold]
335#[cfg(target_os = "redox")]
336pub unsafe fn init(auxvs: Box<[[usize; 2]]>) {
338 use self::auxv_defs::*;
339 use redox_rt::proc::FdGuard;
340
341 let Some(proc_fd) = get_auxv(&auxvs, AT_REDOX_PROC_FD) else {
342 panic!("Missing proc and thread fd!");
343 };
344 let Some(ns_fd) = get_auxv(&auxvs, AT_REDOX_NS_FD) else {
345 panic!("Missing namespace fd!");
346 };
347 unsafe {
348 redox_rt::initialize(
349 FdGuard::new(proc_fd).to_upper().unwrap(),
350 if ns_fd == usize::MAX {
351 None
352 } else {
353 Some(FdGuard::new(ns_fd).to_upper().unwrap())
354 },
355 );
356 init_inner(auxvs)
357 }
358}
359#[cold]
360#[cfg(target_os = "redox")]
361pub unsafe fn init_inner(auxvs: Box<[[usize; 2]]>) {
362 use self::auxv_defs::*;
363 use crate::header::sys_stat::S_ISVTX;
364 use redox_rt::proc::FdGuard;
365 use syscall::MODE_PERM;
366
367 redox_rt::sys::this_proc_call(
369 &mut [],
370 syscall::CallFlags::empty(),
371 &[redox_protocols::protocol::ProcCall::SyncSigPctl as u64],
372 )
373 .expect("failed to sync signal pctl");
374
375 if let (Some(cwd_ptr), Some(cwd_len), Some(cwd_fd)) = (
376 get_auxv(&auxvs, AT_REDOX_INITIAL_CWD_PTR),
377 get_auxv(&auxvs, AT_REDOX_INITIAL_CWD_LEN),
378 get_auxv(&auxvs, AT_REDOX_CWD_FD),
379 ) {
380 let cwd_bytes: &'static [u8] =
381 unsafe { core::slice::from_raw_parts(cwd_ptr as *const u8, cwd_len) };
382 if let (Ok(Ok(cwd_path)), Some(cwd_fd)) = (
383 core::str::from_utf8(cwd_bytes).map(self::sys::path::CwdPath::from),
384 (cwd_fd != usize::MAX).then(|| {
385 FdGuard::new(cwd_fd)
386 .to_upper()
387 .expect("failed to move cwd fd to upper table")
388 }),
389 ) {
390 self::sys::path::set_cwd_manual(cwd_path, cwd_fd);
391 }
392 }
393
394 let mut inherited_sigignmask = 0_u64;
395 if let Some(mask) = get_auxv(&auxvs, AT_REDOX_INHERITED_SIGIGNMASK) {
396 inherited_sigignmask |= mask as u64;
397 }
398 #[cfg(target_pointer_width = "32")]
399 if let Some(mask) = get_auxv(&auxvs, AT_REDOX_INHERITED_SIGIGNMASK_HI) {
400 inherited_sigignmask |= (mask as u64) << 32;
401 }
402 redox_rt::signal::apply_inherited_sigignmask(inherited_sigignmask);
403
404 let mut inherited_sigprocmask = 0_u64;
405
406 if let Some(mask) = get_auxv(&auxvs, AT_REDOX_INHERITED_SIGPROCMASK) {
407 inherited_sigprocmask |= mask as u64;
408 }
409 #[cfg(target_pointer_width = "32")]
410 if let Some(mask) = get_auxv(&auxvs, AT_REDOX_INHERITED_SIGPROCMASK_HI) {
411 inherited_sigprocmask |= (mask as u64) << 32;
412 }
413 redox_rt::signal::set_sigmask(Some(inherited_sigprocmask), None).unwrap();
414
415 if let Some(umask) = get_auxv(&auxvs, AT_REDOX_UMASK) {
416 let _ =
417 redox_rt::sys::swap_umask((umask as u32) & u32::from(MODE_PERM) & !(S_ISVTX as u32));
418 }
419}
420#[expect(clippy::boxed_local)]
421#[cfg(not(target_os = "redox"))]
422pub unsafe fn init(auxvs: Box<[[usize; 2]]>) {}