diff --git a/.gitmodules b/.gitmodules index 6d57d168a7b3dc0b645a1d57d7d59a1f2871d1db..cde224a0c5ec9febe9d4270b683dca366c94583a 100644 --- a/.gitmodules +++ b/.gitmodules @@ -7,3 +7,6 @@ [submodule "ralloc"] path = ralloc url = https://github.com/redox-os/ralloc.git +[submodule "va_list"] + path = va_list + url = https://github.com/redox-os/va_list-rs.git diff --git a/Cargo.lock b/Cargo.lock index 50b797789329e5ef31680aa03a2e622fa2b7bf70..ada4d0b66da37b1d1db0f6c0e9b3bd499435660a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -97,6 +97,11 @@ name = "fuchsia-zircon-sys" version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "gcc" +version = "0.3.54" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "grp" version = "0.1.0" @@ -140,6 +145,14 @@ dependencies = [ "cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "mman" +version = "0.1.0" +dependencies = [ + "cbindgen 0.5.0", + "platform 0.1.0", +] + [[package]] name = "num-traits" version = "0.2.1" @@ -177,6 +190,7 @@ dependencies = [ name = "platform" version = "0.1.0" dependencies = [ + "redox_syscall 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)", "sc 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -197,6 +211,7 @@ dependencies = [ name = "ralloc_shim" version = "0.1.1" dependencies = [ + "redox_syscall 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)", "sc 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -231,6 +246,7 @@ dependencies = [ "ctype 0.1.0", "fcntl 0.1.0", "grp 0.1.0", + "mman 0.1.0", "platform 0.1.0", "stdio 0.1.0", "stdlib 0.1.0", @@ -411,7 +427,7 @@ version = "0.1.0" dependencies = [ "cbindgen 0.5.0", "platform 0.1.0", - "va_list 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "va_list 0.1.0", ] [[package]] @@ -529,7 +545,16 @@ dependencies = [ [[package]] name = "va_list" version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "va_list-helper 0.0.2", +] + +[[package]] +name = "va_list-helper" +version = "0.0.2" +dependencies = [ + "gcc 0.3.54 (registry+https://github.com/rust-lang/crates.io-index)", +] [[package]] name = "vec_map" @@ -575,6 +600,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum dtoa 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "09c3753c3db574d215cba4ea76018483895d7bff25a31b49ba45db21c48e50ab" "checksum fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2e9763c69ebaae630ba35f74888db465e49e259ba1bc0eda7d06f4a067615d82" "checksum fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7" +"checksum gcc 0.3.54 (registry+https://github.com/rust-lang/crates.io-index)" = "5e33ec290da0d127825013597dbdfc28bee4964690c7ce1166cbc2a7bd08b1bb" "checksum itoa 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "8324a32baf01e2ae060e9de58ed0bc2320c9a2833491ee36cd3b4c414de4db8c" "checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" "checksum libc 0.2.37 (registry+https://github.com/rust-lang/crates.io-index)" = "56aebce561378d99a0bb578f8cb15b6114d2a1814a6c7949bbe646d968bb4fa9" @@ -618,7 +644,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum unicode-width 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "bf3a113775714a22dcb774d8ea3655c53a32debae63a063acc00a91cc586245f" "checksum unicode-xid 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "8c1f860d7d29cf02cb2f3f359fd35991af3d30bac52c57d265a3c461074cb4dc" "checksum unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc" -"checksum va_list 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7365862faee55ed0dbc112491aa5f0451ca01bf98afcc6463183b5aaa5bd3128" "checksum vec_map 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "887b5b631c2ad01628bbbaa7dd4c869f80d3186688f8d0b6f58774fbe324988c" "checksum winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a" "checksum winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "04e3bd221fcbe8a271359c04f21a76db7d0c6028862d1bb5512d85e1e2eb5bb3" diff --git a/Cargo.toml b/Cargo.toml index d8d0aa6638325d218770e4c984f438270fa3b5c1..11148175fe47c910fc5ec90a2b9f4f37a530b20a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -17,6 +17,7 @@ ctype = { path = "src/ctype" } fcntl = { path = "src/fcntl" } grp = { path = "src/grp" } semaphore = { path = "src/semaphore" } +mman = { path = "src/mman" } stdio = { path = "src/stdio" } stdlib = { path = "src/stdlib" } string = { path = "src/string" } diff --git a/platform/Cargo.toml b/platform/Cargo.toml index d0e3478f296d229eed1f9d67d683097ac76e7a3e..e25b8251c0c6bb44761c2f5a8af2e7eda0c70881 100644 --- a/platform/Cargo.toml +++ b/platform/Cargo.toml @@ -3,5 +3,8 @@ name = "platform" version = "0.1.0" authors = ["Jeremy Soller <jackpot51@gmail.com>"] -[dependencies] +[target.'cfg(target_os = "linux")'.dependencies] sc = "0.2" + +[target.'cfg(target_os = "redox")'.dependencies] +redox_syscall = "0.1" diff --git a/platform/src/lib.rs b/platform/src/lib.rs index 1a33ffa31823a2780558e4e00abb4bb066c1ecaa..f8fdb8e18eba00fd877abc9188bbc626f976bdf2 100644 --- a/platform/src/lib.rs +++ b/platform/src/lib.rs @@ -20,7 +20,22 @@ pub mod types; use core::fmt; -use types::c_int; +use types::*; + +pub unsafe fn c_str(s: *const c_char) -> &'static [u8] { + use core::slice; + + let mut size = 0; + + loop { + if *s.offset(size) == 0 { + break; + } + size += 1; + } + + slice::from_raw_parts(s as *const u8, size as usize) +} pub struct FileWriter(pub c_int); diff --git a/platform/src/redox/mod.rs b/platform/src/redox/mod.rs index 239d06a6be9fbdf1774b1cb46037edbbf87ef760..b1178bf55ec7faf56057a3e5d9a24668939a9aeb 100644 --- a/platform/src/redox/mod.rs +++ b/platform/src/redox/mod.rs @@ -1,8 +1,24 @@ +use syscall; + +use c_str; +use types::*; + +pub fn close(fd: c_int) -> c_int { + syscall::close(fd as usize); + 0 +} + pub fn exit(status: c_int) -> ! { - syscall::exit(status); + syscall::exit(status as usize); + loop {} +} + +pub fn open(path: *const c_char, oflag: c_int, mode: mode_t) -> c_int { + let path = unsafe { c_str(path) }; + syscall::open(path, (oflag as usize) | (mode as usize)).unwrap() as c_int } pub fn write(fd: c_int, buf: &[u8]) -> ssize_t { - syscall::write(fd, buf); + syscall::write(fd as usize, buf); buf.len() as ssize_t } diff --git a/ralloc b/ralloc index b521bac28702de86c7c4eef9641ec83c6ac38224..31b781a287748c10671a6c7e4415093d2dd4df4a 160000 --- a/ralloc +++ b/ralloc @@ -1 +1 @@ -Subproject commit b521bac28702de86c7c4eef9641ec83c6ac38224 +Subproject commit 31b781a287748c10671a6c7e4415093d2dd4df4a diff --git a/src/mman/Cargo.toml b/src/mman/Cargo.toml new file mode 100644 index 0000000000000000000000000000000000000000..e7e1f0d91588be3e29bc7dbc98b9f67396bbe76c --- /dev/null +++ b/src/mman/Cargo.toml @@ -0,0 +1,11 @@ +[package] +name = "mman" +version = "0.1.0" +authors = ["Jeremy Soller <jackpot51@gmail.com>"] +build = "build.rs" + +[build-dependencies] +cbindgen = { path = "../../cbindgen" } + +[dependencies] +platform = { path = "../../platform" } diff --git a/src/mman/build.rs b/src/mman/build.rs new file mode 100644 index 0000000000000000000000000000000000000000..0758d24db31b59a65fceebd8e6cf3a1e6aea4a69 --- /dev/null +++ b/src/mman/build.rs @@ -0,0 +1,11 @@ +extern crate cbindgen; + +use std::{env, fs}; + +fn main() { + let crate_dir = env::var("CARGO_MANIFEST_DIR").expect("CARGO_MANIFEST_DIR not set"); + fs::create_dir_all("../../target/include").expect("failed to create include directory"); + cbindgen::generate(crate_dir) + .expect("failed to generate bindings") + .write_to_file("../../target/include/mman.h"); +} diff --git a/src/mman/cbindgen.toml b/src/mman/cbindgen.toml new file mode 100644 index 0000000000000000000000000000000000000000..84677294aa2cab886f5ff8b4e454eaabaa78b056 --- /dev/null +++ b/src/mman/cbindgen.toml @@ -0,0 +1,6 @@ +sys_includes = [] +include_guard = "_MMAN_H" +language = "C" + +[enum] +prefix_with_name = true diff --git a/src/mman/src/lib.rs b/src/mman/src/lib.rs new file mode 100644 index 0000000000000000000000000000000000000000..e20b1269ff85fa008631bc9841f4cad6004519a9 --- /dev/null +++ b/src/mman/src/lib.rs @@ -0,0 +1,66 @@ +#![no_std] + +extern crate platform; + +use platform::types::*; + +#[no_mangle] +pub extern "C" fn mlock(addr: *const c_void, len: usize) -> c_int { + unimplemented!(); +} + +#[no_mangle] +pub extern "C" fn mlockall(flags: c_int) -> c_int { + unimplemented!(); +} + +#[no_mangle] +pub extern "C" fn mmap( + addr: *mut c_void, + len: usize, + prot: c_int, + flags: c_int, + fildes: c_int, + off: off_t, +) -> *mut c_void { + unimplemented!(); +} + +#[no_mangle] +pub extern "C" fn mprotect(addr: *mut c_void, len: usize, prot: c_int) -> c_int { + unimplemented!(); +} + +#[no_mangle] +pub extern "C" fn msync(addr: *mut c_void, len: usize, flags: c_int) -> c_int { + unimplemented!(); +} + +#[no_mangle] +pub extern "C" fn munlock(addr: *const c_void, len: usize) -> c_int { + unimplemented!(); +} + +#[no_mangle] +pub extern "C" fn munlockall() -> c_int { + unimplemented!(); +} + +#[no_mangle] +pub extern "C" fn munmap(addr: *mut c_void, len: usize) -> c_int { + unimplemented!(); +} + +#[no_mangle] +pub extern "C" fn shm_open( + name: *const c_char, + oflag: c_int, + mode: mode_t, +) -> c_int { + unimplemented!(); +} + +#[no_mangle] +pub extern "C" fn shm_unlink(name: *const c_char) -> c_int { + unimplemented!(); +} diff --git a/src/stdio/Cargo.toml b/src/stdio/Cargo.toml index 78c082e15add37be8ca15b49e03a4617183d010a..c74b048852e1033ad82bc59abd8cd9b2e8d4b45a 100644 --- a/src/stdio/Cargo.toml +++ b/src/stdio/Cargo.toml @@ -9,4 +9,4 @@ cbindgen = { path = "../../cbindgen" } [dependencies] platform = { path = "../../platform" } -va_list = { version = "0.1", features = ["no_std"] } +va_list = { path = "../../va_list", features = ["no_std"] } diff --git a/src/stdlib/src/lib.rs b/src/stdlib/src/lib.rs index 91ddb0723d6b9dfff0a167ba4b202ba7362d5798..5beef27eea9262f84210d586249cfc9717d492dc 100644 --- a/src/stdlib/src/lib.rs +++ b/src/stdlib/src/lib.rs @@ -116,8 +116,7 @@ pub unsafe extern "C" fn exit(status: c_int) { use core::mem; for i in (0..ATEXIT_FUNCS.len()).rev() { - if ATEXIT_FUNCS[i] != None { - let func = mem::transmute::<usize, extern "C" fn()>(ATEXIT_FUNCS[i].unwrap()); + if let Some(func) = ATEXIT_FUNCS[i] { (func)(); } } diff --git a/src/string/src/lib.rs b/src/string/src/lib.rs index eb98911358dda695825aee8bda1e8b910010e226..e597532763bace6d39720fd53c6ff60317e5cc3d 100644 --- a/src/string/src/lib.rs +++ b/src/string/src/lib.rs @@ -104,16 +104,7 @@ pub extern "C" fn strerror(errnum: c_int) -> *mut c_char { #[no_mangle] pub unsafe extern "C" fn strlen(s: *const c_char) -> size_t { - let mut size = 0; - - loop { - if *s.offset(size) == 0 { - break; - } - size += 1; - } - - size as size_t + platform::c_str(s).len() as size_t } #[no_mangle] diff --git a/src/todo/mman/lib.rs b/src/todo/mman/lib.rs deleted file mode 100644 index 4d6f76a369a5080d2fcacb5078cc6c0b50e49e24..0000000000000000000000000000000000000000 --- a/src/todo/mman/lib.rs +++ /dev/null @@ -1,60 +0,0 @@ -#[no_mangle] -pub extern "C" fn mlock(addr: *const libc::c_void, len: usize) -> libc::c_int { - unimplemented!(); -} - -#[no_mangle] -pub extern "C" fn mlockall(flags: libc::c_int) -> libc::c_int { - unimplemented!(); -} - -#[no_mangle] -pub extern "C" fn mmap( - addr: *mut libc::c_void, - len: usize, - prot: libc::c_int, - flags: libc::c_int, - fildes: libc::c_int, - off: off_t, -) -> *mut libc::c_void { - unimplemented!(); -} - -#[no_mangle] -pub extern "C" fn mprotect(addr: *mut libc::c_void, len: usize, prot: libc::c_int) -> libc::c_int { - unimplemented!(); -} - -#[no_mangle] -pub extern "C" fn msync(addr: *mut libc::c_void, len: usize, flags: libc::c_int) -> libc::c_int { - unimplemented!(); -} - -#[no_mangle] -pub extern "C" fn munlock(addr: *const libc::c_void, len: usize) -> libc::c_int { - unimplemented!(); -} - -#[no_mangle] -pub extern "C" fn munlockall() -> libc::c_int { - unimplemented!(); -} - -#[no_mangle] -pub extern "C" fn munmap(addr: *mut libc::c_void, len: usize) -> libc::c_int { - unimplemented!(); -} - -#[no_mangle] -pub extern "C" fn shm_open( - name: *const libc::c_char, - oflag: libc::c_int, - mode: mode_t, -) -> libc::c_int { - unimplemented!(); -} - -#[no_mangle] -pub extern "C" fn shm_unlink(name: *const libc::c_char) -> libc::c_int { - unimplemented!(); -} diff --git a/src/todo/oldlib/dns/answer.rs b/src/todo/oldlib/dns/answer.rs new file mode 100644 index 0000000000000000000000000000000000000000..d50570bbbd0e77e4eb99f0a37c1b24df67a56158 --- /dev/null +++ b/src/todo/oldlib/dns/answer.rs @@ -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> +} diff --git a/src/todo/oldlib/dns/mod.rs b/src/todo/oldlib/dns/mod.rs new file mode 100644 index 0000000000000000000000000000000000000000..94cc2b0747bc5a8f9a6cfe421da56d757edfa078 --- /dev/null +++ b/src/todo/oldlib/dns/mod.rs @@ -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, + }) + } +} diff --git a/src/todo/oldlib/dns/query.rs b/src/todo/oldlib/dns/query.rs new file mode 100644 index 0000000000000000000000000000000000000000..f0b536fd60bbe8f71c7657c75232715a7b4070fe --- /dev/null +++ b/src/todo/oldlib/dns/query.rs @@ -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 +} diff --git a/src/todo/oldlib/event.rs b/src/todo/oldlib/event.rs new file mode 100644 index 0000000000000000000000000000000000000000..297a18f201cf18f7459553c28a704c38a8bcf82d --- /dev/null +++ b/src/todo/oldlib/event.rs @@ -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) +}); diff --git a/src/todo/oldlib/file.rs b/src/todo/oldlib/file.rs new file mode 100644 index 0000000000000000000000000000000000000000..72dcea0bd9c9365142117a1dda89f60d07d9e756 --- /dev/null +++ b/src/todo/oldlib/file.rs @@ -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 + } +}); diff --git a/src/todo/oldlib/folder.rs b/src/todo/oldlib/folder.rs new file mode 100644 index 0000000000000000000000000000000000000000..1406684b159196c13e7072d9c7fdae82564c3953 --- /dev/null +++ b/src/todo/oldlib/folder.rs @@ -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) +}); diff --git a/src/todo/oldlib/hostname.rs b/src/todo/oldlib/hostname.rs new file mode 100644 index 0000000000000000000000000000000000000000..5618a87f071957a26c66c433c02fe740e6cf4c20 --- /dev/null +++ b/src/todo/oldlib/hostname.rs @@ -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) +}); diff --git a/src/todo/oldlib/lib.rs b/src/todo/oldlib/lib.rs new file mode 100644 index 0000000000000000000000000000000000000000..6e652372449ce76ef2c67e5de5c5f926728795f0 --- /dev/null +++ b/src/todo/oldlib/lib.rs @@ -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); +}); diff --git a/src/todo/oldlib/macros.rs b/src/todo/oldlib/macros.rs new file mode 100644 index 0000000000000000000000000000000000000000..85d8c37334c3e89c802b38a6b4bca2122f78fc1b --- /dev/null +++ b/src/todo/oldlib/macros.rs @@ -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 + } + }; +} diff --git a/src/todo/oldlib/mallocnull.rs b/src/todo/oldlib/mallocnull.rs new file mode 100644 index 0000000000000000000000000000000000000000..25640b7be03b2a265d1d3c215a06fb7fefbc6e5e --- /dev/null +++ b/src/todo/oldlib/mallocnull.rs @@ -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) }; + } + } +} diff --git a/src/todo/oldlib/netdb.rs b/src/todo/oldlib/netdb.rs new file mode 100644 index 0000000000000000000000000000000000000000..68e6a9aa32384ec1e11f5dd07feb0a05fb71763c --- /dev/null +++ b/src/todo/oldlib/netdb.rs @@ -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 { + +//}); diff --git a/src/todo/oldlib/process.rs b/src/todo/oldlib/process.rs new file mode 100644 index 0000000000000000000000000000000000000000..e0fcc629559a22e9d8155354ce62781fcd5af24a --- /dev/null +++ b/src/todo/oldlib/process.rs @@ -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) +}); diff --git a/src/todo/oldlib/rawfile.rs b/src/todo/oldlib/rawfile.rs new file mode 100644 index 0000000000000000000000000000000000000000..4aeec266f6c275eef9a37748df0976cc34d645d2 --- /dev/null +++ b/src/todo/oldlib/rawfile.rs @@ -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 + } +} diff --git a/src/todo/oldlib/redox.rs b/src/todo/oldlib/redox.rs new file mode 100644 index 0000000000000000000000000000000000000000..d386cd7d7f57d524317a121a8c82b8416555556c --- /dev/null +++ b/src/todo/oldlib/redox.rs @@ -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) +}); diff --git a/src/todo/oldlib/socket.rs b/src/todo/oldlib/socket.rs new file mode 100644 index 0000000000000000000000000000000000000000..f0232b96888622887de361eb92dd3736e23e28e2 --- /dev/null +++ b/src/todo/oldlib/socket.rs @@ -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)) +}); diff --git a/src/todo/oldlib/termios.rs b/src/todo/oldlib/termios.rs new file mode 100644 index 0000000000000000000000000000000000000000..c2bceab83ae016b885ef708f87638d7c007cb090 --- /dev/null +++ b/src/todo/oldlib/termios.rs @@ -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) +}); diff --git a/src/todo/oldlib/time.rs b/src/todo/oldlib/time.rs new file mode 100644 index 0000000000000000000000000000000000000000..c233fd614e7339c10496ddc7f3e5ad1c8f6d08f0 --- /dev/null +++ b/src/todo/oldlib/time.rs @@ -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) +}); diff --git a/src/todo/oldlib/types.rs b/src/todo/oldlib/types.rs new file mode 100644 index 0000000000000000000000000000000000000000..5f022cb9a8e0bf419f005c51b7a24ef2de8ab936 --- /dev/null +++ b/src/todo/oldlib/types.rs @@ -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 +} diff --git a/src/todo/oldlib/unimpl.rs b/src/todo/oldlib/unimpl.rs new file mode 100644 index 0000000000000000000000000000000000000000..56c4aa4bc5f2d6ba05feb74f12fa27a381973b16 --- /dev/null +++ b/src/todo/oldlib/unimpl.rs @@ -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) +}); diff --git a/src/todo/oldlib/user.rs b/src/todo/oldlib/user.rs new file mode 100644 index 0000000000000000000000000000000000000000..3de26a89d2cd5fefd288a266c351381dbc077f54 --- /dev/null +++ b/src/todo/oldlib/user.rs @@ -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)) +}); diff --git a/tests/Makefile b/tests/Makefile index 8d98779817e439dd33837e9f338a6769f4254f35..cb605f4eac4046c25d85a8c381c86aa808e66a0a 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -16,6 +16,7 @@ run: $(BINS) %: %.c gcc \ + -fno-stack-protector \ -nostdinc \ -nostdlib \ -I ../include \ diff --git a/va_list b/va_list new file mode 160000 index 0000000000000000000000000000000000000000..4762a184501beedbb58ea218f0c84fea85685c35 --- /dev/null +++ b/va_list @@ -0,0 +1 @@ +Subproject commit 4762a184501beedbb58ea218f0c84fea85685c35