Large reorganization of headers (WIP)

This commit is contained in:
Jeremy Soller
2018-08-26 08:11:35 -06:00
parent ff32c8cbbd
commit c20ce5ffed
261 changed files with 236 additions and 1672 deletions
+7
View File
@@ -0,0 +1,7 @@
sys_includes = []
include_guard = "_TEMPLATE_H"
language = "C"
style = "Tag"
[enum]
prefix_with_name = true
+14
View File
@@ -0,0 +1,14 @@
//! template implementation for Redox, following http://pubs.opengroup.org/onlinepubs/7908799/xsh/template.h.html
#![no_std]
extern crate platform;
use platform::types::*;
/*
#[no_mangle]
pub extern "C" fn func(args) -> c_int {
unimplemented!();
}
*/
+57
View File
@@ -0,0 +1,57 @@
pub struct aiocb {
pub aio_fildes: libc::c_int,
pub aio_lio_opcode: libc::c_int,
pub aio_reqprio: libc::c_int,
pub aio_buf: *mut libc::c_void,
pub aio_nbytes: usize,
pub aio_sigevent: sigevent,
}
// #[no_mangle]
pub extern "C" fn aio_read(aiocbp: *mut aiocb) -> libc::c_int {
unimplemented!();
}
// #[no_mangle]
pub extern "C" fn aio_write(aiocbp: *mut aiocb) -> libc::c_int {
unimplemented!();
}
// #[no_mangle]
pub extern "C" fn lio_listio(
mode: libc::c_int,
list: *const *const aiocb,
nent: libc::c_int,
sig: *mut sigevent,
) -> libc::c_int {
unimplemented!();
}
// #[no_mangle]
pub extern "C" fn aio_error(aiocbp: *const aiocb) -> libc::c_int {
unimplemented!();
}
// #[no_mangle]
pub extern "C" fn aio_return(aiocbp: *mut aiocb) -> usize {
unimplemented!();
}
// #[no_mangle]
pub extern "C" fn aio_cancel(fildes: libc::c_int, aiocbp: *mut aiocb) -> libc::c_int {
unimplemented!();
}
// #[no_mangle]
pub extern "C" fn aio_suspend(
list: *const *const aiocb,
nent: libc::c_int,
timeout: *const timespec,
) -> libc::c_int {
unimplemented!();
}
// #[no_mangle]
pub extern "C" fn aio_fsync(operation: libc::c_int, aiocbp: *mut aiocb) -> libc::c_int {
unimplemented!();
}
+22
View File
@@ -0,0 +1,22 @@
// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use alloc::String;
use alloc::Vec;
#[derive(Clone, Debug)]
pub struct DnsAnswer {
pub name: String,
pub a_type: u16,
pub a_class: u16,
pub ttl_a: u16,
pub ttl_b: u16,
pub data: Vec<u8>
}
+210
View File
@@ -0,0 +1,210 @@
// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
pub use self::answer::DnsAnswer;
pub use self::query::DnsQuery;
use core::slice;
use core::u16;
use alloc::String;
use alloc::Vec;
mod answer;
mod query;
#[allow(non_camel_case_types)]
#[derive(Copy, Clone, Debug, Default)]
#[repr(packed)]
pub struct n16 {
inner: u16
}
impl n16 {
pub fn as_bytes(&self) -> &[u8] {
unsafe { slice::from_raw_parts((&self.inner as *const u16) as *const u8, 2) }
}
pub fn from_bytes(bytes: &[u8]) -> Self {
n16 {
inner: unsafe { slice::from_raw_parts(bytes.as_ptr() as *const u16, bytes.len()/2)[0] }
}
}
}
impl From<u16> for n16 {
fn from(value: u16) -> Self {
n16 {
inner: value.to_be()
}
}
}
impl From<n16> for u16 {
fn from(value: n16) -> Self {
u16::from_be(value.inner)
}
}
#[derive(Clone, Debug)]
pub struct Dns {
pub transaction_id: u16,
pub flags: u16,
pub queries: Vec<DnsQuery>,
pub answers: Vec<DnsAnswer>
}
impl Dns {
pub fn compile(&self) -> Vec<u8> {
let mut data = Vec::new();
macro_rules! push_u8 {
($value:expr) => {
data.push($value);
};
};
macro_rules! push_n16 {
($value:expr) => {
data.extend_from_slice(n16::from($value).as_bytes());
};
};
push_n16!(self.transaction_id);
push_n16!(self.flags);
push_n16!(self.queries.len() as u16);
push_n16!(self.answers.len() as u16);
push_n16!(0);
push_n16!(0);
for query in self.queries.iter() {
for part in query.name.split('.') {
push_u8!(part.len() as u8);
data.extend_from_slice(part.as_bytes());
}
push_u8!(0);
push_n16!(query.q_type);
push_n16!(query.q_class);
}
data
}
pub fn parse(data: &[u8]) -> Result<Self, String> {
let name_ind = 0b11000000;
let mut i = 0;
macro_rules! pop_u8 {
() => {
{
i += 1;
if i > data.len() {
return Err(format!("{}: {}: pop_u8", file!(), line!()));
}
data[i - 1]
}
};
};
macro_rules! pop_n16 {
() => {
{
i += 2;
if i > data.len() {
return Err(format!("{}: {}: pop_n16", file!(), line!()));
}
u16::from(n16::from_bytes(&data[i - 2 .. i]))
}
};
};
macro_rules! pop_data {
() => {
{
let mut data = Vec::new();
let data_len = pop_n16!();
for _data_i in 0..data_len {
data.push(pop_u8!());
}
data
}
};
};
macro_rules! pop_name {
() => {
{
let mut name = String::new();
let old_i = i;
loop {
let name_len = pop_u8!();
if name_len & name_ind == name_ind {
i -= 1;
i = (pop_n16!() - ((name_ind as u16) << 8)) as usize;
continue;
}
if name_len == 0 {
break;
}
if ! name.is_empty() {
name.push('.');
}
for _name_i in 0..name_len {
name.push(pop_u8!() as char);
}
}
if i <= old_i {
i = old_i + 2;
}
name
}
};
};
let transaction_id = pop_n16!();
let flags = pop_n16!();
let queries_len = pop_n16!();
let answers_len = pop_n16!();
pop_n16!();
pop_n16!();
let mut queries = Vec::new();
for _query_i in 0..queries_len {
queries.push(DnsQuery {
name: pop_name!(),
q_type: pop_n16!(),
q_class: pop_n16!()
});
}
let mut answers = Vec::new();
for _answer_i in 0..answers_len {
answers.push(DnsAnswer {
name: pop_name!(),
a_type: pop_n16!(),
a_class: pop_n16!(),
ttl_a: pop_n16!(),
ttl_b: pop_n16!(),
data: pop_data!()
});
}
Ok(Dns {
transaction_id: transaction_id,
flags: flags,
queries: queries,
answers: answers,
})
}
}
+18
View File
@@ -0,0 +1,18 @@
// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use alloc::String;
#[derive(Clone, Debug)]
pub struct DnsQuery {
pub name: String,
pub q_type: u16,
pub q_class: u16
}
+51
View File
@@ -0,0 +1,51 @@
use core::slice;
use libc::{c_int, c_uint};
use syscall::error::{Error, EINVAL};
use types::{fd_set, pollfd, timeval, FD_SETSIZE, POLLIN, POLLOUT, NFDBITS};
libc_fn!(unsafe poll(fds: *mut pollfd, nfds: c_uint, timeout: c_int) -> Result<c_int> {
let fds = slice::from_raw_parts_mut(fds, nfds as usize);
let mut ret = 0;
for fd in fds.iter_mut() {
// always ready for read or write
fd.revents = fd.events & (POLLIN | POLLOUT);
if fd.revents != 0 {
ret += 1;
}
}
Ok(ret)
});
libc_fn!(unsafe select(nfds: c_int, readfds: *mut fd_set, writefds: *mut fd_set, errorfds: *mut fd_set, _timeout: *mut timeval) -> Result<c_int> {
if nfds < 0 || nfds > FD_SETSIZE as i32 {
return Err(Error::new(EINVAL));
}
let mut ret = 0;
for i in 0..nfds as usize {
if ! readfds.is_null() {
// always ready to read
if ((*readfds).fds_bits[i/NFDBITS] & (1 << (i % NFDBITS))) != 0 {
ret += 1;
}
}
if ! writefds.is_null() {
// always ready to write
if ((*writefds).fds_bits[i/NFDBITS] & (1 << (i % NFDBITS))) != 0 {
ret += 1;
}
}
if ! errorfds.is_null() {
// report no errors
if ((*errorfds).fds_bits[i/NFDBITS] & (1 << (i % NFDBITS))) != 0 {
(*errorfds).fds_bits[i/NFDBITS] &= !(1 << (i % NFDBITS));
}
}
}
Ok(ret)
});
+188
View File
@@ -0,0 +1,188 @@
use syscall::{self, O_CLOEXEC, O_STAT, O_CREAT, O_EXCL, O_DIRECTORY, O_WRONLY, O_NOFOLLOW, TimeSpec};
use core::slice;
use libc::{c_int, c_char, off_t, mode_t, size_t, ssize_t};
use ::types::{utimbuf, timeval};
pub const PATH_MAX: usize = 4096;
libc_fn!(unsafe access(path: *mut c_char, _amode: c_int) -> Result<c_int> {
// XXX amode
::RawFile::open(::cstr_to_slice(path), O_CLOEXEC | O_STAT)?;
Ok(0)
});
libc_fn!(unsafe _close(file: c_int) -> Result<c_int> {
Ok(syscall::close(file as usize)? as c_int)
});
libc_fn!(unsafe dup(file: c_int) -> Result<c_int> {
Ok(syscall::dup(file as usize, &[])? as c_int)
});
libc_fn!(unsafe dup2(file: c_int, newfile: c_int) -> Result<c_int> {
Ok(syscall::dup2(file as usize, newfile as usize, &[])? as c_int)
});
libc_fn!(unsafe _fstat(file: c_int, st: *mut syscall::Stat) -> Result<c_int> {
Ok(syscall::fstat(file as usize, &mut *st)? as c_int)
});
libc_fn!(unsafe _fsync(file: c_int) -> Result<c_int> {
Ok(syscall::fsync(file as usize)? as c_int)
});
libc_fn!(unsafe ftruncate(file: c_int, len: off_t) -> Result<c_int> {
Ok(syscall::ftruncate(file as usize, len as usize)? as c_int)
});
libc_fn!(unsafe _lseek(file: c_int, ptr: off_t, dir: c_int) -> Result<off_t> {
Ok(syscall::lseek(file as usize, ptr as isize, dir as usize)? as off_t)
});
libc_fn!(unsafe mkdir(path: *mut c_char, mode: mode_t) -> Result<c_int> {
let flags = O_CREAT | O_EXCL | O_CLOEXEC | O_DIRECTORY | (mode as usize & 0o777);
::RawFile::open(::cstr_to_slice(path), flags)?;
Ok(0)
});
libc_fn!(unsafe _open(path: *mut c_char, flags: c_int, mode: mode_t) -> Result<c_int> {
let mut path = ::cstr_to_slice(path);
// XXX hack; use better method if possible
if path == b"/dev/null" {
path = b"null:"
}
Ok(syscall::open(path, flags as usize | (mode as usize & 0o777))? as c_int)
});
libc_fn!(unsafe pipe(pipefd: *mut [c_int; 2]) -> c_int {
pipe2(pipefd, 0)
});
libc_fn!(unsafe pipe2(pipefd: *mut [c_int; 2], flags: c_int) -> Result<c_int> {
let mut syspipefd = [(*pipefd)[0] as usize, (*pipefd)[1] as usize];
syscall::pipe2(&mut syspipefd, flags as usize)?;
(*pipefd)[0] = syspipefd[0] as c_int;
(*pipefd)[1] = syspipefd[1] as c_int;
Ok(0)
});
libc_fn!(unsafe _read(file: c_int, buf: *mut c_char, len: c_int) -> Result<c_int> {
let buf = slice::from_raw_parts_mut(buf as *mut u8, len as usize);
Ok(syscall::read(file as usize, buf)? as c_int)
});
libc_fn!(unsafe rmdir(path: *mut c_char) -> Result<c_int> {
Ok(syscall::rmdir(::cstr_to_slice(path))? as c_int)
});
libc_fn!(unsafe _stat(path: *const c_char, st: *mut syscall::Stat) -> Result<c_int> {
let fd = ::RawFile::open(::cstr_to_slice(path), O_CLOEXEC | O_STAT)?;
Ok(syscall::fstat(*fd, &mut *st)? as c_int)
});
libc_fn!(unsafe lstat(path: *const c_char, st: *mut syscall::Stat) -> Result<c_int> {
let fd = ::RawFile::open(::cstr_to_slice(path), O_CLOEXEC | O_STAT | O_NOFOLLOW)?;
Ok(syscall::fstat(*fd, &mut *st)? as c_int)
});
libc_fn!(unsafe _unlink(path: *mut c_char) -> Result<c_int> {
Ok(syscall::unlink(::cstr_to_slice(path))? as c_int)
});
libc_fn!(unsafe _write(file: c_int, buf: *const c_char, len: c_int) -> Result<c_int> {
let buf = slice::from_raw_parts(buf as *const u8, len as usize);
Ok(syscall::write(file as usize, buf)? as c_int)
});
libc_fn!(unsafe chmod(path: *mut c_char, mode: mode_t) -> Result<c_int> {
Ok(syscall::chmod(::cstr_to_slice(path), mode as usize)? as c_int)
});
libc_fn!(unsafe realpath(path: *const c_char, resolved_path: *mut c_char) -> Result<*mut c_char> {
let fd = ::RawFile::open(::cstr_to_slice(path), O_STAT)?;
let resolved_path = ::MallocNull::new(resolved_path, PATH_MAX);
let buf = slice::from_raw_parts_mut(resolved_path.as_mut_ptr() as *mut u8, PATH_MAX-1);
let length = syscall::fpath(*fd, buf)?;
buf[length] = b'\0';
Ok(resolved_path.into_raw())
});
libc_fn!(unsafe _rename(old: *const c_char, new: *const c_char) -> Result<c_int> {
// XXX fix this horror when the kernel provides rename() or link()
let old = ::cstr_to_slice(old);
let new = ::cstr_to_slice(new);
let buf = ::file_read_all(old)?;
let mut stat = syscall::Stat::default();
let fd = ::RawFile::open(old, syscall::O_STAT)?;
syscall::fstat(*fd, &mut stat)?;
drop(fd);
let mode = (stat.st_mode & 0o777) as usize;
let fd = ::RawFile::open(new, O_CREAT | O_WRONLY | mode)?;
syscall::write(*fd, &buf)?;
syscall::unlink(old)?;
Ok(0)
});
libc_fn!(fsync(fd: c_int) -> Result<c_int> {
Ok(syscall::fsync(fd as usize)? as c_int)
});
libc_fn!(unsafe symlink(path1: *const c_char, path2: *const c_char) -> Result<c_int> {
let fd = ::RawFile::open(::cstr_to_slice(path2), syscall::O_SYMLINK | syscall::O_CREAT | syscall::O_WRONLY | 0o777)?;
syscall::write(*fd, ::cstr_to_slice(path1))?;
Ok(0)
});
libc_fn!(unsafe readlink(path: *const c_char, buf: *const c_char, bufsize: size_t) -> Result<ssize_t> {
let fd = ::RawFile::open(::cstr_to_slice(path), syscall::O_SYMLINK | syscall::O_RDONLY)?;
let count = syscall::read(*fd, slice::from_raw_parts_mut(buf as *mut u8, bufsize))?;
Ok(count as ssize_t)
});
libc_fn!(unsafe utime(path: *mut c_char, times: *const utimbuf) -> Result<c_int> {
let times = if times.is_null() {
let mut tp = TimeSpec::default();
syscall::clock_gettime(syscall::flag::CLOCK_REALTIME, &mut tp)?;
[tp, tp]
} else {
[TimeSpec { tv_sec: (*times).actime, tv_nsec: 0 },
TimeSpec { tv_sec: (*times).modtime, tv_nsec: 0 }]
};
let fd = ::RawFile::open(::cstr_to_slice(path), 0)?;
syscall::futimens(*fd, &times)?;
Ok(0)
});
libc_fn!(unsafe utimes(path: *mut c_char, times: *const [timeval; 2]) -> Result<c_int> {
let times = [TimeSpec { tv_sec: (*times)[0].tv_sec, tv_nsec: (*times)[0].tv_usec as i32 * 1000 },
TimeSpec { tv_sec: (*times)[1].tv_sec, tv_nsec: (*times)[0].tv_usec as i32 * 1000 }];
let fd = ::RawFile::open(::cstr_to_slice(path), 0)?;
syscall::futimens(*fd, &times)?;
Ok(0)
});
libc_fn!(unsafe futimens(fd: c_int, times: *const [TimeSpec; 2]) -> Result<c_int> {
// XXX UTIME_NOW and UTIME_OMIT (in redoxfs?)
syscall::futimens(fd as usize, &*times)?;
Ok(0)
});
// XXX variadic
libc_fn!(_fcntl(file: c_int, cmd: c_int, arg: c_int) -> Result<c_int> {
Ok(syscall::fcntl(file as usize, cmd as usize, arg as usize)? as c_int)
});
libc_fn!(_isatty(file: c_int) -> c_int {
if let Ok(fd) = syscall::dup(file as usize, b"termios") {
let _ = syscall::close(fd);
1
} else {
0
}
});
+94
View File
@@ -0,0 +1,94 @@
extern crate libc;
extern crate core;
use ::{c_int, c_char};
use syscall::{self, O_CLOEXEC, O_RDONLY, O_DIRECTORY};
use core::ptr::null;
use core::default::Default;
use alloc::boxed::Box;
use ::file::PATH_MAX;
use ::types::{ino_t, off_t};
use libc::*;
#[repr(C)]
pub struct dirent {
pub d_ino: ino_t,
pub d_off: off_t,
pub d_reclen: c_ushort,
pub d_type: c_uchar,
pub d_name: [c_char; PATH_MAX]
}
impl core::default::Default for dirent {
fn default() -> dirent {
dirent {
d_ino: 0,
d_off: 0,
d_reclen: 0,
d_type: 0,
d_name: [0; PATH_MAX],
}
}
}
pub struct DIR {
pub fd: ::RawFile,
pub ent: dirent,
pub buf: [u8; PATH_MAX],
pub count: usize,
pub pos: usize
}
libc_fn!(unsafe opendir(path: *mut c_char) -> Result<*mut DIR> {
let path = ::cstr_to_slice(path);
let fd = ::RawFile::open(path, O_RDONLY | O_CLOEXEC | O_DIRECTORY)?;
let dir = Box::new(DIR {
fd,
ent: dirent::default(),
buf: [0; PATH_MAX],
count: 0,
pos: 0
});
Ok(Box::into_raw(dir))
});
libc_fn!(unsafe readdir(dir: *mut DIR) -> Result<*const dirent> {
if let Some(dir) = dir.as_mut() {
let mut i = 0;
'outer: while i < PATH_MAX - 1 {
while dir.pos < dir.count {
dir.ent.d_name[i] = dir.buf[dir.pos] as c_char;
dir.pos += 1;
if dir.buf[dir.pos-1] == b'\n' {
break 'outer;
}
i += 1;
}
dir.count = syscall::read(*dir.fd, &mut dir.buf)?;
if dir.count == 0 {
break;
}
dir.pos = 0;
}
if i != 0 {
dir.ent.d_name[i] = 0;
return Ok(&dir.ent);
}
}
Ok(null())
});
libc_fn!(unsafe rewinddir(dir: *mut DIR) {
if let Some(dir) = dir.as_mut() {
dir.count = 0;
let _ = syscall::lseek(*dir.fd, 0, syscall::SEEK_SET);
}
});
libc_fn!(unsafe closedir(dir: *mut DIR) -> Result<c_int> {
Box::from_raw(dir);
Ok(0)
});
libc_fn!(unsafe dirfd(dir: *mut DIR) -> Result<c_int> {
Ok(*(*dir).fd as i32)
});
+107
View File
@@ -0,0 +1,107 @@
use core::ptr::null;
use core::{mem, str, slice};
use alloc::vec::IntoIter;
use alloc::string::ToString;
use alloc::{Vec, String};
use ::dns::{Dns, DnsQuery};
use syscall::{self, Result, EINVAL, Error};
use libc::{c_char, size_t, c_int};
use ::types::{in_addr, hostent};
static mut HOST_ENTRY: hostent = hostent { h_name: null(), h_aliases: null(), h_addrtype: 0, h_length: 0, h_addr_list: null() };
static mut HOST_NAME: Option<Vec<u8>> = None;
static mut HOST_ALIASES: [*const c_char; 1] = [null()];
static mut HOST_ADDR: Option<in_addr> = None;
static mut HOST_ADDR_LIST: [*const c_char; 2] = [null(); 2];
struct LookupHost(IntoIter<in_addr>);
impl Iterator for LookupHost {
type Item = in_addr;
fn next(&mut self) -> Option<Self::Item> {
self.0.next()
}
}
// Modified from rust/sys/redox/net/mod.rs
fn lookup_host(host: &str) -> Result<LookupHost> {
// XXX better error handling
let ip_string = String::from_utf8(::file_read_all("/etc/net/ip")?)
.or(Err(Error::new(syscall::EIO)))?;
let ip: Vec<u8> = ip_string.trim().split(".").map(|part| part.parse::<u8>()
.unwrap_or(0)).collect();
let dns_string = String::from_utf8(::file_read_all("/etc/net/dns")?)
.or(Err(Error::new(syscall::EIO)))?;
let dns: Vec<u8> = dns_string.trim().split(".").map(|part| part.parse::<u8>()
.unwrap_or(0)).collect();
if ip.len() == 4 && dns.len() == 4 {
let mut timespec = syscall::TimeSpec::default();
syscall::clock_gettime(syscall::CLOCK_REALTIME, &mut timespec).unwrap();
let tid = (timespec.tv_nsec >> 16) as u16;
let packet = Dns {
transaction_id: tid,
flags: 0x0100,
queries: vec![DnsQuery {
name: host.to_string(),
q_type: 0x0001,
q_class: 0x0001,
}],
answers: vec![]
};
let packet_data = packet.compile();
let fd = ::RawFile::open(format!("udp:/{}.{}.{}.{}:0",
ip[0], ip[1], ip[2], ip[3]).as_bytes(),
syscall::O_RDWR)?;
let timeout = syscall::TimeSpec {
tv_sec: 5,
tv_nsec: 0,
};
let rt = fd.dup(b"read_timeout")?;
syscall::write(*rt, &timeout)?;
drop(rt);
let wt = fd.dup(b"write_timeout")?;
syscall::write(*wt, &timeout)?;
drop(wt);
let sendrecvfd = fd.dup(format!("{}.{}.{}.{}:53", dns[0], dns[1], dns[2], dns[3]).as_bytes())?;
syscall::write(*sendrecvfd, &packet_data)?;
let mut buf = [0; 65536];
let count = syscall::read(*sendrecvfd, &mut buf)?;
drop(sendrecvfd);
drop(fd);
match Dns::parse(&buf[.. count]) {
Ok(response) => {
let mut addrs = vec![];
for answer in response.answers.iter() {
if answer.a_type == 0x0001 && answer.a_class == 0x0001
&& answer.data.len() == 4
{
let addr = in_addr {
s_addr: [answer.data[0], answer.data[1], answer.data[2], answer.data[3]]
};
addrs.push(addr);
}
}
Ok(LookupHost(addrs.into_iter()))
},
Err(_err) => Err(Error::new(EINVAL))
}
} else {
Err(Error::new(EINVAL))
}
}
libc_fn!(unsafe gethostname(name: *mut c_char, namelen: size_t) -> Result<c_int> {
let slice = slice::from_raw_parts_mut(name as *mut u8, namelen);
let fd = ::RawFile::open("/etc/hostname", syscall::O_RDONLY)?;
let len = syscall::read(*fd, &mut slice[..namelen-1])?;
slice[len] = b'\0';
Ok(0)
});
+211
View File
@@ -0,0 +1,211 @@
#![no_std]
#![feature(
alloc,
allocator_api,
alloc_system,
compiler_builtins_lib,
const_fn,
const_ptr_null,
core_intrinsics,
global_allocator,
lang_items,
linkage,
const_size_of,
const_cell_new,
)]
#[macro_use]
extern crate alloc;
extern crate alloc_system;
extern crate byteorder;
extern crate compiler_builtins;
extern crate libc;
extern crate syscall;
extern crate redox_termios;
use alloc::Vec;
use alloc::String;
use alloc::fmt::Write;
use alloc::boxed::Box;
use core::{ptr, mem, intrinsics, slice, str};
use libc::{c_int, c_void, c_char, size_t};
#[macro_use]
mod macros;
mod types;
mod dns;
mod mallocnull;
mod rawfile;
pub mod event;
pub mod process;
pub mod file;
pub mod folder;
pub mod time;
pub mod unimpl;
pub mod user;
pub mod redox;
pub mod socket;
pub mod hostname;
pub mod termios;
pub mod netdb;
pub use mallocnull::MallocNull;
pub use rawfile::RawFile;
#[global_allocator]
static ALLOCATOR: alloc_system::System = alloc_system::System;
extern "C" {
// Newlib uses this function instead of just a global to support reentrancy
pub fn __errno() -> *mut c_int;
pub fn malloc(size: size_t) -> *mut c_void;
pub fn free(ptr: *mut c_void);
pub fn strlen(s: *const c_char) -> size_t;
pub fn __libc_fini_array();
pub static mut environ: *mut *mut c_char;
}
pub unsafe fn cstr_to_slice<'a>(buf: *const c_char) -> &'a [u8] {
slice::from_raw_parts(buf as *const u8, ::strlen(buf) as usize)
}
pub unsafe fn cstr_to_slice_mut<'a>(buf: *const c_char) -> &'a mut [u8] {
slice::from_raw_parts_mut(buf as *mut u8, ::strlen(buf) as usize)
}
pub fn file_read_all<T: AsRef<[u8]>>(path: T) -> syscall::Result<Vec<u8>> {
let fd = RawFile::open(path, syscall::O_RDONLY)?;
let mut st = syscall::Stat::default();
syscall::fstat(*fd, &mut st)?;
let size = st.st_size as usize;
let mut buf = Vec::with_capacity(size);
unsafe { buf.set_len(size) };
syscall::read(*fd, buf.as_mut_slice())?;
Ok(buf)
}
/// Implements an `Iterator` which returns on either newline or EOF.
#[derive(Clone, Copy)]
pub struct RawLineBuffer {
fd: usize,
cur: usize,
read: usize,
buf: [u8; 8 * 1024],
}
impl Default for RawLineBuffer {
fn default() -> RawLineBuffer {
RawLineBuffer {
fd: 0,
cur: 0,
read: 0,
buf: unsafe { mem::uninitialized() },
}
}
}
impl RawLineBuffer {
fn new(fd: usize) -> RawLineBuffer {
RawLineBuffer {
fd: fd,
cur: 0,
read: 0,
buf: unsafe { mem::uninitialized() },
}
}
}
impl Iterator for RawLineBuffer {
type Item = syscall::Result<Box<str>>;
fn next(&mut self) -> Option<Self::Item> {
if self.cur != 0 && self.read != 0 {
if let Some(mut pos) = self.buf[self.cur..self.read].iter().position(
|&x| x == b'\n',
)
{
pos += self.cur + 1;
let line = unsafe { str::from_utf8_unchecked(&self.buf[self.cur..pos]) };
let boxed_array: Box<[u8]> = Box::from(line.as_bytes());
let boxed_line: Box<str> = unsafe { mem::transmute(boxed_array) };
self.cur = pos;
return Some(Ok(boxed_line));
}
let mut temp: [u8; 8 * 1024] = unsafe { mem::uninitialized() };
unsafe {
ptr::copy(self.buf[self.cur..].as_ptr(), temp.as_mut_ptr(), self.read);
ptr::swap(self.buf.as_mut_ptr(), temp.as_mut_ptr());
};
self.read -= self.cur;
self.cur = 0;
}
let end = match syscall::read(self.fd, &mut self.buf[self.cur..]).unwrap() {
0 => return None,
read => {
self.read += read;
self.buf[..self.read]
.iter()
.position(|&x| x == b'\n')
.unwrap_or(0)
}
};
self.cur = end;
let line = unsafe { str::from_utf8_unchecked(&self.buf[..end]) };
let boxed_array: Box<[u8]> = Box::from(line.as_bytes());
let boxed_line: Box<str> = unsafe { mem::transmute(boxed_array) };
Some(Ok(boxed_line))
}
}
#[no_mangle]
pub unsafe extern "C" fn __errno_location() -> *mut c_int {
__errno()
}
#[lang = "eh_personality"]
pub extern "C" fn eh_personality() {}
#[lang = "panic_fmt"]
#[linkage = "weak"]
#[no_mangle]
pub extern "C" fn rust_begin_unwind(_msg: core::fmt::Arguments,
_file: &'static str,
_line: u32,
_col: u32) -> ! {
let mut s = String::new();
let _ = s.write_fmt(_msg);
let _ = syscall::write(2, _file.as_bytes());
let _ = syscall::write(2, "\n".as_bytes());
let _ = syscall::write(2, s.as_bytes());
let _ = syscall::write(2, "\n".as_bytes());
unsafe { intrinsics::abort() }
}
libc_fn!(unsafe initialize_standard_library() {
let mut buf = file_read_all("env:").unwrap();
let size = buf.len();
buf.push(0);
let mut vars = Vec::new();
vars.push(&mut buf[0] as *mut u8 as *mut c_char);
for i in 0..size {
if buf[i] == b'\n' {
if i != size - 1 {
vars.push(&mut buf[i + 1] as *mut u8 as *mut c_char);
}
buf[i] = b'\0';
}
}
vars.push(ptr::null_mut());
environ = vars.as_mut_ptr();
mem::forget(vars); // Do not free memory
mem::forget(buf);
});
+120
View File
@@ -0,0 +1,120 @@
use core::ptr;
use core::any::Any;
/// This struct converts to `NULL` for raw pointers, and `-1` for signed
/// integers.
pub struct Fail;
impl<T: Any> Into<*const T> for Fail {
#[inline(always)]
fn into(self) -> *const T {
ptr::null()
}
}
impl<T: Any> Into<*mut T> for Fail {
#[inline(always)]
fn into(self) -> *mut T {
ptr::null_mut()
}
}
macro_rules! int_fail {
($type:ty) => (
impl Into<$type> for Fail {
#[inline(always)]
fn into(self) -> $type {
-1
}
}
)
}
int_fail!(i8);
int_fail!(i16);
int_fail!(i32);
int_fail!(i64);
int_fail!(isize);
/// If `res` is `Err(..)`, set `errno` and return `-1` or `NULL`, otherwise
/// unwrap.
macro_rules! try_call {
($res:expr) => (
match $res {
Ok(val) => val,
Err(err) => {
*::__errno() = err.errno;
return ::macros::Fail.into();
}
}
);
}
/// Declares a libc function. The body should return syscall::Result, which
/// is used to set errno on error with try_call!
///
/// ```
/// libc_fn!(foo(arg: c_int) -> c_int) {
/// Ok(arg)
/// }
/// ```
///
/// The `unsafe` keyword can be added to make the function unsafe:
///
/// ```
/// libc_fn!(unsafe foo(arg: c_int) -> c_int) {
/// Ok(arg)
/// }
/// ```
macro_rules! libc_fn {
// The next 2 cases handle Result return values, and convert to errno+return
// Call with arguments and return value
($name:ident($($aname:ident : $atype:ty),*) -> Result<$rtype:ty> $content:block) => {
#[no_mangle]
pub extern "C" fn $name($($aname: $atype,)*) -> $rtype {
#[inline(always)]
fn inner($($aname: $atype,)*) -> ::syscall::Result<$rtype> {
$content
}
unsafe { try_call!(inner($($aname,)*)) }
}
};
// Call with `unsafe` keyword (and arguments, return value)
(unsafe $name:ident($($aname:ident : $atype:ty),*) -> Result<$rtype:ty> $content:block) => {
#[no_mangle]
pub unsafe extern "C" fn $name($($aname: $atype,)*) -> $rtype {
#[inline(always)]
unsafe fn inner($($aname: $atype,)*) -> ::syscall::Result<$rtype> {
$content
}
try_call!(inner($($aname,)*))
}
};
// The next 2 cases handle non-Result return values
($name:ident($($aname:ident : $atype:ty),*) -> $rtype:ty $content:block) => {
#[no_mangle]
pub extern "C" fn $name($($aname: $atype,)*) -> $rtype {
$content
}
};
(unsafe $name:ident($($aname:ident : $atype:ty),*) -> $rtype:ty $content:block) => {
#[no_mangle]
pub unsafe extern "C" fn $name($($aname: $atype,)*) -> $rtype {
$content
}
};
// The next 2 cases handle calls with no return value
($name:ident($($aname:ident : $atype:ty),*) $content:block) => {
#[no_mangle]
pub extern "C" fn $name($($aname: $atype,)*) {
$content
}
};
(unsafe $name:ident($($aname:ident : $atype:ty),*) $content:block) => {
#[no_mangle]
pub unsafe extern "C" fn $name($($aname: $atype,)*) {
$content
}
};
}
+46
View File
@@ -0,0 +1,46 @@
use core::mem;
use libc::{c_void, size_t};
/// Malloc memory if pointer is null, and free on drop
pub struct MallocNull<T> {
value: *mut T,
free_on_drop: bool
}
impl<T> MallocNull<T> {
pub fn new(ptr: *mut T, size: usize) -> MallocNull<T> {
if ptr.is_null() {
MallocNull {
value: unsafe { ::malloc(size as size_t) as *mut T },
free_on_drop: true
}
} else {
MallocNull {
value: ptr,
free_on_drop: false
}
}
}
pub fn into_raw(self) -> *mut T {
let ptr = self.value;
mem::forget(self);
ptr
}
pub fn as_ptr(&self) -> *const T {
self.value
}
pub fn as_mut_ptr(&self) -> *mut T {
self.value
}
}
impl<T> Drop for MallocNull<T> {
fn drop(&mut self) {
if self.free_on_drop {
unsafe { ::free(self.value as *mut c_void) };
}
}
}
+727
View File
@@ -0,0 +1,727 @@
use libc;
use types::{in_addr, sockaddr, socklen_t};
use RawLineBuffer;
use core::ptr::null;
use core::{mem, str};
use alloc::vec::IntoIter;
use alloc::string::ToString;
use alloc::{Vec, String};
use alloc::str::SplitWhitespace;
use alloc::boxed::Box;
use dns::{Dns, DnsQuery};
use syscall::{self, Result, EINVAL, Error};
use libc::c_char;
const MAXADDRS: usize = 35;
const MAXALIASES: usize = 35;
struct LookupHost(IntoIter<in_addr>);
impl Iterator for LookupHost {
type Item = in_addr;
fn next(&mut self) -> Option<Self::Item> {
self.0.next()
}
}
#[repr(C)]
pub struct hostent {
h_name: *const libc::c_char,
h_aliases: *const *const libc::c_char,
h_addrtype: libc::c_int,
h_length: libc::c_int,
h_addr_list: *const *const libc::c_char,
}
/*
*#[repr(C)]
*pub struct netent {
* n_name: *const libc::c_char, [> official name of net <]
* n_aliases: *const *const libc::c_char, [> alias list <]
* n_addrtype: libc::c_int, [> net address type <]
* n_net: libc::c_ulong, [> network # <]
*}
*/
#[repr(C)]
pub struct servent {
s_name: *const libc::c_char, /* official service name */
s_aliases: *const *const libc::c_char, /* alias list */
s_port: libc::c_int, /* port # */
s_proto: *const libc::c_char, /* protocol to use */
}
#[repr(C)]
pub struct protoent {
p_name: *const libc::c_char, /* official protocol name */
p_aliases: *const *const libc::c_char, /* alias list */
p_proto: libc::c_int, /* protocol # */
}
#[repr(C)]
pub struct addrinfo {
ai_flags: libc::c_int, /* AI_PASSIVE, AI_CANONNAME, AI_NUMERICHOST */
ai_family: libc::c_int, /* PF_xxx */
ai_socktype: libc::c_int, /* SOCK_xxx */
ai_protocol: libc::c_int, /* 0 or IPPROTO_xxx for IPv4 and IPv6 */
ai_addrlen: libc::size_t, /* length of ai_addr */
ai_canonname: *const libc::c_char, /* canonical name for hostname */
ai_addr: *const sockaddr, /* binary address */
ai_next: *const addrinfo, /* next structure in linked list */
}
static mut HOSTDB: usize = 0;
//static mut NETDB: usize = 0;
static mut PROTODB: usize = 0;
static mut SERVDB: usize = 0;
/*
*static mut NET_ENTRY: netent = netent {
* n_name: 0 as *const libc::c_char,
* n_aliases: 0 as *const *const libc::c_char,
* n_addrtype: 0,
* n_net: 0 as u64,
*};
*static mut NET_NAME: Option<Vec<u8>> = None;
*static mut NET_ALIASES: [*const c_char; MAXALIASES] = [null(); MAXALIASES];
*static mut NET_NUM: Option<u64> = None;
*/
static mut HOST_ENTRY: hostent = hostent {
h_name: 0 as *const libc::c_char,
h_aliases: 0 as *const *const libc::c_char,
h_addrtype: 0,
h_length: 0,
h_addr_list: 0 as *const *const libc::c_char,
};
static mut HOST_NAME: Option<Vec<u8>> = None;
static mut HOST_ALIASES: Option<Vec<Vec<u8>>> = None;
static mut HOST_ADDR: Option<in_addr> = None;
static mut HOST_ADDR_LIST: [*const c_char; 2] = [null(); 2];
static mut H_LINE: RawLineBuffer = RawLineBuffer {
fd: 0,
cur: 0,
read: 0,
buf: [0; 8 * 1024],
};
static mut PROTO_ENTRY: protoent = protoent {
p_name: 0 as *const libc::c_char,
p_aliases: 0 as *const *const libc::c_char,
p_proto: 0 as libc::c_int,
};
static mut PROTO_NAME: Option<Vec<u8>> = None;
static mut PROTO_ALIASES: Option<Vec<Vec<u8>>> = None;
static mut PROTO_NUM: Option<libc::c_int> = None;
static mut P_LINE: RawLineBuffer = RawLineBuffer {
fd: 0,
cur: 0,
read: 0,
buf: [0; 8 * 1024],
};
static mut SERV_ENTRY: servent = servent {
s_name: 0 as *const libc::c_char,
s_aliases: 0 as *const *const libc::c_char,
s_port: 0 as libc::c_int,
s_proto: 0 as *const libc::c_char,
};
static mut SERV_NAME: Option<Vec<u8>> = None;
static mut SERV_ALIASES: Option<Vec<Vec<u8>>> = None;
static mut SERV_PORT: Option<libc::c_int> = None;
static mut SERV_PROTO: Option<Vec<u8>> = None;
static mut S_LINE: RawLineBuffer = RawLineBuffer {
fd: 0,
cur: 0,
read: 0,
buf: [0; 8 * 1024],
};
fn lookup_host(host: &str) -> Result<LookupHost> {
// XXX better error handling
let ip_string = String::from_utf8(::file_read_all("/etc/net/ip")?).or(Err(
Error::new(syscall::EIO),
))?;
let ip: Vec<u8> = ip_string
.trim()
.split(".")
.map(|part| part.parse::<u8>().unwrap_or(0))
.collect();
let dns_string = String::from_utf8(::file_read_all("/etc/net/dns")?).or(Err(
Error::new(syscall::EIO),
))?;
let dns: Vec<u8> = dns_string
.trim()
.split(".")
.map(|part| part.parse::<u8>().unwrap_or(0))
.collect();
if ip.len() == 4 && dns.len() == 4 {
let mut timespec = syscall::TimeSpec::default();
syscall::clock_gettime(syscall::CLOCK_REALTIME, &mut timespec).unwrap();
let tid = (timespec.tv_nsec >> 16) as u16;
let packet = Dns {
transaction_id: tid,
flags: 0x0100,
queries: vec![
DnsQuery {
name: host.to_string(),
q_type: 0x0001,
q_class: 0x0001,
},
],
answers: vec![],
};
let packet_data = packet.compile();
let fd = ::RawFile::open(
format!("udp:/{}.{}.{}.{}:0", ip[0], ip[1], ip[2], ip[3]).as_bytes(),
syscall::O_RDWR,
)?;
let timeout = syscall::TimeSpec {
tv_sec: 5,
tv_nsec: 0,
};
let rt = fd.dup(b"read_timeout")?;
syscall::write(*rt, &timeout)?;
drop(rt);
let wt = fd.dup(b"write_timeout")?;
syscall::write(*wt, &timeout)?;
drop(wt);
let sendrecvfd = fd.dup(
format!("{}.{}.{}.{}:53", dns[0], dns[1], dns[2], dns[3])
.as_bytes(),
)?;
syscall::write(*sendrecvfd, &packet_data)?;
let mut buf = [0; 65536];
let count = syscall::read(*sendrecvfd, &mut buf)?;
drop(sendrecvfd);
drop(fd);
match Dns::parse(&buf[..count]) {
Ok(response) => {
let mut addrs = vec![];
for answer in response.answers.iter() {
if answer.a_type == 0x0001 && answer.a_class == 0x0001 &&
answer.data.len() == 4
{
let addr = in_addr {
s_addr: [
answer.data[0],
answer.data[1],
answer.data[2],
answer.data[3],
],
};
addrs.push(addr);
}
}
Ok(LookupHost(addrs.into_iter()))
}
Err(_err) => Err(Error::new(EINVAL)),
}
} else {
Err(Error::new(EINVAL))
}
}
unsafe fn lookup_addr(addr: in_addr) -> Result<Vec<Vec<u8>>> {
// XXX better error handling
let ip_string = String::from_utf8(::file_read_all("/etc/net/ip")?).or(Err(
Error::new(syscall::EIO),
))?;
let ip: Vec<u8> = ip_string
.trim()
.split(".")
.map(|part| part.parse::<u8>().unwrap_or(0))
.collect();
let dns_string = String::from_utf8(::file_read_all("/etc/net/dns")?).or(Err(
Error::new(syscall::EIO),
))?;
let dns: Vec<u8> = dns_string
.trim()
.split(".")
.map(|part| part.parse::<u8>().unwrap_or(0))
.collect();
let mut addr_vec: Vec<u8> = addr.s_addr.to_vec();
addr_vec.reverse();
let mut name: Vec<u8> = vec![];
for octet in addr_vec {
for ch in format!("{}", octet).as_bytes() {
name.push(*ch);
}
name.push(b"."[0]);
}
name.pop();
for ch in b".IN-ADDR.ARPA" {
name.push(*ch);
}
let _ = syscall::write(2, name.as_slice());
let _ = syscall::write(2, "\n".as_bytes());
if ip.len() == 4 && dns.len() == 4 {
let mut timespec = syscall::TimeSpec::default();
syscall::clock_gettime(syscall::CLOCK_REALTIME, &mut timespec).unwrap();
let tid = (timespec.tv_nsec >> 16) as u16;
let packet = Dns {
transaction_id: tid,
flags: 0x0100,
queries: vec![
DnsQuery {
name: String::from_utf8(name).unwrap(),
q_type: 0x000C,
q_class: 0x0001,
},
],
answers: vec![],
};
let packet_data = packet.compile();
let fd = ::RawFile::open(
format!("udp:/{}.{}.{}.{}:0", ip[0], ip[1], ip[2], ip[3]).as_bytes(),
syscall::O_RDWR,
)?;
let timeout = syscall::TimeSpec {
tv_sec: 5,
tv_nsec: 0,
};
let rt = fd.dup(b"read_timeout")?;
syscall::write(*rt, &timeout)?;
drop(rt);
let wt = fd.dup(b"write_timeout")?;
syscall::write(*wt, &timeout)?;
drop(wt);
let sendrecvfd = fd.dup(
format!("{}.{}.{}.{}:53", dns[0], dns[1], dns[2], dns[3])
.as_bytes(),
)?;
syscall::write(*sendrecvfd, &packet_data)?;
let mut buf = [0; 65536];
let count = syscall::read(*sendrecvfd, &mut buf)?;
drop(sendrecvfd);
drop(fd);
match Dns::parse(&buf[..count]) {
Ok(response) => {
let _ = syscall::write(2, format!("{:?}", response).as_bytes());
let _ = syscall::write(2, "\n".as_bytes());
let mut names = vec![];
for answer in response.answers.iter() {
if answer.a_type == 0x000C && answer.a_class == 0x0001
{
// answer.data is encoded kinda weird.
// Basically length-prefixed strings for each
// subsection of the domain.
// We need to parse this to insert periods where
// they belong (ie at the end of each string)
let data = parse_data(answer.data.clone());
names.push(data);
}
}
Ok(names)
}
Err(_err) => Err(Error::new(EINVAL)),
}
} else {
Err(Error::new(EINVAL))
}
}
fn parse_data(mut data: Vec<u8>) -> Vec<u8> {
let mut cursor = 0;
let mut offset = 0;
let mut index = 0;
let mut output = data.clone();
while index < data.len() - 1 {
offset = data[index] as usize;
index = cursor + offset + 1;
output[index] = '.' as u8;
cursor = index;
}
//we don't want an extra period at the end
output.pop();
return output
}
libc_fn!(unsafe endhostent() {
let _ = syscall::close(HOSTDB);
});
/*
*libc_fn!(unsafe endnetent() {
* let _ = syscall::close(NETDB);
*});
*/
libc_fn!(unsafe endprotoent() {
let _ = syscall::close(PROTODB);
});
libc_fn!(unsafe endservent() {
let _ = syscall::close(SERVDB);
});
libc_fn!(unsafe gethostbyaddr(v: *const libc::c_void, length: socklen_t, format: libc::c_int) -> Result <*const hostent> {
let mut addr: in_addr = *(v as *mut in_addr);
match lookup_addr(addr) {
Ok(s) => {
HOST_ADDR_LIST = [addr.s_addr.as_mut_ptr() as *const c_char, null()];
let host_name = s[0].to_vec();
HOST_ENTRY = hostent {
h_name: host_name.as_ptr() as *const c_char,
h_aliases: [null();2].as_mut_ptr(),
h_addrtype: format,
h_length: length as i32,
h_addr_list: HOST_ADDR_LIST.as_ptr()
};
HOST_NAME = Some(host_name);
return Ok(&HOST_ENTRY)
}
Err(err) => Err(err)
}
});
libc_fn!(unsafe gethostbyname(name: *const c_char) -> Result<*const hostent> {
// XXX h_errno
let mut addr = mem::uninitialized();
let mut host_addr = if ::socket::inet_aton(name, &mut addr) == 1 {
addr
} else {
// XXX
let mut host = lookup_host(str::from_utf8_unchecked(::cstr_to_slice(name)))?;
host.next().ok_or(Error::new(syscall::ENOENT))? // XXX
};
let host_name: Vec<u8> = ::cstr_to_slice(name).to_vec();
HOST_ADDR_LIST = [host_addr.s_addr.as_mut_ptr() as *const c_char, null()];
HOST_ADDR = Some(host_addr);
HOST_ENTRY = hostent {
h_name: host_name.as_ptr() as *const c_char,
h_aliases: [null();2].as_mut_ptr(),
h_addrtype: ::socket::AF_INET,
h_length: 4,
h_addr_list: HOST_ADDR_LIST.as_ptr()
};
HOST_NAME = Some(host_name);
Ok(&HOST_ENTRY as *const hostent)
});
libc_fn!(unsafe gethostent() -> *const hostent {
if HOSTDB == 0 {
HOSTDB = syscall::open("/etc/hosts", syscall::O_RDONLY).unwrap();
H_LINE = RawLineBuffer::new(HOSTDB);
}
let mut r: Box<str> = Box::default();
while r.is_empty() || r.split_whitespace().next() == None || r.starts_with("#") {
r = match H_LINE.next() {
Some(Ok(s)) => s,
Some(Err(_)) => return null(),
None => return null(),
};
}
let mut iter: SplitWhitespace = r.split_whitespace();
let mut addr_vec = iter.next().unwrap().as_bytes().to_vec();
addr_vec.push(b'\0');
let addr_cstr = addr_vec.as_slice().as_ptr() as *const i8;
let mut addr = mem::uninitialized();
::socket::inet_aton(addr_cstr, &mut addr);
HOST_ADDR_LIST = [addr.s_addr.as_mut_ptr() as *const c_char, null()];
HOST_ADDR = Some(addr);
let mut host_name = iter.next().unwrap().as_bytes().to_vec();
host_name.push(b'\0');
let mut host_aliases: Vec<Vec<u8>> = Vec::new();
loop {
let mut alias = match iter.next() {
Some(s) => s.as_bytes().to_vec(),
None => break
};
alias.push(b'\0');
host_aliases.push(alias);
}
//push a 0 so c doesn't segfault when it tries to read the next entry
host_aliases.push(vec![b'\0']);
HOST_ENTRY = hostent {
h_name: host_name.as_ptr() as *const c_char,
h_aliases: host_aliases.as_slice().as_ptr() as *const *const i8,
h_addrtype: ::socket::AF_INET,
h_length: 4,
h_addr_list: HOST_ADDR_LIST.as_ptr()
};
HOST_ALIASES = Some(host_aliases);
HOST_NAME = Some(host_name);
&HOST_ENTRY as *const hostent
});
/*
*libc_fn!(getnetbyaddr(net: libc::uint32_t, net_type: libc::c_int) -> Result<*const netent> {
* if NETDB == 0 {
* NETDB = syscall::open("/etc/networks", syscall::O_RDONLY).unwrap();
* }
*});
*
*libc_fn!(getnetbyname(name: *const libc::c_char) -> Result<*const netent> {
* if NETDB == 0 {
* NETDB = syscall::open("/etc/networks", syscall::O_RDONLY).unwrap();
* }
*});
*
*/
/*
*libc_fn!(getnetent() -> Result<*const netent> {
* if NETDB == 0 {
* NETDB = syscall::open("/etc/networks", syscall::O_RDONLY).unwrap();
* }
*
*});
*/
libc_fn!(unsafe getprotobyname(name: *const libc::c_char) -> Result<*const protoent> {
setprotoent(0);
let mut p: *const protoent;
while {p=getprotoent();
p!=null()} {
if libc::strcmp((*p).p_name, name) == 0 {
return Ok(p);
}
loop {
let mut cp = (*p).p_aliases;
if cp == null() {
break;
}
if libc::strcmp(*cp, name) == 0 {
return Ok(p);
}
cp = cp.offset(1);
}
}
endprotoent();
Err(Error::new(syscall::ENOENT))
});
libc_fn!(unsafe getprotobynumber(number: libc::c_int) -> Result<*const protoent> {
setprotoent(0);
let mut p: *const protoent;
while {p=getprotoent();
p!=null()} {
if (*p).p_proto == number {
return Ok(p);
}
}
endprotoent();
Err(Error::new(syscall::ENOENT))
});
libc_fn!(unsafe getprotoent() -> *const protoent {
if PROTODB == 0 {
PROTODB = syscall::open("/etc/protocols", syscall::O_RDONLY).unwrap();
P_LINE = RawLineBuffer::new(PROTODB);
}
let mut r: Box<str> = Box::default();
while r.is_empty() || r.split_whitespace().next() == None || r.starts_with("#") {
r = match P_LINE.next() {
Some(Ok(s)) => s,
Some(Err(_)) => return null(),
None => return null(),
};
}
let mut iter: SplitWhitespace = r.split_whitespace();
let mut proto_name: Vec<u8> = iter.next().unwrap().as_bytes().to_vec();
proto_name.push(b'\0');
let mut num = iter.next().unwrap().as_bytes().to_vec();
num.push(b'\0');
PROTO_NUM = Some(libc::atoi(num.as_slice().as_ptr() as *mut i8));
let mut proto_aliases: Vec<Vec<u8>> = Vec::new();
loop {
let mut alias = match iter.next() {
Some(s) => s.as_bytes().to_vec(),
None => break
};
alias.push(b'\0');
proto_aliases.push(alias);
}
//push a 0 so c doesn't segfault when it tries to read the next entry
proto_aliases.push(vec![b'\0']);
PROTO_ENTRY = protoent {
p_name: proto_name.as_slice().as_ptr() as *const c_char,
p_aliases: proto_aliases.iter().map(|x| x.as_ptr() as *const i8).collect::<Vec<*const i8>>().as_ptr(),
p_proto: PROTO_NUM.unwrap()
};
PROTO_ALIASES = Some(proto_aliases);
PROTO_NAME = Some(proto_name);
&PROTO_ENTRY as *const protoent
});
libc_fn!(unsafe getservbyname(name: *const libc::c_char, proto: *const libc::c_char) -> Result<*const servent> {
setservent(0);
let mut p: *const servent;
while {p=getservent();
p!=null()} {
if libc::strcmp((*p).s_name, name) == 0 && libc::strcmp((*p).s_proto, proto) == 0 {
return Ok(p);
}
loop {
let mut cp = (*p).s_aliases;
if cp == null() {
break;
}
if libc::strcmp(*cp, name) == 0 && libc::strcmp((*p).s_proto, proto) == 0 {
return Ok(p);
}
cp = cp.offset(1);
}
}
Err(Error::new(syscall::ENOENT))
});
libc_fn!(unsafe getservbyport(port: libc::c_int, proto: *const libc::c_char) -> Result<*const servent> {
setprotoent(0);
let mut p: *const servent;
while {p=getservent();
p!=null()} {
if (*p).s_port == port && libc::strcmp((*p).s_proto, proto) == 0 {
return Ok(p);
}
}
endprotoent();
Err(Error::new(syscall::ENOENT))
});
libc_fn!(unsafe getservent() -> *const servent {
if SERVDB == 0 {
SERVDB = syscall::open("/etc/services", syscall::O_RDONLY).unwrap();
S_LINE = RawLineBuffer::new(SERVDB);
}
let mut r: Box<str> = Box::default();
while r.is_empty() || r.split_whitespace().next() == None || r.starts_with("#") {
r = match S_LINE.next() {
Some(Ok(s)) => s,
Some(Err(_)) => return null(),
None => return null(),
};
}
let mut iter: SplitWhitespace = r.split_whitespace();
let mut serv_name: Vec<u8> = iter.next().unwrap().as_bytes().to_vec();
serv_name.push(b'\0');
let port_proto = iter.next().unwrap();
let mut split = port_proto.split("/");
let port = libc::atoi(split.next().unwrap().as_ptr() as *const i8);
SERV_PORT = Some(port);
let proto = split.next().unwrap().as_bytes().to_vec();
let mut serv_aliases: Vec<Vec<u8>> = Vec::new();
loop {
let mut alias = match iter.next() {
Some(s) => s.as_bytes().to_vec(),
None => break
};
alias.push(b'\0');
serv_aliases.push(alias);
}
//push a 0 so c doesn't segfault when it tries to read the next entry
serv_aliases.push(vec![b'\0']);
SERV_ENTRY = servent {
s_name: serv_name.as_slice().as_ptr() as *const c_char,
s_aliases: serv_aliases.iter().map(|x| x.as_ptr() as *const i8).collect::<Vec<*const i8>>().as_ptr(),
s_port: SERV_PORT.unwrap(),
s_proto: proto.as_slice().as_ptr() as *const c_char
};
SERV_ALIASES = Some(serv_aliases);
SERV_NAME = Some(serv_name);
SERV_PROTO = Some(proto);
&SERV_ENTRY as *const servent
});
libc_fn!(unsafe sethostent(stayopen: libc::c_int) {
if HOSTDB == 0 {
HOSTDB = syscall::open("/etc/hosts", syscall::O_RDONLY).unwrap();
} else {
let _ = syscall::lseek(HOSTDB, 0, syscall::SEEK_SET);
}
H_LINE = RawLineBuffer::new(HOSTDB);
});
/*
*libc_fn!(unsafe setnetent(stayopen: libc::c_int) {
* if NETDB == 0 {
* NETDB = syscall::open("/etc/networks", syscall::O_RDONLY).unwrap();
* } else {
* let _ = syscall::lseek(NETDB, 0, syscall::SEEK_SET);
* }
*});
*/
libc_fn!(unsafe setprotoent(stayopen: libc::c_int) {
if PROTODB == 0 {
PROTODB = syscall::open("/etc/protocols", syscall::O_RDONLY).unwrap();
} else {
let _ = syscall::lseek(PROTODB, 0, syscall::SEEK_SET);
}
P_LINE = RawLineBuffer::new(PROTODB);
});
libc_fn!(unsafe setservent(stayopen: libc::c_int) {
if SERVDB == 0 {
SERVDB = syscall::open("/etc/services", syscall::O_RDONLY).unwrap();
} else {
let _ = syscall::lseek(SERVDB, 0, syscall::SEEK_SET);
}
S_LINE = RawLineBuffer::new(SERVDB);
});
//libc_fn!(getaddrinfo(node: *const libc::c_char, service: *const libc::c_char, hints: *const addrinfo, res: *mut *mut addrinfo) -> libc::c_int {
//});
//libc_fn!(getnameinfo(addr: *const sockaddr, addrlen: socklen_t, host: *mut libc::c_char, hostlen: socklen_t, serv: *mut libc::c_char, servlen: socklen_t, flags: libc::c_int) -> libc::c_int {
//});
//libc_fn!(freeaddrinfo(res: *mut addrinfo) {
//});
//libc_fn!(gai_strerror(errcode: libc::c_int) -> *const libc::c_char {
//});
+207
View File
@@ -0,0 +1,207 @@
use libc::{c_char, c_int, c_void, size_t, gid_t, uid_t, ptrdiff_t};
use ::types::pid_t;
use core::slice;
use alloc::Vec;
use syscall::error::{Error, EINVAL};
use syscall;
const MAXPATHLEN: usize = 1024;
static mut CURR_BRK: usize = 0;
libc_fn!(unsafe chdir(path: *const c_char) -> Result<c_int> {
Ok(syscall::chdir(::cstr_to_slice(path))? as c_int)
});
libc_fn!(unsafe fchdir(fd: c_int) -> Result<c_int> {
let mut buf = [0; MAXPATHLEN];
let length = syscall::fpath(fd as usize, &mut buf)?;
Ok(syscall::chdir(&buf[0..length])? as c_int)
});
libc_fn!(unsafe _exit(code: c_int) {
::__libc_fini_array();
syscall::exit(code as usize).unwrap();
});
libc_fn!(unsafe _execve(name: *const c_char, argv: *const *const c_char, env: *const *const c_char) -> Result<c_int> {
let mut env = env;
while !(*env).is_null() {
let slice = ::cstr_to_slice(*env);
// Should always contain a =, but worth checking
if let Some(sep) = slice.iter().position(|&c| c == b'=') {
let mut path = b"env:".to_vec();
path.extend_from_slice(&slice[..sep]);
if let Ok(fd) = ::RawFile::open(&path, syscall::O_WRONLY | syscall::O_CREAT) {
let _ = syscall::write(*fd, &slice[sep+1..]);
}
}
env = env.offset(1);
}
let mut args: Vec<[usize; 2]> = Vec::new();
let mut arg = argv;
while !(*arg).is_null() {
args.push([*arg as usize, ::strlen(*arg)]);
arg = arg.offset(1);
}
Ok(syscall::execve(::cstr_to_slice(name), &args)? as c_int)
});
libc_fn!(unsafe _fork() -> Result<c_int> {
Ok(syscall::clone(0)? as c_int)
});
libc_fn!(unsafe vfork() -> Result<c_int> {
Ok(syscall::clone(syscall::CLONE_VFORK)? as c_int)
});
libc_fn!(unsafe getcwd(buf: *mut c_char, size: size_t) -> Result<*const c_char> {
let mut size = size;
if size == 0 {
size = ::file::PATH_MAX;
}
let buf = ::MallocNull::new(buf, size);
let slice = slice::from_raw_parts_mut(buf.as_mut_ptr() as *mut u8, size);
let count = syscall::getcwd(&mut slice[..size-1])?;
slice[count] = b'\0';
Ok(buf.into_raw())
// FIXME: buffer too small
});
libc_fn!(unsafe getwd(buf: *mut c_char) -> Result<*const c_char> {
if buf.is_null() {
Err(Error::new(EINVAL))
} else {
let mut tmp: [u8; MAXPATHLEN] = [0; MAXPATHLEN];
syscall::getcwd(&mut tmp)?;
slice::from_raw_parts_mut(buf as *mut u8, MAXPATHLEN)
.copy_from_slice(&mut tmp);
Ok(buf)
}
});
libc_fn!(unsafe _getpid() -> pid_t {
syscall::getpid().unwrap() as pid_t
});
libc_fn!(unsafe getppid() -> pid_t {
syscall::getppid().unwrap() as pid_t
});
libc_fn!(unsafe getegid() -> gid_t {
syscall::getegid().unwrap() as gid_t
});
libc_fn!(unsafe geteuid() -> uid_t {
syscall::geteuid().unwrap() as uid_t
});
libc_fn!(unsafe getgid() -> gid_t {
syscall::getgid().unwrap() as gid_t
});
libc_fn!(unsafe getuid() -> uid_t {
syscall::getuid().unwrap() as uid_t
});
libc_fn!(unsafe _kill(pid: c_int, sig: c_int) -> Result<c_int> {
Ok(syscall::kill(pid as usize, sig as usize)? as c_int)
});
libc_fn!(unsafe _brk(end_data_segment: *mut c_void) -> Result<c_int> {
CURR_BRK = syscall::brk(end_data_segment as usize)?;
Ok(0)
});
libc_fn!(unsafe _sbrk(increment: ptrdiff_t) -> *mut c_void {
if CURR_BRK == 0 {
CURR_BRK = syscall::brk(0).unwrap();
}
let old_brk = CURR_BRK;
if increment != 0 {
let addr = if increment >= 0 {
old_brk + increment as usize
} else {
old_brk - (-increment) as usize
};
CURR_BRK = match syscall::brk(addr) {
Ok(x) => x,
Err(err) => {
*::__errno() = err.errno;
return -1 as isize as *mut c_void;
}
}
}
old_brk as *mut c_void
});
libc_fn!(unsafe _sched_yield() -> Result<c_int> {
Ok(syscall::sched_yield()? as c_int)
});
libc_fn!(unsafe _system(s: *const c_char) -> Result<c_int> {
match syscall::clone(0)? {
0 => {
let shell = "/bin/sh";
let arg1 = "-c";
let args = [
[shell.as_ptr() as usize, shell.len()],
[arg1.as_ptr() as usize, arg1.len()],
[s as usize, ::strlen(s)]
];
syscall::execve(shell, &args)?;
syscall::exit(100)?;
unreachable!()
}
pid => {
let mut status = 0;
syscall::waitpid(pid, &mut status, 0)?;
Ok(status as c_int)
}
}
});
libc_fn!(unsafe setregid(rgid: gid_t, egid: gid_t) -> Result<c_int> {
Ok(syscall::setregid(rgid as usize, egid as usize)? as c_int)
});
libc_fn!(unsafe setegid(egid: gid_t) -> Result<c_int> {
Ok(syscall::setregid(-1isize as usize, egid as usize)? as c_int)
});
libc_fn!(unsafe setgid(gid: gid_t) -> Result<c_int> {
Ok(syscall::setregid(gid as usize, gid as usize)? as c_int)
});
libc_fn!(unsafe setreuid(ruid: uid_t, euid: uid_t) -> Result<c_int> {
Ok(syscall::setreuid(ruid as usize, euid as usize)? as c_int)
});
libc_fn!(unsafe seteuid(euid: uid_t) -> Result<c_int> {
Ok(syscall::setreuid(-1isize as usize, euid as usize)? as c_int)
});
libc_fn!(unsafe setuid(uid: uid_t) -> Result<c_int> {
Ok(syscall::setreuid(uid as usize, uid as usize)? as c_int)
});
libc_fn!(unsafe _wait(status: *mut c_int) -> Result<c_int> {
let mut buf = 0;
let res = syscall::waitpid(0, &mut buf, 0)?;
*status = buf as c_int;
Ok(res as c_int)
});
libc_fn!(unsafe waitpid(pid: pid_t, status: *mut c_int, options: c_int) -> Result<c_int> {
let mut buf = 0;
let pid = if pid == -1 {
0
} else {
pid as usize
};
let res = syscall::waitpid(pid as usize, &mut buf, options as usize)?;
*status = buf as c_int;
Ok(res as c_int)
});
+28
View File
@@ -0,0 +1,28 @@
use syscall;
use core::ops::Deref;
pub struct RawFile(usize);
impl RawFile {
pub fn open<T: AsRef<[u8]>>(path: T, flags: usize) -> syscall::Result<RawFile> {
syscall::open(path, flags).map(RawFile)
}
pub fn dup(&self, buf: &[u8]) -> syscall::Result<RawFile> {
syscall::dup(self.0, buf).map(RawFile)
}
}
impl Drop for RawFile {
fn drop(&mut self) {
let _ = syscall::close(self.0);
}
}
impl Deref for RawFile {
type Target = usize;
fn deref(&self) -> &usize {
&self.0
}
}
+40
View File
@@ -0,0 +1,40 @@
use syscall;
use libc::{c_int, c_char, c_void, size_t};
use core::slice;
libc_fn!(unsafe redox_fevent(file: c_int, flags: c_int) -> Result<c_int> {
Ok(syscall::fevent(file as usize, flags as usize)? as c_int)
});
libc_fn!(unsafe redox_fpath(file: c_int, buf: *mut c_char, len: size_t) -> Result<c_int> {
let buf = slice::from_raw_parts_mut(buf as *mut u8, len);
Ok(syscall::fpath(file as usize, buf)? as c_int)
});
libc_fn!(unsafe redox_fmap(file: c_int, offset: size_t, size: size_t) -> Result<*mut c_void> {
Ok(syscall::fmap(file as usize, offset, size)? as *mut c_void)
});
libc_fn!(unsafe redox_funmap(addr: *mut c_void) -> Result<c_int> {
Ok(syscall::funmap(addr as usize)? as c_int)
});
libc_fn!(unsafe redox_physalloc(size: size_t) -> Result<*mut c_void> {
Ok(syscall::physalloc(size)? as *mut c_void)
});
libc_fn!(unsafe redox_physfree(physical_address: *mut c_void, size: size_t) -> Result<c_int> {
Ok(syscall::physfree(physical_address as usize, size)? as c_int)
});
libc_fn!(unsafe redox_physmap(physical_address: *mut c_void, size: size_t, flags: c_int) -> Result<*mut c_void> {
Ok(syscall::physmap(physical_address as usize, size, flags as usize)? as *mut c_void)
});
libc_fn!(unsafe redox_physunmap(virtual_address: *mut c_void) -> Result<c_int> {
Ok(syscall::physunmap(virtual_address as usize)? as c_int)
});
libc_fn!(unsafe redox_virttophys(virtual_address: *mut c_void) -> Result<*mut c_void> {
Ok(syscall::virttophys(virtual_address as usize)? as *mut c_void)
});
+248
View File
@@ -0,0 +1,248 @@
use core::str::{self, FromStr};
use core::mem;
use core::ptr;
use libc::{c_int, c_char, size_t, c_void, ssize_t};
use ::types::{socklen_t, in_addr, sockaddr, sockaddr_in};
use syscall::{self, O_RDWR};
use syscall::error::{Error, EPROTOTYPE, EPROTONOSUPPORT, EAFNOSUPPORT, EINVAL, EOPNOTSUPP, ENOBUFS, ENOSPC};
use core::slice;
use byteorder::{BigEndian, ByteOrder};
pub const AF_INET: c_int = 2;
pub const SOCK_STREAM: c_int = 1;
pub const SOCK_DGRAM: c_int = 2;
static mut NTOA_ADDR: [c_char; 16] = [0; 16];
libc_fn!(unsafe inet_aton(cp: *const c_char, inp: *mut in_addr) -> c_int {
// TODO: octal/hex
inet_pton(AF_INET, cp, inp as *mut c_void)
});
libc_fn!(unsafe inet_ntoa(addr: in_addr) -> *const c_char {
inet_ntop(AF_INET, &addr as *const in_addr as *const c_void, NTOA_ADDR.as_mut_ptr(), 16)
});
libc_fn!(unsafe inet_pton(domain: c_int, src: *const c_char, dest: *mut c_void) -> Result<c_int> {
if domain != AF_INET {
Err(Error::new(EAFNOSUPPORT))
} else {
let s_addr = &mut ((*(dest as *mut in_addr)).s_addr);
let mut octets = str::from_utf8_unchecked(::cstr_to_slice(src)).split('.');
for i in 0..4 {
if let Some(n) = octets.next().and_then(|x| u8::from_str(x).ok()) {
s_addr[i] = n;
} else {
return Ok(0);
}
}
if octets.next() == None {
Ok(1) // Success
} else {
Ok(0)
}
}
});
libc_fn!(unsafe inet_ntop(domain: c_int, src: *const c_void, dest: *mut c_char, size: socklen_t) -> Result<*const c_char> {
if domain != AF_INET {
Err(Error::new(EAFNOSUPPORT))
} else if size < 16 {
Err(Error::new(ENOSPC))
} else {
let s_addr = (&*(src as *const in_addr)).s_addr;
let addr = format!("{}.{}.{}.{}\0", s_addr[0], s_addr[1], s_addr[2], s_addr[3]);
ptr::copy(addr.as_ptr() as *const c_char, dest, addr.len());
Ok(dest)
}
});
libc_fn!(unsafe socket(domain: c_int, type_: c_int, protocol: c_int) -> Result<c_int> {
if domain != AF_INET {
Err(Error::new(EAFNOSUPPORT))
} else if protocol != 0 {
Err(Error::new(EPROTONOSUPPORT))
} else {
let fd = match type_ {
SOCK_STREAM => syscall::open("tcp:", O_RDWR),
SOCK_DGRAM => syscall::open("udp:", O_RDWR),
_ => Err(Error::new(EPROTOTYPE))
}?;
Ok(fd as c_int)
}
});
libc_fn!(unsafe connect(socket: c_int, address: *const sockaddr, _address_len: socklen_t) -> Result<c_int> {
// XXX with UDP, should recieve messages only from that peer after this
// XXX Check address_len
if (*address).sa_family as i32 != AF_INET {
return Err(Error::new(EINVAL))
};
let address = &*(address as *const sockaddr_in);
let s_addr =address.sin_addr.s_addr;
let path = format!("{}.{}.{}.{}:{}", s_addr[0], s_addr[1], s_addr[2], s_addr[3], ntohs(address.sin_port));
let fd = syscall::dup(socket as usize, path.as_bytes())?;
let ret = syscall::dup2(fd, socket as usize, &vec![]);
let _ = syscall::close(fd);
ret?;
Ok(0)
});
libc_fn!(unsafe bind(socket: c_int, address: *const sockaddr, _address_len: socklen_t) -> Result<c_int> {
// XXX Check address_len
if (*address).sa_family as i32 != AF_INET {
return Err(Error::new(EINVAL))
};
let address = &*(address as *const sockaddr_in);
let s_addr =address.sin_addr.s_addr;
let path = format!("/{}.{}.{}.{}:{}", s_addr[0], s_addr[1], s_addr[2], s_addr[3], ntohs(address.sin_port));
let fd = syscall::dup(socket as usize, path.as_bytes())?;
let ret = syscall::dup2(fd, socket as usize, &vec![]);
let _ = syscall::close(fd);
ret?;
Ok(0)
});
libc_fn!(unsafe listen(_socket: c_int, _backlog: c_int) -> Result<c_int> {
// TODO
Ok(0)
});
libc_fn!(unsafe recv(socket: c_int, buffer: *mut c_void, length: size_t, flags: c_int) -> Result<ssize_t> {
// XXX flags
if flags != 0 {
Err(Error::new(EOPNOTSUPP))
} else {
let buf = slice::from_raw_parts_mut(buffer as *mut u8, length);
Ok(syscall::read(socket as usize, buf)? as ssize_t)
}
});
libc_fn!(unsafe send(socket: c_int, buffer: *const c_void, length: size_t, flags: c_int) -> Result<ssize_t> {
if flags != 0 {
Err(Error::new(EOPNOTSUPP))
} else {
let buf = slice::from_raw_parts(buffer as *const u8, length);
Ok(syscall::write(socket as usize, buf)? as ssize_t)
}
});
libc_fn!(unsafe recvfrom(socket: c_int, buffer: *mut c_void, length: size_t, flags: c_int, _address: *const sockaddr, _address_len: *const socklen_t) -> Result<ssize_t> {
let fd = syscall::dup(socket as usize, b"listen")?;
let mut path = [0; 4096];
syscall::fpath(socket as usize, &mut path)?;
// XXX process path and write to address
let ret = recv(socket, buffer, length, flags);
syscall::close(fd)?;
Ok(ret)
});
libc_fn!(unsafe sendto(socket: c_int, message: *const c_void, length: size_t, flags: c_int, dest_addr: *const sockaddr, _dest_len: socklen_t) -> Result<ssize_t> {
// XXX test dest_len
if (*dest_addr).sa_family as i32 == AF_INET {
let addr = &*(dest_addr as *const sockaddr_in);
let s_addr = addr.sin_addr.s_addr;
let url = format!("{}.{}.{}.{}:{}", s_addr[0], s_addr[1], s_addr[2], s_addr[3], ntohs(addr.sin_port));
let fd = syscall::dup(socket as usize, url.as_bytes())?;
let ret = send(fd as c_int, message, length, flags);
syscall::close(fd)?;
Ok(ret)
} else {
Err(Error::new(EOPNOTSUPP))
}
});
libc_fn!(unsafe getpeername(socket: c_int, address: *mut sockaddr, address_len: *mut socklen_t) -> Result<c_int> {
// XXX will need to be changed for other sockaddr types
if *address_len < mem::size_of::<sockaddr_in>() {
return Err(Error::new(ENOBUFS));
}
*address_len = mem::size_of::<sockaddr_in>();
let addr = &mut *(address as *mut sockaddr_in);
addr.sin_family = AF_INET as u16;
let mut path = [0; 4096];
syscall::fpath(socket as usize, &mut path)?;
let start;
let sep;
let end;
{
let mut iter = path.iter();
start = iter.position(|x| *x == b':').ok_or(Error::new(EINVAL))? + 1;
sep = start + iter.position(|x| *x == b':').ok_or(Error::new(EINVAL))?;
end = sep + 1 + iter.position(|x| *x == b'/').ok_or(Error::new(EINVAL))?;
}
path[sep] = b'\0';
if inet_aton(&path[start] as *const u8 as *const c_char, &mut addr.sin_addr) == 1 {
if let Ok(port) = u16::from_str(str::from_utf8_unchecked(&path[sep+1..end])) {
addr.sin_port = htons(port);
Ok(0)
} else {
Err(Error::new(EINVAL))
}
} else {
Err(Error::new(EINVAL)) // ?
}
});
libc_fn!(unsafe getsockname(socket: c_int, address: *mut sockaddr, address_len: *mut socklen_t) -> Result<c_int> {
// XXX will need to be changed for other sockaddr types
if *address_len < mem::size_of::<sockaddr_in>() {
return Err(Error::new(ENOBUFS));
}
*address_len = mem::size_of::<sockaddr_in>();
let addr = &mut *(address as *mut sockaddr_in);
addr.sin_family = AF_INET as u16;
let mut path = [0; 4096];
syscall::fpath(socket as usize, &mut path)?;
let start;
let sep;
let end;
{
let mut iter = path.iter();
start = iter.position(|x| *x == b'/').ok_or(Error::new(EINVAL))? + 1;
sep = start + iter.position(|x| *x == b':').ok_or(Error::new(EINVAL))?;
end = sep + 1 + iter.position(|x| *x == b'\0').ok_or(Error::new(EINVAL))?;
}
path[sep] = b'\0';
if inet_aton(&path[start] as *const u8 as *const c_char, &mut addr.sin_addr) == 1 {
if let Ok(port) = u16::from_str(str::from_utf8_unchecked(&path[sep+1..end])) {
addr.sin_port = htons(port);
Ok(0)
} else {
Err(Error::new(EINVAL))
}
} else {
Err(Error::new(EINVAL)) // ?
}
});
libc_fn!(htonl(hostlong: u32) -> [u8; 4] {
let mut netlong = [0; 4];
BigEndian::write_u32(&mut netlong, hostlong);
netlong
});
libc_fn!(htons(hostshort: u16) -> [u8; 2] {
let mut netshort = [0; 2];
BigEndian::write_u16(&mut netshort, hostshort);
netshort
});
libc_fn!(ntohl(netlong: [u8; 4]) -> u32 {
BigEndian::read_u32(&netlong)
});
libc_fn!(ntohs(netshort: [u8; 2]) -> u16 {
BigEndian::read_u16(&netshort)
});
libc_fn!(setsockopt(socket: c_int, level: c_int, option_name: c_int, option_value: *const c_void, option_len: socklen_t) -> Result<c_int> {
syscall::write(2, format!("unimplemented: setsockopt({}, {}, {}, {:?}, {})\n",
socket, level, option_name, option_value, option_len).as_bytes()).unwrap();
Err(Error::new(syscall::ENOSYS))
});
+93
View File
@@ -0,0 +1,93 @@
#![allow(non_camel_case_types)]
use libc::{self, c_int};
use redox_termios::{tcflag_t, Termios};
use syscall::{self, EINVAL, Error};
use ::types::pid_t;
type speed_t = libc::c_uint;
// tcsetattr args
pub const TCSANOW: tcflag_t = 0x1;
pub const TCSADRAIN: tcflag_t = 0x2;
pub const TCSAFLUSH: tcflag_t = 0x4;
// tcflush args
pub const TCIFLUSH: tcflag_t = 0x1;
pub const TCIOFLUSH: tcflag_t = 0x3;
pub const TCOFLUSH: tcflag_t = 0x2;
// tcflow args
pub const TCIOFF: tcflag_t = 0x1;
pub const TCION: tcflag_t = 0x2;
pub const TCOOFF: tcflag_t = 0x4;
pub const TCOON: tcflag_t = 0x8;
libc_fn!(unsafe tcgetattr(fd: c_int, tio: *mut Termios) -> Result<c_int> {
let fd = syscall::dup(fd as usize, b"termios")?;
let res = syscall::read(fd, &mut *tio);
let _ = syscall::close(fd);
if res? == (&*tio).len() {
Ok(0)
} else {
Err(Error::new(EINVAL))
}
});
libc_fn!(unsafe tcsetattr(fd: c_int, _arg: c_int, tio: *mut Termios) -> Result<c_int> {
let fd = syscall::dup(fd as usize, b"termios")?;
let res = syscall::write(fd, &*tio);
let _ = syscall::close(fd);
if res? == (&*tio).len() {
Ok(0)
} else {
Err(Error::new(EINVAL))
}
});
libc_fn!(cfgetispeed(_tio: *mut Termios) -> speed_t {
// TODO
0 as speed_t
});
libc_fn!(cfgetospeed(_tio: *mut Termios) -> speed_t {
// TODO
0 as speed_t
});
libc_fn!(cfsetispeed(_tio: *mut Termios, _speed: speed_t) -> Result<c_int> {
// TODO
Ok(0)
});
libc_fn!(cfsetospeed(_tio: *mut Termios, _speed: speed_t) -> Result<c_int> {
// TODO
Ok(0)
});
libc_fn!(tcdrain(_i: c_int) -> Result<c_int> {
// TODO
Ok(0)
});
libc_fn!(tcflow(_fd: c_int, _arg: c_int) -> Result<c_int> {
// TODO
Ok(0)
});
libc_fn!(tcflush(_fd: c_int, _arg: c_int) -> Result<c_int> {
// TODO
Ok(0)
});
libc_fn!(unsafe tcgetsid(_fd: c_int) -> pid_t {
// TODO
::process::_getpid()
});
libc_fn!(tcsendbreak(_fd: c_int, _arg: c_int) -> Result<c_int> {
// TODO
Ok(0)
});
+25
View File
@@ -0,0 +1,25 @@
use syscall;
use syscall::data::TimeSpec;
use syscall::error::{Error, EFAULT};
use libc::{c_int, c_void};
use types::timeval;
libc_fn!(unsafe clock_gettime(clk_id: c_int, tp: *mut TimeSpec) -> Result<c_int> {
Ok(syscall::clock_gettime(clk_id as usize, &mut *tp)? as c_int)
});
libc_fn!(unsafe _gettimeofday(tv: *mut timeval, _tz: *const c_void) -> Result<c_int> {
if !tv.is_null() {
let mut tp = TimeSpec::default();
syscall::clock_gettime(syscall::flag::CLOCK_REALTIME, &mut tp)?;
(*tv).tv_sec = tp.tv_sec;
(*tv).tv_usec = (tp.tv_nsec / 1000) as i64;
Ok(0)
} else {
Err(Error::new(EFAULT))
}
});
libc_fn!(unsafe nanosleep(req: *const TimeSpec, rem: *mut TimeSpec) -> Result<c_int> {
Ok(syscall::nanosleep(&*req, &mut *rem)? as c_int)
});
+110
View File
@@ -0,0 +1,110 @@
#![allow(non_camel_case_types, dead_code)]
use libc;
pub type pid_t = libc::c_int;
pub type time_t = i64;
pub type suseconds_t = libc::c_long;
// Socket related types
pub type in_addr_t = [u8; 4];
pub type sa_family_t = u16;
pub type socklen_t = libc::size_t;
pub type in_port_t = [u8; 2];
// Statvfs types
pub type dev_t = libc::c_ulong;
pub type ino_t = libc::c_ulong;
pub type mode_t = libc::c_uint;
pub type nlink_t = libc::c_ulong;
pub type uid_t = libc::c_uint;
pub type gid_t = libc::c_uint;
pub type off_t = libc::c_long;
pub type blksize_t = libc::c_long;
pub type blkcnt_t = libc::c_long;
pub type fsblkcnt_t = libc::c_ulong;
pub type fsfilcnt_t = libc::c_ulong;
pub type __fsword_t = libc::c_long;
#[repr(C)]
pub struct fsid_t {
__val: [libc::c_int; 2]
}
#[repr(C)]
#[derive(Clone,Copy)]
pub struct in_addr {
pub s_addr: in_addr_t
}
#[repr(C)]
pub struct sockaddr {
pub sa_family: sa_family_t,
sa_data: [libc::c_char; 14]
}
#[repr(C)]
pub struct sockaddr_in {
pub sin_family: sa_family_t,
pub sin_port: in_port_t,
pub sin_addr: in_addr,
__pad: [u8; 8]
}
#[repr(C)]
pub struct hostent {
pub h_name: *const libc::c_char,
pub h_aliases: *const *const libc::c_char,
pub h_addrtype: libc::c_int,
pub h_length: libc::c_int,
pub h_addr_list: *const *const libc::c_char
}
#[repr(C)]
#[derive(Debug)]
pub struct timeval {
pub tv_sec: time_t,
pub tv_usec: suseconds_t
}
#[repr(C)]
pub struct utimbuf {
pub actime: time_t,
pub modtime: time_t
}
pub type fd_mask = libc::c_ulong;
pub const FD_SETSIZE: usize = 64;
pub const NFDBITS: usize = 8 * 8; // Bits in a fd_mask
#[repr(C)]
#[derive(Debug)]
pub struct fd_set {
pub fds_bits: [fd_mask; (FD_SETSIZE + NFDBITS - 1) / NFDBITS]
}
pub const POLLIN: libc::c_short = 0x0001;
pub const POLLPRI: libc::c_short = 0x0002;
pub const POLLOUT: libc::c_short = 0x0004;
pub const POLLERR: libc::c_short = 0x0008;
pub const POLLHUP: libc::c_short = 0x0010;
pub const POLLNVAL: libc::c_short = 0x0020;
#[repr(C)]
pub struct pollfd {
pub fd: libc::c_int,
pub events: libc::c_short,
pub revents: libc::c_short,
}
#[repr(C)]
pub struct passwd {
pub pw_name: *const libc::c_char,
pub pw_passwd: *const libc::c_char,
pub pw_uid: libc::uid_t,
pub pw_gid: libc::gid_t,
pub pw_gecos: *const libc::c_char,
pub pw_dir: *const libc::c_char,
pub pw_shell: *const libc::c_char
}
+66
View File
@@ -0,0 +1,66 @@
use syscall;
use libc::{c_uint, c_int, c_char, gid_t, uid_t, c_void, c_long, mode_t};
use syscall::error::{Error, EACCES, EPERM, EINVAL};
#[allow(non_camel_case_types)]
type clock_t = c_long;
macro_rules! UNIMPL {
// Call with arguments and return value
($func:ident, $err:ident) => {{
let err = Error::new($err);
let _ = syscall::write(2, format!("unimplemented: {}: {}\n",
stringify!($func), err).as_bytes());
Err(err)
}};
}
libc_fn!(alarm(_seconds: c_uint) -> c_uint {
let _ = syscall::write(2, "unimplemented: alarm\n".as_bytes());
0
});
libc_fn!(chown(_path: *mut c_char, _order: uid_t, _group: gid_t) -> Result<c_int> {
UNIMPL!(chown, EACCES)
});
libc_fn!(_getdtablesize() -> Result<c_int> {
Ok(65536)
});
// XXX variadic
libc_fn!(_ioctl(_file: c_int, _request: c_int) -> Result<c_int> {
UNIMPL!(_ioctl, EINVAL)
});
libc_fn!(_link(_old: *const c_char, _new: *const c_char) -> Result<c_int> {
UNIMPL!(_link, EPERM)
});
/*
libc_fn!(sysconf(_name: c_int) -> Result<c_long> {
UNIMPL!(sysconf, EINVAL)
});
*/
// XXX type of argument pointer
libc_fn!(_times(_buf: *mut c_void) -> Result<clock_t> {
UNIMPL!(_times, EINVAL)
});
libc_fn!(umask(_mode: mode_t) -> mode_t {
// All permissions granted
0o000
});
libc_fn!(ttyname(_fd: c_int) -> Result<*const c_char> {
UNIMPL!(ttyname, EINVAL)
});
libc_fn!(fpathconf(_fildes: c_int, _name: c_int) -> Result<c_long> {
UNIMPL!(fpathconf, EINVAL)
});
libc_fn!(getlogin() -> Result<*const c_char> {
UNIMPL!(getlogin, EINVAL)
});
+95
View File
@@ -0,0 +1,95 @@
use core::ptr::null;
use libc::{uid_t, gid_t, c_char};
use ::types::passwd;
use syscall::{Error, ENOENT};
use alloc::string::{String, ToString};
use core::str::FromStr;
static mut PASSWD: passwd = passwd {
pw_name: null(),
pw_passwd: null(),
pw_uid: 0,
pw_gid: 0,
pw_gecos: null(),
pw_dir: null(),
pw_shell: null()
};
static mut PW_NAME: Option<String> = None;
static mut PW_PASSWD: Option<String> = None;
static mut PW_GECOS: Option<String> = None;
static mut PW_DIR: Option<String> = None;
static mut PW_SHELL: Option<String> = None;
macro_rules! try_opt {
($e:expr) =>(
match $e {
Some(v) => v,
None => return None,
}
)
}
unsafe fn parse_passwd(pwd: &str) -> Option<*const passwd> {
let mut parts = pwd.split(';');
let name = try_opt!(parts.next()).to_string() + "\0";
let passwd = try_opt!(parts.next()).to_string() + "\0";
let uid = if let Ok(uid) = uid_t::from_str(try_opt!(parts.next())) {
uid
} else {
return None
};
let gid = if let Ok(gid) = gid_t::from_str(try_opt!(parts.next())) {
gid
} else {
return None
};
let gecos = try_opt!(parts.next()).to_string() + "\0";
let dir = try_opt!(parts.next()).to_string() + "\0";
let shell = try_opt!(parts.next()).to_string() + "\0";
PASSWD = passwd {
pw_name: name.as_ptr() as *const c_char,
pw_passwd: passwd.as_ptr() as *const c_char,
pw_uid: uid,
pw_gid: gid,
pw_gecos: gecos.as_ptr() as *const c_char,
pw_dir: dir.as_ptr() as *const c_char,
pw_shell: shell.as_ptr() as *const c_char
};
PW_NAME = Some(name);
PW_PASSWD = Some(passwd);
PW_GECOS = Some(gecos);
PW_DIR = Some(dir);
PW_SHELL = Some(shell);
Some(&PASSWD as *const _)
}
libc_fn!(unsafe getpwnam(name: *const c_char) -> Result<*const passwd> {
if let Ok(passwd_string) = String::from_utf8(::file_read_all("/etc/passwd")?) {
for line in passwd_string.lines() {
if line.split(';').nth(0).map(str::as_bytes) == Some(::cstr_to_slice(name)) {
if let Some(pass) = parse_passwd(line) {
return Ok(pass);
}
}
}
}
Err(Error::new(ENOENT))
});
libc_fn!(unsafe getpwuid(uid: uid_t) -> Result<*const passwd> {
if let Ok(passwd_string) = String::from_utf8(::file_read_all("/etc/passwd")?) {
for line in passwd_string.lines() {
if line.split(';').nth(2).map(uid_t::from_str) == Some(Ok(uid)) {
if let Some(pass) = parse_passwd(line) {
return Ok(pass);
}
}
}
}
Err(Error::new(ENOENT))
});
+548
View File
@@ -0,0 +1,548 @@
// #[no_mangle]
pub extern "C" fn pthread_attr_destroy(attr: *mut pthread_attr_t) -> libc::c_int {
unimplemented!();
}
// #[no_mangle]
pub extern "C" fn pthread_attr_getdetachstate(
attr: *const pthread_attr_t,
detachstate: *mut libc::c_int,
) -> libc::c_int {
unimplemented!();
}
// #[no_mangle]
pub extern "C" fn pthread_attr_getguardsize(
attr: *const pthread_attr_t,
guardsize: *mut usize,
) -> libc::c_int {
unimplemented!();
}
// #[no_mangle]
pub extern "C" fn pthread_attr_getinheritsched(
attr: *const pthread_attr_t,
inheritsched: *mut libc::c_int,
) -> libc::c_int {
unimplemented!();
}
// #[no_mangle]
pub extern "C" fn pthread_attr_getschedparam(
attr: *const pthread_attr_t,
param: *mut sched_param,
) -> libc::c_int {
unimplemented!();
}
// #[no_mangle]
pub extern "C" fn pthread_attr_getschedpolicy(
attr: *const pthread_attr_t,
policy: *mut libc::c_int,
) -> libc::c_int {
unimplemented!();
}
// #[no_mangle]
pub extern "C" fn pthread_attr_getscope(
attr: *const pthread_attr_t,
contentionscope: *mut libc::c_int,
) -> libc::c_int {
unimplemented!();
}
// #[no_mangle]
pub extern "C" fn pthread_attr_getstackaddr(
attr: *const pthread_attr_t,
stackaddr: *mut *mut libc::c_void,
) -> libc::c_int {
unimplemented!();
}
// #[no_mangle]
pub extern "C" fn pthread_attr_getstacksize(
attr: *const pthread_attr_t,
stacksize: *mut usize,
) -> libc::c_int {
unimplemented!();
}
// #[no_mangle]
pub extern "C" fn pthread_attr_init(arg1: *mut pthread_attr_t) -> libc::c_int {
unimplemented!();
}
// #[no_mangle]
pub extern "C" fn pthread_attr_setdetachstate(
attr: *mut pthread_attr_t,
detachstate: libc::c_int,
) -> libc::c_int {
unimplemented!();
}
// #[no_mangle]
pub extern "C" fn pthread_attr_setguardsize(arg1: *mut pthread_attr_t, arg2: usize) -> libc::c_int {
unimplemented!();
}
// #[no_mangle]
pub extern "C" fn pthread_attr_setinheritsched(
attr: *mut pthread_attr_t,
inheritsched: libc::c_int,
) -> libc::c_int {
unimplemented!();
}
// #[no_mangle]
pub extern "C" fn pthread_attr_setschedparam(
attr: *mut pthread_attr_t,
param: *mut sched_param,
) -> libc::c_int {
unimplemented!();
}
// #[no_mangle]
pub extern "C" fn pthread_attr_setschedpolicy(
attr: *mut pthread_attr_t,
policy: libc::c_int,
) -> libc::c_int {
unimplemented!();
}
// #[no_mangle]
pub extern "C" fn pthread_attr_setscope(
attr: *mut pthread_attr_t,
contentionscope: libc::c_int,
) -> libc::c_int {
unimplemented!();
}
// #[no_mangle]
pub extern "C" fn pthread_attr_setstackaddr(
attr: *mut pthread_attr_t,
stackaddr: *mut libc::c_void,
) -> libc::c_int {
unimplemented!();
}
// #[no_mangle]
pub extern "C" fn pthread_attr_setstacksize(attr: *mut pthread_attr_t, stacksize: usize) -> libc::c_int {
unimplemented!();
}
// #[no_mangle]
pub extern "C" fn pthread_cancel(thread: pthread_t) -> libc::c_int {
unimplemented!();
}
// #[no_mangle]
pub extern "C" fn pthread_cleanup_push(routine: *mut libc::c_void, arg: *mut libc::c_void) {
unimplemented!();
}
// #[no_mangle]
pub extern "C" fn pthread_cleanup_pop(execute: libc::c_int) {
unimplemented!();
}
// #[no_mangle]
pub extern "C" fn pthread_cond_broadcast(cond: *mut pthread_cond_t) -> libc::c_int {
unimplemented!();
}
// #[no_mangle]
pub extern "C" fn pthread_cond_destroy(cond: *mut pthread_cond_t) -> libc::c_int {
unimplemented!();
}
// #[no_mangle]
pub extern "C" fn pthread_cond_init(
cond: *mut pthread_cond_t,
attr: *const pthread_condattr_t,
) -> libc::c_int {
unimplemented!();
}
// #[no_mangle]
pub extern "C" fn pthread_cond_signal(cond: *mut pthread_cond_t) -> libc::c_int {
unimplemented!();
}
// #[no_mangle]
pub extern "C" fn pthread_cond_timedwait(
cond: *mut pthread_cond_t,
mutex: *mut pthread_mutex_t,
abstime: *const timespec,
) -> libc::c_int {
unimplemented!();
}
// #[no_mangle]
pub extern "C" fn pthread_cond_wait(
cond: *mut pthread_cond_t,
mutex: *mut pthread_mutex_t,
) -> libc::c_int {
unimplemented!();
}
// #[no_mangle]
pub extern "C" fn pthread_condattr_destroy(attr: *mut pthread_condattr_t) -> libc::c_int {
unimplemented!();
}
// #[no_mangle]
pub extern "C" fn pthread_condattr_getpshared(
attr: *const pthread_condattr_t,
pshared: *mut libc::c_int,
) -> libc::c_int {
unimplemented!();
}
// #[no_mangle]
pub extern "C" fn pthread_condattr_init(attr: *mut pthread_condattr_t) -> libc::c_int {
unimplemented!();
}
// #[no_mangle]
pub extern "C" fn pthread_condattr_setpshared(
attr: *mut pthread_condattr_t,
pshared: libc::c_int,
) -> libc::c_int {
unimplemented!();
}
// #[no_mangle]
pub extern "C" fn pthread_create(
thread: *mut pthread_t,
attr: *const pthread_attr_t,
start_routine: Option<unsafe extern "C" fn(arg1: *mut libc::c_void) -> *mut libc::c_void>,
arg: *mut libc::c_void,
) -> libc::c_int {
unimplemented!();
}
// #[no_mangle]
pub extern "C" fn pthread_detach(thread: pthread_t) -> libc::c_int {
unimplemented!();
}
// #[no_mangle]
pub extern "C" fn pthread_equal(t1: pthread_t, t2: pthread_t) -> libc::c_int {
unimplemented!();
}
// #[no_mangle]
pub extern "C" fn pthread_exit(value_ptr: *mut libc::c_void) {
unimplemented!();
}
// #[no_mangle]
pub extern "C" fn pthread_getconcurrency() -> libc::c_int {
unimplemented!();
}
// #[no_mangle]
pub extern "C" fn pthread_getschedparam(
thread: pthread_t,
policy: *mut libc::c_int,
param: *mut sched_param,
) -> libc::c_int {
unimplemented!();
}
// #[no_mangle]
pub extern "C" fn pthread_getspecific(key: pthread_key_t) -> *mut libc::c_void {
unimplemented!();
}
// #[no_mangle]
pub extern "C" fn pthread_join(thread: pthread_t, value_ptr: *mut *mut libc::c_void) -> libc::c_int {
unimplemented!();
}
// #[no_mangle]
pub extern "C" fn pthread_key_create(
key: *mut pthread_key_t,
destructor: Option<unsafe extern "C" fn(arg1: *mut libc::c_void)>,
) -> libc::c_int {
unimplemented!();
}
// #[no_mangle]
pub extern "C" fn pthread_key_delete(key: pthread_key_t) -> libc::c_int {
unimplemented!();
}
// #[no_mangle]
pub extern "C" fn pthread_mutex_destroy(mutex: *mut pthread_mutex_t) -> libc::c_int {
unimplemented!();
}
// #[no_mangle]
pub extern "C" fn pthread_mutex_getprioceiling(
mutex: *const pthread_mutex_t,
prioceiling: *mut libc::c_int,
) -> libc::c_int {
unimplemented!();
}
// #[no_mangle]
pub extern "C" fn pthread_mutex_init(
mutex: *mut pthread_mutex_t,
attr: *const pthread_mutexattr_t,
) -> libc::c_int {
unimplemented!();
}
// #[no_mangle]
pub extern "C" fn pthread_mutex_lock(mutex: *mut pthread_mutex_t) -> libc::c_int {
unimplemented!();
}
// #[no_mangle]
pub extern "C" fn pthread_mutex_setprioceiling(
mutex: *mut pthread_mutex_t,
prioceiling: libc::c_int,
old_ceiling: *mut libc::c_int,
) -> libc::c_int {
unimplemented!();
}
// #[no_mangle]
pub extern "C" fn pthread_mutex_trylock(mutex: *mut pthread_mutex_t) -> libc::c_int {
unimplemented!();
}
// #[no_mangle]
pub extern "C" fn pthread_mutex_unlock(mutex: *mut pthread_mutex_t) -> libc::c_int {
unimplemented!();
}
// #[no_mangle]
pub extern "C" fn pthread_mutexattr_destroy(attr: *mut pthread_mutexattr_t) -> libc::c_int {
unimplemented!();
}
// #[no_mangle]
pub extern "C" fn pthread_mutexattr_getprioceiling(
attr: *const pthread_mutexattr_t,
prioceiling: *mut libc::c_int,
) -> libc::c_int {
unimplemented!();
}
// #[no_mangle]
pub extern "C" fn pthread_mutexattr_getprotocol(
attr: *const pthread_mutexattr_t,
protocol: *mut libc::c_int,
) -> libc::c_int {
unimplemented!();
}
// #[no_mangle]
pub extern "C" fn pthread_mutexattr_getpshared(
attr: *const pthread_mutexattr_t,
pshared: *mut libc::c_int,
) -> libc::c_int {
unimplemented!();
}
// #[no_mangle]
pub extern "C" fn pthread_mutexattr_gettype(
attr: *const pthread_mutexattr_t,
type_: *mut libc::c_int,
) -> libc::c_int {
unimplemented!();
}
// #[no_mangle]
pub extern "C" fn pthread_mutexattr_init(attr: *mut pthread_mutexattr_t) -> libc::c_int {
unimplemented!();
}
// #[no_mangle]
pub extern "C" fn pthread_mutexattr_setprioceiling(
attr: *mut pthread_mutexattr_t,
prioceiling: libc::c_int,
) -> libc::c_int {
unimplemented!();
}
// #[no_mangle]
pub extern "C" fn pthread_mutexattr_setprotocol(
attr: *mut pthread_mutexattr_t,
protocol: libc::c_int,
) -> libc::c_int {
unimplemented!();
}
// #[no_mangle]
pub extern "C" fn pthread_mutexattr_setpshared(
attr: *mut pthread_mutexattr_t,
pshared: libc::c_int,
) -> libc::c_int {
unimplemented!();
}
// #[no_mangle]
pub extern "C" fn pthread_mutexattr_settype(
attr: *mut pthread_mutexattr_t,
type_: libc::c_int,
) -> libc::c_int {
unimplemented!();
}
// #[no_mangle]
pub extern "C" fn pthread_once(
once_control: *mut pthread_once_t,
init_routine: Option<unsafe extern "C" fn()>,
) -> libc::c_int {
unimplemented!();
}
// #[no_mangle]
pub extern "C" fn pthread_rwlock_destroy(rwlock: *mut pthread_rwlock_t) -> libc::c_int {
unimplemented!();
}
// #[no_mangle]
pub extern "C" fn pthread_rwlock_init(
rwlock: *mut pthread_rwlock_t,
attr: *const pthread_rwlockattr_t,
) -> libc::c_int {
unimplemented!();
}
// #[no_mangle]
pub extern "C" fn pthread_rwlock_rdlock(rwlock: *mut pthread_rwlock_t) -> libc::c_int {
unimplemented!();
}
// #[no_mangle]
pub extern "C" fn pthread_rwlock_tryrdlock(rwlock: *mut pthread_rwlock_t) -> libc::c_int {
unimplemented!();
}
// #[no_mangle]
pub extern "C" fn pthread_rwlock_trywrlock(rwlock: *mut pthread_rwlock_t) -> libc::c_int {
unimplemented!();
}
// #[no_mangle]
pub extern "C" fn pthread_rwlock_unlock(rwlock: *mut pthread_rwlock_t) -> libc::c_int {
unimplemented!();
}
// #[no_mangle]
pub extern "C" fn pthread_rwlock_wrlock(rwlock: *mut pthread_rwlock_t) -> libc::c_int {
unimplemented!();
}
// #[no_mangle]
pub extern "C" fn pthread_rwlockattr_destroy(rwlock: *mut pthread_rwlockattr_t) -> libc::c_int {
unimplemented!();
}
// #[no_mangle]
pub extern "C" fn pthread_rwlockattr_getpshared(
rwlock: *const pthread_rwlockattr_t,
pshared: *mut libc::c_int,
) -> libc::c_int {
unimplemented!();
}
// #[no_mangle]
pub extern "C" fn pthread_rwlockattr_init(rwlock: *mut pthread_rwlockattr_t) -> libc::c_int {
unimplemented!();
}
// #[no_mangle]
pub extern "C" fn pthread_rwlockattr_setpshared(
rwlock: *mut pthread_rwlockattr_t,
pshared: libc::c_int,
) -> libc::c_int {
unimplemented!();
}
// #[no_mangle]
pub extern "C" fn pthread_self() -> pthread_t {
unimplemented!();
}
// #[no_mangle]
pub extern "C" fn pthread_setcancelstate(state: libc::c_int, oldstate: *mut libc::c_int) -> libc::c_int {
unimplemented!();
}
// #[no_mangle]
pub extern "C" fn pthread_setcanceltype(type_: libc::c_int, oldtype: *mut libc::c_int) -> libc::c_int {
unimplemented!();
}
// #[no_mangle]
pub extern "C" fn pthread_setconcurrency(new_level: libc::c_int) -> libc::c_int {
unimplemented!();
}
// #[no_mangle]
pub extern "C" fn pthread_setschedparam(
thread: pthread_t,
policy: libc::c_int,
param: *mut sched_param,
) -> libc::c_int {
unimplemented!();
}
// #[no_mangle]
pub extern "C" fn pthread_setspecific(
key: pthread_key_t,
value: *const libc::c_void,
) -> libc::c_int {
unimplemented!();
}
// #[no_mangle]
pub extern "C" fn pthread_testcancel() {
unimplemented!();
}
#[repr(C)]
#[derive(Debug, Copy)]
pub struct sched_param {
pub _address: u8,
}
impl Clone for sched_param {
fn clone(&self) -> Self {
*self
}
}
#[repr(C)]
#[derive(Debug, Copy)]
pub struct sched_param {
pub _address: u8,
}
impl Clone for sched_param {
fn clone(&self) -> Self {
*self
}
}
#[repr(C)]
#[derive(Debug, Copy)]
pub struct sched_param {
pub _address: u8,
}
impl Clone for sched_param {
fn clone(&self) -> Self {
*self
}
}
#[repr(C)]
#[derive(Debug, Copy)]
pub struct sched_param {
pub _address: u8,
}
impl Clone for sched_param {
fn clone(&self) -> Self {
*self
}
}
+89
View File
@@ -0,0 +1,89 @@
// #[no_mangle]
pub extern "C" fn iswalnum(wc: wint_t, locale: locale_t) -> libc::c_int {
unimplemented!();
}
// #[no_mangle]
pub extern "C" fn iswalpha(wc: wint_t, locale: locale_t) -> libc::c_int {
unimplemented!();
}
// #[no_mangle]
pub extern "C" fn iswcntrl(wc: wint_t, locale: locale_t) -> libc::c_int {
unimplemented!();
}
// #[no_mangle]
pub extern "C" fn iswdigit(wc: wint_t, locale: locale_t) -> libc::c_int {
unimplemented!();
}
// #[no_mangle]
pub extern "C" fn iswgraph(wc: wint_t, locale: locale_t) -> libc::c_int {
unimplemented!();
}
// #[no_mangle]
pub extern "C" fn iswlower(wc: wint_t, locale: locale_t) -> libc::c_int {
unimplemented!();
}
// #[no_mangle]
pub extern "C" fn iswprint(wc: wint_t, locale: locale_t) -> libc::c_int {
unimplemented!();
}
// #[no_mangle]
pub extern "C" fn iswpunct(wc: wint_t, locale: locale_t) -> libc::c_int {
unimplemented!();
}
// #[no_mangle]
pub extern "C" fn iswspace(wc: wint_t, locale: locale_t) -> libc::c_int {
unimplemented!();
}
// #[no_mangle]
pub extern "C" fn iswupper(wc: wint_t, locale: locale_t) -> libc::c_int {
unimplemented!();
}
// #[no_mangle]
pub extern "C" fn iswxdigit(wc: wint_t, locale: locale_t) -> libc::c_int {
unimplemented!();
}
// #[no_mangle]
pub extern "C" fn iswblank(wc: wint_t, locale: locale_t) -> libc::c_int {
unimplemented!();
}
// #[no_mangle]
pub extern "C" fn wctype(property: *const libc::c_char, locale: locale_t) -> wctype_t {
unimplemented!();
}
// #[no_mangle]
pub extern "C" fn iswctype(wc: wint_t, desc: wctype_t, locale: locale_t) -> libc::c_int {
unimplemented!();
}
// #[no_mangle]
pub extern "C" fn towlower(wc: wint_t, locale: locale_t) -> wint_t {
unimplemented!();
}
// #[no_mangle]
pub extern "C" fn towupper(wc: wint_t, locale: locale_t) -> wint_t {
unimplemented!();
}
// #[no_mangle]
pub extern "C" fn wctrans(property: *const libc::c_char, locale: locale_t) -> wctrans_t {
unimplemented!();
}
// #[no_mangle]
pub extern "C" fn towctrans(wc: wint_t, desc: wctrans_t, locale: locale_t) -> wint_t {
unimplemented!();
}
+7
View File
@@ -0,0 +1,7 @@
sys_includes = ["stddef.h", "sys/socket.h", "netinet/in.h"]
include_guard = "_ARPA_INET_H"
language = "C"
style = "Tag"
[enum]
prefix_with_name = true
+124
View File
@@ -0,0 +1,124 @@
//! arpa/inet implementation for Redox, following http://pubs.opengroup.org/onlinepubs/7908799/xsh/arpainet.h.html
use core::str::FromStr;
use core::{mem, ptr, slice, str};
use header::errno::*;
use header::netinet_in::in_addr;
use header::sys_socket;
use platform;
use platform::c_str;
use platform::types::*;
#[no_mangle]
pub extern "C" fn htonl(hostlong: u32) -> u32 {
hostlong.to_be()
}
#[no_mangle]
pub extern "C" fn htons(hostshort: u16) -> u16 {
hostshort.to_be()
}
#[no_mangle]
pub extern "C" fn ntohl(netlong: u32) -> u32 {
u32::from_be(netlong)
}
#[no_mangle]
pub extern "C" fn ntohs(netshort: u16) -> u16 {
u16::from_be(netshort)
}
static mut NTOA_ADDR: [c_char; 16] = [0; 16];
#[no_mangle]
pub unsafe extern "C" fn inet_aton(cp: *const c_char, inp: *mut in_addr) -> c_int {
// TODO: octal/hex
inet_pton(AF_INET, cp, inp as *mut c_void)
}
#[no_mangle]
pub unsafe extern "C" fn inet_ntoa(addr: in_addr) -> *const c_char {
inet_ntop(
AF_INET,
&addr as *const in_addr as *const c_void,
NTOA_ADDR.as_mut_ptr(),
16,
)
}
#[no_mangle]
pub unsafe extern "C" fn inet_pton(domain: c_int, src: *const c_char, dest: *mut c_void) -> c_int {
if domain != AF_INET {
platform::errno = EAFNOSUPPORT;
-1
} else {
let mut s_addr = slice::from_raw_parts_mut(
&mut (*(dest as *mut in_addr)).s_addr as *mut _ as *mut u8,
4,
);
let mut octets = str::from_utf8_unchecked(c_str(src)).split('.');
for i in 0..4 {
if let Some(n) = octets.next().and_then(|x| u8::from_str(x).ok()) {
s_addr[i] = n;
} else {
return 0;
}
}
if octets.next() == None {
1 // Success
} else {
0
}
}
}
#[no_mangle]
pub unsafe extern "C" fn inet_ntop(
domain: c_int,
src: *const c_void,
dest: *mut c_char,
size: socklen_t,
) -> *const c_char {
if domain != AF_INET {
platform::errno = EAFNOSUPPORT;
ptr::null()
} else if size < 16 {
platform::errno = ENOSPC;
ptr::null()
} else {
let s_addr = slice::from_raw_parts(
&(*(src as *const in_addr)).s_addr as *const _ as *const u8,
4,
);
let addr = format!("{}.{}.{}.{}\0", s_addr[0], s_addr[1], s_addr[2], s_addr[3]);
ptr::copy(addr.as_ptr() as *const c_char, dest, addr.len());
dest
}
}
#[no_mangle]
pub extern "C" fn inet_addr(cp: *const c_char) -> in_addr_t {
unimplemented!();
}
#[no_mangle]
pub extern "C" fn inet_lnaof(_in: in_addr) -> in_addr_t {
unimplemented!();
}
#[no_mangle]
pub extern "C" fn inet_makeaddr(net: in_addr_t, lna: in_addr_t) -> in_addr {
unimplemented!();
}
#[no_mangle]
pub extern "C" fn inet_netof(_in: in_addr) -> in_addr_t {
unimplemented!();
}
#[no_mangle]
pub extern "C" fn inet_network(cp: *const c_char) -> in_addr_t {
unimplemented!();
}
+7
View File
@@ -0,0 +1,7 @@
sys_includes = []
include_guard = "_CTYPE_H"
language = "C"
style = "Tag"
[enum]
prefix_with_name = true
+94
View File
@@ -0,0 +1,94 @@
//! ctype implementation for Redox, following http://pubs.opengroup.org/onlinepubs/7908799/xsh/ctype.h.html
use platform;
use platform::types::*;
#[no_mangle]
pub extern "C" fn isalnum(c: c_int) -> c_int {
(isdigit(c) != 0 || isalpha(c) != 0) as c_int
}
#[no_mangle]
pub extern "C" fn isalpha(c: c_int) -> c_int {
(islower(c) != 0 || isupper(c) != 0) as c_int
}
#[no_mangle]
pub extern "C" fn isascii(c: c_int) -> c_int {
((c & !0x7f) == 0) as c_int
}
#[no_mangle]
pub extern "C" fn isblank(c: c_int) -> c_int {
(c == ' ' as c_int || c == '\t' as c_int) as c_int
}
#[no_mangle]
pub extern "C" fn iscntrl(c: c_int) -> c_int {
((c as c_uint) < 0x20 || c == 0x7f) as c_int
}
#[no_mangle]
pub extern "C" fn isdigit(c: c_int) -> c_int {
(((c - 0x30) as c_uint) < 10) as c_int
}
#[no_mangle]
pub extern "C" fn isgraph(c: c_int) -> c_int {
(((c - 0x21) as c_uint) < 0x5e) as c_int
}
#[no_mangle]
pub extern "C" fn islower(c: c_int) -> c_int {
(((c - 0x61) as c_uint) < 26) as c_int
}
#[no_mangle]
pub extern "C" fn isprint(c: c_int) -> c_int {
(((c - 0x20) as c_uint) < 0x5f) as c_int
}
#[no_mangle]
pub extern "C" fn ispunct(c: c_int) -> c_int {
(isgraph(c) != 0 && !isalnum(c) != 0) as c_int
}
#[no_mangle]
pub extern "C" fn isspace(c: c_int) -> c_int {
(c == 0x20) as c_int
}
#[no_mangle]
pub extern "C" fn isupper(c: c_int) -> c_int {
(((c - 0x41) as c_uint) < 26) as c_int
}
#[no_mangle]
pub extern "C" fn isxdigit(c: c_int) -> c_int {
(isdigit(c) != 0 || ((c as c_int) | 32) - ('a' as c_int) < 6) as c_int
}
#[no_mangle]
/// The comment in musl:
/// "nonsense function that should NEVER be used!"
pub extern "C" fn toascii(c: c_int) -> c_int {
c & 0x7f
}
#[no_mangle]
pub extern "C" fn tolower(c: c_int) -> c_int {
if isupper(c) != 0 {
c + 0x20
} else {
c
}
}
#[no_mangle]
pub extern "C" fn toupper(c: c_int) -> c_int {
if islower(c) != 0 {
c - 0x20
} else {
c
}
}
+8
View File
@@ -0,0 +1,8 @@
sys_includes = ["sys/types.h"]
include_guard = "_DIRENT_H"
language = "C"
style = "Both"
trailer = "#include <bits/dirent.h>"
[enum]
prefix_with_name = true
+124
View File
@@ -0,0 +1,124 @@
//! dirent implementation following http://pubs.opengroup.org/onlinepubs/009695399/basedefs/dirent.h.html
use alloc::boxed::Box;
use core::{mem, ptr};
use header::{errno, fcntl, stdio, unistd};
use platform::{Pal, Sys};
use platform::types::*;
const DIR_BUF_SIZE: usize = mem::size_of::<dirent>() * 3;
// No repr(C) needed, C won't see the content
// TODO: ***THREAD SAFETY***
pub struct DIR {
fd: c_int,
buf: [c_char; DIR_BUF_SIZE],
// index & len are specified in bytes
index: usize,
len: usize,
// Offset is like the total index, never erased It is used as an
// alternative to dirent's d_off, but works on redox too.
offset: usize,
}
#[repr(C)]
pub struct dirent {
pub d_ino: ino_t,
pub d_off: off_t,
pub d_reclen: c_ushort,
pub d_type: c_uchar,
pub d_name: [c_char; 256],
}
#[no_mangle]
pub extern "C" fn opendir(path: *const c_char) -> *mut DIR {
let fd = Sys::open(
path,
fcntl::O_RDONLY | fcntl::O_DIRECTORY | fcntl::O_CLOEXEC,
0,
);
if fd < 0 {
return ptr::null_mut();
}
Box::into_raw(Box::new(DIR {
fd,
buf: [0; DIR_BUF_SIZE],
index: 0,
len: 0,
offset: 0,
}))
}
#[no_mangle]
pub unsafe extern "C" fn closedir(dir: *mut DIR) -> c_int {
let ret = Sys::close((*dir).fd);
Box::from_raw(dir);
ret
}
#[no_mangle]
pub unsafe extern "C" fn readdir(dir: *mut DIR) -> *mut dirent {
if (*dir).index >= (*dir).len {
let read = Sys::getdents(
(*dir).fd,
(*dir).buf.as_mut_ptr() as *mut platform::types::dirent,
(*dir).buf.len(),
);
if read <= 0 {
if read != 0 && read != -errno::ENOENT {
platform::errno = -read;
}
return ptr::null_mut();
}
(*dir).index = 0;
(*dir).len = read as usize;
}
let ptr = (*dir).buf.as_mut_ptr().offset((*dir).index as isize) as *mut dirent;
#[cfg(target_os = "redox")]
{
if (*dir).index != 0 || (*dir).offset != 0 {
// This should happen every time but the first, making the offset
// point to the current element and not the next
(*dir).offset += mem::size_of::<dirent>();
}
(*ptr).d_off = (*dir).offset as off_t;
}
#[cfg(not(target_os = "redox"))]
{
(*dir).offset = (*ptr).d_off as usize;
}
(*dir).index += (*ptr).d_reclen as usize;
ptr
}
// #[no_mangle]
pub extern "C" fn readdir_r(
_dir: *mut DIR,
_entry: *mut dirent,
_result: *mut *mut dirent,
) -> *mut dirent {
unimplemented!(); // plus, deprecated
}
#[no_mangle]
pub unsafe extern "C" fn telldir(dir: *mut DIR) -> c_long {
(*dir).offset as c_long
}
#[no_mangle]
pub unsafe extern "C" fn seekdir(dir: *mut DIR, off: c_long) {
unistd::lseek((*dir).fd, off, unistd::SEEK_SET);
(*dir).offset = off as usize;
(*dir).index = 0;
(*dir).len = 0;
}
#[no_mangle]
pub unsafe extern "C" fn rewinddir(dir: *mut DIR) {
seekdir(dir, 0)
}
+7
View File
@@ -0,0 +1,7 @@
sys_includes = ["bits/errno.h"]
include_guard = "_ERRNO_H"
language = "C"
style = "Tag"
[enum]
prefix_with_name = true
+281
View File
@@ -0,0 +1,281 @@
//! errno implementation for Redox, following http://pubs.opengroup.org/onlinepubs/7908799/xsh/errno.h.html
use platform;
use platform::types::*;
#[no_mangle]
pub unsafe extern "C" fn __errno() -> *mut c_int {
&mut platform::errno
}
#[no_mangle]
pub unsafe extern "C" fn __errno_location() -> *mut c_int {
__errno()
}
pub const EPERM: c_int = 1; /* Operation not permitted */
pub const ENOENT: c_int = 2; /* No such file or directory */
pub const ESRCH: c_int = 3; /* No such process */
pub const EINTR: c_int = 4; /* Interrupted system call */
pub const EIO: c_int = 5; /* I/O error */
pub const ENXIO: c_int = 6; /* No such device or address */
pub const E2BIG: c_int = 7; /* Argument list too long */
pub const ENOEXEC: c_int = 8; /* Exec format error */
pub const EBADF: c_int = 9; /* Bad file number */
pub const ECHILD: c_int = 10; /* No child processes */
pub const EAGAIN: c_int = 11; /* Try again */
pub const ENOMEM: c_int = 12; /* Out of memory */
pub const EACCES: c_int = 13; /* Permission denied */
pub const EFAULT: c_int = 14; /* Bad address */
pub const ENOTBLK: c_int = 15; /* Block device required */
pub const EBUSY: c_int = 16; /* Device or resource busy */
pub const EEXIST: c_int = 17; /* File exists */
pub const EXDEV: c_int = 18; /* Cross-device link */
pub const ENODEV: c_int = 19; /* No such device */
pub const ENOTDIR: c_int = 20; /* Not a directory */
pub const EISDIR: c_int = 21; /* Is a directory */
pub const EINVAL: c_int = 22; /* Invalid argument */
pub const ENFILE: c_int = 23; /* File table overflow */
pub const EMFILE: c_int = 24; /* Too many open files */
pub const ENOTTY: c_int = 25; /* Not a typewriter */
pub const ETXTBSY: c_int = 26; /* Text file busy */
pub const EFBIG: c_int = 27; /* File too large */
pub const ENOSPC: c_int = 28; /* No space left on device */
pub const ESPIPE: c_int = 29; /* Illegal seek */
pub const EROFS: c_int = 30; /* Read-only file system */
pub const EMLINK: c_int = 31; /* Too many links */
pub const EPIPE: c_int = 32; /* Broken pipe */
pub const EDOM: c_int = 33; /* Math argument out of domain of func */
pub const ERANGE: c_int = 34; /* Math result not representable */
pub const EDEADLK: c_int = 35; /* Resource deadlock would occur */
pub const ENAMETOOLONG: c_int = 36; /* File name too long */
pub const ENOLCK: c_int = 37; /* No record locks available */
pub const ENOSYS: c_int = 38; /* Function not implemented */
pub const ENOTEMPTY: c_int = 39; /* Directory not empty */
pub const ELOOP: c_int = 40; /* Too many symbolic links encountered */
pub const EWOULDBLOCK: c_int = 41; /* Operation would block */
pub const ENOMSG: c_int = 42; /* No message of desired type */
pub const EIDRM: c_int = 43; /* Identifier removed */
pub const ECHRNG: c_int = 44; /* Channel number out of range */
pub const EL2NSYNC: c_int = 45; /* Level 2 not synchronized */
pub const EL3HLT: c_int = 46; /* Level 3 halted */
pub const EL3RST: c_int = 47; /* Level 3 reset */
pub const ELNRNG: c_int = 48; /* Link number out of range */
pub const EUNATCH: c_int = 49; /* Protocol driver not attached */
pub const ENOCSI: c_int = 50; /* No CSI structure available */
pub const EL2HLT: c_int = 51; /* Level 2 halted */
pub const EBADE: c_int = 52; /* Invalid exchange */
pub const EBADR: c_int = 53; /* Invalid request descriptor */
pub const EXFULL: c_int = 54; /* Exchange full */
pub const ENOANO: c_int = 55; /* No anode */
pub const EBADRQC: c_int = 56; /* Invalid request code */
pub const EBADSLT: c_int = 57; /* Invalid slot */
pub const EDEADLOCK: c_int = 58; /* Resource deadlock would occur */
pub const EBFONT: c_int = 59; /* Bad font file format */
pub const ENOSTR: c_int = 60; /* Device not a stream */
pub const ENODATA: c_int = 61; /* No data available */
pub const ETIME: c_int = 62; /* Timer expired */
pub const ENOSR: c_int = 63; /* Out of streams resources */
pub const ENONET: c_int = 64; /* Machine is not on the network */
pub const ENOPKG: c_int = 65; /* Package not installed */
pub const EREMOTE: c_int = 66; /* Object is remote */
pub const ENOLINK: c_int = 67; /* Link has been severed */
pub const EADV: c_int = 68; /* Advertise error */
pub const ESRMNT: c_int = 69; /* Srmount error */
pub const ECOMM: c_int = 70; /* Communication error on send */
pub const EPROTO: c_int = 71; /* Protocol error */
pub const EMULTIHOP: c_int = 72; /* Multihop attempted */
pub const EDOTDOT: c_int = 73; /* RFS specific error */
pub const EBADMSG: c_int = 74; /* Not a data message */
pub const EOVERFLOW: c_int = 75; /* Value too large for defined data type */
pub const ENOTUNIQ: c_int = 76; /* Name not unique on network */
pub const EBADFD: c_int = 77; /* File descriptor in bad state */
pub const EREMCHG: c_int = 78; /* Remote address changed */
pub const ELIBACC: c_int = 79; /* Can not access a needed shared library */
pub const ELIBBAD: c_int = 80; /* Accessing a corrupted shared library */
pub const ELIBSCN: c_int = 81; /* .lib section in a.out corrupted */
pub const ELIBMAX: c_int = 82; /* Attempting to link in too many shared libraries */
pub const ELIBEXEC: c_int = 83; /* Cannot exec a shared library directly */
pub const EILSEQ: c_int = 84; /* Illegal byte sequence */
pub const ERESTART: c_int = 85; /* Interrupted system call should be restarted */
pub const ESTRPIPE: c_int = 86; /* Streams pipe error */
pub const EUSERS: c_int = 87; /* Too many users */
pub const ENOTSOCK: c_int = 88; /* Socket operation on non-socket */
pub const EDESTADDRREQ: c_int = 89; /* Destination address required */
pub const EMSGSIZE: c_int = 90; /* Message too long */
pub const EPROTOTYPE: c_int = 91; /* Protocol wrong type for socket */
pub const ENOPROTOOPT: c_int = 92; /* Protocol not available */
pub const EPROTONOSUPPORT: c_int = 93; /* Protocol not supported */
pub const ESOCKTNOSUPPORT: c_int = 94; /* Socket type not supported */
pub const EOPNOTSUPP: c_int = 95; /* Operation not supported on transport endpoint */
pub const EPFNOSUPPORT: c_int = 96; /* Protocol family not supported */
pub const EAFNOSUPPORT: c_int = 97; /* Address family not supported by protocol */
pub const EADDRINUSE: c_int = 98; /* Address already in use */
pub const EADDRNOTAVAIL: c_int = 99; /* Cannot assign requested address */
pub const ENETDOWN: c_int = 100; /* Network is down */
pub const ENETUNREACH: c_int = 101; /* Network is unreachable */
pub const ENETRESET: c_int = 102; /* Network dropped connection because of reset */
pub const ECONNABORTED: c_int = 103; /* Software caused connection abort */
pub const ECONNRESET: c_int = 104; /* Connection reset by peer */
pub const ENOBUFS: c_int = 105; /* No buffer space available */
pub const EISCONN: c_int = 106; /* Transport endpoint is already connected */
pub const ENOTCONN: c_int = 107; /* Transport endpoint is not connected */
pub const ESHUTDOWN: c_int = 108; /* Cannot send after transport endpoint shutdown */
pub const ETOOMANYREFS: c_int = 109; /* Too many references: cannot splice */
pub const ETIMEDOUT: c_int = 110; /* Connection timed out */
pub const ECONNREFUSED: c_int = 111; /* Connection refused */
pub const EHOSTDOWN: c_int = 112; /* Host is down */
pub const EHOSTUNREACH: c_int = 113; /* No route to host */
pub const EALREADY: c_int = 114; /* Operation already in progress */
pub const EINPROGRESS: c_int = 115; /* Operation now in progress */
pub const ESTALE: c_int = 116; /* Stale NFS file handle */
pub const EUCLEAN: c_int = 117; /* Structure needs cleaning */
pub const ENOTNAM: c_int = 118; /* Not a XENIX named type file */
pub const ENAVAIL: c_int = 119; /* No XENIX semaphores available */
pub const EISNAM: c_int = 120; /* Is a named type file */
pub const EREMOTEIO: c_int = 121; /* Remote I/O error */
pub const EDQUOT: c_int = 122; /* Quota exceeded */
pub const ENOMEDIUM: c_int = 123; /* No medium found */
pub const EMEDIUMTYPE: c_int = 124; /* Wrong medium type */
pub const ECANCELED: c_int = 125; /* Operation Canceled */
pub const ENOKEY: c_int = 126; /* Required key not available */
pub const EKEYEXPIRED: c_int = 127; /* Key has expired */
pub const EKEYREVOKED: c_int = 128; /* Key has been revoked */
pub const EKEYREJECTED: c_int = 129; /* Key was rejected by service */
pub const EOWNERDEAD: c_int = 130; /* Owner died */
pub const ENOTRECOVERABLE: c_int = 131; /* State not recoverable */
pub static STR_ERROR: [&'static str; 132] = [
"Success",
"Operation not permitted",
"No such file or directory",
"No such process",
"Interrupted system call",
"I/O error",
"No such device or address",
"Argument list too long",
"Exec format error",
"Bad file number",
"No child processes",
"Try again",
"Out of memory",
"Permission denied",
"Bad address",
"Block device required",
"Device or resource busy",
"File exists",
"Cross-device link",
"No such device",
"Not a directory",
"Is a directory",
"Invalid argument",
"File table overflow",
"Too many open files",
"Not a typewriter",
"Text file busy",
"File too large",
"No space left on device",
"Illegal seek",
"Read-only file system",
"Too many links",
"Broken pipe",
"Math argument out of domain of func",
"Math result not representable",
"Resource deadlock would occur",
"File name too long",
"No record locks available",
"Function not implemented",
"Directory not empty",
"Too many symbolic links encountered",
"Operation would block",
"No message of desired type",
"Identifier removed",
"Channel number out of range",
"Level 2 not synchronized",
"Level 3 halted",
"Level 3 reset",
"Link number out of range",
"Protocol driver not attached",
"No CSI structure available",
"Level 2 halted",
"Invalid exchange",
"Invalid request descriptor",
"Exchange full",
"No anode",
"Invalid request code",
"Invalid slot",
"Resource deadlock would occur",
"Bad font file format",
"Device not a stream",
"No data available",
"Timer expired",
"Out of streams resources",
"Machine is not on the network",
"Package not installed",
"Object is remote",
"Link has been severed",
"Advertise error",
"Srmount error",
"Communication error on send",
"Protocol error",
"Multihop attempted",
"RFS specific error",
"Not a data message",
"Value too large for defined data type",
"Name not unique on network",
"File descriptor in bad state",
"Remote address changed",
"Can not access a needed shared library",
"Accessing a corrupted shared library",
".lib section in a.out corrupted",
"Attempting to link in too many shared libraries",
"Cannot exec a shared library directly",
"Illegal byte sequence",
"Interrupted system call should be restarted",
"Streams pipe error",
"Too many users",
"Socket operation on non-socket",
"Destination address required",
"Message too long",
"Protocol wrong type for socket",
"Protocol not available",
"Protocol not supported",
"Socket type not supported",
"Operation not supported on transport endpoint",
"Protocol family not supported",
"Address family not supported by protocol",
"Address already in use",
"Cannot assign requested address",
"Network is down",
"Network is unreachable",
"Network dropped connection because of reset",
"Software caused connection abort",
"Connection reset by peer",
"No buffer space available",
"Transport endpoint is already connected",
"Transport endpoint is not connected",
"Cannot send after transport endpoint shutdown",
"Too many references: cannot splice",
"Connection timed out",
"Connection refused",
"Host is down",
"No route to host",
"Operation already in progress",
"Operation now in progress",
"Stale NFS file handle",
"Structure needs cleaning",
"Not a XENIX named type file",
"No XENIX semaphores available",
"Is a named type file",
"Remote I/O error",
"Quota exceeded",
"No medium found",
"Wrong medium type",
"Operation Canceled",
"Required key not available",
"Key has expired",
"Key has been revoked",
"Key was rejected by service",
"Owner died",
"State not recoverable",
];
+12
View File
@@ -0,0 +1,12 @@
sys_includes = ["stdarg.h", "sys/types.h"]
include_guard = "_FCNTL_H"
trailer = "#include <bits/fcntl.h>"
language = "C"
style = "Tag"
[defines]
"target_os=linux" = "__linux__"
"target_os=redox" = "__redox__"
[enum]
prefix_with_name = true
+15
View File
@@ -0,0 +1,15 @@
use platform::types::*;
pub const O_RDONLY: c_int = 0x0000;
pub const O_WRONLY: c_int = 0x0001;
pub const O_RDWR: c_int = 0x0002;
pub const O_CREAT: c_int = 0x0040;
pub const O_EXCL: c_int = 0x0080;
pub const O_TRUNC: c_int = 0x0200;
pub const O_APPEND: c_int = 0x0400;
pub const O_NONBLOCK: c_int = 0x0800;
pub const O_DIRECTORY: c_int = 0x1_0000;
pub const O_NOFOLLOW: c_int = 0x2_0000;
pub const O_CLOEXEC: c_int = 0x8_0000;
pub const O_PATH: c_int = 0x20_0000;
pub const O_ACCMODE: c_int = O_RDONLY | O_WRONLY | O_RDWR;
+45
View File
@@ -0,0 +1,45 @@
//! fcntl implementation for Redox, following http://pubs.opengroup.org/onlinepubs/7908799/xsh/fcntl.h.html
use platform;
use platform::{Pal, Sys};
use platform::types::*;
pub use sys::*;
#[cfg(target_os = "linux")]
#[path = "linux.rs"]
pub mod sys;
#[cfg(target_os = "redox")]
#[path = "redox.rs"]
pub mod sys;
pub const F_DUPFD: c_int = 0;
pub const F_GETFD: c_int = 1;
pub const F_SETFD: c_int = 2;
pub const F_GETFL: c_int = 3;
pub const F_SETFL: c_int = 4;
pub const F_GETLK: c_int = 5;
pub const F_SETLK: c_int = 6;
pub const F_SETLKW: c_int = 7;
pub const FD_CLOEXEC: c_int = 0x0100_0000;
pub const F_RDLCK: c_int = 0;
pub const F_WRLCK: c_int = 1;
pub const F_UNLCK: c_int = 2;
#[no_mangle]
pub extern "C" fn creat(path: *const c_char, mode: mode_t) -> c_int {
sys_open(path, O_WRONLY | O_CREAT | O_TRUNC, mode)
}
#[no_mangle]
pub extern "C" fn sys_fcntl(fildes: c_int, cmd: c_int, arg: c_int) -> c_int {
Sys::fcntl(fildes, cmd, arg)
}
#[no_mangle]
pub extern "C" fn sys_open(path: *const c_char, oflag: c_int, mode: mode_t) -> c_int {
Sys::open(path, oflag, mode)
}
+20
View File
@@ -0,0 +1,20 @@
use platform::types::*;
pub const O_RDONLY: c_int = 0x0001_0000;
pub const O_WRONLY: c_int = 0x0002_0000;
pub const O_RDWR: c_int = 0x0003_0000;
pub const O_NONBLOCK: c_int = 0x0004_0000;
pub const O_APPEND: c_int = 0x0008_0000;
pub const O_SHLOCK: c_int = 0x0010_0000;
pub const O_EXLOCK: c_int = 0x0020_0000;
pub const O_ASYNC: c_int = 0x0040_0000;
pub const O_FSYNC: c_int = 0x0080_0000;
pub const O_CLOEXEC: c_int = 0x0100_0000;
pub const O_CREAT: c_int = 0x0200_0000;
pub const O_TRUNC: c_int = 0x0400_0000;
pub const O_EXCL: c_int = 0x0800_0000;
pub const O_DIRECTORY: c_int = 0x1000_0000;
pub const O_PATH: c_int = 0x2000_0000;
pub const O_SYMLINK: c_int = 0x4000_0000;
pub const O_NOFOLLOW: c_int = 0x8000_0000;
pub const O_ACCMODE: c_int = O_RDONLY | O_WRONLY | O_RDWR;
+7
View File
@@ -0,0 +1,7 @@
sys_includes = ["stdint.h", "sys/types.h"]
include_guard = "_FENV_H"
language = "C"
style = "Tag"
[enum]
prefix_with_name = true
+70
View File
@@ -0,0 +1,70 @@
//! fenv.h implementation for Redox, following
//! http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/fenv.h.html
use platform;
use platform::types::*;
pub const FE_ALL_EXCEPT: c_int = 0;
pub const FE_TONEAREST: c_int = 0;
pub type fexcept_t = u64;
#[repr(C)]
pub struct fenv_t {
pub cw: u64,
}
// #[no_mangle]
pub unsafe extern "C" fn feclearexcept(excepts: c_int) -> c_int {
unimplemented!();
}
// #[no_mangle]
pub unsafe extern "C" fn fegenenv(envp: *mut fenv_t) -> c_int {
unimplemented!();
}
// #[no_mangle]
pub unsafe extern "C" fn fegetexceptflag(flagp: *mut fexcept_t, excepts: c_int) -> c_int {
unimplemented!();
}
#[no_mangle]
pub unsafe extern "C" fn fegetround() -> c_int {
FE_TONEAREST
}
// #[no_mangle]
pub unsafe extern "C" fn feholdexcept(envp: *mut fenv_t) -> c_int {
unimplemented!();
}
// #[no_mangle]
pub unsafe extern "C" fn feraiseexcept(except: c_int) -> c_int {
unimplemented!();
}
// #[no_mangle]
pub unsafe extern "C" fn fesetenv(envp: *const fenv_t) -> c_int {
unimplemented!();
}
// #[no_mangle]
pub unsafe extern "C" fn fesetexceptflag(flagp: *const fexcept_t, excepts: c_int) -> c_int {
unimplemented!();
}
// #[no_mangle]
pub unsafe extern "C" fn fesetround(round: c_int) -> c_int {
unimplemented!();
}
// #[no_mangle]
pub unsafe extern "C" fn fetestexcept(excepts: c_int) -> c_int {
unimplemented!();
}
// #[no_mangle]
pub unsafe extern "C" fn feupdateenv(envp: *const fenv_t) -> c_int {
unimplemented!();
}
+7
View File
@@ -0,0 +1,7 @@
sys_includes = ["sys/types.h", "bits/float.h"]
include_guard = "_FLOAT_H"
language = "C"
style = "Tag"
[enum]
prefix_with_name = true
+16
View File
@@ -0,0 +1,16 @@
//! float.h implementation for Redox, following
//! http://pubs.opengroup.org/onlinepubs/7908799/xsh/float.h.html
use header::fenv::{fegetround, FE_TONEAREST};
use platform;
use platform::types::*;
pub const FLT_RADIX: c_int = 2;
#[no_mangle]
pub unsafe extern "C" fn flt_rounds() -> c_int {
match fegetround() {
FE_TONEAREST => 1,
_ => -1,
}
}
+6
View File
@@ -0,0 +1,6 @@
include_guard = "_FNMATCH_H"
language = "C"
style = "Tag"
[enum]
prefix_with_name = true
+163
View File
@@ -0,0 +1,163 @@
//! fnmatch implementation
use alloc::vec::Vec;
use platform;
use platform::types::*;
pub const FNM_NOMATCH: c_int = 1;
pub const FNM_NOESCAPE: c_int = 1;
pub const FNM_PATHNAME: c_int = 2;
pub const FNM_PERIOD: c_int = 4;
pub const FNM_CASEFOLD: c_int = 8;
#[derive(Debug)]
enum Token {
Any,
Char(u8),
Match(bool, Vec<u8>),
Wildcard,
// TODO: FNM_EXTMATCH, which is basically a whole another custom regex
// format that's ambigious and ugh. The C standard library is really bloaty
// and I sure hope we can get away with delaying this as long as possible.
// If you need to implement this, you can contact jD91mZM2 for assistance
// in reading this code in case it's ugly.
}
unsafe fn next_token(pattern: &mut *const c_char, flags: c_int) -> Option<Token> {
let c = **pattern as u8;
if c == 0 {
return None;
}
*pattern = pattern.offset(1);
Some(match c {
b'\\' if flags & FNM_NOESCAPE == FNM_NOESCAPE => {
let c = **pattern as u8;
if c == 0 {
// Trailing backslash. Maybe error here?
return None;
}
*pattern = pattern.offset(1);
Token::Char(c)
},
b'?' => Token::Any,
b'*' => Token::Wildcard,
b'[' => {
let mut matches = Vec::new();
let invert = if **pattern as u8 == b'!' {
*pattern = pattern.offset(1);
true
} else { false };
loop {
let mut c = **pattern as u8;
if c == 0 {
break;
}
*pattern = pattern.offset(1);
match c {
b']' => break,
b'\\' => {
c = **pattern as u8;
*pattern = pattern.offset(1);
if c == 0 {
// Trailing backslash. Maybe error?
break;
}
},
_ => ()
}
if matches.len() >= 2 && matches[matches.len() - 1] == b'-' {
let len = matches.len();
let start = matches[len - 2];
matches.drain(len - 2..);
// Exclusive range because we'll push C later
for c in start..c {
matches.push(c);
}
}
matches.push(c);
}
// Otherwise, there was no closing ]. Maybe error?
Token::Match(invert, matches)
},
c => Token::Char(c)
})
}
#[no_mangle]
pub unsafe extern "C" fn fnmatch(mut pattern: *const c_char, mut input: *const c_char, flags: c_int) -> c_int {
let pathname = flags & FNM_PATHNAME == FNM_PATHNAME;
let casefold = flags & FNM_CASEFOLD == FNM_CASEFOLD;
let mut leading = true;
loop {
if *input == 0 {
return if *pattern == 0 { 0 } else { FNM_NOMATCH };
}
if leading && flags & FNM_PERIOD == FNM_PERIOD {
if *input as u8 == b'.' && *pattern as u8 != b'.' {
return FNM_NOMATCH;
}
}
leading = false;
match next_token(&mut pattern, flags) {
Some(Token::Any) => {
if pathname && *input as u8 == b'/' {
return FNM_NOMATCH;
}
input = input.offset(1);
},
Some(Token::Char(c)) => {
let mut a = *input as u8;
if casefold && a >= b'a' && a <= b'z' {
a -= b'a' - b'A';
}
let mut b = c;
if casefold && b >= b'a' && b <= b'z' {
b -= b'a' - b'A';
}
if a != b {
return FNM_NOMATCH;
}
if pathname && a == b'/' {
leading = true;
}
input = input.offset(1);
},
Some(Token::Match(invert, matches)) => {
if (pathname && *input as u8 == b'/') || matches.contains(&(*input as u8)) == invert {
// Found it, but it's inverted! Or vise versa.
return FNM_NOMATCH;
}
input = input.offset(1);
},
Some(Token::Wildcard) => {
loop {
let c = *input as u8;
if c == 0 {
return if *pattern == 0 { 0 } else { FNM_NOMATCH };
}
let ret = fnmatch(pattern, input, flags);
if ret == FNM_NOMATCH {
input = input.offset(1);
} else {
// Either an error or a match. Forward the return.
return ret;
}
if pathname && c == b'/' {
// End of segment, no match yet
return FNM_NOMATCH;
}
}
unreachable!("nothing should be able to break out of the loop");
},
None => return FNM_NOMATCH // Pattern ended but there's still some input
}
}
}
+7
View File
@@ -0,0 +1,7 @@
sys_includes = []
include_guard = "_GRP_H"
language = "C"
style = "Tag"
[enum]
prefix_with_name = true
+66
View File
@@ -0,0 +1,66 @@
//! grp implementation for Redox, following http://pubs.opengroup.org/onlinepubs/7908799/xsh/grp.h.html
use platform;
use platform::types::*;
#[repr(C)]
pub struct group {
pub gr_name: *mut c_char,
pub gr_passwd: *mut c_char,
pub gr_gid: gid_t,
pub gr_mem: *mut *mut c_char,
}
// #[no_mangle]
pub extern "C" fn getgrgid(gid: gid_t) -> *mut group {
unimplemented!();
}
// #[no_mangle]
pub extern "C" fn getgrnam(name: *const c_char) -> *mut group {
unimplemented!();
}
// #[no_mangle]
pub extern "C" fn getgrgid_r(
gid: gid_t,
grp: *mut group,
buffer: *mut c_char,
bufsize: usize,
result: *mut *mut group,
) -> c_int {
unimplemented!();
}
// #[no_mangle]
pub extern "C" fn getgrnam_r(
name: *const c_char,
grp: *mut group,
buffer: *mut c_char,
bufsize: usize,
result: *mut *mut group,
) -> c_int {
unimplemented!();
}
// #[no_mangle]
pub extern "C" fn getgrent() -> *mut group {
unimplemented!();
}
// #[no_mangle]
pub extern "C" fn endgrent() {
unimplemented!();
}
// #[no_mangle]
pub extern "C" fn setgrent() {
unimplemented!();
}
/*
#[no_mangle]
pub extern "C" fn func(args) -> c_int {
unimplemented!();
}
*/
+8
View File
@@ -0,0 +1,8 @@
sys_includes = ["stdint.h", "wchar.h"]
include_guard = "_INTTYPES_H"
trailer = "#include <bits/inttypes.h>"
language = "C"
style = "Type"
[enum]
prefix_with_name = true
+80
View File
@@ -0,0 +1,80 @@
use header::{ctype, stdlib};
use header::errno::*;
use platform;
use platform::types::*;
#[no_mangle]
pub extern "C" fn imaxabs(i: intmax_t) -> intmax_t {
i.abs()
}
#[no_mangle]
#[repr(C)]
pub struct intmaxdiv_t {
quot: intmax_t,
rem: intmax_t,
}
#[no_mangle]
pub extern "C" fn imaxdiv(i: intmax_t, j: intmax_t) -> intmaxdiv_t {
intmaxdiv_t {
quot: i / j,
rem: i % j,
}
}
#[no_mangle]
pub unsafe extern "C" fn strtoimax(
s: *const c_char,
endptr: *mut *mut c_char,
base: c_int,
) -> intmax_t {
use stdlib::*;
strto_impl!(
intmax_t,
false,
intmax_t::max_value(),
intmax_t::min_value(),
s,
endptr,
base
)
}
#[no_mangle]
pub unsafe extern "C" fn strtoumax(
s: *const c_char,
endptr: *mut *mut c_char,
base: c_int,
) -> uintmax_t {
use stdlib::*;
strto_impl!(
uintmax_t,
false,
uintmax_t::max_value(),
uintmax_t::min_value(),
s,
endptr,
base
)
}
#[allow(unused)]
// #[no_mangle]
pub extern "C" fn wcstoimax(
nptr: *const wchar_t,
endptr: *mut *mut wchar_t,
base: c_int,
) -> intmax_t {
unimplemented!();
}
#[allow(unused)]
// #[no_mangle]
pub extern "C" fn wcstoumax(
nptr: *const wchar_t,
endptr: *mut *mut wchar_t,
base: c_int,
) -> uintmax_t {
unimplemented!();
}
+7
View File
@@ -0,0 +1,7 @@
include_guard = "_LOCALE_H"
trailer = "#include <bits/locale.h>"
language = "C"
style = "Tag"
[enum]
prefix_with_name = true
+69
View File
@@ -0,0 +1,69 @@
//! locale implementation for Redox, following http://pubs.opengroup.org/onlinepubs/7908799/xsh/locale.h.html
use core::ptr;
use platform;
use platform::types::*;
const EMPTY_PTR: *const c_char = "\0" as *const _ as *const c_char;
// Can't use &str because of the mutability
static mut C_LOCALE: [c_char; 2] = [b'C' as c_char, 0];
#[repr(C)]
#[no_mangle]
pub struct lconv {
currency_symbol: *const c_char,
decimal_point: *const c_char,
frac_digits: c_char,
grouping: *const c_char,
int_curr_symbol: *const c_char,
int_frac_digits: c_char,
mon_decimal_point: *const c_char,
mon_grouping: *const c_char,
mon_thousands_sep: *const c_char,
negative_sign: *const c_char,
n_cs_precedes: c_char,
n_sep_by_space: c_char,
n_sign_posn: c_char,
positive_sign: *const c_char,
p_cs_precedes: c_char,
p_sep_by_space: c_char,
p_sign_posn: c_char,
thousands_sep: *const c_char,
}
unsafe impl Sync for lconv {}
static CURRENT_LOCALE: lconv = lconv {
currency_symbol: EMPTY_PTR,
decimal_point: ".\0" as *const _ as *const c_char,
frac_digits: c_char::max_value(),
grouping: EMPTY_PTR,
int_curr_symbol: EMPTY_PTR,
int_frac_digits: c_char::max_value(),
mon_decimal_point: EMPTY_PTR,
mon_grouping: EMPTY_PTR,
mon_thousands_sep: EMPTY_PTR,
negative_sign: EMPTY_PTR,
n_cs_precedes: c_char::max_value(),
n_sep_by_space: c_char::max_value(),
n_sign_posn: c_char::max_value(),
positive_sign: EMPTY_PTR,
p_cs_precedes: c_char::max_value(),
p_sep_by_space: c_char::max_value(),
p_sign_posn: c_char::max_value(),
thousands_sep: EMPTY_PTR,
};
#[no_mangle]
pub extern "C" fn localeconv() -> *const lconv {
&CURRENT_LOCALE as *const _
}
#[no_mangle]
pub unsafe extern "C" fn setlocale(_option: c_int, val: *const c_char) -> *mut c_char {
if val.is_null() {
return C_LOCALE.as_mut_ptr() as *mut c_char;
}
// TODO actually implement
ptr::null_mut()
}
+38
View File
@@ -0,0 +1,38 @@
pub mod arpa_inet;
pub mod ctype;
pub mod dirent;
pub mod errno;
pub mod fcntl;
pub mod fenv;
pub mod float;
pub mod fnmatch;
pub mod grp;
pub mod inttypes;
pub mod locale;
pub mod netinet_in;
pub mod pwd;
pub mod semaphore;
pub mod sgtty;
pub mod signal;
pub mod stdio;
pub mod stdlib;
pub mod string;
pub mod strings;
pub mod sys_file;
pub mod sys_ioctl;
pub mod sys_mman;
pub mod sys_resource;
pub mod sys_select;
pub mod sys_socket;
pub mod sys_stat;
pub mod sys_time;
pub mod sys_times;
pub mod sys_un;
pub mod sys_utsname;
pub mod sys_wait;
pub mod termios;
pub mod time;
pub mod unistd;
pub mod utime;
pub mod wchar;
pub mod wctype;
+7
View File
@@ -0,0 +1,7 @@
[package]
name = "netinet"
version = "0.1.0"
authors = ["Dan Robertson <danlrobertson89@gmail.com>"]
[dependencies]
in_h = { path = "in" }
+10
View File
@@ -0,0 +1,10 @@
sys_includes = ["sys/types.h", "sys/socket.h"]
include_guard = "_NETINET_IN_H"
style = "Both"
language = "C"
[export]
include = ["sockaddr_in6", "sockaddr_in", "ipv6_mreq"]
[enum]
prefix_with_name = true
+64
View File
@@ -0,0 +1,64 @@
#![allow(non_camel_case_types)]
use header::sys_socket::{self, sa_family_t, sockaddr};
use platform;
use platform::types::*;
pub type in_addr_t = u32;
pub type in_port_t = u16;
#[repr(C)]
#[derive(Debug, Clone, Copy)]
pub struct in_addr {
pub s_addr: in_addr_t
}
#[repr(C)]
pub struct in6_addr {
pub s6_addr: [u8; 16]
}
#[repr(C)]
pub struct sockaddr_in {
pub sin_family: sa_family_t,
pub sin_port: in_port_t,
pub sin_addr: in_addr
}
#[repr(C)]
pub struct sockaddr_in6 {
pub sin6_family: sa_family_t,
pub sin6_port: in_port_t,
pub sin6_flowinfo: u32,
pub sin6_addr: in6_addr,
pub sin6_scope_id: u32
}
#[repr(C)]
pub struct ipv6_mreq {
pub ipv6mr_multiaddr: in6_addr,
pub ipv6mr_interface: u32,
}
// Address String Lengths
pub const INET_ADDRSTRLEN: c_int = 16;
pub const INET6_ADDRSTRLEN: c_int = 46;
// Protocol Numbers
pub const IPPROTO_IP: u8 = 0x00;
pub const IPPROTO_ICMP: u8 = 0x01;
pub const IPPROTO_TCP: u8 = 0x06;
pub const IPPROTO_UDP: u8 = 0x11;
pub const IPPROTO_IPV6: u8 = 0x29;
pub const IPPROTO_RAW: u8 = 0xff;
pub const IPPROTO_MAX: u8 = 0xff;
pub const INADDR_ANY: u32 = 0; // Can't use in_addr_t alias because cbindgen :(
pub const INADDR_BROADCAST: u32 = 0xFFFFFFFF; // Can't use core::u32::MAX because cbindgen :(
pub const INADDR_NONE: u32 = 0xFFFFFFFF;
pub const INADDR_LOOPBACK: u32 = 0x7F000001;
pub const INADDR_UNSPEC_GROUP: u32 = 0xE0000000;
pub const INADDR_ALLHOSTS_GROUP: u32 = 0xE0000001;
pub const INADDR_ALLRTRS_GROUP: u32 = 0xE0000002;
pub const INADDR_MAX_LOCAL_GROUP: u32 = 0xE00000FF;
+7
View File
@@ -0,0 +1,7 @@
sys_includes = ["stddef.h", "sys/types.h"]
include_guard = "_PWD_H"
language = "C"
style = "Tag"
[enum]
prefix_with_name = true
+291
View File
@@ -0,0 +1,291 @@
//! pwd implementation for relibc
use alloc::vec::Vec;
use core::ptr;
use header::{errno, fcntl};
use platform;
use platform::{Pal, Sys};
use platform::types::*;
use platform::RawFile;
#[repr(C)]
pub struct passwd {
pw_name: *mut c_char,
pw_passwd: *mut c_char,
pw_uid: uid_t,
pw_gid: gid_t,
pw_gecos: *mut c_char,
pw_dir: *mut c_char,
pw_shell: *mut c_char,
}
static mut PASSWD_BUF: *mut c_char = ptr::null_mut();
static mut PASSWD: passwd = passwd {
pw_name: ptr::null_mut(),
pw_passwd: ptr::null_mut(),
pw_uid: 0,
pw_gid: 0,
pw_gecos: ptr::null_mut(),
pw_dir: ptr::null_mut(),
pw_shell: ptr::null_mut(),
};
enum OptionPasswd {
Error,
NotFound,
Found(*mut c_char),
}
fn pwd_lookup<F>(
out: *mut passwd,
alloc: Option<(*mut c_char, size_t)>,
mut callback: F,
) -> OptionPasswd
where
// TODO F: FnMut(impl Iterator<Item = &[u8]>) -> bool
F: FnMut(&[&[u8]]) -> bool,
{
let file = match RawFile::open(
"/etc/passwd\0".as_ptr() as *const c_char,
fcntl::O_RDONLY,
0,
) {
Ok(file) => file,
Err(_) => return OptionPasswd::Error,
};
let mut buf = Vec::new();
let mut newline = None;
loop {
// TODO when nll becomes a thing:
// let mut newline;
// WORKAROUND:
if let Some(newline) = newline {
buf.drain(..newline + 1);
}
// Read until newline
loop {
newline = buf.iter().position(|b| *b == b'\n');
if newline.is_some() {
break;
}
let len = buf.len();
if len >= buf.capacity() {
buf.reserve(1024);
}
unsafe {
let capacity = buf.capacity();
buf.set_len(capacity);
}
let read = Sys::read(*file, &mut buf[len..]);
unsafe {
buf.set_len(len + read as usize);
}
if read == 0 {
return OptionPasswd::NotFound;
}
if read < 0 {
return OptionPasswd::Error;
}
}
// Parse into passwd
let newline = newline.unwrap(); // safe because it doesn't break the loop otherwise
let line = &buf[..newline];
let mut parts: [&[u8]; 7] = [&[]; 7];
for (i, part) in line.splitn(7, |b| *b == b':').enumerate() {
parts[i] = part;
}
if !callback(&parts) {
// TODO when nll becomes a thing:
// buf.drain(..newline + 1);
continue;
}
let len = parts
.iter()
.enumerate()
.filter(|(i, _)| *i != 2 && *i != 3)
.map(|(_, part)| part.len() + 1)
.sum();
if alloc.map(|(_, s)| len > s as usize).unwrap_or(false) {
unsafe {
platform::errno = errno::ERANGE;
}
return OptionPasswd::Error;
}
let alloc = match alloc {
Some((alloc, _)) => alloc,
None => unsafe { platform::alloc(len) as *mut c_char },
};
// _ prefix so it won't complain about the trailing
// _off += <thing>
// in the macro that is never read
let mut _off = 0;
let mut parts = parts.into_iter();
macro_rules! copy_into {
($entry:expr) => {
debug_assert!(_off as usize <= len);
let src = parts.next().unwrap_or(&(&[] as &[u8])); // this is madness
let dst = unsafe { alloc.offset(_off) };
for (i, c) in src.iter().enumerate() {
unsafe {
*dst.offset(i as isize) = *c as c_char;
}
}
unsafe {
*dst.offset(src.len() as isize) = 0;
$entry = dst;
}
_off += src.len() as isize + 1;
};
($entry:expr,parse) => {
unsafe {
$entry = parts
.next()
.and_then(|part| core::str::from_utf8(part).ok())
.and_then(|part| part.parse().ok())
.unwrap_or(0);
}
};
}
copy_into!((*out).pw_name);
copy_into!((*out).pw_passwd);
copy_into!((*out).pw_uid, parse);
copy_into!((*out).pw_gid, parse);
copy_into!((*out).pw_gecos);
copy_into!((*out).pw_dir);
copy_into!((*out).pw_shell);
return OptionPasswd::Found(alloc);
}
}
#[no_mangle]
pub extern "C" fn getpwnam_r(
name: *const c_char,
out: *mut passwd,
buf: *mut c_char,
size: size_t,
result: *mut *mut passwd,
) -> c_int {
match pwd_lookup(out, Some((buf, size)), |parts| {
let part = parts.get(0).unwrap_or(&(&[] as &[u8]));
for (i, c) in part.iter().enumerate() {
// /etc/passwd should not contain any NUL bytes in the middle
// of entries, but if this happens, it can't possibly match the
// search query since it's NUL terminated.
if *c == 0 || unsafe { *name.offset(i as isize) } != *c as c_char {
return false;
}
}
true
}) {
OptionPasswd::Error => unsafe {
*result = ptr::null_mut();
-1
},
OptionPasswd::NotFound => unsafe {
*result = ptr::null_mut();
0
},
OptionPasswd::Found(_) => unsafe {
*result = out;
0
},
}
}
#[no_mangle]
pub extern "C" fn getpwuid_r(
uid: uid_t,
out: *mut passwd,
buf: *mut c_char,
size: size_t,
result: *mut *mut passwd,
) -> c_int {
match pwd_lookup(out, Some((buf, size)), |parts| {
let part = parts
.get(2)
.and_then(|part| core::str::from_utf8(part).ok())
.and_then(|part| part.parse().ok());
part == Some(uid)
}) {
OptionPasswd::Error => unsafe {
*result = ptr::null_mut();
-1
},
OptionPasswd::NotFound => unsafe {
*result = ptr::null_mut();
0
},
OptionPasswd::Found(_) => unsafe {
*result = out;
0
},
}
}
#[no_mangle]
pub extern "C" fn getpwnam(name: *const c_char) -> *mut passwd {
match pwd_lookup(unsafe { &mut PASSWD }, None, |parts| {
let part = parts.get(0).unwrap_or(&(&[] as &[u8]));
for (i, c) in part.iter().enumerate() {
// /etc/passwd should not contain any NUL bytes in the middle
// of entries, but if this happens, it can't possibly match the
// search query since it's NUL terminated.
if *c == 0 || unsafe { *name.offset(i as isize) } != *c as c_char {
return false;
}
}
true
}) {
OptionPasswd::Error => ptr::null_mut(),
OptionPasswd::NotFound => ptr::null_mut(),
OptionPasswd::Found(buf) => unsafe {
PASSWD_BUF = buf;
&mut PASSWD
},
}
}
#[no_mangle]
pub extern "C" fn getpwuid(uid: uid_t) -> *mut passwd {
match pwd_lookup(unsafe { &mut PASSWD }, None, |parts| {
let part = parts
.get(2)
.and_then(|part| core::str::from_utf8(part).ok())
.and_then(|part| part.parse().ok());
part == Some(uid)
}) {
OptionPasswd::Error => ptr::null_mut(),
OptionPasswd::NotFound => ptr::null_mut(),
OptionPasswd::Found(buf) => unsafe {
if PASSWD_BUF != ptr::null_mut() {
platform::free(PASSWD_BUF as *mut c_void);
}
PASSWD_BUF = buf;
&mut PASSWD
},
}
}
+7
View File
@@ -0,0 +1,7 @@
sys_includes = []
include_guard = "_SEMAPHORE_H"
language = "C"
style = "Tag"
[enum]
prefix_with_name = true
+62
View File
@@ -0,0 +1,62 @@
use platform;
use platform::types::*;
#[repr(C)]
#[derive(Copy)]
pub union sem_t {
pub size: [c_char; 32usize],
pub align: c_long,
_bindgen_union_align: [u64; 4usize],
}
impl Clone for sem_t {
fn clone(&self) -> Self {
*self
}
}
// #[no_mangle]
pub extern "C" fn sem_init(sem: *mut sem_t, pshared: c_int, value: c_uint) -> c_int {
unimplemented!();
}
// #[no_mangle]
pub extern "C" fn sem_destroy(sem: *mut sem_t) -> c_int {
unimplemented!();
}
/*
*#[no_mangle]
*pub extern "C" fn sem_open(name: *const c_char,
* oflag: c_int, ...) -> *mut sem_t {
* unimplemented!();
*}
*/
// #[no_mangle]
pub extern "C" fn sem_close(sem: *mut sem_t) -> c_int {
unimplemented!();
}
// #[no_mangle]
pub extern "C" fn sem_unlink(name: *const c_char) -> c_int {
unimplemented!();
}
// #[no_mangle]
pub extern "C" fn sem_wait(sem: *mut sem_t) -> c_int {
unimplemented!();
}
// #[no_mangle]
pub extern "C" fn sem_trywait(sem: *mut sem_t) -> c_int {
unimplemented!();
}
// #[no_mangle]
pub extern "C" fn sem_post(sem: *mut sem_t) -> c_int {
unimplemented!();
}
// #[no_mangle]
pub extern "C" fn sem_getvalue(sem: *mut sem_t, sval: *mut c_int) -> c_int {
unimplemented!();
}
+4
View File
@@ -0,0 +1,4 @@
[package]
name = "setjmp"
version = "0.1.0"
authors = ["Jeremy Soller <jackpot51@gmail.com>"]
+6
View File
@@ -0,0 +1,6 @@
# setjmp implementation
All this code belongs to [musl libc](https://www.musl-libc.org/).
They own it. All rights go to them.
Huge thanks to them for doing this tedious per-arch assembly work!
We will reuse this awesome effort :)
@@ -0,0 +1,24 @@
.global _longjmp
.global longjmp
.type _longjmp,%function
.type longjmp,%function
_longjmp:
longjmp:
// IHI0055B_aapcs64.pdf 5.1.1, 5.1.2 callee saved registers
ldp x19, x20, [x0,#0]
ldp x21, x22, [x0,#16]
ldp x23, x24, [x0,#32]
ldp x25, x26, [x0,#48]
ldp x27, x28, [x0,#64]
ldp x29, x30, [x0,#80]
ldr x2, [x0,#104]
mov sp, x2
ldp d8 , d9, [x0,#112]
ldp d10, d11, [x0,#128]
ldp d12, d13, [x0,#144]
ldp d14, d15, [x0,#160]
mov x0, x1
cbnz x1, 1f
mov x0, #1
1: br x30
@@ -0,0 +1,24 @@
.global __setjmp
.global _setjmp
.global setjmp
.type __setjmp,@function
.type _setjmp,@function
.type setjmp,@function
__setjmp:
_setjmp:
setjmp:
// IHI0055B_aapcs64.pdf 5.1.1, 5.1.2 callee saved registers
stp x19, x20, [x0,#0]
stp x21, x22, [x0,#16]
stp x23, x24, [x0,#32]
stp x25, x26, [x0,#48]
stp x27, x28, [x0,#64]
stp x29, x30, [x0,#80]
mov x2, sp
str x2, [x0,#104]
stp d8, d9, [x0,#112]
stp d10, d11, [x0,#128]
stp d12, d13, [x0,#144]
stp d14, d15, [x0,#160]
mov x0, #0
ret
+43
View File
@@ -0,0 +1,43 @@
.syntax unified
.global _longjmp
.global longjmp
.type _longjmp,%function
.type longjmp,%function
_longjmp:
longjmp:
mov ip,r0
movs r0,r1
moveq r0,#1
ldmia ip!, {v1,v2,v3,v4,v5,v6,sl,fp}
ldmia ip!, {r2,lr}
mov sp,r2
adr r1,1f
ldr r2,1f
ldr r1,[r1,r2]
tst r1,#0x260
beq 3f
tst r1,#0x20
beq 2f
ldc p2, cr4, [ip], #48
2: tst r1,#0x40
beq 2f
.fpu vfp
vldmia ip!, {d8-d15}
.fpu softvfp
.eabi_attribute 10, 0
.eabi_attribute 27, 0
2: tst r1,#0x200
beq 3f
ldcl p1, cr10, [ip], #8
ldcl p1, cr11, [ip], #8
ldcl p1, cr12, [ip], #8
ldcl p1, cr13, [ip], #8
ldcl p1, cr14, [ip], #8
ldcl p1, cr15, [ip], #8
3: bx lr
.hidden __hwcap
.align 2
1: .word __hwcap-1b
+45
View File
@@ -0,0 +1,45 @@
.syntax unified
.global __setjmp
.global _setjmp
.global setjmp
.type __setjmp,%function
.type _setjmp,%function
.type setjmp,%function
__setjmp:
_setjmp:
setjmp:
mov ip,r0
stmia ip!,{v1,v2,v3,v4,v5,v6,sl,fp}
mov r2,sp
stmia ip!,{r2,lr}
mov r0,#0
adr r1,1f
ldr r2,1f
ldr r1,[r1,r2]
tst r1,#0x260
beq 3f
tst r1,#0x20
beq 2f
stc p2, cr4, [ip], #48
2: tst r1,#0x40
beq 2f
.fpu vfp
vstmia ip!, {d8-d15}
.fpu softvfp
.eabi_attribute 10, 0
.eabi_attribute 27, 0
2: tst r1,#0x200
beq 3f
stcl p1, cr10, [ip], #8
stcl p1, cr11, [ip], #8
stcl p1, cr12, [ip], #8
stcl p1, cr13, [ip], #8
stcl p1, cr14, [ip], #8
stcl p1, cr15, [ip], #8
3: bx lr
.hidden __hwcap
.align 2
1: .word __hwcap-1b
+20
View File
@@ -0,0 +1,20 @@
.global _longjmp
.global longjmp
.type _longjmp,@function
.type longjmp,@function
_longjmp:
longjmp:
mov 4(%esp),%edx
mov 8(%esp),%eax
test %eax,%eax
jnz 1f
inc %eax
1:
mov (%edx),%ebx
mov 4(%edx),%esi
mov 8(%edx),%edi
mov 12(%edx),%ebp
mov 16(%edx),%ecx
mov %ecx,%esp
mov 20(%edx),%ecx
jmp *%ecx
+23
View File
@@ -0,0 +1,23 @@
.global ___setjmp
.hidden ___setjmp
.global __setjmp
.global _setjmp
.global setjmp
.type __setjmp,@function
.type _setjmp,@function
.type setjmp,@function
___setjmp:
__setjmp:
_setjmp:
setjmp:
mov 4(%esp), %eax
mov %ebx, (%eax)
mov %esi, 4(%eax)
mov %edi, 8(%eax)
mov %ebp, 12(%eax)
lea 4(%esp), %ecx
mov %ecx, 16(%eax)
mov (%esp), %ecx
mov %ecx, 20(%eax)
xor %eax, %eax
ret
+14
View File
@@ -0,0 +1,14 @@
.global _longjmp
.global longjmp
.type _longjmp,@function
.type longjmp,@function
_longjmp:
longjmp:
movea.l 4(%sp),%a0
move.l 8(%sp),%d0
bne 1f
move.l #1,%d0
1: movem.l (%a0),%d2-%d7/%a2-%a7
fmovem.x 52(%a0),%fp2-%fp7
move.l 48(%a0),(%sp)
rts
+18
View File
@@ -0,0 +1,18 @@
.global ___setjmp
.hidden ___setjmp
.global __setjmp
.global _setjmp
.global setjmp
.type __setjmp,@function
.type _setjmp,@function
.type setjmp,@function
___setjmp:
__setjmp:
_setjmp:
setjmp:
movea.l 4(%sp),%a0
movem.l %d2-%d7/%a2-%a7,(%a0)
move.l (%sp),48(%a0)
fmovem.x %fp2-%fp7,52(%a0)
clr.l %d0
rts
@@ -0,0 +1,29 @@
.global _longjmp
.global longjmp
.type _longjmp,@function
.type longjmp,@function
_longjmp:
longjmp:
addi r3, r6, 0
bnei r3, 1f
addi r3, r3, 1
1: lwi r1, r5, 0
lwi r15, r5, 4
lwi r2, r5, 8
lwi r13, r5, 12
lwi r18, r5, 16
lwi r19, r5, 20
lwi r20, r5, 24
lwi r21, r5, 28
lwi r22, r5, 32
lwi r23, r5, 36
lwi r24, r5, 40
lwi r25, r5, 44
lwi r26, r5, 48
lwi r27, r5, 52
lwi r28, r5, 56
lwi r29, r5, 60
lwi r30, r5, 64
lwi r31, r5, 68
rtsd r15, 8
nop
@@ -0,0 +1,32 @@
.global ___setjmp
.hidden ___setjmp
.global __setjmp
.global _setjmp
.global setjmp
.type __setjmp,@function
.type _setjmp,@function
.type setjmp,@function
___setjmp:
__setjmp:
_setjmp:
setjmp:
swi r1, r5, 0
swi r15, r5, 4
swi r2, r5, 8
swi r13, r5, 12
swi r18, r5, 16
swi r19, r5, 20
swi r20, r5, 24
swi r21, r5, 28
swi r22, r5, 32
swi r23, r5, 36
swi r24, r5, 40
swi r25, r5, 44
swi r26, r5, 48
swi r27, r5, 52
swi r28, r5, 56
swi r29, r5, 60
swi r30, r5, 64
swi r31, r5, 68
rtsd r15, 8
ori r3, r0, 0
+40
View File
@@ -0,0 +1,40 @@
.set noreorder
.global _longjmp
.global longjmp
.type _longjmp,@function
.type longjmp,@function
_longjmp:
longjmp:
move $2, $5
bne $2, $0, 1f
nop
addu $2, $2, 1
1:
#ifndef __mips_soft_float
lwc1 $20, 56($4)
lwc1 $21, 60($4)
lwc1 $22, 64($4)
lwc1 $23, 68($4)
lwc1 $24, 72($4)
lwc1 $25, 76($4)
lwc1 $26, 80($4)
lwc1 $27, 84($4)
lwc1 $28, 88($4)
lwc1 $29, 92($4)
lwc1 $30, 96($4)
lwc1 $31, 100($4)
#endif
lw $ra, 0($4)
lw $sp, 4($4)
lw $16, 8($4)
lw $17, 12($4)
lw $18, 16($4)
lw $19, 20($4)
lw $20, 24($4)
lw $21, 28($4)
lw $22, 32($4)
lw $23, 36($4)
lw $30, 40($4)
jr $ra
lw $28, 44($4)
+39
View File
@@ -0,0 +1,39 @@
.set noreorder
.global __setjmp
.global _setjmp
.global setjmp
.type __setjmp,@function
.type _setjmp,@function
.type setjmp,@function
__setjmp:
_setjmp:
setjmp:
sw $ra, 0($4)
sw $sp, 4($4)
sw $16, 8($4)
sw $17, 12($4)
sw $18, 16($4)
sw $19, 20($4)
sw $20, 24($4)
sw $21, 28($4)
sw $22, 32($4)
sw $23, 36($4)
sw $30, 40($4)
sw $28, 44($4)
#ifndef __mips_soft_float
swc1 $20, 56($4)
swc1 $21, 60($4)
swc1 $22, 64($4)
swc1 $23, 68($4)
swc1 $24, 72($4)
swc1 $25, 76($4)
swc1 $26, 80($4)
swc1 $27, 84($4)
swc1 $28, 88($4)
swc1 $29, 92($4)
swc1 $30, 96($4)
swc1 $31, 100($4)
#endif
jr $ra
li $2, 0
@@ -0,0 +1,37 @@
.set noreorder
.global _longjmp
.global longjmp
.type _longjmp,@function
.type longjmp,@function
_longjmp:
longjmp:
move $2, $5
bne $2, $0, 1f
nop
daddu $2, $2, 1
1:
#ifndef __mips_soft_float
ldc1 $24, 96($4)
ldc1 $25, 104($4)
ldc1 $26, 112($4)
ldc1 $27, 120($4)
ldc1 $28, 128($4)
ldc1 $29, 136($4)
ldc1 $30, 144($4)
ldc1 $31, 152($4)
#endif
ld $ra, 0($4)
ld $sp, 8($4)
ld $gp, 16($4)
ld $16, 24($4)
ld $17, 32($4)
ld $18, 40($4)
ld $19, 48($4)
ld $20, 56($4)
ld $21, 64($4)
ld $22, 72($4)
ld $23, 80($4)
ld $30, 88($4)
jr $ra
nop
@@ -0,0 +1,34 @@
.set noreorder
.global __setjmp
.global _setjmp
.global setjmp
.type __setjmp,@function
.type _setjmp,@function
.type setjmp,@function
__setjmp:
_setjmp:
setjmp:
sd $ra, 0($4)
sd $sp, 8($4)
sd $gp, 16($4)
sd $16, 24($4)
sd $17, 32($4)
sd $18, 40($4)
sd $19, 48($4)
sd $20, 56($4)
sd $21, 64($4)
sd $22, 72($4)
sd $23, 80($4)
sd $30, 88($4)
#ifndef __mips_soft_float
sdc1 $24, 96($4)
sdc1 $25, 104($4)
sdc1 $26, 112($4)
sdc1 $27, 120($4)
sdc1 $28, 128($4)
sdc1 $29, 136($4)
sdc1 $30, 144($4)
sdc1 $31, 152($4)
#endif
jr $ra
li $2, 0
@@ -0,0 +1,36 @@
.set noreorder
.global _longjmp
.global longjmp
.type _longjmp,@function
.type longjmp,@function
_longjmp:
longjmp:
move $2, $5
bne $2, $0, 1f
nop
addu $2, $2, 1
1:
#ifndef __mips_soft_float
ldc1 $24, 96($4)
ldc1 $25, 104($4)
ldc1 $26, 112($4)
ldc1 $27, 120($4)
ldc1 $28, 128($4)
ldc1 $29, 136($4)
ldc1 $30, 144($4)
ldc1 $31, 152($4)
#endif
ld $ra, 0($4)
ld $sp, 8($4)
ld $gp, 16($4)
ld $16, 24($4)
ld $17, 32($4)
ld $18, 40($4)
ld $19, 48($4)
ld $20, 56($4)
ld $21, 64($4)
ld $22, 72($4)
ld $23, 80($4)
ld $30, 88($4)
jr $ra
nop
@@ -0,0 +1,34 @@
.set noreorder
.global __setjmp
.global _setjmp
.global setjmp
.type __setjmp,@function
.type _setjmp,@function
.type setjmp,@function
__setjmp:
_setjmp:
setjmp:
sd $ra, 0($4)
sd $sp, 8($4)
sd $gp, 16($4)
sd $16, 24($4)
sd $17, 32($4)
sd $18, 40($4)
sd $19, 48($4)
sd $20, 56($4)
sd $21, 64($4)
sd $22, 72($4)
sd $23, 80($4)
sd $30, 88($4)
#ifndef __mips_soft_float
sdc1 $24, 96($4)
sdc1 $25, 104($4)
sdc1 $26, 112($4)
sdc1 $27, 120($4)
sdc1 $28, 128($4)
sdc1 $29, 136($4)
sdc1 $30, 144($4)
sdc1 $31, 152($4)
#endif
jr $ra
li $2, 0
+25
View File
@@ -0,0 +1,25 @@
.global _longjmp
.global longjmp
.type _longjmp,@function
.type longjmp,@function
_longjmp:
longjmp:
l.sfeqi r4, 0
l.bnf 1f
l.addi r11, r4,0
l.ori r11, r0, 1
1: l.lwz r1, 0(r3)
l.lwz r2, 4(r3)
l.lwz r9, 8(r3)
l.lwz r10, 12(r3)
l.lwz r14, 16(r3)
l.lwz r16, 20(r3)
l.lwz r18, 24(r3)
l.lwz r20, 28(r3)
l.lwz r22, 32(r3)
l.lwz r24, 36(r3)
l.lwz r26, 40(r3)
l.lwz r28, 44(r3)
l.lwz r30, 48(r3)
l.jr r9
l.nop
+27
View File
@@ -0,0 +1,27 @@
.global ___setjmp
.hidden ___setjmp
.global __setjmp
.global _setjmp
.global setjmp
.type __setjmp,@function
.type _setjmp,@function
.type setjmp,@function
___setjmp:
__setjmp:
_setjmp:
setjmp:
l.sw 0(r3), r1
l.sw 4(r3), r2
l.sw 8(r3), r9
l.sw 12(r3), r10
l.sw 16(r3), r14
l.sw 20(r3), r16
l.sw 24(r3), r18
l.sw 28(r3), r20
l.sw 32(r3), r22
l.sw 36(r3), r24
l.sw 40(r3), r26
l.sw 44(r3), r28
l.sw 48(r3), r30
l.jr r9
l.ori r11,r0,0
@@ -0,0 +1,69 @@
.global _longjmp
.global longjmp
.type _longjmp,@function
.type longjmp,@function
_longjmp:
longjmp:
/*
* void longjmp(jmp_buf env, int val);
* put val into return register and restore the env saved in setjmp
* if val(r4) is 0, put 1 there.
*/
/* 0) move old return address into r0 */
lwz 0, 0(3)
/* 1) put it into link reg */
mtlr 0
/* 2 ) restore stack ptr */
lwz 1, 4(3)
/* 3) restore control reg */
lwz 0, 8(3)
mtcr 0
/* 4) restore r14-r31 */
lwz 14, 12(3)
lwz 15, 16(3)
lwz 16, 20(3)
lwz 17, 24(3)
lwz 18, 28(3)
lwz 19, 32(3)
lwz 20, 36(3)
lwz 21, 40(3)
lwz 22, 44(3)
lwz 23, 48(3)
lwz 24, 52(3)
lwz 25, 56(3)
lwz 26, 60(3)
lwz 27, 64(3)
lwz 28, 68(3)
lwz 29, 72(3)
lwz 30, 76(3)
lwz 31, 80(3)
#ifndef _SOFT_FLOAT
lfd 14,88(3)
lfd 15,96(3)
lfd 16,104(3)
lfd 17,112(3)
lfd 18,120(3)
lfd 19,128(3)
lfd 20,136(3)
lfd 21,144(3)
lfd 22,152(3)
lfd 23,160(3)
lfd 24,168(3)
lfd 25,176(3)
lfd 26,184(3)
lfd 27,192(3)
lfd 28,200(3)
lfd 29,208(3)
lfd 30,216(3)
lfd 31,224(3)
#endif
/* 5) put val into return reg r3 */
mr 3, 4
/* 6) check if return value is 0, make it 1 in that case */
cmpwi cr7, 4, 0
bne cr7, 1f
li 3, 1
1:
blr
@@ -0,0 +1,63 @@
.global ___setjmp
.hidden ___setjmp
.global __setjmp
.global _setjmp
.global setjmp
.type __setjmp,@function
.type _setjmp,@function
.type setjmp,@function
___setjmp:
__setjmp:
_setjmp:
setjmp:
/* 0) store IP int 0, then into the jmpbuf pointed to by r3 (first arg) */
mflr 0
stw 0, 0(3)
/* 1) store reg1 (SP) */
stw 1, 4(3)
/* 2) store cr */
mfcr 0
stw 0, 8(3)
/* 3) store r14-31 */
stw 14, 12(3)
stw 15, 16(3)
stw 16, 20(3)
stw 17, 24(3)
stw 18, 28(3)
stw 19, 32(3)
stw 20, 36(3)
stw 21, 40(3)
stw 22, 44(3)
stw 23, 48(3)
stw 24, 52(3)
stw 25, 56(3)
stw 26, 60(3)
stw 27, 64(3)
stw 28, 68(3)
stw 29, 72(3)
stw 30, 76(3)
stw 31, 80(3)
#ifndef _SOFT_FLOAT
stfd 14,88(3)
stfd 15,96(3)
stfd 16,104(3)
stfd 17,112(3)
stfd 18,120(3)
stfd 19,128(3)
stfd 20,136(3)
stfd 21,144(3)
stfd 22,152(3)
stfd 23,160(3)
stfd 24,168(3)
stfd 25,176(3)
stfd 26,184(3)
stfd 27,192(3)
stfd 28,200(3)
stfd 29,208(3)
stfd 30,216(3)
stfd 31,224(3)
#endif
/* 4) set return value to 0 */
li 3, 0
/* 5) return */
blr
@@ -0,0 +1,81 @@
.global _longjmp
.global longjmp
.type _longjmp,@function
.type longjmp,@function
_longjmp:
longjmp:
# 0) move old return address into the link register
ld 0, 0*8(3)
mtlr 0
# 1) restore cr
ld 0, 1*8(3)
mtcr 0
# 2) restore SP
ld 1, 2*8(3)
# 3) restore TOC into both r2 and the caller's stack.
# Which location is required depends on whether setjmp was called
# locally or non-locally, but it's always safe to restore to both.
ld 2, 3*8(3)
std 2, 24(1)
# 4) restore r14-r31
ld 14, 4*8(3)
ld 15, 5*8(3)
ld 16, 6*8(3)
ld 17, 7*8(3)
ld 18, 8*8(3)
ld 19, 9*8(3)
ld 20, 10*8(3)
ld 21, 11*8(3)
ld 22, 12*8(3)
ld 23, 13*8(3)
ld 24, 14*8(3)
ld 25, 15*8(3)
ld 26, 16*8(3)
ld 27, 17*8(3)
ld 28, 18*8(3)
ld 29, 19*8(3)
ld 30, 20*8(3)
ld 31, 21*8(3)
# 5) restore floating point registers f14-f31
lfd 14, 22*8(3)
lfd 15, 23*8(3)
lfd 16, 24*8(3)
lfd 17, 25*8(3)
lfd 18, 26*8(3)
lfd 19, 27*8(3)
lfd 20, 28*8(3)
lfd 21, 29*8(3)
lfd 22, 30*8(3)
lfd 23, 31*8(3)
lfd 24, 32*8(3)
lfd 25, 33*8(3)
lfd 26, 34*8(3)
lfd 27, 35*8(3)
lfd 28, 36*8(3)
lfd 29, 37*8(3)
lfd 30, 38*8(3)
lfd 31, 39*8(3)
# 6) restore vector registers v20-v31
addi 3, 3, 40*8
lvx 20, 0, 3 ; addi 3, 3, 16
lvx 21, 0, 3 ; addi 3, 3, 16
lvx 22, 0, 3 ; addi 3, 3, 16
lvx 23, 0, 3 ; addi 3, 3, 16
lvx 24, 0, 3 ; addi 3, 3, 16
lvx 25, 0, 3 ; addi 3, 3, 16
lvx 26, 0, 3 ; addi 3, 3, 16
lvx 27, 0, 3 ; addi 3, 3, 16
lvx 28, 0, 3 ; addi 3, 3, 16
lvx 29, 0, 3 ; addi 3, 3, 16
lvx 30, 0, 3 ; addi 3, 3, 16
lvx 31, 0, 3
# 7) return r4 ? r4 : 1
mr 3, 4
cmpwi cr7, 4, 0
bne cr7, 1f
li 3, 1
1:
blr
@@ -0,0 +1,89 @@
.global __setjmp
.global _setjmp
.global setjmp
.type __setjmp,@function
.type _setjmp,@function
.type setjmp,@function
__setjmp:
_setjmp:
setjmp:
ld 5, 24(1) # load from the TOC slot in the caller's stack frame
b __setjmp_toc
.localentry __setjmp,.-__setjmp
.localentry _setjmp,.-_setjmp
.localentry setjmp,.-setjmp
mr 5, 2
.global __setjmp_toc
.hidden __setjmp_toc
# same as normal setjmp, except TOC pointer to save is provided in r5.
# r4 would normally be the 2nd parameter, but we're using r5 to simplify calling from sigsetjmp.
# solves the problem of knowing whether to save the TOC pointer from r2 or the caller's stack frame.
__setjmp_toc:
# 0) store IP into 0, then into the jmpbuf pointed to by r3 (first arg)
mflr 0
std 0, 0*8(3)
# 1) store cr
mfcr 0
std 0, 1*8(3)
# 2) store SP and TOC
std 1, 2*8(3)
std 5, 3*8(3)
# 3) store r14-31
std 14, 4*8(3)
std 15, 5*8(3)
std 16, 6*8(3)
std 17, 7*8(3)
std 18, 8*8(3)
std 19, 9*8(3)
std 20, 10*8(3)
std 21, 11*8(3)
std 22, 12*8(3)
std 23, 13*8(3)
std 24, 14*8(3)
std 25, 15*8(3)
std 26, 16*8(3)
std 27, 17*8(3)
std 28, 18*8(3)
std 29, 19*8(3)
std 30, 20*8(3)
std 31, 21*8(3)
# 4) store floating point registers f14-f31
stfd 14, 22*8(3)
stfd 15, 23*8(3)
stfd 16, 24*8(3)
stfd 17, 25*8(3)
stfd 18, 26*8(3)
stfd 19, 27*8(3)
stfd 20, 28*8(3)
stfd 21, 29*8(3)
stfd 22, 30*8(3)
stfd 23, 31*8(3)
stfd 24, 32*8(3)
stfd 25, 33*8(3)
stfd 26, 34*8(3)
stfd 27, 35*8(3)
stfd 28, 36*8(3)
stfd 29, 37*8(3)
stfd 30, 38*8(3)
stfd 31, 39*8(3)
# 5) store vector registers v20-v31
addi 3, 3, 40*8
stvx 20, 0, 3 ; addi 3, 3, 16
stvx 21, 0, 3 ; addi 3, 3, 16
stvx 22, 0, 3 ; addi 3, 3, 16
stvx 23, 0, 3 ; addi 3, 3, 16
stvx 24, 0, 3 ; addi 3, 3, 16
stvx 25, 0, 3 ; addi 3, 3, 16
stvx 26, 0, 3 ; addi 3, 3, 16
stvx 27, 0, 3 ; addi 3, 3, 16
stvx 28, 0, 3 ; addi 3, 3, 16
stvx 29, 0, 3 ; addi 3, 3, 16
stvx 30, 0, 3 ; addi 3, 3, 16
stvx 31, 0, 3
# 6) return 0
li 3, 0
blr
@@ -0,0 +1,23 @@
.global _longjmp
.global longjmp
.type _longjmp,@function
.type longjmp,@function
_longjmp:
longjmp:
1:
lmg %r6, %r15, 0(%r2)
ld %f8, 10*8(%r2)
ld %f9, 11*8(%r2)
ld %f10, 12*8(%r2)
ld %f11, 13*8(%r2)
ld %f12, 14*8(%r2)
ld %f13, 15*8(%r2)
ld %f14, 16*8(%r2)
ld %f15, 17*8(%r2)
ltgr %r2, %r3
bnzr %r14
lhi %r2, 1
br %r14
+25
View File
@@ -0,0 +1,25 @@
.global ___setjmp
.hidden ___setjmp
.global __setjmp
.global _setjmp
.global setjmp
.type __setjmp,@function
.type _setjmp,@function
.type setjmp,@function
___setjmp:
__setjmp:
_setjmp:
setjmp:
stmg %r6, %r15, 0(%r2)
std %f8, 10*8(%r2)
std %f9, 11*8(%r2)
std %f10, 12*8(%r2)
std %f11, 13*8(%r2)
std %f12, 14*8(%r2)
std %f13, 15*8(%r2)
std %f14, 16*8(%r2)
std %f15, 17*8(%r2)
lghi %r2, 0
br %r14
+28
View File
@@ -0,0 +1,28 @@
.global _longjmp
.global longjmp
.type _longjmp, @function
.type longjmp, @function
_longjmp:
longjmp:
mov.l @r4+, r8
mov.l @r4+, r9
mov.l @r4+, r10
mov.l @r4+, r11
mov.l @r4+, r12
mov.l @r4+, r13
mov.l @r4+, r14
mov.l @r4+, r15
lds.l @r4+, pr
#if __SH_FPU_ANY__ || __SH4__
fmov.s @r4+, fr12
fmov.s @r4+, fr13
fmov.s @r4+, fr14
fmov.s @r4+, fr15
#endif
tst r5, r5
movt r0
add r5, r0
rts
nop
+32
View File
@@ -0,0 +1,32 @@
.global ___setjmp
.hidden ___setjmp
.global __setjmp
.global _setjmp
.global setjmp
.type __setjmp, @function
.type _setjmp, @function
.type setjmp, @function
___setjmp:
__setjmp:
_setjmp:
setjmp:
#if __SH_FPU_ANY__ || __SH4__
add #52, r4
fmov.s fr15, @-r4
fmov.s fr14, @-r4
fmov.s fr13, @-r4
fmov.s fr12, @-r4
#else
add #36, r4
#endif
sts.l pr, @-r4
mov.l r15, @-r4
mov.l r14, @-r4
mov.l r13, @-r4
mov.l r12, @-r4
mov.l r11, @-r4
mov.l r10, @-r4
mov.l r9, @-r4
mov.l r8, @-r4
rts
mov #0, r0
+22
View File
@@ -0,0 +1,22 @@
/* Copyright 2011-2012 Nicholas J. Kain, licensed under standard MIT license */
.global _longjmp
.global longjmp
.type _longjmp,@function
.type longjmp,@function
_longjmp:
longjmp:
mov %rsi,%rax /* val will be longjmp return */
test %rax,%rax
jnz 1f
inc %rax /* if val==0, val=1 per longjmp semantics */
1:
mov (%rdi),%rbx /* rdi is the jmp_buf, restore regs from it */
mov 8(%rdi),%rbp
mov 16(%rdi),%r12
mov 24(%rdi),%r13
mov 32(%rdi),%r14
mov 40(%rdi),%r15
mov 48(%rdi),%rdx /* this ends up being the stack pointer */
mov %rdx,%rsp
mov 56(%rdi),%rdx /* this is the instruction pointer */
jmp *%rdx /* goto saved address without altering rsp */
+22
View File
@@ -0,0 +1,22 @@
/* Copyright 2011-2012 Nicholas J. Kain, licensed under standard MIT license */
.global __setjmp
.global _setjmp
.global setjmp
.type __setjmp,@function
.type _setjmp,@function
.type setjmp,@function
__setjmp:
_setjmp:
setjmp:
mov %rbx,(%rdi) /* rdi is jmp_buf, move registers onto it */
mov %rbp,8(%rdi)
mov %r12,16(%rdi)
mov %r13,24(%rdi)
mov %r14,32(%rdi)
mov %r15,40(%rdi)
lea 8(%rsp),%rdx /* this is our rsp WITHOUT current ret addr */
mov %rdx,48(%rdi)
mov (%rsp),%rdx /* save return addr ptr for new rip */
mov %rdx,56(%rdi)
xor %rax,%rax /* always return 0 */
ret
@@ -0,0 +1,22 @@
/* Copyright 2011-2012 Nicholas J. Kain, licensed under standard MIT license */
.global _longjmp
.global longjmp
.type _longjmp,@function
.type longjmp,@function
_longjmp:
longjmp:
mov %rsi,%rax /* val will be longjmp return */
test %rax,%rax
jnz 1f
inc %rax /* if val==0, val=1 per longjmp semantics */
1:
mov (%rdi),%rbx /* rdi is the jmp_buf, restore regs from it */
mov 8(%rdi),%rbp
mov 16(%rdi),%r12
mov 24(%rdi),%r13
mov 32(%rdi),%r14
mov 40(%rdi),%r15
mov 48(%rdi),%rdx /* this ends up being the stack pointer */
mov %rdx,%rsp
mov 56(%rdi),%rdx /* this is the instruction pointer */
jmp *%rdx /* goto saved address without altering rsp */
@@ -0,0 +1,22 @@
/* Copyright 2011-2012 Nicholas J. Kain, licensed under standard MIT license */
.global __setjmp
.global _setjmp
.global setjmp
.type __setjmp,@function
.type _setjmp,@function
.type setjmp,@function
__setjmp:
_setjmp:
setjmp:
mov %rbx,(%rdi) /* rdi is jmp_buf, move registers onto it */
mov %rbp,8(%rdi)
mov %r12,16(%rdi)
mov %r13,24(%rdi)
mov %r14,32(%rdi)
mov %r15,40(%rdi)
lea 8(%rsp),%rdx /* this is our rsp WITHOUT current ret addr */
mov %rdx,48(%rdi)
mov (%rsp),%rdx /* save return addr ptr for new rip */
mov %rdx,56(%rdi)
xor %rax,%rax /* always return 0 */
ret
+33
View File
@@ -0,0 +1,33 @@
//! setjmp implementation for Redox, following http://pubs.opengroup.org/onlinepubs/7908799/xsh/setjmp.h.html
#![no_std]
#![feature(global_asm)]
macro_rules! platform_specific {
($($arch:expr,$ext:expr;)+) => {
$(
#[cfg(target_arch = $arch)]
global_asm!(include_str!(concat!("impl/", $arch, "/setjmp.", $ext)));
#[cfg(target_arch = $arch)]
global_asm!(include_str!(concat!("impl/", $arch, "/longjmp.", $ext)));
)+
}
}
platform_specific! {
"aarch64","s";
"arm","s";
"i386","s";
"m68k","s";
"microblaze","s";
"mips","S";
"mips64","S";
"mipsn32","S";
"or1k","s";
"powerpc","S";
"powerpc64","s";
"s390x","s";
"sh","S";
"x32","s";
"x86_64","s";
}
+7
View File
@@ -0,0 +1,7 @@
sys_includes = ["sys/ioctl.h"]
include_guard = "_SGTTY_H"
style = "Tag"
language = "C"
[enum]
prefix_with_name = true
+18
View File
@@ -0,0 +1,18 @@
//! sgtty implementation that won't work on redox because no ioctl
use core::fmt::Write;
use platform;
use platform::types::*;
use header::sys_ioctl::*;
#[no_mangle]
pub extern "C" fn gtty(fd: c_int, out: *mut sgttyb) -> c_int {
writeln!(
platform::FileWriter(2),
"unimplemented: gtty({}, {:p})",
fd,
out
);
-1
}
+11
View File
@@ -0,0 +1,11 @@
sys_includes = ["stdint.h", "sys/types.h", "bits/signal.h"]
include_guard = "_SIGNAL_H"
style = "Tag"
language = "C"
[defines]
"target_os=linux" = "__linux__"
"target_os=redox" = "__redox__"
[enum]
prefix_with_name = true
+63
View File
@@ -0,0 +1,63 @@
// Needs to be defined in assembly because it can't have a function prologue
#[cfg(target_arch = "x86_64")]
global_asm!(
"
.global __restore_rt
__restore_rt:
mov $15, %rax # <- rax is register, 15 is RT_SIGRETURN
syscall
"
);
#[cfg(target_arch = "aarch64")]
global_asm!(
"
.global __restore_rt
__restore_rt:
mov x8, #139 # <- x8 is register, 139 is RT_SIGRETURN
svc 0
"
);
pub const SIGHUP: usize = 1;
pub const SIGINT: usize = 2;
pub const SIGQUIT: usize = 3;
pub const SIGILL: usize = 4;
pub const SIGTRAP: usize = 5;
pub const SIGABRT: usize = 6;
pub const SIGIOT: usize = SIGABRT;
pub const SIGBUS: usize = 7;
pub const SIGFPE: usize = 8;
pub const SIGKILL: usize = 9;
pub const SIGUSR1: usize = 10;
pub const SIGSEGV: usize = 11;
pub const SIGUSR2: usize = 12;
pub const SIGPIPE: usize = 13;
pub const SIGALRM: usize = 14;
pub const SIGTERM: usize = 15;
pub const SIGSTKFLT: usize = 16;
pub const SIGCHLD: usize = 17;
pub const SIGCONT: usize = 18;
pub const SIGSTOP: usize = 19;
pub const SIGTSTP: usize = 20;
pub const SIGTTIN: usize = 21;
pub const SIGTTOU: usize = 22;
pub const SIGURG: usize = 23;
pub const SIGXCPU: usize = 24;
pub const SIGXFSZ: usize = 25;
pub const SIGVTALRM: usize = 26;
pub const SIGPROF: usize = 27;
pub const SIGWINCH: usize = 28;
pub const SIGIO: usize = 29;
pub const SIGPOLL: usize = SIGIO;
pub const SIGPWR: usize = 30;
pub const SIGSYS: usize = 31;
pub const SIGUNUSED: usize = SIGSYS;
pub const SA_NOCLDSTOP: usize = 1;
pub const SA_NOCLDWAIT: usize = 2;
pub const SA_SIGINFO: usize = 4;
pub const SA_ONSTACK: usize = 0x08000000;
pub const SA_RESTART: usize = 0x10000000;
pub const SA_NODEFER: usize = 0x40000000;
pub const SA_RESETHAND: usize = 0x80000000;
pub const SA_RESTORER: usize = 0x04000000;
+233
View File
@@ -0,0 +1,233 @@
//! signal implementation for Redox, following http://pubs.opengroup.org/onlinepubs/7908799/xsh/signal.h.html
#[cfg(target_os = "linux")]
#[path = "linux.rs"]
pub mod sys;
#[cfg(target_os = "redox")]
#[path = "redox.rs"]
pub mod sys;
pub use sys::*;
use core::{mem, ptr};
use header::errno;
use platform;
use platform::{PalSignal, Sys};
use platform::types::*;
const SIG_ERR: usize = !0;
pub const SIG_BLOCK: c_int = 0;
pub const SIG_UNBLOCK: c_int = 1;
pub const SIG_SETMASK: c_int = 2;
// Need both here and in platform because cbindgen :(
#[repr(C)]
#[derive(Clone)]
pub struct sigaction {
// I don't actually want these to be optional. They can have more than just
// one invalid value. But because of rust's non-null optimization, this
// causes Some(sigaction) with a null sa_handler to become None. Maybe
// these should be usizes and transmuted when needed... However, then I
// couldn't let cbindgen do its job.
pub sa_handler: Option<extern "C" fn(c_int)>,
pub sa_flags: c_ulong,
pub sa_restorer: Option<unsafe extern "C" fn()>,
pub sa_mask: sigset_t,
}
pub const NSIG: usize = 64;
pub type sigset_t = c_ulong;
#[no_mangle]
pub extern "C" fn kill(pid: pid_t, sig: c_int) -> c_int {
Sys::kill(pid, sig)
}
#[no_mangle]
pub extern "C" fn killpg(pgrp: pid_t, sig: c_int) -> c_int {
Sys::killpg(pgrp, sig)
}
#[no_mangle]
pub extern "C" fn raise(sig: c_int) -> c_int {
Sys::raise(sig)
}
#[no_mangle]
pub unsafe extern "C" fn sigaction(
sig: c_int,
act: *const sigaction,
oact: *mut sigaction,
) -> c_int {
let mut _sigaction = None;
let ptr = if !act.is_null() {
_sigaction = Some((*act).clone());
_sigaction.as_mut().unwrap().sa_flags |= SA_RESTORER as c_ulong;
_sigaction.as_mut().unwrap() as *mut _ as *mut platform::types::sigaction
} else {
ptr::null_mut()
};
Sys::sigaction(sig, ptr, oact as *mut platform::types::sigaction)
}
#[no_mangle]
pub extern "C" fn sigaddset(set: *mut sigset_t, mut signo: c_int) -> c_int {
if signo <= 0 || signo as usize > NSIG {
unsafe {
platform::errno = errno::EINVAL;
}
return -1;
}
let signo = signo as usize - 1; // 0-indexed usize, please!
unsafe {
*set |= 1 << (signo & (8 * mem::size_of::<sigset_t>() - 1));
}
0
}
#[no_mangle]
pub extern "C" fn sigdelset(set: *mut sigset_t, signo: c_int) -> c_int {
if signo <= 0 || signo as usize > NSIG {
unsafe {
platform::errno = errno::EINVAL;
}
return -1;
}
let signo = signo as usize - 1; // 0-indexed usize, please!
unsafe {
*set &= !(1 << (signo & (8 * mem::size_of::<sigset_t>() - 1)));
}
0
}
#[no_mangle]
pub extern "C" fn sigemptyset(set: *mut sigset_t) -> c_int {
unsafe {
*set = 0;
}
0
}
#[no_mangle]
pub extern "C" fn sigfillset(set: *mut sigset_t) -> c_int {
unsafe {
*set = c_ulong::max_value();
}
0
}
// #[no_mangle]
pub extern "C" fn sighold(sig: c_int) -> c_int {
unimplemented!();
}
// #[no_mangle]
pub extern "C" fn sigignore(sig: c_int) -> c_int {
unimplemented!();
}
// #[no_mangle]
pub extern "C" fn siginterrupt(sig: c_int, flag: c_int) -> c_int {
unimplemented!();
}
// #[no_mangle]
pub extern "C" fn sigismember(set: *const sigset_t, signo: c_int) -> c_int {
unimplemented!();
}
extern "C" {
// Defined in assembly inside platform/x/mod.rs
fn __restore_rt();
}
#[no_mangle]
pub extern "C" fn signal(sig: c_int, func: Option<extern "C" fn(c_int)>) -> Option<extern "C" fn(c_int)> {
let sa = sigaction {
sa_handler: func,
sa_flags: SA_RESTART as c_ulong,
sa_restorer: Some(__restore_rt),
sa_mask: sigset_t::default(),
};
let mut old_sa = unsafe { mem::uninitialized() };
if unsafe { sigaction(sig, &sa, &mut old_sa) } < 0 {
mem::forget(old_sa);
return unsafe { mem::transmute(SIG_ERR) };
}
old_sa.sa_handler
}
// #[no_mangle]
pub extern "C" fn sigpause(sig: c_int) -> c_int {
unimplemented!();
}
// #[no_mangle]
pub extern "C" fn sigpending(set: *mut sigset_t) -> c_int {
unimplemented!();
}
#[no_mangle]
pub extern "C" fn sigprocmask(how: c_int, set: *const sigset_t, oset: *mut sigset_t) -> c_int {
Sys::sigprocmask(how, set, oset)
}
// #[no_mangle]
pub extern "C" fn sigrelse(sig: c_int) -> c_int {
unimplemented!();
}
// #[no_mangle]
pub extern "C" fn sigset(sig: c_int, func: fn(c_int)) -> fn(c_int) {
unimplemented!();
}
// #[no_mangle]
pub extern "C" fn sigsuspend(sigmask: *const sigset_t) -> c_int {
unimplemented!();
}
// #[no_mangle]
pub extern "C" fn sigwait(set: *const sigset_t, sig: *mut c_int) -> c_int {
unimplemented!();
}
pub const _signal_strings: [&'static str; 32] = [
"Unknown signal\0",
"Hangup\0",
"Interrupt\0",
"Quit\0",
"Illegal instruction\0",
"Trace/breakpoint trap\0",
"Aborted\0",
"Bus error\0",
"Arithmetic exception\0",
"Killed\0",
"User defined signal 1\0",
"Segmentation fault\0",
"User defined signal 2\0",
"Broken pipe\0",
"Alarm clock\0",
"Terminated\0",
"Stack fault\0",
"Child process status\0",
"Continued\0",
"Stopped (signal)\0",
"Stopped\0",
"Stopped (tty input)\0",
"Stopped (tty output)\0",
"Urgent I/O condition\0",
"CPU time limit exceeded\0",
"File size limit exceeded\0",
"Virtual timer expired\0",
"Profiling timer expired\0",
"Window changed\0",
"I/O possible\0",
"Power failure\0",
"Bad system call\0"
];
+60
View File
@@ -0,0 +1,60 @@
// Needs to be defined in assembly because it can't have a function prologue
#[cfg(target_arch = "x86_64")]
global_asm!(
"
.global __restore_rt
__restore_rt:
mov $119, %rax # <- rax is register, 119 is SIGRETURN
int $0x80
"
);
#[cfg(target_arch = "aarch64")]
global_asm!(
"
.global __restore_rt
__restore_rt:
mov x8, #119 # <- x8 is register, 119 is SIGRETURN
svc 0
"
);
pub const SIGHUP: usize = 1;
pub const SIGINT: usize = 2;
pub const SIGQUIT: usize = 3;
pub const SIGILL: usize = 4;
pub const SIGTRAP: usize = 5;
pub const SIGABRT: usize = 6;
pub const SIGBUS: usize = 7;
pub const SIGFPE: usize = 8;
pub const SIGKILL: usize = 9;
pub const SIGUSR1: usize = 10;
pub const SIGSEGV: usize = 11;
pub const SIGUSR2: usize = 12;
pub const SIGPIPE: usize = 13;
pub const SIGALRM: usize = 14;
pub const SIGTERM: usize = 15;
pub const SIGSTKFLT: usize = 16;
pub const SIGCHLD: usize = 17;
pub const SIGCONT: usize = 18;
pub const SIGSTOP: usize = 19;
pub const SIGTSTP: usize = 20;
pub const SIGTTIN: usize = 21;
pub const SIGTTOU: usize = 22;
pub const SIGURG: usize = 23;
pub const SIGXCPU: usize = 24;
pub const SIGXFSZ: usize = 25;
pub const SIGVTALRM: usize = 26;
pub const SIGPROF: usize = 27;
pub const SIGWINCH: usize = 28;
pub const SIGIO: usize = 29;
pub const SIGPWR: usize = 30;
pub const SIGSYS: usize = 31;
pub const SA_NOCLDSTOP: usize = 0x00000001;
pub const SA_NOCLDWAIT: usize = 0x00000002;
pub const SA_SIGINFO: usize = 0x00000004;
pub const SA_RESTORER: usize = 0x04000000;
pub const SA_ONSTACK: usize = 0x08000000;
pub const SA_RESTART: usize = 0x10000000;
pub const SA_NODEFER: usize = 0x40000000;
pub const SA_RESETHAND: usize = 0x80000000;
+11
View File
@@ -0,0 +1,11 @@
sys_includes = ["stdarg.h", "stddef.h", "stdint.h", "sys/types.h"]
include_guard = "_STDIO_H"
trailer = "#include <bits/stdio.h>"
language = "C"
style = "Type"
[enum]
prefix_with_name = true
[export.rename]
"AtomicBool" = "volatile char"
+27
View File
@@ -0,0 +1,27 @@
use platform::types::*;
pub const BUFSIZ: size_t = 1024;
pub const UNGET: size_t = 8;
pub const FILENAME_MAX: c_int = 4096;
pub const F_PERM: c_int = 1;
pub const F_NORD: c_int = 4;
pub const F_NOWR: c_int = 8;
pub const F_EOF: c_int = 16;
pub const F_ERR: c_int = 32;
pub const F_SVB: c_int = 64;
pub const F_APP: c_int = 128;
pub const F_BADJ: c_int = 256;
pub const SEEK_SET: c_int = 0;
pub const SEEK_CUR: c_int = 1;
pub const SEEK_END: c_int = 2;
pub const _IOFBF: c_int = 0;
pub const _IOLBF: c_int = 1;
pub const _IONBF: c_int = 2;
#[allow(non_camel_case_types)]
pub type fpos_t = off_t;
+61
View File
@@ -0,0 +1,61 @@
use super::{constants, BUFSIZ, FILE, UNGET};
use core::cell::UnsafeCell;
use core::ptr;
use core::sync::atomic::AtomicBool;
pub struct GlobalFile(UnsafeCell<FILE>);
impl GlobalFile {
const fn new(file: FILE) -> Self {
GlobalFile(UnsafeCell::new(file))
}
pub fn get(&self) -> *mut FILE {
self.0.get()
}
}
// 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(FILE {
flags: constants::F_PERM | constants::F_NOWR,
read: None,
write: None,
fd: 0,
buf: vec![0u8;(BUFSIZ + UNGET) as usize],
buf_char: -1,
unget: UNGET,
lock: AtomicBool::new(false),
});
#[allow(non_upper_case_globals)]
pub static ref default_stdout: GlobalFile = GlobalFile::new(FILE {
flags: constants::F_PERM | constants::F_NORD,
read: None,
write: None,
fd: 1,
buf: vec![0u8;(BUFSIZ + UNGET) as usize],
buf_char: b'\n' as i8,
unget: 0,
lock: AtomicBool::new(false),
});
#[allow(non_upper_case_globals)]
pub static ref default_stderr: GlobalFile = GlobalFile::new(FILE {
flags: constants::F_PERM | constants::F_NORD,
read: None,
write: None,
fd: 2,
buf: vec![0u8;(BUFSIZ + UNGET) as usize],
buf_char: -1,
unget: 0,
lock: AtomicBool::new(false),
});
}
#[no_mangle]
pub static mut stdin: *mut FILE = ptr::null_mut();
#[no_mangle]
pub static mut stdout: *mut FILE = ptr::null_mut();
#[no_mangle]
pub static mut stderr: *mut FILE = ptr::null_mut();
+154
View File
@@ -0,0 +1,154 @@
use super::constants::*;
use super::{BUFSIZ, FILE, UNGET};
use core::mem;
use core::sync::atomic::AtomicBool;
use errno;
use fcntl::*;
use platform;
use platform::types::*;
/// Parse mode flags as a string and output a mode flags integer
pub unsafe fn parse_mode_flags(mode_str: *const c_char) -> i32 {
use string::strchr;
let mut flags = if !strchr(mode_str, b'+' as i32).is_null() {
O_RDWR
} else if (*mode_str) == b'r' as i8 {
O_RDONLY
} else {
O_WRONLY
};
if !strchr(mode_str, b'x' as i32).is_null() {
flags |= O_EXCL;
}
if !strchr(mode_str, b'e' as i32).is_null() {
flags |= O_CLOEXEC;
}
if (*mode_str) != b'r' as i8 {
flags |= O_CREAT;
}
if (*mode_str) == b'w' as i8 {
flags |= O_TRUNC;
}
if (*mode_str) != b'a' as i8 {
flags |= O_APPEND;
}
flags
}
/// Open a file with the file descriptor `fd` in the mode `mode`
pub unsafe fn _fdopen(fd: c_int, mode: *const c_char) -> Option<*mut FILE> {
use string::strchr;
if *mode != b'r' as i8 && *mode != b'w' as i8 && *mode != b'a' as i8 {
platform::errno = errno::EINVAL;
return None;
}
let mut flags = 0;
if strchr(mode, b'+' as i32).is_null() {
flags |= if *mode == b'r' as i8 { F_NOWR } else { F_NORD };
}
if !strchr(mode, b'e' as i32).is_null() {
sys_fcntl(fd, F_SETFD, FD_CLOEXEC);
}
if *mode == 'a' as i8 {
let f = sys_fcntl(fd, F_GETFL, 0);
if (f & O_APPEND) == 0 {
sys_fcntl(fd, F_SETFL, f | O_APPEND);
}
flags |= F_APP;
}
let f = platform::alloc(mem::size_of::<FILE>()) as *mut FILE;
// Allocate the file
if f.is_null() {
None
} else {
(*f).flags = flags;
(*f).read = None;
(*f).write = None;
(*f).fd = fd;
(*f).buf = vec![0u8; BUFSIZ + UNGET];
(*f).buf_char = -1;
(*f).unget = UNGET;
(*f).lock = AtomicBool::new(false);
Some(f)
}
}
/// Write buffer `buf` of length `l` into `stream`
pub fn fwritex(buf: *const u8, l: size_t, stream: &mut FILE) -> size_t {
use core::ptr::copy_nonoverlapping;
use core::slice;
let buf: &'static [u8] = unsafe { slice::from_raw_parts(buf, l) };
let mut l = l;
let mut advance = 0;
if stream.write.is_none() && !stream.can_write() {
// We can't write to this stream
return 0;
}
if let Some((wbase, wpos, wend)) = stream.write {
if l > wend - wpos {
// We can't fit all of buf in the buffer
return stream.write(buf);
}
let i = if stream.buf_char >= 0 {
let mut i = l;
while i > 0 && buf[i - 1] != b'\n' {
i -= 1;
}
if i > 0 {
let n = stream.write(buf);
if n < i {
return n;
}
advance += i;
l -= i;
}
i
} else {
0
};
unsafe {
copy_nonoverlapping(
&buf[advance..] as *const _ as *const u8,
&mut stream.buf[wpos..] as *mut _ as *mut u8,
l,
);
}
stream.write = Some((wbase, wpos + l, wend));
l + i
} else {
0
}
}
/// Flush `stream` without locking it.
pub fn fflush_unlocked(stream: &mut FILE) -> c_int {
if let Some((wbase, wpos, _)) = stream.write {
if wpos > wbase {
stream.write(&[]);
/*
if stream.wpos.is_null() {
return -1;
}
*/
}
}
if let Some((rpos, rend)) = stream.read {
if rpos < rend {
stream.seek(rpos as i64 - rend as i64, SEEK_CUR);
}
}
stream.write = None;
stream.read = None;
0
}

Some files were not shown because too many files have changed in this diff Show More