geofft / redhook

Dynamic function call interposition / hooking (LD_PRELOAD) for Rust
BSD 2-Clause "Simplified" License
176 stars 18 forks source link

string conversion between C (char*) and Rust (&str, String) #23

Open milahu opened 2 years ago

milahu commented 2 years ago

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 ```rust 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 libc::c_chars: *const libc::c_char = c_string.as_ptr() as *const libc::c_char;

    libc::printf(c_chars, path_resolved);