xref: /relibc/src/platform/mod.rs (revision 6fd98d550c9d0636b12b0cece86bf1442dac7378)
1 use crate::io::{self, Read, Write};
2 use alloc::{boxed::Box, vec::Vec};
3 use core::{fmt, ptr};
4 
5 pub use self::allocator::*;
6 
7 #[cfg(not(feature = "ralloc"))]
8 #[path = "allocator/dlmalloc.rs"]
9 mod allocator;
10 
11 #[cfg(feature = "ralloc")]
12 #[path = "allocator/ralloc.rs"]
13 mod allocator;
14 
15 pub use self::pal::{Pal, PalEpoll, PalPtrace, PalSignal, PalSocket};
16 
17 mod pal;
18 
19 pub use self::sys::{e, Sys};
20 
21 #[cfg(all(not(feature = "no_std"), target_os = "linux"))]
22 #[path = "linux/mod.rs"]
23 pub(crate) mod sys;
24 
25 #[cfg(all(not(feature = "no_std"), target_os = "dragonos"))]
26 #[path = "dragonos/mod.rs"]
27 pub(crate) mod sys;
28 
29 #[cfg(all(not(feature = "no_std"), target_os = "redox"))]
30 #[path = "redox/mod.rs"]
31 pub(crate) mod sys;
32 
33 #[cfg(test)]
34 mod test;
35 
36 mod pte;
37 
38 pub use self::rlb::{Line, RawLineBuffer};
39 pub mod rlb;
40 
41 #[cfg(target_os = "linux")]
42 pub mod auxv_defs;
43 
44 #[cfg(target_os = "dragonos")]
45 pub mod auxv_defs;
46 
47 #[cfg(target_os = "redox")]
48 pub use redox_exec::auxv_defs;
49 
50 use self::types::*;
51 pub mod types;
52 
53 #[thread_local]
54 #[allow(non_upper_case_globals)]
55 #[no_mangle]
56 pub static mut errno: c_int = 0;
57 
58 #[allow(non_upper_case_globals)]
59 pub static mut argv: *mut *mut c_char = ptr::null_mut();
60 #[allow(non_upper_case_globals)]
61 pub static mut inner_argv: Vec<*mut c_char> = Vec::new();
62 #[allow(non_upper_case_globals)]
63 pub static mut program_invocation_name: *mut c_char = ptr::null_mut();
64 #[allow(non_upper_case_globals)]
65 pub static mut program_invocation_short_name: *mut c_char = ptr::null_mut();
66 
67 #[allow(non_upper_case_globals)]
68 #[no_mangle]
69 pub static mut environ: *mut *mut c_char = ptr::null_mut();
70 
71 pub static mut OUR_ENVIRON: Vec<*mut c_char> = Vec::new();
72 
73 pub fn environ_iter() -> impl Iterator<Item = *mut c_char> + 'static {
74     unsafe {
75         let mut ptrs = environ;
76 
77         core::iter::from_fn(move || {
78             let ptr = ptrs.read();
79             if ptr.is_null() {
80                 None
81             } else {
82                 ptrs = ptrs.add(1);
83                 Some(ptr)
84             }
85         })
86     }
87 }
88 
89 pub trait WriteByte: fmt::Write {
90     fn write_u8(&mut self, byte: u8) -> fmt::Result;
91 }
92 
93 impl<'a, W: WriteByte> WriteByte for &'a mut W {
94     fn write_u8(&mut self, byte: u8) -> fmt::Result {
95         (**self).write_u8(byte)
96     }
97 }
98 
99 pub struct FileWriter(pub c_int);
100 
101 impl FileWriter {
102     pub fn write(&mut self, buf: &[u8]) -> isize {
103         Sys::write(self.0, buf)
104     }
105 }
106 
107 impl fmt::Write for FileWriter {
108     fn write_str(&mut self, s: &str) -> fmt::Result {
109         self.write(s.as_bytes());
110         Ok(())
111     }
112 }
113 
114 impl WriteByte for FileWriter {
115     fn write_u8(&mut self, byte: u8) -> fmt::Result {
116         self.write(&[byte]);
117         Ok(())
118     }
119 }
120 
121 pub struct FileReader(pub c_int);
122 
123 impl FileReader {
124     pub fn read(&mut self, buf: &mut [u8]) -> isize {
125         Sys::read(self.0, buf)
126     }
127 }
128 
129 impl Read for FileReader {
130     fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
131         let i = Sys::read(self.0, buf);
132         if i >= 0 {
133             Ok(i as usize)
134         } else {
135             Err(io::Error::from_raw_os_error(-i as i32))
136         }
137     }
138 }
139 
140 pub struct StringWriter(pub *mut u8, pub usize);
141 impl Write for StringWriter {
142     fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
143         if self.1 > 1 {
144             let copy_size = buf.len().min(self.1 - 1);
145             unsafe {
146                 ptr::copy_nonoverlapping(buf.as_ptr(), self.0, copy_size);
147                 self.1 -= copy_size;
148 
149                 self.0 = self.0.add(copy_size);
150                 *self.0 = 0;
151             }
152         }
153 
154         // Pretend the entire slice was written. This is because many functions
155         // (like snprintf) expects a return value that reflects how many bytes
156         // *would have* been written. So keeping track of this information is
157         // good, and then if we want the *actual* written size we can just go
158         // `cmp::min(written, maxlen)`.
159         Ok(buf.len())
160     }
161     fn flush(&mut self) -> io::Result<()> {
162         Ok(())
163     }
164 }
165 impl fmt::Write for StringWriter {
166     fn write_str(&mut self, s: &str) -> fmt::Result {
167         // can't fail
168         self.write(s.as_bytes()).unwrap();
169         Ok(())
170     }
171 }
172 impl WriteByte for StringWriter {
173     fn write_u8(&mut self, byte: u8) -> fmt::Result {
174         // can't fail
175         self.write(&[byte]).unwrap();
176         Ok(())
177     }
178 }
179 
180 pub struct UnsafeStringWriter(pub *mut u8);
181 impl Write for UnsafeStringWriter {
182     fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
183         unsafe {
184             ptr::copy_nonoverlapping(buf.as_ptr(), self.0, buf.len());
185             self.0 = self.0.add(buf.len());
186             *self.0 = b'\0';
187         }
188         Ok(buf.len())
189     }
190     fn flush(&mut self) -> io::Result<()> {
191         Ok(())
192     }
193 }
194 impl fmt::Write for UnsafeStringWriter {
195     fn write_str(&mut self, s: &str) -> fmt::Result {
196         // can't fail
197         self.write(s.as_bytes()).unwrap();
198         Ok(())
199     }
200 }
201 impl WriteByte for UnsafeStringWriter {
202     fn write_u8(&mut self, byte: u8) -> fmt::Result {
203         // can't fail
204         self.write(&[byte]).unwrap();
205         Ok(())
206     }
207 }
208 
209 pub struct UnsafeStringReader(pub *const u8);
210 impl Read for UnsafeStringReader {
211     fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
212         unsafe {
213             for i in 0..buf.len() {
214                 if *self.0 == 0 {
215                     return Ok(i);
216                 }
217 
218                 buf[i] = *self.0;
219                 self.0 = self.0.offset(1);
220             }
221             Ok(buf.len())
222         }
223     }
224 }
225 
226 pub struct CountingWriter<T> {
227     pub inner: T,
228     pub written: usize,
229 }
230 impl<T> CountingWriter<T> {
231     pub fn new(writer: T) -> Self {
232         Self {
233             inner: writer,
234             written: 0,
235         }
236     }
237 }
238 impl<T: fmt::Write> fmt::Write for CountingWriter<T> {
239     fn write_str(&mut self, s: &str) -> fmt::Result {
240         self.written += s.len();
241         self.inner.write_str(s)
242     }
243 }
244 impl<T: WriteByte> WriteByte for CountingWriter<T> {
245     fn write_u8(&mut self, byte: u8) -> fmt::Result {
246         self.written += 1;
247         self.inner.write_u8(byte)
248     }
249 }
250 impl<T: Write> Write for CountingWriter<T> {
251     fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
252         let res = self.inner.write(buf);
253         if let Ok(written) = res {
254             self.written += written;
255         }
256         res
257     }
258     fn write_all(&mut self, buf: &[u8]) -> io::Result<()> {
259         match self.inner.write_all(&buf) {
260             Ok(()) => (),
261             Err(ref err) if err.kind() == io::ErrorKind::WriteZero => (),
262             Err(err) => return Err(err),
263         }
264         self.written += buf.len();
265         Ok(())
266     }
267     fn flush(&mut self) -> io::Result<()> {
268         self.inner.flush()
269     }
270 }
271 
272 // TODO: Set a global variable once get_auxvs is called, and then implement getauxval based on
273 // get_auxv.
274 
275 #[cold]
276 pub unsafe fn get_auxvs(mut ptr: *const usize) -> Box<[[usize; 2]]> {
277     //traverse the stack and collect argument environment variables
278     let mut auxvs = Vec::new();
279 
280     while *ptr != self::auxv_defs::AT_NULL {
281         let kind = ptr.read();
282         ptr = ptr.add(1);
283         let value = ptr.read();
284         ptr = ptr.add(1);
285         auxvs.push([kind, value]);
286     }
287 
288     auxvs.sort_unstable_by_key(|[kind, _]| *kind);
289     auxvs.into_boxed_slice()
290 }
291 pub fn get_auxv(auxvs: &[[usize; 2]], key: usize) -> Option<usize> {
292     auxvs
293         .binary_search_by_key(&key, |[entry_key, _]| *entry_key)
294         .ok()
295         .map(|idx| auxvs[idx][1])
296 }
297 
298 #[cold]
299 #[cfg(target_os = "redox")]
300 pub fn init(auxvs: Box<[[usize; 2]]>) {
301     use self::auxv_defs::*;
302 
303     if let (Some(cwd_ptr), Some(cwd_len)) = (
304         get_auxv(&auxvs, AT_REDOX_INITIALCWD_PTR),
305         get_auxv(&auxvs, AT_REDOX_INITIALCWD_LEN),
306     ) {
307         let cwd_bytes: &'static [u8] =
308             unsafe { core::slice::from_raw_parts(cwd_ptr as *const u8, cwd_len) };
309         if let Ok(cwd) = core::str::from_utf8(cwd_bytes) {
310             self::sys::path::setcwd_manual(cwd.into());
311         }
312     }
313 }
314 #[cfg(not(target_os = "redox"))]
315 pub fn init(auxvs: Box<[[usize; 2]]>) {}
316