diff --git a/src/header/string/mod.rs b/src/header/string/mod.rs index 92bf959ab682604d91ac083643d7137d39bdf18a..d313552f94e0098ba195a23783da0f6c585c9021 100644 --- a/src/header/string/mod.rs +++ b/src/header/string/mod.rs @@ -263,6 +263,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