From 01081729c83d62ff83950f2a197a73f8ef719b59 Mon Sep 17 00:00:00 2001 From: Dan Robertson Date: Thu, 15 Mar 2018 17:19:58 +0000 Subject: [PATCH 01/11] Add structures and stub fns for sys/socket.h Add some of the basic structures and stub functions for sys/socket.h --- Cargo.lock | 9 +++ Cargo.toml | 1 + src/lib.rs | 1 + src/socket/Cargo.toml | 11 +++ src/socket/build.rs | 11 +++ src/socket/cbindgen.toml | 11 +++ src/socket/src/lib.rs | 153 +++++++++++++++++++++++++++++++++++++++ 7 files changed, 197 insertions(+) create mode 100644 src/socket/Cargo.toml create mode 100644 src/socket/build.rs create mode 100644 src/socket/cbindgen.toml create mode 100644 src/socket/src/lib.rs diff --git a/Cargo.lock b/Cargo.lock index 224eaaa31c..4eab6e0089 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -263,6 +263,7 @@ dependencies = [ "resource 0.1.0", "semaphore 0.1.0", "signal 0.1.0", + "socket 0.1.0", "stat 0.1.0", "stdio 0.1.0", "stdlib 0.1.0", @@ -351,6 +352,14 @@ dependencies = [ "platform 0.1.0", ] +[[package]] +name = "socket" +version = "0.1.0" +dependencies = [ + "cbindgen 0.5.2", + "platform 0.1.0", +] + [[package]] name = "standalone-quote" version = "0.5.0" diff --git a/Cargo.toml b/Cargo.toml index ffd5eea4ec..f1481acd6b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -23,6 +23,7 @@ platform = { path = "src/platform" } resource = { path = "src/resource" } semaphore = { path = "src/semaphore" } signal = { path = "src/signal" } +socket = { path = "src/socket" } stat = { path = "src/stat" } stdio = { path = "src/stdio" } stdlib = { path = "src/stdlib" } diff --git a/src/lib.rs b/src/lib.rs index b51ef10c08..27572f76fa 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -13,6 +13,7 @@ extern crate grp; extern crate mman; extern crate resource; extern crate semaphore; +extern crate socket; extern crate stat; extern crate stdio; extern crate stdlib; diff --git a/src/socket/Cargo.toml b/src/socket/Cargo.toml new file mode 100644 index 0000000000..12801f04aa --- /dev/null +++ b/src/socket/Cargo.toml @@ -0,0 +1,11 @@ +[package] +name = "socket" +version = "0.1.0" +authors = ["Dan Robertson "] +build = "build.rs" + +[build-dependencies] +cbindgen = { path = "../../cbindgen" } + +[dependencies] +platform = { path = "../platform" } diff --git a/src/socket/build.rs b/src/socket/build.rs new file mode 100644 index 0000000000..ad891ecb68 --- /dev/null +++ b/src/socket/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/sys/socket.h"); +} diff --git a/src/socket/cbindgen.toml b/src/socket/cbindgen.toml new file mode 100644 index 0000000000..fc968ead01 --- /dev/null +++ b/src/socket/cbindgen.toml @@ -0,0 +1,11 @@ +sys_includes = ["sys/types.h"] +include_guard = "_SYS_SOCKET_H" +style = "Tag" +language = "C" + +[defines] +"target_os=linux" = "__linux__" +"target_os=redox" = "__redox__" + +[enum] +prefix_with_name = true diff --git a/src/socket/src/lib.rs b/src/socket/src/lib.rs new file mode 100644 index 0000000000..c7c0b5f2bc --- /dev/null +++ b/src/socket/src/lib.rs @@ -0,0 +1,153 @@ +//! socket implementation for Redox, following http://pubs.opengroup.org/onlinepubs/7908799/xns/syssocket.h.html + +#![no_std] +#![allow(non_camel_case_types)] + +extern crate platform; + +use platform::types::*; + +pub type sa_family_t = u16; +pub type socklen_t = u32; + +#[repr(C)] +pub struct sockaddr { + pub sa_family: sa_family_t, + pub sa_data: [c_char; 14], +} + +#[no_mangle] +pub unsafe extern "C" fn accept( + socket: c_int, + address: *mut sockaddr, + address_len: *mut socklen_t, +) -> c_int { + unimplemented!(); +} + +#[no_mangle] +pub unsafe extern "C" fn bind( + socket: c_int, + address: *const sockaddr, + address_len: socklen_t, +) -> c_int { + unimplemented!(); +} + +#[no_mangle] +pub unsafe extern "C" fn connect( + socket: c_int, + address: *const sockaddr, + address_len: socklen_t, +) -> c_int { + unimplemented!(); +} + +#[no_mangle] +pub unsafe extern "C" fn getpeername( + socket: c_int, + address: *const sockaddr, + address_len: socklen_t, +) -> c_int { + unimplemented!(); +} + +#[no_mangle] +pub unsafe extern "C" fn getsockname( + socket: c_int, + address: *mut sockaddr, + address_len: *mut socklen_t, +) -> c_int { + unimplemented!(); +} + +#[no_mangle] +pub unsafe extern "C" fn getsockopt( + socket: c_int, + level: c_int, + option_name: c_int, + option_value: *mut c_void, + option_len: *mut socklen_t, +) -> c_int { + unimplemented!(); +} + +#[no_mangle] +pub unsafe extern "C" fn listen(socket: c_int, backlog: c_int) -> c_int { + unimplemented!(); +} + +#[no_mangle] +pub unsafe extern "C" fn recv( + socket: c_int, + buffer: *mut c_void, + length: size_t, + flags: c_int, +) -> ssize_t { + unimplemented!(); +} + +#[no_mangle] +pub unsafe extern "C" fn recvfrom( + socket: c_int, + buffer: *mut c_void, + length: size_t, + flags: c_int, + address: *mut sockaddr, + address_len: *mut socklen_t, +) -> ssize_t { + unimplemented!(); +} + +#[no_mangle] +pub unsafe extern "C" fn send( + socket: c_int, + message: *const c_void, + length: size_t, + flags: c_int, +) -> ssize_t { + unimplemented!(); +} + +#[no_mangle] +pub unsafe extern "C" fn sento( + socket: c_int, + message: *const c_void, + length: size_t, + flags: c_int, + dest_addr: *const sockaddr, + dest_len: socklen_t, +) -> ssize_t { + unimplemented!(); +} + +#[no_mangle] +pub unsafe extern "C" fn setsockopt( + socket: c_int, + level: c_int, + option_name: c_int, + option_value: *const c_void, + option_len: socklen_t, +) -> c_int { + unimplemented!(); +} + +#[no_mangle] +pub unsafe extern "C" fn shutdown(socket: c_int, how: c_int) -> c_int { + unimplemented!(); +} + +#[no_mangle] +pub unsafe extern "C" fn socket(domain: c_int, _type: c_int, protocol: c_int) -> c_int { + unimplemented!(); +} + +#[no_mangle] +pub unsafe extern "C" fn socketpair( + domain: c_int, + _type: c_int, + protocol: c_int, + socket_vector: [c_int; 2], +) -> c_int { + unimplemented!(); +} From 16e82636fbd9f8af82e7c3e85b357c54a0dd20ae Mon Sep 17 00:00:00 2001 From: Dan Robertson Date: Thu, 15 Mar 2018 13:04:11 +0000 Subject: [PATCH 02/11] Add basic structures for netinet/in.h crate Add the basic structures for the netinet/in.h header. --- Cargo.lock | 16 ++++++++++ Cargo.toml | 1 + src/lib.rs | 1 + src/netinet/Cargo.toml | 7 +++++ src/netinet/in/Cargo.toml | 12 ++++++++ src/netinet/in/build.rs | 12 ++++++++ src/netinet/in/cbindgen.toml | 10 +++++++ src/netinet/in/src/lib.rs | 58 ++++++++++++++++++++++++++++++++++++ src/netinet/src/lib.rs | 3 ++ 9 files changed, 120 insertions(+) create mode 100644 src/netinet/Cargo.toml create mode 100644 src/netinet/in/Cargo.toml create mode 100644 src/netinet/in/build.rs create mode 100644 src/netinet/in/cbindgen.toml create mode 100644 src/netinet/in/src/lib.rs create mode 100644 src/netinet/src/lib.rs diff --git a/Cargo.lock b/Cargo.lock index 4eab6e0089..b69becf544 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -139,6 +139,14 @@ dependencies = [ "platform 0.1.0", ] +[[package]] +name = "in_h" +version = "0.1.0" +dependencies = [ + "cbindgen 0.5.2", + "platform 0.1.0", +] + [[package]] name = "itoa" version = "0.3.4" @@ -182,6 +190,13 @@ dependencies = [ "platform 0.1.0", ] +[[package]] +name = "netinet" +version = "0.1.0" +dependencies = [ + "in_h 0.1.0", +] + [[package]] name = "num-traits" version = "0.2.1" @@ -259,6 +274,7 @@ dependencies = [ "float 0.1.0", "grp 0.1.0", "mman 0.1.0", + "netinet 0.1.0", "platform 0.1.0", "resource 0.1.0", "semaphore 0.1.0", diff --git a/Cargo.toml b/Cargo.toml index f1481acd6b..42b6f83621 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -19,6 +19,7 @@ fenv = { path = "src/fenv" } float = { path = "src/float" } grp = { path = "src/grp" } mman = { path = "src/mman" } +netinet = { path = "src/netinet" } platform = { path = "src/platform" } resource = { path = "src/resource" } semaphore = { path = "src/semaphore" } diff --git a/src/lib.rs b/src/lib.rs index 27572f76fa..2a0f87862f 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -11,6 +11,7 @@ extern crate fenv; extern crate float; extern crate grp; extern crate mman; +extern crate netinet; extern crate resource; extern crate semaphore; extern crate socket; diff --git a/src/netinet/Cargo.toml b/src/netinet/Cargo.toml new file mode 100644 index 0000000000..eccbe4ee94 --- /dev/null +++ b/src/netinet/Cargo.toml @@ -0,0 +1,7 @@ +[package] +name = "netinet" +version = "0.1.0" +authors = ["Dan Robertson "] + +[dependencies] +in_h = { path = "in" } diff --git a/src/netinet/in/Cargo.toml b/src/netinet/in/Cargo.toml new file mode 100644 index 0000000000..4bd5518ba2 --- /dev/null +++ b/src/netinet/in/Cargo.toml @@ -0,0 +1,12 @@ +[package] +name = "in_h" +version = "0.1.0" +authors = ["Dan Robertson "] +build = "build.rs" + +[build-dependencies] +cbindgen = { path = "../../../cbindgen" } + +[dependencies] +platform = { path = "../../platform" } +socket = { path = "../../socket" } diff --git a/src/netinet/in/build.rs b/src/netinet/in/build.rs new file mode 100644 index 0000000000..f9df3f1a78 --- /dev/null +++ b/src/netinet/in/build.rs @@ -0,0 +1,12 @@ +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"); + fs::create_dir_all("../../../target/include/netinet").expect("failed to create include directory"); + cbindgen::generate(crate_dir) + .expect("failed to generate bindings") + .write_to_file("../../../target/include/netinet/in.h"); +} diff --git a/src/netinet/in/cbindgen.toml b/src/netinet/in/cbindgen.toml new file mode 100644 index 0000000000..0067295d34 --- /dev/null +++ b/src/netinet/in/cbindgen.toml @@ -0,0 +1,10 @@ +sys_includes = ["sys/types.h", "sys/socket.h"] +include_guard = "_NETINET_IN_H" +style = "Tag" +language = "C" + +[export] +include = ["sockaddr_in6", "sockaddr_in", "ipv6_mreq"] + +[enum] +prefix_with_name = true diff --git a/src/netinet/in/src/lib.rs b/src/netinet/in/src/lib.rs new file mode 100644 index 0000000000..789a9e4b4b --- /dev/null +++ b/src/netinet/in/src/lib.rs @@ -0,0 +1,58 @@ +#![no_std] + +#![allow(non_camel_case_types)] + +extern crate platform; +extern crate socket; + +use platform::types::*; +use socket::sa_family_t; + +pub type in_addr_t = u32; +pub type in_port_t = u16; + +#[repr(C)] +#[derive(Debug)] +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 sa_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; diff --git a/src/netinet/src/lib.rs b/src/netinet/src/lib.rs new file mode 100644 index 0000000000..40de25ffa2 --- /dev/null +++ b/src/netinet/src/lib.rs @@ -0,0 +1,3 @@ +#![no_std] + +extern crate in_h; From f60fafe8fbfd671606ccac9ae16ca60a4dd58c95 Mon Sep 17 00:00:00 2001 From: Timothy Bess Date: Sat, 17 Mar 2018 02:58:08 -0400 Subject: [PATCH 03/11] * create basic strtok * add test and expected output --- .gitignore | 1 + src/string/src/lib.rs | 33 +++++++++++++++++++++++++++-- tests/Makefile | 1 + tests/expected/string/strtok.stderr | 0 tests/expected/string/strtok.stdout | 2 ++ tests/string/strtok.c | 15 +++++++++++++ 6 files changed, 50 insertions(+), 2 deletions(-) create mode 100644 tests/expected/string/strtok.stderr create mode 100644 tests/expected/string/strtok.stdout create mode 100644 tests/string/strtok.c diff --git a/.gitignore b/.gitignore index b83d22266a..431845ed05 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,2 @@ /target/ +.idea/ diff --git a/src/string/src/lib.rs b/src/string/src/lib.rs index 49bfe11be9..9ab7818826 100644 --- a/src/string/src/lib.rs +++ b/src/string/src/lib.rs @@ -323,8 +323,37 @@ pub unsafe extern "C" fn strstr(s1: *const c_char, s2: *const c_char) -> *mut c_ } #[no_mangle] -pub extern "C" fn strtok(s1: *mut c_char, s2: *const c_char) -> *mut c_char { - unimplemented!(); +pub extern "C" fn strtok(s1: *mut c_char, delimiter: *const c_char) -> *mut c_char { + // Loosely based on GLIBC implementation + unsafe { + static mut HAYSTACK: *mut c_char = ptr::null_mut(); + if !s1.is_null() { + HAYSTACK = s1; + } else if HAYSTACK.is_null() { + return ptr::null_mut(); + } + + // Skip past any extra delimiter left over from previous call + HAYSTACK = HAYSTACK.add(strspn(HAYSTACK, delimiter)); + if *HAYSTACK == 0 { + HAYSTACK = ptr::null_mut(); + return ptr::null_mut(); + } + + // Build token by injecting null byte into delimiter + let token = HAYSTACK; + HAYSTACK = strpbrk(token, delimiter); + if !HAYSTACK.is_null() { + HAYSTACK.write(0 as c_char); + HAYSTACK = HAYSTACK.add(1); + } else { + HAYSTACK = ptr::null_mut(); + } + + return token; + } + + ptr::null_mut() } #[no_mangle] diff --git a/tests/Makefile b/tests/Makefile index c2aad5593a..c492f3b791 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -29,6 +29,7 @@ EXPECT_BINS=\ string/strspn \ string/strstr \ string/strpbrk \ + string/strtok \ unlink \ waitpid \ write diff --git a/tests/expected/string/strtok.stderr b/tests/expected/string/strtok.stderr new file mode 100644 index 0000000000..e69de29bb2 diff --git a/tests/expected/string/strtok.stdout b/tests/expected/string/strtok.stdout new file mode 100644 index 0000000000..4e58193c85 --- /dev/null +++ b/tests/expected/string/strtok.stdout @@ -0,0 +1,2 @@ +I'd_just_like_to_interject_for_a_moment.__What_you're_referring_to_as_Linux, +is_in_fact,_GNU/Linux,_or_as_I've_recently_taken_to_calling_it,_GNU_plus_Linux. \ No newline at end of file diff --git a/tests/string/strtok.c b/tests/string/strtok.c new file mode 100644 index 0000000000..59abe9eca1 --- /dev/null +++ b/tests/string/strtok.c @@ -0,0 +1,15 @@ +#include +#include + +int main(int argc, char* argv[]) { + char source[] = "I'd just like to interject for a moment. What you're referring to as Linux, " + "is in fact, GNU/Linux, or as I've recently taken to calling it, GNU plus Linux.\n"; + + char* token = strtok(source, " "); + while (token) { + printf("%s_", token); + token = strtok(NULL, " "); + } + + return 0; +} From 898cf98ccc56f8e41fb4b0c69359c72cca0045cd Mon Sep 17 00:00:00 2001 From: Timothy Bess Date: Sat, 17 Mar 2018 03:06:59 -0400 Subject: [PATCH 04/11] * fix test case a bit * remove unnecessary cast --- src/string/src/lib.rs | 2 +- tests/expected/string/strtok.stdout | 2 +- tests/string/strtok.c | 6 ++++-- 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/src/string/src/lib.rs b/src/string/src/lib.rs index 9ab7818826..f2bb99ac5d 100644 --- a/src/string/src/lib.rs +++ b/src/string/src/lib.rs @@ -344,7 +344,7 @@ pub extern "C" fn strtok(s1: *mut c_char, delimiter: *const c_char) -> *mut c_ch let token = HAYSTACK; HAYSTACK = strpbrk(token, delimiter); if !HAYSTACK.is_null() { - HAYSTACK.write(0 as c_char); + HAYSTACK.write(0); HAYSTACK = HAYSTACK.add(1); } else { HAYSTACK = ptr::null_mut(); diff --git a/tests/expected/string/strtok.stdout b/tests/expected/string/strtok.stdout index 4e58193c85..201357e8cb 100644 --- a/tests/expected/string/strtok.stdout +++ b/tests/expected/string/strtok.stdout @@ -1,2 +1,2 @@ I'd_just_like_to_interject_for_a_moment.__What_you're_referring_to_as_Linux, -is_in_fact,_GNU/Linux,_or_as_I've_recently_taken_to_calling_it,_GNU_plus_Linux. \ No newline at end of file +is_in_fact,_GNU/Linux,_or_as_I've_recently_taken_to_calling_it,_GNU_plus_Linux. diff --git a/tests/string/strtok.c b/tests/string/strtok.c index 59abe9eca1..9809fdf054 100644 --- a/tests/string/strtok.c +++ b/tests/string/strtok.c @@ -7,8 +7,10 @@ int main(int argc, char* argv[]) { char* token = strtok(source, " "); while (token) { - printf("%s_", token); - token = strtok(NULL, " "); + printf("%s", token); + if (token = strtok(NULL, " ")) { + printf("_"); + } } return 0; From e91891625fd73a250a2755d66e89745caf633377 Mon Sep 17 00:00:00 2001 From: Timothy Bess Date: Sat, 17 Mar 2018 03:56:40 -0400 Subject: [PATCH 05/11] * add strtok_r --- src/string/src/lib.rs | 37 ++++++++++++++++++++++++--- tests/Makefile | 1 + tests/expected/string/strtok_r.stderr | 0 tests/expected/string/strtok_r.stdout | 2 ++ tests/string/strtok_r.c | 18 +++++++++++++ 5 files changed, 54 insertions(+), 4 deletions(-) create mode 100644 tests/expected/string/strtok_r.stderr create mode 100644 tests/expected/string/strtok_r.stdout create mode 100644 tests/string/strtok_r.c diff --git a/src/string/src/lib.rs b/src/string/src/lib.rs index f2bb99ac5d..f70fdebb64 100644 --- a/src/string/src/lib.rs +++ b/src/string/src/lib.rs @@ -352,17 +352,46 @@ pub extern "C" fn strtok(s1: *mut c_char, delimiter: *const c_char) -> *mut c_ch return token; } - - ptr::null_mut() } #[no_mangle] pub extern "C" fn strtok_r( s: *mut c_char, - sep: *const c_char, + delimiter: *const c_char, lasts: *mut *mut c_char, ) -> *mut c_char { - unimplemented!(); + // Loosely based on GLIBC implementation + unsafe { + let mut haystack = s; + if haystack.is_null() { + if (*lasts).is_null() { + return ptr::null_mut(); + } + haystack = *lasts; + } + + // Skip past any extra delimiter left over from previous call + haystack = haystack.add(strspn(haystack, delimiter)); + if *haystack == 0 { + haystack = ptr::null_mut(); + *lasts = ptr::null_mut(); + return ptr::null_mut(); + } + + // Build token by injecting null byte into delimiter + let token = haystack; + haystack = strpbrk(token, delimiter); + if !haystack.is_null() { + haystack.write(0); + haystack = haystack.add(1); + *lasts = haystack; + } else { + haystack = ptr::null_mut(); + *lasts = ptr::null_mut(); + } + + return token; + } } #[no_mangle] diff --git a/tests/Makefile b/tests/Makefile index c492f3b791..ab820592e4 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -30,6 +30,7 @@ EXPECT_BINS=\ string/strstr \ string/strpbrk \ string/strtok \ + string/strtok_r \ unlink \ waitpid \ write diff --git a/tests/expected/string/strtok_r.stderr b/tests/expected/string/strtok_r.stderr new file mode 100644 index 0000000000..e69de29bb2 diff --git a/tests/expected/string/strtok_r.stdout b/tests/expected/string/strtok_r.stdout new file mode 100644 index 0000000000..201357e8cb --- /dev/null +++ b/tests/expected/string/strtok_r.stdout @@ -0,0 +1,2 @@ +I'd_just_like_to_interject_for_a_moment.__What_you're_referring_to_as_Linux, +is_in_fact,_GNU/Linux,_or_as_I've_recently_taken_to_calling_it,_GNU_plus_Linux. diff --git a/tests/string/strtok_r.c b/tests/string/strtok_r.c new file mode 100644 index 0000000000..36becfe296 --- /dev/null +++ b/tests/string/strtok_r.c @@ -0,0 +1,18 @@ +#include +#include + +int main(int argc, char* argv[]) { + char source[] = "I'd just like to interject for a moment. What you're referring to as Linux, " + "is in fact, GNU/Linux, or as I've recently taken to calling it, GNU plus Linux.\n"; + char* sp; + + char* token = strtok_r(source, " ", &sp); + while (token) { + printf("%s", token); + if (token = strtok_r(NULL, " ", &sp)) { + printf("_"); + } + } + + return 0; +} From 06de920be6c3b381f5f5d57df32e882d579d22f3 Mon Sep 17 00:00:00 2001 From: Timothy Bess Date: Sat, 17 Mar 2018 12:58:10 -0400 Subject: [PATCH 06/11] * remove unnecessary assignments --- src/string/src/lib.rs | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/string/src/lib.rs b/src/string/src/lib.rs index f70fdebb64..c795ee160b 100644 --- a/src/string/src/lib.rs +++ b/src/string/src/lib.rs @@ -373,7 +373,6 @@ pub extern "C" fn strtok_r( // Skip past any extra delimiter left over from previous call haystack = haystack.add(strspn(haystack, delimiter)); if *haystack == 0 { - haystack = ptr::null_mut(); *lasts = ptr::null_mut(); return ptr::null_mut(); } @@ -386,7 +385,6 @@ pub extern "C" fn strtok_r( haystack = haystack.add(1); *lasts = haystack; } else { - haystack = ptr::null_mut(); *lasts = ptr::null_mut(); } From b7d68895b04f242b3fbdb107b168273aca1cfe24 Mon Sep 17 00:00:00 2001 From: Ian Douglas Scott Date: Sat, 17 Mar 2018 14:59:54 -0700 Subject: [PATCH 07/11] Use build matrix on Travis CI This makes it easy to see which target failed to build. --- .travis.yml | 11 ++++++++--- ci.sh | 12 ------------ 2 files changed, 8 insertions(+), 15 deletions(-) delete mode 100755 ci.sh diff --git a/.travis.yml b/.travis.yml index 15083598be..6fd8524c77 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,12 +1,17 @@ language: rust +env: + - + - TARGET=aarch64-unknown-linux-gnu + - TARGET=x86_64-unknown-redox rust: - nightly cache: cargo before_script: - rustup component add rustfmt-preview - - rustup target add x86_64-unknown-redox - - rustup target add aarch64-unknown-linux-gnu + - if [ -n "$TARGET" ]; then rustup target add $TARGET; fi script: - - bash ./ci.sh + - ./fmt.sh -- --write-mode=diff + - cargo build $([ -n "$TARGET" ] && echo --target="$TARGET") + - if [ -z "$TARGET" ]; then ./test.sh; fi notifications: email: false diff --git a/ci.sh b/ci.sh deleted file mode 100755 index fd7dd91a48..0000000000 --- a/ci.sh +++ /dev/null @@ -1,12 +0,0 @@ -#!/bin/bash -set -ex - -./fmt.sh -- --write-mode=diff -./test.sh -cargo build --target=x86_64-unknown-redox -if [ $(arch) == "x86_64" ] -then - cargo build --target=aarch64-unknown-linux-gnu -else - cargo build --target=x86_64-unknown-linux-gnu -fi From 3a89f66cfd0d00972a8f49fddd0d21d34b0c2748 Mon Sep 17 00:00:00 2001 From: Timothy Bess Date: Sun, 18 Mar 2018 00:05:13 -0400 Subject: [PATCH 08/11] * simplify strtok implementation --- src/string/src/lib.rs | 28 ++-------------------------- 1 file changed, 2 insertions(+), 26 deletions(-) diff --git a/src/string/src/lib.rs b/src/string/src/lib.rs index c795ee160b..c97302b92b 100644 --- a/src/string/src/lib.rs +++ b/src/string/src/lib.rs @@ -324,33 +324,9 @@ pub unsafe extern "C" fn strstr(s1: *const c_char, s2: *const c_char) -> *mut c_ #[no_mangle] pub extern "C" fn strtok(s1: *mut c_char, delimiter: *const c_char) -> *mut c_char { - // Loosely based on GLIBC implementation + static mut HAYSTACK: *mut c_char = ptr::null_mut(); unsafe { - static mut HAYSTACK: *mut c_char = ptr::null_mut(); - if !s1.is_null() { - HAYSTACK = s1; - } else if HAYSTACK.is_null() { - return ptr::null_mut(); - } - - // Skip past any extra delimiter left over from previous call - HAYSTACK = HAYSTACK.add(strspn(HAYSTACK, delimiter)); - if *HAYSTACK == 0 { - HAYSTACK = ptr::null_mut(); - return ptr::null_mut(); - } - - // Build token by injecting null byte into delimiter - let token = HAYSTACK; - HAYSTACK = strpbrk(token, delimiter); - if !HAYSTACK.is_null() { - HAYSTACK.write(0); - HAYSTACK = HAYSTACK.add(1); - } else { - HAYSTACK = ptr::null_mut(); - } - - return token; + return strtok_r(s1, delimiter, &mut HAYSTACK); } } From 31516989c0c61afc002045fd5dd2fedea044498f Mon Sep 17 00:00:00 2001 From: Marat Safin Date: Sun, 18 Mar 2018 12:15:48 +0300 Subject: [PATCH 09/11] refactor nanosleep --- src/platform/src/redox/mod.rs | 36 ++++++++++++++++------------------- src/platform/src/types.rs | 12 ++++++++++++ 2 files changed, 28 insertions(+), 20 deletions(-) diff --git a/src/platform/src/redox/mod.rs b/src/platform/src/redox/mod.rs index f63870866c..f125166fa9 100644 --- a/src/platform/src/redox/mod.rs +++ b/src/platform/src/redox/mod.rs @@ -138,27 +138,23 @@ pub fn mkdir(path: *const c_char, mode: mode_t) -> c_int { } pub fn nanosleep(rqtp: *const timespec, rmtp: *mut timespec) -> c_int { - unsafe { - let redox_rqtp = redox_timespec { - tv_sec: (*rqtp).tv_sec, - tv_nsec: (*rqtp).tv_nsec as i32, - }; - let mut redox_rmtp: redox_timespec; - if rmtp.is_null() { - redox_rmtp = redox_timespec::default(); - } else { - redox_rmtp = redox_timespec { - tv_sec: (*rmtp).tv_sec, - tv_nsec: (*rmtp).tv_nsec as i32, - }; - } - match e(syscall::nanosleep(&redox_rqtp, &mut redox_rmtp)) as c_int { - -1 => -1, - _ => { - (*rmtp).tv_sec = redox_rmtp.tv_sec; - (*rmtp).tv_nsec = redox_rmtp.tv_nsec as i64; - 0 + let redox_rqtp = unsafe { redox_timespec::from(&*rqtp) }; + let mut redox_rmtp: redox_timespec; + if rmtp.is_null() { + redox_rmtp = redox_timespec::default(); + } else { + redox_rmtp = unsafe { redox_timespec::from(&*rmtp) }; + } + match e(syscall::nanosleep(&redox_rqtp, &mut redox_rmtp)) as c_int { + -1 => -1, + _ => { + unsafe { + if !rmtp.is_null() { + (*rmtp).tv_sec = redox_rmtp.tv_sec; + (*rmtp).tv_nsec = redox_rmtp.tv_nsec as i64; + } } + 0 } } } diff --git a/src/platform/src/types.rs b/src/platform/src/types.rs index 9268bf55c3..d6e19dbd58 100644 --- a/src/platform/src/types.rs +++ b/src/platform/src/types.rs @@ -1,3 +1,5 @@ +#[cfg(target_os = "redox")] +use syscall::data::TimeSpec as redox_timespec; // Use repr(u8) as LLVM expects `void*` to be the same as `i8*` to help enable // more optimization opportunities around it recognizing things like // malloc/free. @@ -70,3 +72,13 @@ pub struct timespec { pub tv_sec: time_t, pub tv_nsec: c_long, } + +#[cfg(target_os = "redox")] +impl<'a> From<&'a timespec> for redox_timespec { + fn from(tp: ×pec) -> redox_timespec { + redox_timespec { + tv_sec: tp.tv_sec, + tv_nsec: tp.tv_nsec as i32, + } + } +} From a0c76f7ce51b7576af13b662bc5431b523fe3f30 Mon Sep 17 00:00:00 2001 From: Justin Raymond Date: Sun, 18 Mar 2018 17:11:43 -0400 Subject: [PATCH 10/11] bsearch --- src/stdlib/src/lib.rs | 24 ++++++++++++++++--- tests/.gitignore | 1 + tests/Makefile | 1 + tests/stdlib/bsearch.c | 54 ++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 77 insertions(+), 3 deletions(-) create mode 100644 tests/stdlib/bsearch.c diff --git a/src/stdlib/src/lib.rs b/src/stdlib/src/lib.rs index 7813b9bdc9..575f759a26 100644 --- a/src/stdlib/src/lib.rs +++ b/src/stdlib/src/lib.rs @@ -130,15 +130,33 @@ pub extern "C" fn atol(s: *const c_char) -> c_long { dec_num_from_ascii!(s, c_long) } +unsafe extern "C" fn void_cmp(a: *const c_void, b: *const c_void) -> c_int { + return *(a as *const i32) - *(b as *const i32) as c_int; +} + #[no_mangle] -pub extern "C" fn bsearch( +pub unsafe extern "C" fn bsearch( key: *const c_void, base: *const c_void, nel: size_t, width: size_t, - compar: Option c_int>, + compar: Option c_int>, ) -> *mut c_void { - unimplemented!(); + let mut start = base; + let mut len = nel; + let cmp_fn = compar.unwrap_or(void_cmp); + while len > 0 { + let med = (start as size_t + (len >> 1) * width) as *const c_void; + let diff = cmp_fn(key, med); + if diff == 0 { + return med as *mut c_void; + } else if diff > 0 { + start = (med as usize + width) as *const c_void; + len -= 1; + } + len >>= 1; + } + ptr::null_mut() } #[no_mangle] diff --git a/tests/.gitignore b/tests/.gitignore index 0edf72a5dc..ff5cc28a8c 100644 --- a/tests/.gitignore +++ b/tests/.gitignore @@ -25,6 +25,7 @@ /rmdir /setid /sprintf +/stdlib/bsearch /stdlib/strtol /stdlib/a64l /string/strncmp diff --git a/tests/Makefile b/tests/Makefile index c2aad5593a..8dffd5edd5 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -20,6 +20,7 @@ EXPECT_BINS=\ rmdir \ sleep \ sprintf \ + stdlib/bsearch \ stdlib/strtol \ stdlib/a64l \ string/strncmp \ diff --git a/tests/stdlib/bsearch.c b/tests/stdlib/bsearch.c new file mode 100644 index 0000000000..7f2b4e1d09 --- /dev/null +++ b/tests/stdlib/bsearch.c @@ -0,0 +1,54 @@ +#include +#include + +int int_cmp(const void* a, const void* b) { + return *(const int*) a - *(const int*) b; +} + +#define BSEARCH_TEST_INT(key, arr, len, expect) \ + do { \ + void* res = bsearch((const void*) &key, (void*) arr, len, sizeof(int), int_cmp); \ + if (res != expect) { \ + printf("FAIL bsearch for %d in [", key); \ + for (size_t i = 0; i < len; ++i) printf("%d,", arr[i]); \ + printf("] expected %p but got %p\n", (void*) expect, res); \ + return 1; \ + } \ + } while (0); + + + +int main(int argc, char* argv[]) { + int x = 0; + int y = 1024; + int empty[] = {}; + BSEARCH_TEST_INT(x, empty, 0, NULL); + + int singleton[] = {42}; + printf("%p\n%p\n", singleton, &singleton[1]); + BSEARCH_TEST_INT(x, singleton, 1, NULL); + BSEARCH_TEST_INT(singleton[0], singleton, 1, &singleton[0]); + BSEARCH_TEST_INT(y, singleton, 1, NULL); + + int two[] = {14, 42}; + BSEARCH_TEST_INT(x, two, 2, NULL); + BSEARCH_TEST_INT(y, two, 2, NULL); + BSEARCH_TEST_INT(two[0], two, 2, &two[0]); + BSEARCH_TEST_INT(two[0], two, 1, &two[0]); + BSEARCH_TEST_INT(two[1], two, 2, &two[1]); + BSEARCH_TEST_INT(two[1], two, 1, NULL); + + int three[] = {-5, -1, 4}; + BSEARCH_TEST_INT(three[0], three, 3, &three[0]); + BSEARCH_TEST_INT(three[1], three, 3, &three[1]); + BSEARCH_TEST_INT(three[2], three, 3, &three[2]); + + int big[] = {-19, -13, -7, -3, 2, 5, 11}; + BSEARCH_TEST_INT(big[0], big, 7, big); + BSEARCH_TEST_INT(big[6], big, 7, &big[6]); + BSEARCH_TEST_INT(big[3], big, 7, &big[3]); + BSEARCH_TEST_INT(x, big, 7, NULL); + + printf("PASS bsearch\n"); + return 0; +} From d3583e11d25ab5b673861fa5986f24b25492de16 Mon Sep 17 00:00:00 2001 From: Justin Raymond Date: Sun, 18 Mar 2018 17:58:29 -0400 Subject: [PATCH 11/11] fix c99 mode --- tests/stdlib/bsearch.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/stdlib/bsearch.c b/tests/stdlib/bsearch.c index 7f2b4e1d09..efe8d46521 100644 --- a/tests/stdlib/bsearch.c +++ b/tests/stdlib/bsearch.c @@ -10,7 +10,8 @@ int int_cmp(const void* a, const void* b) { void* res = bsearch((const void*) &key, (void*) arr, len, sizeof(int), int_cmp); \ if (res != expect) { \ printf("FAIL bsearch for %d in [", key); \ - for (size_t i = 0; i < len; ++i) printf("%d,", arr[i]); \ + size_t i = 0; \ + for (; i < len; ++i) printf("%d,", arr[i]); \ printf("] expected %p but got %p\n", (void*) expect, res); \ return 1; \ } \