Merge branch 'cstr' into 'master'

Switch to a lightweight CStr wrapper

See merge request redox-os/relibc!431
This commit is contained in:
Jeremy Soller
2023-11-04 18:29:38 +00:00
24 changed files with 374 additions and 1590 deletions
+62 -1228
View File
File diff suppressed because it is too large Load Diff
+1 -1
View File
@@ -44,7 +44,7 @@ impl<R: BufRead> Db<R> {
pub type FileDb = Db<BufReader<File>>;
impl FileDb {
pub fn open(path: &CStr, separator: Separator) -> io::Result<Self> {
pub fn open(path: CStr, separator: Separator) -> io::Result<Self> {
let file = File::open(path, fcntl::O_RDONLY | fcntl::O_CLOEXEC)?;
Ok(Db::new(BufReader::new(file), separator))
}
+2 -2
View File
@@ -24,14 +24,14 @@ impl File {
}
}
pub fn open(path: &CStr, oflag: c_int) -> io::Result<Self> {
pub fn open(path: CStr, oflag: c_int) -> io::Result<Self> {
match Sys::open(path, oflag, 0) {
-1 => Err(io::last_os_error()),
ok => Ok(Self::new(ok)),
}
}
pub fn create(path: &CStr, oflag: c_int, mode: mode_t) -> io::Result<Self> {
pub fn create(path: CStr, oflag: c_int, mode: mode_t) -> io::Result<Self> {
match Sys::open(path, oflag | O_CREAT, mode) {
-1 => Err(io::last_os_error()),
ok => Ok(Self::new(ok)),
+1 -1
View File
@@ -12,7 +12,7 @@ pub const RTLD_NOW: c_int = 0x0002;
pub const RTLD_GLOBAL: c_int = 0x0100;
pub const RTLD_LOCAL: c_int = 0x0000;
static ERROR_NOT_SUPPORTED: &'static CStr = c_str!("dlfcn not supported");
static ERROR_NOT_SUPPORTED: CStr = c_str!("dlfcn not supported");
#[thread_local]
static ERROR: AtomicUsize = AtomicUsize::new(0);
+50 -39
View File
@@ -1,8 +1,9 @@
//! grp implementation for Redox, following http://pubs.opengroup.org/onlinepubs/7908799/xsh/grp.h.html
//! grp implementation, following http://pubs.opengroup.org/onlinepubs/7908799/xsh/grp.h.html
use core::{
cell::SyncUnsafeCell,
convert::{TryFrom, TryInto},
mem,
mem::{self, MaybeUninit},
num::ParseIntError,
ops::{Deref, DerefMut},
pin::Pin,
@@ -11,8 +12,6 @@ use core::{
str::Matches,
};
use lazy_static::lazy_static;
use alloc::{
borrow::ToOwned,
string::{FromUtf8Error, String},
@@ -80,9 +79,7 @@ static mut GROUP: group = group {
gr_mem: ptr::null_mut(),
};
lazy_static! {
static ref LINE_READER: Mutex<Option<Lines<BufReader<File>>>> = Mutex::new(None);
}
static LINE_READER: SyncUnsafeCell<Option<Lines<BufReader<File>>>> = SyncUnsafeCell::new(None);
#[repr(C)]
#[derive(Debug)]
@@ -307,7 +304,7 @@ pub unsafe extern "C" fn getgrnam_r(
// MT-Unsafe race:grent race:grentbuf locale
#[no_mangle]
pub unsafe extern "C" fn getgrent() -> *mut group {
let mut line_reader = LINE_READER.lock();
let mut line_reader = &mut *LINE_READER.get();
if line_reader.is_none() {
let Ok(db) = File::open(c_str!("/etc/group"), fcntl::O_RDONLY) else { return ptr::null_mut() };
@@ -331,60 +328,74 @@ pub unsafe extern "C" fn getgrent() -> *mut group {
// MT-Unsafe race:grent locale
#[no_mangle]
pub unsafe extern "C" fn endgrent() {
let mut line_reader = LINE_READER.lock();
*line_reader = None;
*(&mut *LINE_READER.get()) = None;
}
// MT-Unsafe race:grent locale
#[no_mangle]
pub unsafe extern "C" fn setgrent() {
let mut line_reader = LINE_READER.lock();
let mut line_reader = &mut *LINE_READER.get();
let Ok(db) = File::open(c_str!("/etc/group"), fcntl::O_RDONLY) else { return };
*line_reader = Some(BufReader::new(db).lines());
}
// MT-Safe locale
// Not POSIX
#[no_mangle]
pub unsafe extern "C" fn getgrouplist(
user: *const c_char,
group: gid_t,
groups: *mut gid_t,
ngroups: i32,
) -> i32 {
let mut grps = Vec::<gid_t>::from_raw_parts(groups, 0, ngroups as usize);
let Ok(usr) = (crate::c_str::CStr::from_ptr(user).to_str()) else { return 0 };
ngroups: *mut c_int,
) -> c_int {
let mut grps =
slice::from_raw_parts_mut(groups.cast::<MaybeUninit<gid_t>>(), ngroups.read() as usize);
// FIXME: This API probably expects the group database to already exist in memory, as it
// doesn't seem to have any documented error handling.
let Ok(user) = (crate::c_str::CStr::from_ptr(user).to_str()) else { return 0 };
let Ok(db) = File::open(c_str!("/etc/group"), fcntl::O_RDONLY) else { return 0; };
let mut groups_found: c_int = 0;
for line in BufReader::new(db).lines() {
if grps.len() >= ngroups as usize {
return ngroups;
let Ok(line) = line else {
return 0;
};
let mut parts = line.split(SEPARATOR);
let group_name = parts.next().unwrap_or("");
let group_password = parts.next().unwrap_or("");
let group_id = parts.next().unwrap_or("-1").parse::<c_int>().unwrap();
let members = parts
.next()
.unwrap_or("")
.split(",")
.map(|i| i.trim())
.collect::<Vec<_>>();
if !members.iter().any(|i| *i == user) {
continue;
}
match line {
Err(_) => return 0,
Ok(line) => {
let mut parts = line.split(SEPARATOR);
if let Some(dst) = grps.get_mut(groups_found as usize) {
dst.write(group_id);
}
let group_name = parts.next().unwrap_or("");
let group_password = parts.next().unwrap_or("");
let group_id = parts.next().unwrap_or("-1").parse::<i32>().unwrap();
let members = parts
.next()
.unwrap_or("")
.split(",")
.map(|i| i.trim())
.collect::<Vec<_>>();
if members.iter().any(|i| *i == usr) {
grps.push(group_id);
}
}
groups_found = match groups_found.checked_add(1) {
Some(g) => g,
None => break,
};
}
if grps.len() <= 0 {
grps.push(group);
}
ngroups.write(groups_found);
return grps.len() as i32;
if groups_found as usize > grps.len() {
-1
} else {
grps.len() as c_int
}
}
+2 -2
View File
@@ -45,7 +45,7 @@ pub unsafe extern "C" fn endhostent() {
pub unsafe extern "C" fn sethostent(stayopen: c_int) {
HOST_STAYOPEN = stayopen;
if HOSTDB < 0 {
HOSTDB = Sys::open(&CString::new("/etc/hosts").unwrap(), O_RDONLY, 0)
HOSTDB = Sys::open(c_str!("/etc/hosts"), O_RDONLY, 0)
} else {
Sys::lseek(HOSTDB, 0, SEEK_SET);
}
@@ -55,7 +55,7 @@ pub unsafe extern "C" fn sethostent(stayopen: c_int) {
#[no_mangle]
pub unsafe extern "C" fn gethostent() -> *mut hostent {
if HOSTDB < 0 {
HOSTDB = Sys::open(&CString::new("/etc/hosts").unwrap(), O_RDONLY, 0);
HOSTDB = Sys::open(c_str!("/etc/hosts"), O_RDONLY, 0);
}
let mut rlb = RawLineBuffer::new(HOSTDB);
rlb.seek(H_POS);
+1 -1
View File
@@ -7,7 +7,7 @@ use crate::{
use alloc::string::String;
pub fn get_dns_server() -> String {
let file = match File::open(&CString::new("/etc/resolv.conf").unwrap(), fcntl::O_RDONLY) {
let file = match File::open(c_str!("/etc/resolv.conf"), fcntl::O_RDONLY) {
Ok(file) => file,
Err(_) => return String::new(), // TODO: better error handling
};
+10 -19
View File
@@ -370,7 +370,7 @@ pub unsafe extern "C" fn getnetbyname(name: *const c_char) -> *mut netent {
#[no_mangle]
pub unsafe extern "C" fn getnetent() -> *mut netent {
if NETDB == 0 {
NETDB = Sys::open(&CString::new("/etc/networks").unwrap(), O_RDONLY, 0);
NETDB = Sys::open(c_str!("/etc/networks"), O_RDONLY, 0);
}
let mut rlb = RawLineBuffer::new(NETDB);
@@ -484,7 +484,7 @@ pub unsafe extern "C" fn getprotobynumber(number: c_int) -> *mut protoent {
#[no_mangle]
pub unsafe extern "C" fn getprotoent() -> *mut protoent {
if PROTODB == 0 {
PROTODB = Sys::open(&CString::new("/etc/protocols").unwrap(), O_RDONLY, 0);
PROTODB = Sys::open(c_str!("/etc/protocols"), O_RDONLY, 0);
}
let mut rlb = RawLineBuffer::new(PROTODB);
@@ -603,7 +603,7 @@ pub unsafe extern "C" fn getservbyport(port: c_int, proto: *const c_char) -> *mu
#[no_mangle]
pub unsafe extern "C" fn getservent() -> *mut servent {
if SERVDB == 0 {
SERVDB = Sys::open(&CString::new("/etc/services").unwrap(), O_RDONLY, 0);
SERVDB = Sys::open(c_str!("/etc/services"), O_RDONLY, 0);
}
let mut rlb = RawLineBuffer::new(SERVDB);
rlb.seek(S_POS);
@@ -690,7 +690,7 @@ pub unsafe extern "C" fn getservent() -> *mut servent {
pub unsafe extern "C" fn setnetent(stayopen: c_int) {
NET_STAYOPEN = stayopen;
if NETDB == 0 {
NETDB = Sys::open(&CString::new("/etc/networks").unwrap(), O_RDONLY, 0)
NETDB = Sys::open(c_str!("/etc/networks"), O_RDONLY, 0)
} else {
Sys::lseek(NETDB, 0, SEEK_SET);
N_POS = 0;
@@ -701,7 +701,7 @@ pub unsafe extern "C" fn setnetent(stayopen: c_int) {
pub unsafe extern "C" fn setprotoent(stayopen: c_int) {
PROTO_STAYOPEN = stayopen;
if PROTODB == 0 {
PROTODB = Sys::open(&CString::new("/etc/protocols").unwrap(), O_RDONLY, 0)
PROTODB = Sys::open(c_str!("/etc/protocols"), O_RDONLY, 0)
} else {
Sys::lseek(PROTODB, 0, SEEK_SET);
P_POS = 0;
@@ -712,7 +712,7 @@ pub unsafe extern "C" fn setprotoent(stayopen: c_int) {
pub unsafe extern "C" fn setservent(stayopen: c_int) {
SERV_STAYOPEN = stayopen;
if SERVDB == 0 {
SERVDB = Sys::open(&CString::new("/etc/services").unwrap(), O_RDONLY, 0)
SERVDB = Sys::open(c_str!("/etc/services"), O_RDONLY, 0)
} else {
Sys::lseek(SERVDB, 0, SEEK_SET);
S_POS = 0;
@@ -727,17 +727,8 @@ pub unsafe extern "C" fn getaddrinfo(
res: *mut *mut addrinfo,
) -> c_int {
//TODO: getaddrinfo
let node_opt = if node.is_null() {
None
} else {
Some(CStr::from_ptr(node))
};
let service_opt = if service.is_null() {
None
} else {
Some(CStr::from_ptr(service))
};
let node_opt = CStr::from_nullable_ptr(node);
let service_opt = CStr::from_nullable_ptr(service);
let hints_opt = if hints.is_null() { None } else { Some(&*hints) };
@@ -791,7 +782,7 @@ pub unsafe extern "C" fn getaddrinfo(
let ai_canonname = if ai_flags & AI_CANONNAME > 0 {
ai_flags &= !AI_CANONNAME;
node.to_owned().into_raw()
node.to_owned_cstring().into_raw()
} else {
ptr::null_mut()
};
@@ -859,7 +850,7 @@ pub unsafe extern "C" fn freeaddrinfo(res: *mut addrinfo) {
while !ai.is_null() {
let bai = Box::from_raw(ai);
if !bai.ai_canonname.is_null() {
CString::from_raw(bai.ai_canonname);
drop(CString::from_raw(bai.ai_canonname));
}
if !bai.ai_addr.is_null() {
if bai.ai_addrlen == mem::size_of::<sockaddr_in>() {
+2 -2
View File
@@ -1,9 +1,9 @@
use crate::{c_str::CString, fs::File, header::fcntl, io::Read};
use crate::{fs::File, header::fcntl, io::Read};
use alloc::string::String;
pub fn get_dns_server() -> String {
let mut string = String::new();
let mut file = File::open(&CString::new("/etc/net/dns").unwrap(), fcntl::O_RDONLY).unwrap(); // TODO: error handling
let mut file = File::open(c_str!("/etc/net/dns"), fcntl::O_RDONLY).unwrap(); // TODO: error handling
file.read_to_string(&mut string).unwrap(); // TODO: error handling
string
}
+20 -9
View File
@@ -1,10 +1,17 @@
use super::{constants, Buffer, BUFSIZ, FILE};
use core::{cell::UnsafeCell, ptr};
use crate::{fs::File, io::LineWriter, platform::types::*, sync::Mutex};
use crate::{
fs::File,
io::LineWriter,
platform::types::*,
sync::{Mutex, Once},
};
use alloc::{boxed::Box, vec::Vec};
// TODO: Change FILE to allow const fn initialization?
pub struct GlobalFile(UnsafeCell<FILE>);
impl GlobalFile {
fn new(file: c_int, flags: c_int) -> Self {
let file = File::new(file);
@@ -32,15 +39,19 @@ impl GlobalFile {
// statics need to be Sync
unsafe impl Sync for GlobalFile {}
lazy_static! {
#[allow(non_upper_case_globals)]
pub static ref default_stdin: GlobalFile = GlobalFile::new(0, constants::F_NOWR);
// TODO: Allow const fn initialization of FILE
static DEFAULT_STDIN: Once<GlobalFile> = Once::new();
static DEFAULT_STDOUT: Once<GlobalFile> = Once::new();
static DEFAULT_STDERR: Once<GlobalFile> = Once::new();
#[allow(non_upper_case_globals)]
pub static ref default_stdout: GlobalFile = GlobalFile::new(1, constants::F_NORD);
#[allow(non_upper_case_globals)]
pub static ref default_stderr: GlobalFile = GlobalFile::new(2, constants::F_NORD);
pub fn default_stdin() -> &'static GlobalFile {
DEFAULT_STDIN.call_once(|| GlobalFile::new(0, constants::F_NOWR))
}
pub fn default_stdout() -> &'static GlobalFile {
DEFAULT_STDOUT.call_once(|| GlobalFile::new(1, constants::F_NORD))
}
pub fn default_stderr() -> &'static GlobalFile {
DEFAULT_STDERR.call_once(|| GlobalFile::new(2, constants::F_NORD))
}
#[no_mangle]
+5
View File
@@ -107,11 +107,16 @@ pub struct FILE {
file: File,
// pub for stdio_ext
pub(crate) flags: c_int,
// TODO: Is the read_buf dropped?
read_buf: Buffer<'static>,
read_pos: usize,
read_size: usize,
unget: Vec<u8>,
// pub for stdio_ext
// TODO: To support const fn initialization, use static dispatch (perhaps partially)?
pub(crate) writer: Box<dyn Writer + Send>,
// Optional pid for use with popen/pclose
+58 -52
View File
@@ -3,10 +3,10 @@
use core::{convert::TryFrom, intrinsics, iter, mem, ptr, slice};
use rand::{
distributions::{Alphanumeric, Distribution, Uniform},
prng::XorShiftRng,
rngs::JitterRng,
Rng, SeedableRng,
};
use rand_jitter::JitterRng;
use rand_xorshift::XorShiftRng;
use crate::{
c_str::CStr,
@@ -25,6 +25,7 @@ use crate::{
},
ld_so,
platform::{self, types::*, Pal, Sys},
sync::Once,
};
mod rand48;
@@ -44,8 +45,11 @@ static mut ATEXIT_FUNCS: [Option<extern "C" fn()>; 32] = [None; 32];
static mut L64A_BUFFER: [c_char; 7] = [0; 7]; // up to 6 digits plus null terminator
static mut RNG: Option<XorShiftRng> = None;
lazy_static! {
static ref RNG_SAMPLER: Uniform<c_int> = Uniform::new_inclusive(0, RAND_MAX);
// TODO: This could be const fn, but the trait system won't allow that.
static RNG_SAMPLER: Once<Uniform<c_int>> = Once::new();
fn rng_sampler() -> &'static Uniform<c_int> {
RNG_SAMPLER.call_once(|| Uniform::new_inclusive(0, RAND_MAX))
}
#[no_mangle]
@@ -131,55 +135,53 @@ pub unsafe extern "C" fn atof(s: *const c_char) -> c_double {
}
macro_rules! dec_num_from_ascii {
($s:expr, $t:ty) => {
unsafe {
let mut s = $s;
// Iterate past whitespace
while ctype::isspace(*s as c_int) != 0 {
s = s.offset(1);
}
// Find out if there is a - sign
let neg_sign = match *s {
0x2d => {
s = s.offset(1);
true
}
// '+' increment s and continue parsing
0x2b => {
s = s.offset(1);
false
}
_ => false,
};
let mut n: $t = 0;
while ctype::isdigit(*s as c_int) != 0 {
n = 10 * n - (*s as $t - 0x30);
s = s.offset(1);
}
if neg_sign {
n
} else {
-n
}
($s:expr, $t:ty) => {{
let mut s = $s;
// Iterate past whitespace
while ctype::isspace(*s as c_int) != 0 {
s = s.offset(1);
}
};
// Find out if there is a - sign
let neg_sign = match *s {
0x2d => {
s = s.offset(1);
true
}
// '+' increment s and continue parsing
0x2b => {
s = s.offset(1);
false
}
_ => false,
};
let mut n: $t = 0;
while ctype::isdigit(*s as c_int) != 0 {
n = 10 * n - (*s as $t - 0x30);
s = s.offset(1);
}
if neg_sign {
n
} else {
-n
}
}};
}
#[no_mangle]
pub extern "C" fn atoi(s: *const c_char) -> c_int {
pub unsafe extern "C" fn atoi(s: *const c_char) -> c_int {
dec_num_from_ascii!(s, c_int)
}
#[no_mangle]
pub extern "C" fn atol(s: *const c_char) -> c_long {
pub unsafe extern "C" fn atol(s: *const c_char) -> c_long {
dec_num_from_ascii!(s, c_long)
}
#[no_mangle]
pub extern "C" fn atoll(s: *const c_char) -> c_longlong {
pub unsafe extern "C" fn atoll(s: *const c_char) -> c_longlong {
dec_num_from_ascii!(s, c_longlong)
}
@@ -643,12 +645,16 @@ fn get_nstime() -> u64 {
}
#[no_mangle]
pub extern "C" fn mkostemps(name: *mut c_char, suffix_len: c_int, mut flags: c_int) -> c_int {
pub unsafe extern "C" fn mkostemps(
name: *mut c_char,
suffix_len: c_int,
mut flags: c_int,
) -> c_int {
flags &= !O_ACCMODE;
flags |= O_RDWR | O_CREAT | O_EXCL;
inner_mktemp(name, suffix_len, || {
let name = unsafe { CStr::from_ptr(name) };
let name = CStr::from_ptr(name);
let fd = Sys::open(name, flags, 0o600);
if fd >= 0 {
@@ -661,15 +667,15 @@ pub extern "C" fn mkostemps(name: *mut c_char, suffix_len: c_int, mut flags: c_i
}
#[no_mangle]
pub extern "C" fn mkstemp(name: *mut c_char) -> c_int {
pub unsafe extern "C" fn mkstemp(name: *mut c_char) -> c_int {
mkostemps(name, 0, 0)
}
#[no_mangle]
pub extern "C" fn mkostemp(name: *mut c_char, flags: c_int) -> c_int {
pub unsafe extern "C" fn mkostemp(name: *mut c_char, flags: c_int) -> c_int {
mkostemps(name, 0, flags)
}
#[no_mangle]
pub extern "C" fn mkstemps(name: *mut c_char, suffix_len: c_int) -> c_int {
pub unsafe extern "C" fn mkstemps(name: *mut c_char, suffix_len: c_int) -> c_int {
mkostemps(name, suffix_len, 0)
}
@@ -744,7 +750,7 @@ pub unsafe extern "C" fn putenv(insert: *mut c_char) -> c_int {
}
#[no_mangle]
pub extern "C" fn qsort(
pub unsafe extern "C" fn qsort(
base: *mut c_void,
nel: size_t,
width: size_t,
@@ -763,10 +769,10 @@ pub extern "C" fn qsort(
#[no_mangle]
pub unsafe extern "C" fn rand() -> c_int {
match RNG {
Some(ref mut rng) => RNG_SAMPLER.sample(rng),
Some(ref mut rng) => rng_sampler().sample(rng),
None => {
let mut rng = XorShiftRng::from_seed([1; 16]);
let ret = RNG_SAMPLER.sample(&mut rng);
let ret = rng_sampler().sample(&mut rng);
RNG = Some(rng);
ret
}
@@ -782,7 +788,7 @@ pub unsafe extern "C" fn rand_r(seed: *mut c_uint) -> c_int {
let seed_arr: [u8; 16] = mem::transmute([*seed; 16 / mem::size_of::<c_uint>()]);
let mut rng = XorShiftRng::from_seed(seed_arr);
let ret = RNG_SAMPLER.sample(&mut rng);
let ret = rng_sampler().sample(&mut rng);
*seed = ret as _;
@@ -861,7 +867,7 @@ pub unsafe extern "C" fn realpath(pathname: *const c_char, resolved: *mut c_char
let out = slice::from_raw_parts_mut(ptr as *mut u8, limits::PATH_MAX);
{
let file = match File::open(&CStr::from_ptr(pathname), O_PATH | O_CLOEXEC) {
let file = match File::open(CStr::from_ptr(pathname), O_PATH | O_CLOEXEC) {
Ok(file) => file,
Err(_) => return ptr::null_mut(),
};
@@ -945,7 +951,7 @@ pub unsafe extern "C" fn setenv(
}
// #[no_mangle]
pub extern "C" fn setkey(key: *const c_char) {
pub unsafe extern "C" fn setkey(key: *const c_char) {
unimplemented!();
}
+2 -2
View File
@@ -18,17 +18,17 @@ use core::{
};
#[cfg(target_pointer_width = "32")]
use goblin::elf32::{
dynamic::{Dyn, DT_DEBUG, DT_RUNPATH},
header::ET_DYN,
program_header,
r#dyn::{Dyn, DT_DEBUG, DT_RUNPATH},
section_header::{SHN_UNDEF, SHT_FINI_ARRAY, SHT_INIT_ARRAY},
sym,
};
#[cfg(target_pointer_width = "64")]
use goblin::elf64::{
dynamic::{Dyn, DT_DEBUG, DT_RUNPATH},
header::ET_DYN,
program_header,
r#dyn::{Dyn, DT_DEBUG, DT_RUNPATH},
section_header::{SHN_UNDEF, SHT_FINI_ARRAY, SHT_INIT_ARRAY},
sym,
};
+2 -2
View File
@@ -11,7 +11,7 @@ use goblin::{
};
use crate::{
c_str::CString,
c_str::{CStr, CString},
fs::File,
header::{
dl_tls::{__tls_get_addr, dl_tls_index},
@@ -293,7 +293,7 @@ impl Linker {
let path_c = CString::new(path)
.map_err(|err| Error::Malformed(format!("invalid path '{}': {}", path, err)))?;
let flags = fcntl::O_RDONLY | fcntl::O_CLOEXEC;
let mut file = File::open(&path_c, flags)
let mut file = File::open(CStr::borrow(&path_c), flags)
.map_err(|err| Error::Malformed(format!("failed to open '{}': {}", path, err)))?;
file.read_to_end(&mut data)
.map_err(|err| Error::Malformed(format!("failed to read '{}': {}", path, err)))?;
+1 -5
View File
@@ -13,6 +13,7 @@
#![feature(linkage)]
#![feature(stmt_expr_attributes)]
#![feature(str_internals)]
#![feature(sync_unsafe_cell)]
#![feature(thread_local)]
#![feature(vec_into_raw_parts)]
#![allow(clippy::cast_lossless)]
@@ -28,8 +29,6 @@ extern crate alloc;
extern crate cbitset;
extern crate core_io;
extern crate goblin;
#[macro_use]
extern crate lazy_static;
extern crate memchr;
#[macro_use]
extern crate memoffset;
@@ -43,9 +42,6 @@ extern crate sc;
#[cfg(target_os = "redox")]
extern crate syscall;
#[cfg(target_os = "redox")]
extern crate spin;
#[macro_use]
mod macros;
pub mod c_str;
+16 -16
View File
@@ -89,7 +89,7 @@ impl Sys {
}
impl Pal for Sys {
fn access(path: &CStr, mode: c_int) -> c_int {
fn access(path: CStr, mode: c_int) -> c_int {
e(unsafe { syscall!(ACCESS, path.as_ptr(), mode) }) as c_int
}
@@ -97,15 +97,15 @@ impl Pal for Sys {
unsafe { syscall!(BRK, addr) as *mut c_void }
}
fn chdir(path: &CStr) -> c_int {
fn chdir(path: CStr) -> c_int {
e(unsafe { syscall!(CHDIR, path.as_ptr()) }) as c_int
}
fn chmod(path: &CStr, mode: mode_t) -> c_int {
fn chmod(path: CStr, mode: mode_t) -> c_int {
e(unsafe { syscall!(FCHMODAT, AT_FDCWD, path.as_ptr(), mode, 0) }) as c_int
}
fn chown(path: &CStr, owner: uid_t, group: gid_t) -> c_int {
fn chown(path: CStr, owner: uid_t, group: gid_t) -> c_int {
e(unsafe {
syscall!(
FCHOWNAT,
@@ -141,7 +141,7 @@ impl Pal for Sys {
e(unsafe { syscall!(DUP3, fildes, fildes2, 0) }) as c_int
}
unsafe fn execve(path: &CStr, argv: *const *mut c_char, envp: *const *mut c_char) -> c_int {
unsafe fn execve(path: CStr, argv: *const *mut c_char, envp: *const *mut c_char) -> c_int {
e(syscall!(EXECVE, path.as_ptr(), argv, envp)) as c_int
}
unsafe fn fexecve(fildes: c_int, argv: *const *mut c_char, envp: *const *mut c_char) -> c_int {
@@ -252,7 +252,7 @@ impl Pal for Sys {
e(unsafe { syscall!(UTIMENSAT, fd, ptr::null::<c_char>(), times, 0) }) as c_int
}
fn utimens(path: &CStr, times: *const timespec) -> c_int {
fn utimens(path: CStr, times: *const timespec) -> c_int {
e(unsafe { syscall!(UTIMENSAT, AT_FDCWD, path.as_ptr(), times, 0) }) as c_int
}
@@ -332,11 +332,11 @@ impl Pal for Sys {
e(unsafe { syscall!(GETUID) }) as uid_t
}
fn lchown(path: &CStr, owner: uid_t, group: gid_t) -> c_int {
fn lchown(path: CStr, owner: uid_t, group: gid_t) -> c_int {
e(unsafe { syscall!(LCHOWN, path.as_ptr(), owner, group) }) as c_int
}
fn link(path1: &CStr, path2: &CStr) -> c_int {
fn link(path1: CStr, path2: CStr) -> c_int {
e(unsafe {
syscall!(
LINKAT,
@@ -353,11 +353,11 @@ impl Pal for Sys {
e(unsafe { syscall!(LSEEK, fildes, offset, whence) }) as off_t
}
fn mkdir(path: &CStr, mode: mode_t) -> c_int {
fn mkdir(path: CStr, mode: mode_t) -> c_int {
e(unsafe { syscall!(MKDIRAT, AT_FDCWD, path.as_ptr(), mode) }) as c_int
}
fn mkfifo(path: &CStr, mode: mode_t) -> c_int {
fn mkfifo(path: CStr, mode: mode_t) -> c_int {
e(unsafe { syscall!(MKNODAT, AT_FDCWD, path.as_ptr(), mode | S_IFIFO, 0) }) as c_int
}
@@ -408,7 +408,7 @@ impl Pal for Sys {
e(unsafe { syscall!(NANOSLEEP, rqtp, rmtp) }) as c_int
}
fn open(path: &CStr, oflag: c_int, mode: mode_t) -> c_int {
fn open(path: CStr, oflag: c_int, mode: mode_t) -> c_int {
e(unsafe { syscall!(OPENAT, AT_FDCWD, path.as_ptr(), oflag, mode) }) as c_int
}
@@ -491,7 +491,7 @@ impl Pal for Sys {
e(unsafe { syscall!(READ, fildes, buf.as_mut_ptr(), buf.len()) }) as ssize_t
}
fn readlink(pathname: &CStr, out: &mut [u8]) -> ssize_t {
fn readlink(pathname: CStr, out: &mut [u8]) -> ssize_t {
e(unsafe {
syscall!(
READLINKAT,
@@ -503,11 +503,11 @@ impl Pal for Sys {
}) as ssize_t
}
fn rename(old: &CStr, new: &CStr) -> c_int {
fn rename(old: CStr, new: CStr) -> c_int {
e(unsafe { syscall!(RENAMEAT, AT_FDCWD, old.as_ptr(), AT_FDCWD, new.as_ptr()) }) as c_int
}
fn rmdir(path: &CStr) -> c_int {
fn rmdir(path: CStr) -> c_int {
e(unsafe { syscall!(UNLINKAT, AT_FDCWD, path.as_ptr(), AT_REMOVEDIR) }) as c_int
}
@@ -539,7 +539,7 @@ impl Pal for Sys {
e(unsafe { syscall!(SETSID) }) as c_int
}
fn symlink(path1: &CStr, path2: &CStr) -> c_int {
fn symlink(path1: CStr, path2: CStr) -> c_int {
e(unsafe { syscall!(SYMLINKAT, path1.as_ptr(), AT_FDCWD, path2.as_ptr()) }) as c_int
}
@@ -555,7 +555,7 @@ impl Pal for Sys {
e(unsafe { syscall!(UNAME, utsname, 0) }) as c_int
}
fn unlink(path: &CStr) -> c_int {
fn unlink(path: CStr) -> c_int {
e(unsafe { syscall!(UNLINKAT, AT_FDCWD, path.as_ptr(), 0) }) as c_int
}
+16 -16
View File
@@ -25,15 +25,15 @@ pub use self::socket::PalSocket;
mod socket;
pub trait Pal {
fn access(path: &CStr, mode: c_int) -> c_int;
fn access(path: CStr, mode: c_int) -> c_int;
fn brk(addr: *mut c_void) -> *mut c_void;
fn chdir(path: &CStr) -> c_int;
fn chdir(path: CStr) -> c_int;
fn chmod(path: &CStr, mode: mode_t) -> c_int;
fn chmod(path: CStr, mode: mode_t) -> c_int;
fn chown(path: &CStr, owner: uid_t, group: gid_t) -> c_int;
fn chown(path: CStr, owner: uid_t, group: gid_t) -> c_int;
fn clock_getres(clk_id: clockid_t, tp: *mut timespec) -> c_int;
@@ -47,7 +47,7 @@ pub trait Pal {
fn dup2(fildes: c_int, fildes2: c_int) -> c_int;
unsafe fn execve(path: &CStr, argv: *const *mut c_char, envp: *const *mut c_char) -> c_int;
unsafe fn execve(path: CStr, argv: *const *mut c_char, envp: *const *mut c_char) -> c_int;
unsafe fn fexecve(fildes: c_int, argv: *const *mut c_char, envp: *const *mut c_char) -> c_int;
fn exit(status: c_int) -> !;
@@ -87,7 +87,7 @@ pub trait Pal {
fn futimens(fd: c_int, times: *const timespec) -> c_int;
fn utimens(path: &CStr, times: *const timespec) -> c_int;
fn utimens(path: CStr, times: *const timespec) -> c_int;
fn getcwd(buf: *mut c_char, size: size_t) -> *mut c_char;
@@ -128,15 +128,15 @@ pub trait Pal {
fn getuid() -> uid_t;
fn lchown(path: &CStr, owner: uid_t, group: gid_t) -> c_int;
fn lchown(path: CStr, owner: uid_t, group: gid_t) -> c_int;
fn link(path1: &CStr, path2: &CStr) -> c_int;
fn link(path1: CStr, path2: CStr) -> c_int;
fn lseek(fildes: c_int, offset: off_t, whence: c_int) -> off_t;
fn mkdir(path: &CStr, mode: mode_t) -> c_int;
fn mkdir(path: CStr, mode: mode_t) -> c_int;
fn mkfifo(path: &CStr, mode: mode_t) -> c_int;
fn mkfifo(path: CStr, mode: mode_t) -> c_int;
unsafe fn mlock(addr: *const c_void, len: usize) -> c_int;
@@ -165,7 +165,7 @@ pub trait Pal {
fn nanosleep(rqtp: *const timespec, rmtp: *mut timespec) -> c_int;
fn open(path: &CStr, oflag: c_int, mode: mode_t) -> c_int;
fn open(path: CStr, oflag: c_int, mode: mode_t) -> c_int;
fn pipe2(fildes: &mut [c_int], flags: c_int) -> c_int;
@@ -179,11 +179,11 @@ pub trait Pal {
fn read(fildes: c_int, buf: &mut [u8]) -> ssize_t;
fn readlink(pathname: &CStr, out: &mut [u8]) -> ssize_t;
fn readlink(pathname: CStr, out: &mut [u8]) -> ssize_t;
fn rename(old: &CStr, new: &CStr) -> c_int;
fn rename(old: CStr, new: CStr) -> c_int;
fn rmdir(path: &CStr) -> c_int;
fn rmdir(path: CStr) -> c_int;
fn sched_yield() -> c_int;
@@ -199,7 +199,7 @@ pub trait Pal {
fn setsid() -> c_int;
fn symlink(path1: &CStr, path2: &CStr) -> c_int;
fn symlink(path1: CStr, path2: CStr) -> c_int;
fn sync() -> c_int;
@@ -207,7 +207,7 @@ pub trait Pal {
fn uname(utsname: *mut utsname) -> c_int;
fn unlink(path: &CStr) -> c_int;
fn unlink(path: CStr) -> c_int;
fn waitpid(pid: pid_t, stat_loc: *mut c_int, options: c_int) -> pid_t;
+3 -2
View File
@@ -81,7 +81,7 @@ pub enum ArgEnv<'a> {
}
pub enum Executable<'a> {
AtPath(&'a CStr),
AtPath(CStr<'a>),
InFd { file: File, arg0: &'a [u8] },
}
@@ -187,7 +187,8 @@ pub fn execve(
interpreter.pop().unwrap();
}
let cstring = CString::new(interpreter).map_err(|_| Error::new(ENOEXEC))?;
image_file = File::open(&cstring, O_RDONLY as c_int).map_err(|_| Error::new(ENOENT))?;
image_file = File::open(CStr::borrow(&cstring), O_RDONLY as c_int)
.map_err(|_| Error::new(ENOENT))?;
// Make sure path is kept alive long enough, and push it to the arguments
_interpreter_path = Some(cstring);
+18 -21
View File
@@ -80,7 +80,7 @@ pub fn e(sys: Result<usize>) -> usize {
pub struct Sys;
impl Pal for Sys {
fn access(path: &CStr, mode: c_int) -> c_int {
fn access(path: CStr, mode: c_int) -> c_int {
let fd = match File::open(path, fcntl::O_PATH | fcntl::O_CLOEXEC) {
Ok(fd) => fd,
Err(_) => return -1,
@@ -165,19 +165,19 @@ impl Pal for Sys {
}
}
fn chdir(path: &CStr) -> c_int {
fn chdir(path: CStr) -> c_int {
let path = path_from_c_str!(path);
e(path::chdir(path).map(|()| 0)) as c_int
}
fn chmod(path: &CStr, mode: mode_t) -> c_int {
fn chmod(path: CStr, mode: mode_t) -> c_int {
match File::open(path, fcntl::O_PATH | fcntl::O_CLOEXEC) {
Ok(file) => Self::fchmod(*file, mode),
Err(_) => -1,
}
}
fn chown(path: &CStr, owner: uid_t, group: gid_t) -> c_int {
fn chown(path: CStr, owner: uid_t, group: gid_t) -> c_int {
match File::open(path, fcntl::O_PATH | fcntl::O_CLOEXEC) {
Ok(file) => Self::fchown(*file, owner, group),
Err(_) => -1,
@@ -232,7 +232,7 @@ impl Pal for Sys {
loop {}
}
unsafe fn execve(path: &CStr, argv: *const *mut c_char, envp: *const *mut c_char) -> c_int {
unsafe fn execve(path: CStr, argv: *const *mut c_char, envp: *const *mut c_char) -> c_int {
e(self::exec::execve(
Executable::AtPath(path),
self::exec::ArgEnv::C { argv, envp },
@@ -257,7 +257,7 @@ impl Pal for Sys {
!0
} else {
match str::from_utf8(&buf[..res]) {
Ok(path) => Sys::chdir(&CString::new(path).unwrap()),
Ok(path) => e(path::chdir(path).map(|()| 0)) as c_int,
Err(_) => {
unsafe { errno = EINVAL };
return -1;
@@ -387,7 +387,7 @@ impl Pal for Sys {
e(syscall::futimens(fd as usize, &times)) as c_int
}
fn utimens(path: &CStr, times: *const timespec) -> c_int {
fn utimens(path: CStr, times: *const timespec) -> c_int {
match File::open(path, fcntl::O_PATH | fcntl::O_CLOEXEC) {
Ok(file) => Self::futimens(*file, times),
Err(_) => -1,
@@ -637,7 +637,7 @@ impl Pal for Sys {
e(syscall::getuid()) as pid_t
}
fn lchown(path: &CStr, owner: uid_t, group: gid_t) -> c_int {
fn lchown(path: CStr, owner: uid_t, group: gid_t) -> c_int {
// TODO: Is it correct for regular chown to use O_PATH? On Linux the meaning of that flag
// is to forbid file operations, including fchown.
@@ -648,7 +648,7 @@ impl Pal for Sys {
}
}
fn link(path1: &CStr, path2: &CStr) -> c_int {
fn link(path1: CStr, path2: CStr) -> c_int {
e(unsafe { syscall::link(path1.as_ptr() as *const u8, path2.as_ptr() as *const u8) })
as c_int
}
@@ -661,7 +661,7 @@ impl Pal for Sys {
)) as off_t
}
fn mkdir(path: &CStr, mode: mode_t) -> c_int {
fn mkdir(path: CStr, mode: mode_t) -> c_int {
match File::create(
path,
fcntl::O_DIRECTORY | fcntl::O_EXCL | fcntl::O_CLOEXEC,
@@ -672,7 +672,7 @@ impl Pal for Sys {
}
}
fn mkfifo(path: &CStr, mode: mode_t) -> c_int {
fn mkfifo(path: CStr, mode: mode_t) -> c_int {
match File::create(
path,
fcntl::O_CREAT | fcntl::O_CLOEXEC,
@@ -788,7 +788,7 @@ impl Pal for Sys {
}
}
fn open(path: &CStr, oflag: c_int, mode: mode_t) -> c_int {
fn open(path: CStr, oflag: c_int, mode: mode_t) -> c_int {
let path = path_from_c_str!(path);
e(libredox::open(path, oflag, mode)) as c_int
@@ -828,7 +828,7 @@ impl Pal for Sys {
e(syscall::fpath(fildes as usize, out)) as ssize_t
}
fn readlink(pathname: &CStr, out: &mut [u8]) -> ssize_t {
fn readlink(pathname: CStr, out: &mut [u8]) -> ssize_t {
match File::open(
pathname,
fcntl::O_RDONLY | fcntl::O_SYMLINK | fcntl::O_CLOEXEC,
@@ -838,7 +838,7 @@ impl Pal for Sys {
}
}
fn rename(oldpath: &CStr, newpath: &CStr) -> c_int {
fn rename(oldpath: CStr, newpath: CStr) -> c_int {
let newpath = path_from_c_str!(newpath);
match File::open(oldpath, fcntl::O_PATH | fcntl::O_CLOEXEC) {
Ok(file) => e(syscall::frename(*file as usize, newpath)) as c_int,
@@ -846,7 +846,7 @@ impl Pal for Sys {
}
}
fn rmdir(path: &CStr) -> c_int {
fn rmdir(path: CStr) -> c_int {
let path = path_from_c_str!(path);
e(canonicalize(path).and_then(|path| syscall::rmdir(&path))) as c_int
}
@@ -891,7 +891,7 @@ impl Pal for Sys {
e(syscall::setreuid(ruid as usize, euid as usize)) as c_int
}
fn symlink(path1: &CStr, path2: &CStr) -> c_int {
fn symlink(path1: CStr, path2: CStr) -> c_int {
let mut file = match File::create(
path2,
fcntl::O_WRONLY | fcntl::O_SYMLINK | fcntl::O_CLOEXEC,
@@ -922,10 +922,7 @@ impl Pal for Sys {
return Ok(());
}
let mut file = File::open(
&CString::new("/etc/hostname").unwrap(),
fcntl::O_RDONLY | fcntl::O_CLOEXEC,
)?;
let mut file = File::open(c_str!("/etc/hostname"), fcntl::O_RDONLY | fcntl::O_CLOEXEC)?;
let mut read = 0;
let name_len = name.len();
@@ -1001,7 +998,7 @@ impl Pal for Sys {
}
}
fn unlink(path: &CStr) -> c_int {
fn unlink(path: CStr) -> c_int {
let path = path_from_c_str!(path);
e(canonicalize(path).and_then(|path| syscall::unlink(&path))) as c_int
}
+7 -7
View File
@@ -10,7 +10,7 @@ use crate::header::arch_aarch64_user::user_regs_struct;
#[cfg(target_arch = "x86_64")]
use crate::header::arch_x64_user::user_regs_struct;
use crate::{
c_str::CString,
c_str::{CStr, CString},
fs::File,
header::{errno as errnoh, fcntl, signal, sys_ptrace},
io::{self, prelude::*},
@@ -57,7 +57,7 @@ pub fn is_traceme(pid: pid_t) -> bool {
return false;
}
File::open(
&CString::new(format!("chan:ptrace-relibc/{}/traceme", pid)).unwrap(),
CStr::borrow(&CString::new(format!("chan:ptrace-relibc/{}/traceme", pid)).unwrap()),
fcntl::O_PATH,
)
.is_ok()
@@ -74,19 +74,19 @@ pub fn get_session(
Ok(entry.insert(Session {
first: true,
tracer: File::open(
&CString::new(format!("proc:{}/trace", pid)).unwrap(),
CStr::borrow(&CString::new(format!("proc:{}/trace", pid)).unwrap()),
NEW_FLAGS,
)?,
mem: File::open(
&CString::new(format!("proc:{}/mem", pid)).unwrap(),
CStr::borrow(&CString::new(format!("proc:{}/mem", pid)).unwrap()),
NEW_FLAGS,
)?,
regs: File::open(
&CString::new(format!("proc:{}/regs/int", pid)).unwrap(),
CStr::borrow(&CString::new(format!("proc:{}/regs/int", pid)).unwrap()),
NEW_FLAGS,
)?,
fpregs: File::open(
&CString::new(format!("proc:{}/regs/float", pid)).unwrap(),
CStr::borrow(&CString::new(format!("proc:{}/regs/float", pid)).unwrap()),
NEW_FLAGS,
)?,
}))
@@ -136,7 +136,7 @@ fn inner_ptrace(
// Mark this child as traced, parent will check for this marker file
let pid = Sys::getpid();
mem::forget(File::open(
&CString::new(format!("chan:ptrace-relibc/{}/traceme", pid)).unwrap(),
CStr::borrow(&CString::new(format!("chan:ptrace-relibc/{}/traceme", pid)).unwrap()),
fcntl::O_CREAT | fcntl::O_PATH | fcntl::O_EXCL,
)?);
return Ok(0);
+1 -2
View File
@@ -9,6 +9,5 @@ license = "MIT"
[dependencies]
redox_syscall = "0.4"
# TODO: Update
goblin = { version = "0.0.21", default-features = false, features = ["elf32", "elf64", "endian_fd"] }
goblin = { version = "0.7", default-features = false, features = ["elf32", "elf64", "endian_fd"] }
plain = "0.2"
+5 -4
View File
@@ -119,10 +119,11 @@ extern "C" fn init_array() {
}
fn io_init() {
unsafe {
// Initialize stdin/stdout/stderr, see https://github.com/rust-lang/rust/issues/51718
stdio::stdin = stdio::default_stdin.get();
stdio::stdout = stdio::default_stdout.get();
stdio::stderr = stdio::default_stderr.get();
// Initialize stdin/stdout/stderr.
// TODO: const fn initialization of FILE
stdio::stdin = stdio::default_stdin().get();
stdio::stdout = stdio::default_stdout().get();
stdio::stderr = stdio::default_stderr().get();
}
}