Large reorganization of headers (WIP)
This commit is contained in:
@@ -0,0 +1,7 @@
|
||||
sys_includes = []
|
||||
include_guard = "_TEMPLATE_H"
|
||||
language = "C"
|
||||
style = "Tag"
|
||||
|
||||
[enum]
|
||||
prefix_with_name = true
|
||||
@@ -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!();
|
||||
}
|
||||
*/
|
||||
@@ -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!();
|
||||
}
|
||||
@@ -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>
|
||||
}
|
||||
@@ -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,
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
@@ -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)
|
||||
});
|
||||
@@ -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, ×)?;
|
||||
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, ×)?;
|
||||
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
|
||||
}
|
||||
});
|
||||
@@ -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)
|
||||
});
|
||||
@@ -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)
|
||||
});
|
||||
@@ -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);
|
||||
});
|
||||
@@ -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
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -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) };
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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 {
|
||||
|
||||
//});
|
||||
@@ -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)
|
||||
});
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
@@ -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)
|
||||
});
|
||||
@@ -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))
|
||||
});
|
||||
@@ -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)
|
||||
});
|
||||
@@ -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)
|
||||
});
|
||||
@@ -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
|
||||
}
|
||||
@@ -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)
|
||||
});
|
||||
@@ -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))
|
||||
});
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
@@ -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!();
|
||||
}
|
||||
@@ -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
|
||||
@@ -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!();
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
sys_includes = []
|
||||
include_guard = "_CTYPE_H"
|
||||
language = "C"
|
||||
style = "Tag"
|
||||
|
||||
[enum]
|
||||
prefix_with_name = true
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
@@ -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)
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
sys_includes = ["bits/errno.h"]
|
||||
include_guard = "_ERRNO_H"
|
||||
language = "C"
|
||||
style = "Tag"
|
||||
|
||||
[enum]
|
||||
prefix_with_name = true
|
||||
@@ -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",
|
||||
];
|
||||
@@ -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
|
||||
@@ -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;
|
||||
@@ -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)
|
||||
}
|
||||
@@ -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;
|
||||
@@ -0,0 +1,7 @@
|
||||
sys_includes = ["stdint.h", "sys/types.h"]
|
||||
include_guard = "_FENV_H"
|
||||
language = "C"
|
||||
style = "Tag"
|
||||
|
||||
[enum]
|
||||
prefix_with_name = true
|
||||
@@ -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!();
|
||||
}
|
||||
@@ -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
|
||||
@@ -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,
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
include_guard = "_FNMATCH_H"
|
||||
language = "C"
|
||||
style = "Tag"
|
||||
|
||||
[enum]
|
||||
prefix_with_name = true
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
sys_includes = []
|
||||
include_guard = "_GRP_H"
|
||||
language = "C"
|
||||
style = "Tag"
|
||||
|
||||
[enum]
|
||||
prefix_with_name = true
|
||||
@@ -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!();
|
||||
}
|
||||
*/
|
||||
@@ -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
|
||||
@@ -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!();
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
include_guard = "_LOCALE_H"
|
||||
trailer = "#include <bits/locale.h>"
|
||||
language = "C"
|
||||
style = "Tag"
|
||||
|
||||
[enum]
|
||||
prefix_with_name = true
|
||||
@@ -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()
|
||||
}
|
||||
@@ -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;
|
||||
@@ -0,0 +1,7 @@
|
||||
[package]
|
||||
name = "netinet"
|
||||
version = "0.1.0"
|
||||
authors = ["Dan Robertson <danlrobertson89@gmail.com>"]
|
||||
|
||||
[dependencies]
|
||||
in_h = { path = "in" }
|
||||
@@ -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
|
||||
@@ -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;
|
||||
@@ -0,0 +1,7 @@
|
||||
sys_includes = ["stddef.h", "sys/types.h"]
|
||||
include_guard = "_PWD_H"
|
||||
language = "C"
|
||||
style = "Tag"
|
||||
|
||||
[enum]
|
||||
prefix_with_name = true
|
||||
@@ -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
|
||||
},
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
sys_includes = []
|
||||
include_guard = "_SEMAPHORE_H"
|
||||
language = "C"
|
||||
style = "Tag"
|
||||
|
||||
[enum]
|
||||
prefix_with_name = true
|
||||
@@ -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!();
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
[package]
|
||||
name = "setjmp"
|
||||
version = "0.1.0"
|
||||
authors = ["Jeremy Soller <jackpot51@gmail.com>"]
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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)
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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";
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
sys_includes = ["sys/ioctl.h"]
|
||||
include_guard = "_SGTTY_H"
|
||||
style = "Tag"
|
||||
language = "C"
|
||||
|
||||
[enum]
|
||||
prefix_with_name = true
|
||||
@@ -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
|
||||
}
|
||||
@@ -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
|
||||
@@ -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;
|
||||
@@ -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"
|
||||
];
|
||||
@@ -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;
|
||||
@@ -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"
|
||||
@@ -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;
|
||||
@@ -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();
|
||||
@@ -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
Reference in New Issue
Block a user