From 9de73d0e5b7d222b040b4093138f3f2c4b69d089 Mon Sep 17 00:00:00 2001 From: jD91mZM2 <me@krake.one> Date: Tue, 26 Jun 2018 16:37:26 +0200 Subject: [PATCH] Add uname and gethostname --- Cargo.lock | 10 + Cargo.toml | 3 +- src/lib.rs | 1 + src/platform/src/lib.rs | 2 +- src/platform/src/linux/mod.rs | 4 + src/sys_utsname/Cargo.toml | 11 + src/sys_utsname/build.rs | 11 + src/sys_utsname/cbindgen.toml | 5 + src/sys_utsname/src/lib.rs | 28 +++ src/unistd/Cargo.toml | 1 + src/unistd/src/lib.rs | 49 +++++ src/wchar/src/lib.rs | 394 ++++++++++++++++++++++++++++++++++ tests/.gitignore | 3 +- tests/Makefile | 1 + tests/gethostname.c | 12 ++ 15 files changed, 532 insertions(+), 3 deletions(-) create mode 100644 src/sys_utsname/Cargo.toml create mode 100644 src/sys_utsname/build.rs create mode 100644 src/sys_utsname/cbindgen.toml create mode 100644 src/sys_utsname/src/lib.rs create mode 100644 src/wchar/src/lib.rs create mode 100644 tests/gethostname.c diff --git a/Cargo.lock b/Cargo.lock index d242203e..27019339 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -300,6 +300,7 @@ dependencies = [ "sys_socket 0.1.0", "sys_stat 0.1.0", "sys_time 0.1.0", + "sys_utsname 0.1.0", "sys_wait 0.1.0", "time 0.1.0", "unistd 0.1.0", @@ -493,6 +494,14 @@ dependencies = [ "platform 0.1.0", ] +[[package]] +name = "sys_utsname" +version = "0.1.0" +dependencies = [ + "cbindgen 0.5.2", + "platform 0.1.0", +] + [[package]] name = "sys_wait" version = "0.1.0" @@ -574,6 +583,7 @@ dependencies = [ "platform 0.1.0", "stdio 0.1.0", "string 0.1.0", + "sys_utsname 0.1.0", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index c644f512..b64015bd 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -35,6 +35,7 @@ sys_resource = { path = "src/sys_resource" } sys_socket = { path = "src/sys_socket" } sys_stat = { path = "src/sys_stat" } sys_time = { path = "src/sys_time" } +sys_utsname = { path = "src/sys_utsname" } sys_wait = { path = "src/sys_wait" } time = { path = "src/time" } unistd = { path = "src/unistd" } @@ -43,7 +44,7 @@ wctype = { path = "src/wctype" } [dependencies.compiler_builtins] git = "https://github.com/rust-lang-nursery/compiler-builtins.git" default-features = false -features = ["no-lang-items"] +features = ["no-lang-items", "mangled-names"] [profile.dev] panic = "abort" diff --git a/src/lib.rs b/src/lib.rs index db4ed938..6d5cc2d2 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -24,6 +24,7 @@ pub extern crate sys_resource; pub extern crate sys_socket; pub extern crate sys_stat; pub extern crate sys_time; +pub extern crate sys_utsname; pub extern crate sys_wait; pub extern crate time; pub extern crate unistd; diff --git a/src/platform/src/lib.rs b/src/platform/src/lib.rs index 3784ea30..4919e613 100644 --- a/src/platform/src/lib.rs +++ b/src/platform/src/lib.rs @@ -10,7 +10,7 @@ extern crate sc; #[cfg(all(not(feature = "no_std"), target_os = "redox"))] #[macro_use] -extern crate syscall; +pub extern crate syscall; pub use sys::*; diff --git a/src/platform/src/linux/mod.rs b/src/platform/src/linux/mod.rs index d241a4f5..0ae481e4 100644 --- a/src/platform/src/linux/mod.rs +++ b/src/platform/src/linux/mod.rs @@ -198,6 +198,10 @@ pub fn stat(file: *const c_char, buf: *mut stat) -> c_int { e(unsafe { syscall!(NEWFSTATAT, AT_FDCWD, file, buf, 0) }) as c_int } +pub fn uname(utsname: usize) -> c_int { + e(unsafe { syscall!(UNAME, utsname, 0) }) as c_int +} + pub fn unlink(path: *const c_char) -> c_int { e(unsafe { syscall!(UNLINKAT, AT_FDCWD, path, 0) }) as c_int } diff --git a/src/sys_utsname/Cargo.toml b/src/sys_utsname/Cargo.toml new file mode 100644 index 00000000..e03fbb2f --- /dev/null +++ b/src/sys_utsname/Cargo.toml @@ -0,0 +1,11 @@ +[package] +name = "sys_utsname" +version = "0.1.0" +authors = ["jD91mZM2 <me@krake.one>"] +build = "build.rs" + +[build-dependencies] +cbindgen = { path = "../../cbindgen" } + +[dependencies] +platform = { path = "../platform" } diff --git a/src/sys_utsname/build.rs b/src/sys_utsname/build.rs new file mode 100644 index 00000000..2f45974e --- /dev/null +++ b/src/sys_utsname/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/utsname.h"); +} diff --git a/src/sys_utsname/cbindgen.toml b/src/sys_utsname/cbindgen.toml new file mode 100644 index 00000000..7429451f --- /dev/null +++ b/src/sys_utsname/cbindgen.toml @@ -0,0 +1,5 @@ +include_guard = "_SYS_UTSNAME_H" +language = "C" + +[enum] +prefix_with_name = true diff --git a/src/sys_utsname/src/lib.rs b/src/sys_utsname/src/lib.rs new file mode 100644 index 00000000..a0792dd5 --- /dev/null +++ b/src/sys_utsname/src/lib.rs @@ -0,0 +1,28 @@ +//! sys/utsname implementation for Redox, following http://pubs.opengroup.org/onlinepubs/7908799/xsh/sysutsname.h.html + +#![no_std] +#![cfg(target_os = "linux")] + +extern crate platform; + +use core::ptr; +use platform::types::*; + +const LENGTH: usize = 65; + +#[allow(non_camel_case)] +#[no_mangle] +#[repr(C)] +pub struct utsname { + pub sysname: [c_char; LENGTH], + pub nodename: [c_char; LENGTH], + pub release: [c_char; LENGTH], + pub version: [c_char; LENGTH], + pub machine: [c_char; LENGTH], + pub domainname: [c_char; LENGTH] +} + +#[no_mangle] +pub unsafe extern "C" fn uname(uts: *mut utsname) -> c_int { + platform::uname(uts as usize) +} diff --git a/src/unistd/Cargo.toml b/src/unistd/Cargo.toml index 8de8a2b9..69cd4b57 100644 --- a/src/unistd/Cargo.toml +++ b/src/unistd/Cargo.toml @@ -11,3 +11,4 @@ cbindgen = { path = "../../cbindgen" } platform = { path = "../platform" } stdio = { path = "../stdio" } string = { path = "../string" } +sys_utsname = { path = "../sys_utsname" } diff --git a/src/unistd/src/lib.rs b/src/unistd/src/lib.rs index e5aa6bc9..a757781e 100644 --- a/src/unistd/src/lib.rs +++ b/src/unistd/src/lib.rs @@ -5,6 +5,7 @@ extern crate platform; extern crate stdio; extern crate string; +extern crate sys_utsname; pub use platform::types::*; pub use getopt::*; @@ -199,6 +200,54 @@ pub extern "C" fn gethostid() -> c_long { unimplemented!(); } +#[no_mangle] +pub unsafe extern "C" fn gethostname(mut name: *mut c_char, len: size_t) -> c_int { + #[cfg(target_os = "linux")] { + use core::mem; + + // len only needs to be mutable on linux + let mut len = len; + + let mut uts: sys_utsname::utsname = mem::uninitialized(); + let err = sys_utsname::uname(&mut uts); + if err < 0 { + mem::forget(uts); + return err; + } + for c in uts.nodename.iter() { + if len == 0 { break; } + len -= 1; + + *name = *c; + + if *name == 0 { + // We do want to copy the zero also, so we check this after the copying. + break; + } + + name = name.offset(1); + } + 0 + } + #[cfg(target_os = "redox")] { + use platform::{FileReader, Read}; + use platform::syscall::flag::*; + + let fd = platform::open("/etc/hostname\0",as_ptr(), 0, O_RDONLY); + if fd < 0 { + return fd; + } + let reader = FileReader(fd); + for _ in 0..len { + if !reader.read_u8(&mut *name) { + *name = 0; + break; + } + name = name.offset(1); + } + } +} + #[no_mangle] pub extern "C" fn getlogin() -> *mut c_char { unimplemented!(); diff --git a/src/wchar/src/lib.rs b/src/wchar/src/lib.rs new file mode 100644 index 00000000..96bb95d1 --- /dev/null +++ b/src/wchar/src/lib.rs @@ -0,0 +1,394 @@ +//! wchar implementation for Redox, following http://pubs.opengroup.org/onlinepubs/7908799/xsh/string.h.html + +#![no_std] + +extern crate errno; +extern crate platform; +extern crate stdlib; +extern crate string; +extern crate time; + +use platform::types::*; +use errno::*; +use time::*; +use core::cmp; +use core::usize; +use core::ptr; +use core::mem; +use string::*; + +pub type wint_t = i32; + +#[repr(C)] +pub struct mbstate_t { + pub mbs_count: c_int, + pub mbs_length: c_int, + pub mbs_wch: wint_t, +} + +#[no_mangle] +pub unsafe extern "C" fn btowc(c: c_int) -> wint_t { + //Check for EOF + if c == -1 { + return -1; + } + + let uc = c as u8; + let c = uc as c_char; + let mut ps: mbstate_t = mbstate_t { + mbs_count: 0, + mbs_length: 0, + mbs_wch: 0, + }; + let mut wc: wchar_t = 0; + let saved_errno = platform::errno; + let status = mbrtowc(&mut wc, &c as (*const c_char), 1, &mut ps); + if status == usize::max_value() || status == usize::max_value() - 1 { + platform::errno = saved_errno; + return platform::errno; + } + return wc as wint_t; +} + +#[no_mangle] +pub extern "C" fn getwchar() -> wint_t { + unimplemented!(); +} + +#[no_mangle] +pub unsafe extern "C" fn mbsinit(ps: *const mbstate_t) -> c_int { + if ps.is_null() || (*ps).mbs_count == 0 { + return 1; + } else { + return 0; + } +} + +#[no_mangle] +pub unsafe extern "C" fn mbrlen(s: *const c_char, n: usize, ps: *mut mbstate_t) -> usize { + static mut internal: mbstate_t = mbstate_t { + mbs_count: 0, + mbs_length: 0, + mbs_wch: 0, + }; + return mbrtowc(ptr::null_mut(), s, n, &mut internal); +} + +//Only works for utf8! +#[no_mangle] +pub unsafe extern "C" fn mbrtowc( + pwc: *mut wchar_t, + s: *const c_char, + n: usize, + ps: *mut mbstate_t, +) -> usize { + static mut internal: mbstate_t = mbstate_t { + mbs_count: 0, + mbs_length: 0, + mbs_wch: 0, + }; + + if ps.is_null() { + let ps = &mut internal; + } + if s.is_null() { + let xs: [c_char; 1] = [0]; + utf8_mbrtowc(pwc, &xs[0] as *const c_char, 1, ps); + } + + return utf8_mbrtowc(pwc, s, n, ps); +} + +#[no_mangle] +unsafe extern "C" fn utf8_mbrtowc( + pwc: *mut wchar_t, + s: *const c_char, + n: usize, + ps: *mut mbstate_t, +) -> usize { + let mut i: usize = 0; + + while !(i > 0 && (*ps).mbs_count == 0) { + if (n <= i) { + return -2isize as usize; + } + let c = s.offset(i as isize); + let uc = c as u8; + + if (*ps).mbs_count == 0 { + //1 byte sequence - 00–7F + if (uc & 0b10000000) == 0b00000000 { + (*ps).mbs_count = 0; + (*ps).mbs_length = 1; + (*ps).mbs_wch = (uc as wchar_t & 0b1111111) as wint_t; + } + //2 byte sequence - C2–DF + else if (uc & 0b11100000) == 0b11000000 { + (*ps).mbs_count = 1; + (*ps).mbs_length = 2; + (*ps).mbs_wch = (uc as wchar_t & 0b11111) as wint_t; + } + //3 byte sequence - E0–EF + else if (uc & 0b11110000) == 0b11100000 { + (*ps).mbs_count = 2; + (*ps).mbs_length = 3; + (*ps).mbs_wch = (uc as wchar_t & 0b1111) as wint_t; + } + //4 byte sequence - F0–F4 + else if (uc & 0b11111000) == 0b11110000 { + (*ps).mbs_count = 3; + (*ps).mbs_length = 4; + (*ps).mbs_wch = (uc as wchar_t & 0b111) as wint_t; + } else { + platform::errno = errno::EILSEQ; + return -1isize as usize; + } + } else { + if (uc & 0b11000000) != 0b10000000 { + platform::errno = errno::EILSEQ; + return -1isize as usize; + } + + (*ps).mbs_wch = (*ps).mbs_wch << 6 | (uc & 0b00111111) as wint_t; + (*ps).mbs_count -= 1; + } + + i += 1; + } + + // Reject the character if it was produced with an overly long sequence. + if (*ps).mbs_length == 1 && 1 << 7 <= (*ps).mbs_wch { + platform::errno = errno::EILSEQ; + return -1isize as usize; + } + if (*ps).mbs_length == 2 && 1 << (5 + 1 * 6) <= (*ps).mbs_wch { + platform::errno = errno::EILSEQ; + return -1isize as usize; + } + if (*ps).mbs_length == 3 && 1 << (5 + 2 * 6) <= (*ps).mbs_wch { + platform::errno = errno::EILSEQ; + return -1isize as usize; + } + if (*ps).mbs_length == 4 && 1 << (5 + 3 * 6) <= (*ps).mbs_wch { + platform::errno = errno::EILSEQ; + return -1isize as usize; + } + + // The definition of UTF-8 prohibits encoding character numbers between + // U+D800 and U+DFFF, which are reserved for use with the UTF-16 encoding + // form (as surrogate pairs) and do not directly represent characters. + if 0xD800 <= (*ps).mbs_wch && (*ps).mbs_wch <= 0xDFFF { + platform::errno = errno::EILSEQ; + return -1isize as usize; + } + // RFC 3629 limits UTF-8 to 0x0 through 0x10FFFF. + if 0x10FFFF <= (*ps).mbs_wch { + platform::errno = errno::EILSEQ; + return -1isize as usize; + } + + let result: wchar_t = (*ps).mbs_wch as wchar_t; + + if !pwc.is_null() { + *pwc = result; + } + + (*ps).mbs_length = 0; + (*ps).mbs_wch = 0; + + return if result != 0 { i } else { 0 }; +} + +#[no_mangle] +pub extern "C" fn mbsrtowcs( + dst: *mut wchar_t, + src: *mut *const c_char, + len: usize, + ps: *mut mbstate_t, +) -> usize { + unimplemented!(); +} + +#[no_mangle] +pub extern "C" fn putwchar(wc: wchar_t) -> wint_t { + unimplemented!(); +} + +#[no_mangle] +pub extern "C" fn towlower(wc: wint_t) -> wint_t { + unimplemented!(); +} + +#[no_mangle] +pub extern "C" fn towupper(wc: wint_t) -> wint_t { + unimplemented!(); +} + +#[no_mangle] +pub extern "C" fn wcrtomb(s: *mut c_char, wc: wchar_t, ps: *mut mbstate_t) -> usize { + unimplemented!(); +} + +#[no_mangle] +pub extern "C" fn wcscat(ws1: *mut wchar_t, ws2: *const wchar_t) -> *mut wchar_t { + unimplemented!(); +} + +#[no_mangle] +pub extern "C" fn wcschr(ws1: *const wchar_t, ws2: wchar_t) -> *mut c_int { + unimplemented!(); +} + +#[no_mangle] +pub extern "C" fn wcscmp(ws1: *const wchar_t, ws2: *const wchar_t) -> c_int { + unimplemented!(); +} + +#[no_mangle] +pub extern "C" fn wcscoll(ws1: *const wchar_t, ws2: *const wchar_t) -> c_int { + unimplemented!(); +} + +#[no_mangle] +pub extern "C" fn wcscpy(ws1: *mut wchar_t, ws2: *const wchar_t) -> *mut wchar_t { + unimplemented!(); +} + +#[no_mangle] +pub extern "C" fn wcscspn(ws1: *const wchar_t, ws2: *const wchar_t) -> usize { + unimplemented!(); +} + +#[no_mangle] +pub extern "C" fn wcsftime( + wcs: *mut wchar_t, + maxsize: usize, + format: *const wchar_t, + timptr: *mut tm, +) -> usize { + unimplemented!(); +} + +#[no_mangle] +pub extern "C" fn wcslen(ws: *const wchar_t) -> c_ulong { + unimplemented!(); +} + +#[no_mangle] +pub extern "C" fn wcsncat(ws1: *mut wchar_t, ws2: *const wchar_t, n: usize) -> *mut wchar_t { + unimplemented!(); +} + +#[no_mangle] +pub extern "C" fn wcsncmp(ws1: *const wchar_t, ws2: *const wchar_t, n: usize) -> c_int { + unimplemented!(); +} + +#[no_mangle] +pub extern "C" fn wcsncpy(ws1: *mut wchar_t, ws2: *const wchar_t, n: usize) -> *mut wchar_t { + unimplemented!(); +} + +#[no_mangle] +pub extern "C" fn wcspbrk(ws1: *const wchar_t, ws2: *const wchar_t) -> *mut wchar_t { + unimplemented!(); +} + +#[no_mangle] +pub extern "C" fn wcsrchr(ws1: *const wchar_t, ws2: wchar_t) -> *mut wchar_t { + unimplemented!(); +} + +#[no_mangle] +pub extern "C" fn wcsrtombs( + dst: *mut c_char, + src: *mut *const wchar_t, + len: usize, + ps: *mut mbstate_t, +) -> usize { + unimplemented!(); +} + +#[no_mangle] +pub extern "C" fn wcsspn(ws1: *const wchar_t, ws2: *const wchar_t) -> usize { + unimplemented!(); +} + +#[no_mangle] +pub extern "C" fn wcsstr(ws1: *const wchar_t, ws2: *const wchar_t) -> *mut wchar_t { + unimplemented!(); +} + +#[no_mangle] +pub extern "C" fn wcstod(nptr: *const wchar_t, endptr: *mut *mut wchar_t) -> f64 { + unimplemented!(); +} + +#[no_mangle] +pub extern "C" fn wcstok( + ws1: *mut wchar_t, + ws2: *const wchar_t, + ptr: *mut *mut wchar_t, +) -> *mut wchar_t { + unimplemented!(); +} + +#[no_mangle] +pub extern "C" fn wcstol(nptr: *const wchar_t, endptr: *mut *mut wchar_t, base: c_int) -> c_long { + unimplemented!(); +} + +#[no_mangle] +pub extern "C" fn wcstoul(nptr: *const wchar_t, endptr: *mut *mut wchar_t, base: c_int) -> c_ulong { + unimplemented!(); +} + +#[no_mangle] +pub extern "C" fn wcswcs(ws1: *const wchar_t, ws2: *const wchar_t) -> *mut wchar_t { + unimplemented!(); +} + +#[no_mangle] +pub extern "C" fn wcswidth(pwcs: *const wchar_t, n: usize) -> c_int { + unimplemented!(); +} + +#[no_mangle] +pub extern "C" fn wcsxfrm(ws1: *mut wchar_t, ws2: *const wchar_t, n: usize) -> usize { + unimplemented!(); +} + +#[no_mangle] +pub extern "C" fn wctob(c: wint_t) -> c_int { + unimplemented!(); +} + +#[no_mangle] +pub extern "C" fn wcwidth(wc: wchar_t) -> c_int { + unimplemented!(); +} + +#[no_mangle] +pub extern "C" fn wmemchr(ws: *const wchar_t, wc: wchar_t, n: usize) -> *mut c_int { + unimplemented!(); +} + +#[no_mangle] +pub extern "C" fn wmemcmp(ws1: *const wchar_t, ws2: *const wchar_t, n: usize) -> c_int { + unimplemented!(); +} + +#[no_mangle] +pub extern "C" fn wmemcpy(ws1: *mut wchar_t, ws2: *const wchar_t, n: usize) -> *mut wchar_t { + unimplemented!(); +} + +#[no_mangle] +pub extern "C" fn wmemmove(ws1: *mut wchar_t, ws2: *const wchar_t, n: usize) -> *mut wchar_t { + unimplemented!(); +} + +#[no_mangle] +pub extern "C" fn wmemset(ws1: *mut wchar_t, ws2: wchar_t, n: usize) -> *mut wchar_t { + unimplemented!(); +} diff --git a/tests/.gitignore b/tests/.gitignore index 156ddf26..7887a5a6 100644 --- a/tests/.gitignore +++ b/tests/.gitignore @@ -15,8 +15,9 @@ /fcntl /fsync /ftruncate -/getid /getc_unget +/gethostname +/getid /link /locale /math diff --git a/tests/Makefile b/tests/Makefile index c08209e3..fd7a02ab 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -57,6 +57,7 @@ BINS=\ $(EXPECT_BINS) \ alloc \ chdir \ + gethostname \ getid \ setid diff --git a/tests/gethostname.c b/tests/gethostname.c new file mode 100644 index 00000000..02a0b7a7 --- /dev/null +++ b/tests/gethostname.c @@ -0,0 +1,12 @@ +#include <stdlib.h> +#include <stdio.h> +#include <unistd.h> + +int main() { + char* hostname = malloc(256); + if (gethostname(hostname, 256) == 0) { + printf("Hostname: %s\n", hostname); + } else { + puts("error getting hostname"); + } +} -- GitLab