safe_libc/posix/
string.rs1use std::ffi::CString;
28use std::{ptr,slice};
29use libc::c_void;
30
31use crate::stdlib::realloc;
32use crate::errno::{Error,Result};
33use crate::errno;
34
35const BUF_SIZE: usize = 512;
36
37macro_rules! rv2errnum {
38 ($rv:ident) => {
39 match $rv {
40 0 => 0,
41 -1 => errno::errno(),
42 _ => $rv
43 }
44 }
45}
46
47pub fn strerror(errnum: i32) -> Result<String> {
48 unsafe {
49 let mut buflen = BUF_SIZE;
50 let buf = ptr::null_mut();
51
52 loop {
53 let buf = realloc(buf, buflen)?;
54 let rv = libc::strerror_r(errnum, buf as *mut i8, buflen);
55 let errnum = rv2errnum!(rv);
56
57 if errnum == 0 { let string = c_void2string(buf)?;
59 return Ok(string);
60 }
61
62 if errnum == libc::EINVAL {
63 let string = c_void2string(buf)?;
64 return Err(Error::new_msg(errnum, string));
65 }
66
67 buflen *= 2;
69 }
70 }
71}
72
73pub(crate) fn strerror_s(errnum: i32) -> Result<String> {
75 let mut buf: [u8; BUF_SIZE] = [0; BUF_SIZE];
76
77 let rv = unsafe {
78 libc::strerror_r(errnum, buf.as_mut_ptr() as *mut i8, BUF_SIZE)
79 };
80
81 let errnum = rv2errnum!(rv);
82 if errnum == libc::ERANGE {
83 buf[BUF_SIZE - 1] = 0;
84 }
85
86 let string = String::from_utf8_lossy(&buf).to_string();
87 if errnum == libc::EINVAL {
88 return Err(Error::new_msg(errnum, string));
89 }
90 Ok(string)
91}
92
93unsafe fn c_void2string(buf: *mut c_void) -> Result<String> {
94 let len = libc::strlen(buf as *mut i8) + 1;
95 let buf = buf as *const u8;
96 let vec: Vec<u8> = slice::from_raw_parts(buf, len).into();
97 let string = CString::from_vec_with_nul(vec)?
98 .to_string_lossy().to_string();
99
100 libc::free(buf as *mut c_void);
101 Ok(string)
102}
103
104#[cfg(test)]
105mod tests {
106 use super::strerror;
107 use crate::errno::Error;
108
109 #[test]
110 fn test_strerror() {
111 let msg = strerror(libc::EACCES);
112 assert_eq!(msg, Ok(String::from("Permission denied")));
113 }
114
115 #[test]
116 fn test_strerror_invalid() {
117 let msg = strerror(1234567890);
118 assert_eq!(msg, Err(Error::new(libc::EINVAL)));
119 }
120}