diff --git a/Cargo.lock b/Cargo.lock index 557319c6df231f95c8c888aeafe9a7ad72026976..06030c19ea05d5922a0af3a6571c44f193a17294 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -445,6 +445,7 @@ name = "stdio" version = "0.1.0" dependencies = [ "cbindgen 0.5.0", + "errno 0.1.0", "platform 0.1.0", "va_list 0.1.0", ] diff --git a/README.md b/README.md index d47a17e90a72a18c050187472bfcc7f74b07b36f..e55d89f29d2ff84a8b54a8c479f2b351e2696507 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,2 @@ # relibc -C Library in Rust for Redox and Linux (WIP) +relibc is a portable POSIX C standard library written in Rust. It is under heavy development, and currently supports Redox and Linux. diff --git a/src/platform/src/linux/mod.rs b/src/platform/src/linux/mod.rs index a8d720939d9705ec39e9c4b9a05d6310611a2e0a..66fafabbb4ba0784fac5132442eaf6b7f1505cae 100644 --- a/src/platform/src/linux/mod.rs +++ b/src/platform/src/linux/mod.rs @@ -62,6 +62,10 @@ pub fn fchdir(fildes: c_int) -> c_int { e(unsafe { syscall!(FCHDIR, fildes) }) as c_int } +pub fn fork() -> pid_t { + e(unsafe {syscall!(FORK) }) as pid_t +} + pub fn fsync(fildes: c_int) -> c_int { e(unsafe { syscall!(FSYNC, fildes) }) as c_int } @@ -114,6 +118,14 @@ pub fn open(path: *const c_char, oflag: c_int, mode: mode_t) -> c_int { e(unsafe { syscall!(OPENAT, AT_FDCWD, path, oflag, mode) }) as c_int } +pub fn pipe(fildes: [c_int; 2]) -> c_int { + e(unsafe { syscall!(PIPE2, fildes.as_ptr(), 0) }) as c_int +} + +pub fn read(fildes: c_int, buf: &[u8]) -> ssize_t { + e(unsafe { syscall!(READ, fildes, buf.as_ptr(), buf.len()) }) as ssize_t +} + pub fn write(fildes: c_int, buf: &[u8]) -> ssize_t { e(unsafe { syscall!(WRITE, fildes, buf.as_ptr(), buf.len()) }) as ssize_t } diff --git a/src/platform/src/redox/mod.rs b/src/platform/src/redox/mod.rs index 057ad80ba00bd4dff487112d5e7dae9e1167f484..5a18ed234b5a9a525741b4a1131e90a848175da7 100644 --- a/src/platform/src/redox/mod.rs +++ b/src/platform/src/redox/mod.rs @@ -63,6 +63,10 @@ pub fn fchdir(fd: c_int) -> c_int { } } +pub fn fork() -> pid_t { + e(unsafe { syscall::clone(0) }) as pid_t +} + pub fn fsync(fd: c_int) -> c_int { e(syscall::fsync(fd as usize)) as c_int } @@ -119,6 +123,18 @@ pub fn open(path: *const c_char, oflag: c_int, mode: mode_t) -> c_int { e(syscall::open(path, (oflag as usize) | (mode as usize))) as c_int } +pub fn pipe(fds: [c_int; 2]) -> c_int { + let mut usize_fds: [usize; 2] = [0; 2]; + let res = e(syscall::pipe2(&mut usize_fds)); + fds[0] = usize_fds[0] as c_int; + fds[1] = usize_fds[1] as c_int; + res as c_int +} + +pub fn read(fd: c_int, buf: &mut [u8]) -> ssize_t { + e(syscall::read(fd as usize, buf)) as ssize_t +} + pub fn write(fd: c_int, buf: &[u8]) -> ssize_t { e(syscall::write(fd as usize, buf)) as ssize_t } diff --git a/src/stdio/Cargo.toml b/src/stdio/Cargo.toml index e64c0df1a573822c7169f99b5041c08070749bbb..2f53e58dc70578c5c48c0a96c5bb6fb83b1c62ca 100644 --- a/src/stdio/Cargo.toml +++ b/src/stdio/Cargo.toml @@ -10,3 +10,4 @@ cbindgen = { path = "../../cbindgen" } [dependencies] platform = { path = "../platform" } va_list = { path = "../../va_list", features = ["no_std"] } +errno = { path = "../errno"} diff --git a/src/stdio/src/lib.rs b/src/stdio/src/lib.rs index 7ac9d8170dc991fd7033a78d1bfb98199085e9fb..83d4446314b505ea6a7c977a3aed38044996aff0 100644 --- a/src/stdio/src/lib.rs +++ b/src/stdio/src/lib.rs @@ -4,10 +4,15 @@ extern crate platform; extern crate va_list as vl; +extern crate errno; -use core::slice; +use core::str; +use core::fmt::Write; use platform::types::*; +use platform::c_str; +use platform::errno; +use errno::STR_ERROR; use vl::VaList as va_list; mod printf; @@ -203,8 +208,15 @@ pub extern "C" fn pclose(stream: *mut FILE) -> c_int { } #[no_mangle] -pub extern "C" fn perror(s: *const c_char) { - unimplemented!(); +pub unsafe extern "C" fn perror(s: *const c_char) { + let s_str = str::from_utf8_unchecked(c_str(s)); + + let mut w = platform::FileWriter(2); + if errno >= 0 && errno < STR_ERROR.len() as c_int { + w.write_fmt(format_args!("{}: {}\n", s_str, STR_ERROR[errno as usize])); + } else { + w.write_fmt(format_args!("{}: Unknown error {}\n", s_str, errno)); + } } #[no_mangle] diff --git a/src/unistd/src/lib.rs b/src/unistd/src/lib.rs index 90811a6c7da45d4adade5b7822acdc415dd8a13d..ea4609ba50405de7305fd72437092fa666a23e92 100644 --- a/src/unistd/src/lib.rs +++ b/src/unistd/src/lib.rs @@ -140,7 +140,7 @@ pub extern "C" fn fdatasync(fildes: c_int) -> c_int { #[no_mangle] pub extern "C" fn fork() -> pid_t { - unimplemented!(); + platform::fork() } #[no_mangle] @@ -295,7 +295,7 @@ pub extern "C" fn pause() -> c_int { #[no_mangle] pub extern "C" fn pipe(fildes: [c_int; 2]) -> c_int { - unimplemented!(); + platform::pipe(fildes) } #[no_mangle] @@ -324,7 +324,9 @@ pub extern "C" fn pwrite( #[no_mangle] pub extern "C" fn read(fildes: c_int, buf: *const c_void, nbyte: size_t) -> ssize_t { - unimplemented!(); + use core::slice; + let buf = unsafe { slice::from_raw_parts_mut(buf as *mut u8, nbyte as usize) }; + platform::read(fildes, buf) } #[no_mangle] diff --git a/tests/.gitignore b/tests/.gitignore index 76cf8f3e05b7a8a4d9692736c0d5bf149278bd65..e5819ec54577f63583b4398ca86d61af361a7ef1 100644 --- a/tests/.gitignore +++ b/tests/.gitignore @@ -17,5 +17,6 @@ /link /link.out /math +/pipe /printf /write diff --git a/tests/Makefile b/tests/Makefile index d8abbea9714dafb39ecf7c004e56c4ef2558f881..b371961d99a6ce9fcc32e2cdcb2bf424a1008cd8 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -14,6 +14,7 @@ BINS=\ getid \ link \ math \ + pipe \ printf \ write diff --git a/tests/error.c b/tests/error.c index 67fb25ed394c43fb1771d8bf2ec897097ca5fe75..9ab04c2bd967a08d2d8089c8d94deb00c31266d3 100644 --- a/tests/error.c +++ b/tests/error.c @@ -6,4 +6,5 @@ int main(int argc, char** argv) { chdir("nonexistent"); printf("errno: %d = %s\n", errno, strerror(errno)); + perror("perror"); } diff --git a/tests/pipe.c b/tests/pipe.c new file mode 100644 index 0000000000000000000000000000000000000000..6772cd5112701bd36613d505806daa86d5edd75f --- /dev/null +++ b/tests/pipe.c @@ -0,0 +1,33 @@ +//http://www2.cs.uregina.ca/~hamilton/courses/330/notes/unix/pipes/pipes.html +#include <string.h> +#include <unistd.h> + +int main() +{ + + int pid, pip[2]; + char instring[20]; + char * outstring = "Hello World!"; + + pipe(pip); + + pid = fork(); + if (pid == 0) /* child : sends message to parent*/ + { + /* close read end */ + close(pip[0]); + /* send 7 characters in the string, including end-of-string */ + write(pip[1], outstring, strlen(outstring)); + /* close write end */ + close(pip[1]); + } + else /* parent : receives message from child */ + { + /* close write end */ + close(pip[1]); + /* read from the pipe */ + read(pip[0], instring, 7); + /* close read end */ + close(pip[0]); + } +}