diff --git a/src/platform/src/redox/mod.rs b/src/platform/src/redox/mod.rs index 48585668f3e9d4b7ebc5a20f884ea256d10e4c12..05afc235116f63dd0c914dab305f2bd61f0e45e7 100644 --- a/src/platform/src/redox/mod.rs +++ b/src/platform/src/redox/mod.rs @@ -346,10 +346,14 @@ pub fn utimens(path: *const c_char, times: *const timespec) -> c_int { } pub fn getcwd(buf: *mut c_char, size: size_t) -> *mut c_char { - let buf_slice = unsafe { slice::from_raw_parts_mut(buf as *mut u8, size as usize) }; - if e(syscall::getcwd(buf_slice)) == !0 { + let buf_slice = unsafe { slice::from_raw_parts_mut(buf as *mut u8, size as usize - 1) }; + let read = e(syscall::getcwd(buf_slice)); + if read == !0 { ptr::null_mut() } else { + unsafe { + *buf.offset(read as isize + 1) = 0; + } buf } } diff --git a/src/unistd/src/lib.rs b/src/unistd/src/lib.rs index 95c3eac42228e5aca3fcee80a0bf1cb6187fe416..944d9726694dd6d58cd301a86b15307d50f36c02 100644 --- a/src/unistd/src/lib.rs +++ b/src/unistd/src/lib.rs @@ -38,6 +38,8 @@ pub const STDIN_FILENO: c_int = 0; pub const STDOUT_FILENO: c_int = 1; pub const STDERR_FILENO: c_int = 2; +const PATH_MAX: usize = 4096; + #[no_mangle] pub extern "C" fn _exit(status: c_int) { platform::exit(status) @@ -184,8 +186,31 @@ pub extern "C" fn ftruncate(fildes: c_int, length: off_t) -> c_int { } #[no_mangle] -pub extern "C" fn getcwd(buf: *mut c_char, size: size_t) -> *mut c_char { - platform::getcwd(buf, size) +pub extern "C" fn getcwd(mut buf: *mut c_char, mut size: size_t) -> *mut c_char { + let alloc = buf.is_null(); + let mut stack_buf = [0; PATH_MAX]; + if alloc { + buf = stack_buf.as_mut_ptr(); + size = stack_buf.len(); + } + + let ret = platform::getcwd(buf, size); + if ret == ptr::null_mut() { + return ptr::null_mut(); + } + + if alloc { + let mut len = stack_buf.iter().position(|b| *b == 0).expect("no nul-byte in getcwd string") + 1; + let mut heap_buf = unsafe { platform::alloc(len) as *mut c_char }; + for i in 0..len { + unsafe { + *heap_buf.offset(i as isize) = stack_buf[i]; + } + } + heap_buf + } else { + ret + } } // #[no_mangle] @@ -275,7 +300,7 @@ pub extern "C" fn getuid() -> uid_t { #[no_mangle] pub extern "C" fn getwd(path_name: *mut c_char) -> *mut c_char { - getcwd(path_name, 4096 /* PATH_MAX */) + getcwd(path_name, PATH_MAX) } #[no_mangle] diff --git a/tests/Makefile b/tests/Makefile index cad834e36194176af396e60b0f53f15b6fd68521..3ca980061dbcbb2951df6da78690aa620ffff94f 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -77,6 +77,7 @@ BINS=\ time/gettimeofday \ time/times \ unistd/chdir \ + unistd/getcwd \ unistd/gethostname \ unistd/getid \ unistd/link \ diff --git a/tests/unistd/getcwd.c b/tests/unistd/getcwd.c new file mode 100644 index 0000000000000000000000000000000000000000..0d8e5f108dc608e307a79294c848bb03b8392942 --- /dev/null +++ b/tests/unistd/getcwd.c @@ -0,0 +1,22 @@ +#include <limits.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +int main() { + char first[PATH_MAX]; + getcwd(first, PATH_MAX); + puts(first); + + char* second = getcwd(NULL, 0); + puts(second); + + if (strcmp(first, second)) { + puts("Not matching"); + free(second); + return 1; + } + + free(second); +}