redhook
redhook copied to clipboard
string conversion between C (char*) and Rust (&str, String)
can we add this somehow? im new to rust, so i hope there is a shorter way ...
convert string from C to Rust
unsafe fn str_of_chars(cstr: *const libc::c_char) -> &'static str {
return std::str::from_utf8(std::ffi::CStr::from_ptr(cstr).to_bytes()).unwrap();
}
// https://users.rust-lang.org/t/how-to-convert-a-non-zero-terminated-c-string-to-rust-str-or-string/2177
unsafe fn str_of_chars_size(cstr: *const libc::c_char, size: isize) -> &'static str {
return std::str::from_utf8(std::slice::from_raw_parts(cstr as *const u8, size as usize)).unwrap()
}
sample use
hook! {
unsafe fn statx(
dirfd: libc::c_int,
pathname: *const libc::c_char,
flags: libc::c_int,
mask: libc::c_uint,
statxbuf: *mut libc::statx // https://docs.rs/libc/0.2.103/libc/struct.statx.html
) -> libc::c_int => my_statx {
let retval = real!(statx)(dirfd, pathname, flags, mask, statxbuf);
let pathname_str = str_of_chars(pathname);
println!("statx({}) -> retval {}, stx_mode {:#o}", pathname_str, retval, (*statxbuf).stx_mode);
return retval;
}
}
hook! {
unsafe fn readlink(
path: *const libc::c_char,
buf: *mut libc::c_char,
bufsiz: libc::size_t
) -> libc::ssize_t => my_readlink {
let buf_len = real!(readlink)(path, buf, bufsiz);
let path_str = str_of_chars(path);
let buf_str = str_of_chars_size(buf, buf_len);
println!("readlink({}) -> target {}, bufsiz {} of {}", path_str, buf_str, buf_len, bufsiz);
return buf_len;
}
}
convert string from Rust to C
path_resolved_str = "some string ...";
// TODO move to function/macro
let r_string_2 = path_resolved_str.to_owned();
let c_string_2 = CString::new(r_string_2).unwrap();
let path_resolved: *const libc::c_char = c_string_2.as_ptr() as *const libc::c_char;
let r_string = "open: path_resolved = \"%s\"\n";
let c_string = CString::new(r_string).unwrap();
let c_chars: *const libc::c_char = c_string.as_ptr() as *const libc::c_char;
libc::printf(c_chars, path_resolved);
write Rust string to C buffer
unsafe fn str_to_c_char_buf(
src_str: &str,
buf: *mut libc::c_char,
bufsz: libc::size_t
) -> libc::size_t {
// write string to buffer
// https://stackoverflow.com/questions/51320714
let src_string = String::from(src_str);
let src_cstring = CString::new(src_string).unwrap();
//let src_bytes = src_cstring.as_bytes_with_nul();
let src_bytes = src_cstring.as_bytes();
let buf_bytes = slice::from_raw_parts_mut(buf as *mut u8, bufsz as usize);
buf_bytes[..src_bytes.len()].copy_from_slice(src_bytes);
return src_bytes.len() as libc::size_t;
}
// example use
hook! {
// https://docs.rs/libc/latest/libc/fn.readlink.html
unsafe fn readlink(
path: *const libc::c_char,
buf: *mut libc::c_char,
bufsz: libc::size_t
) -> libc::ssize_t => readlink_hooked {
let mut retval = real!(readlink)(path, buf, bufsz);
if true {
// modify result
retval = str_to_c_char_buf("/asdf", buf, bufsz) as libc::ssize_t;
}
return retval;
}
}