diff --git a/src/header/string/mod.rs b/src/header/string/mod.rs index 444fd8c61fd80d5f0d07506e119e32110cfd5206..d43d157b19c637329c2a5c836336292584da8802 100644 --- a/src/header/string/mod.rs +++ b/src/header/string/mod.rs @@ -259,6 +259,25 @@ pub unsafe extern "C" fn strerror(errnum: c_int) -> *mut c_char { strerror_buf.as_mut_ptr() as *mut c_char } +#[no_mangle] +pub unsafe extern "C" fn strerror_r( + errnum: c_int, + buf: *mut c_char, + buflen: size_t, +) -> c_int { + let msg = strerror(errnum); + let len = strlen(msg); + + if len >= buflen { + memcpy(buf as *mut c_void, msg as *const c_void, buflen - 1); + *buf.add(buflen - 1) = 0; + return ERANGE as c_int; + } + memcpy(buf as *mut c_void, msg as *const c_void, len + 1); + + 0 +} + #[no_mangle] pub unsafe extern "C" fn strlen(s: *const c_char) -> size_t { strnlen(s, usize::MAX) diff --git a/tests/error.c b/tests/error.c index 0ae8de70db80be565539cc3ab0963fc688558667..bb613b92239e30170482fde52dda1de9385f2f75 100644 --- a/tests/error.c +++ b/tests/error.c @@ -7,6 +7,16 @@ int main(void) { chdir("nonexistent"); - printf("errno: %d = %s\n", errno, strerror(errno)); + int err = errno; + + printf("errno: %d = %s\n", err, strerror(errno)); perror("perror"); + + char buf1[256]; + int ret1 = strerror_r(err, buf1, 256); + printf("errno: %d = %s, return: %d\n", err, buf1, ret1); + + char buf2[3]; + int ret2 = strerror_r(err, buf2, 3); + printf("errno: %d = %s, return: %d\n", err, buf2, ret2); } diff --git a/tests/expected/error.stdout b/tests/expected/error.stdout index f4ea5c920d19509171eff96610dc67881b4d6e04..d1c1a211ff8f941db9dde9b85a068b78fa665341 100644 --- a/tests/expected/error.stdout +++ b/tests/expected/error.stdout @@ -1 +1,3 @@ errno: 2 = No such file or directory +errno: 2 = No such file or directory, return: 0 +errno: 2 = No, return: 34