1b8a62b91Sopenharmony_ci//! Libc call arguments and return values are often things like `c_int`, 2b8a62b91Sopenharmony_ci//! `c_uint`, or libc-specific pointer types. This module provides functions 3b8a62b91Sopenharmony_ci//! for converting between rustix's types and libc types. 4b8a62b91Sopenharmony_ci 5b8a62b91Sopenharmony_ci#![allow(dead_code)] 6b8a62b91Sopenharmony_ci 7b8a62b91Sopenharmony_ciuse super::c; 8b8a62b91Sopenharmony_ciuse super::fd::{AsRawFd, BorrowedFd, FromRawFd, IntoRawFd, LibcFd, OwnedFd, RawFd}; 9b8a62b91Sopenharmony_ci#[cfg(not(windows))] 10b8a62b91Sopenharmony_ci#[cfg(feature = "fs")] 11b8a62b91Sopenharmony_ciuse super::offset::libc_off_t; 12b8a62b91Sopenharmony_ci#[cfg(not(windows))] 13b8a62b91Sopenharmony_ciuse crate::ffi::CStr; 14b8a62b91Sopenharmony_ciuse crate::io; 15b8a62b91Sopenharmony_ci#[cfg(windows)] 16b8a62b91Sopenharmony_ciuse core::convert::TryInto; 17b8a62b91Sopenharmony_ci 18b8a62b91Sopenharmony_ci#[cfg(not(windows))] 19b8a62b91Sopenharmony_ci#[inline] 20b8a62b91Sopenharmony_cipub(super) fn c_str(c: &CStr) -> *const c::c_char { 21b8a62b91Sopenharmony_ci c.as_ptr() 22b8a62b91Sopenharmony_ci} 23b8a62b91Sopenharmony_ci 24b8a62b91Sopenharmony_ci#[cfg(not(windows))] 25b8a62b91Sopenharmony_ci#[inline] 26b8a62b91Sopenharmony_cipub(super) fn no_fd() -> LibcFd { 27b8a62b91Sopenharmony_ci -1 28b8a62b91Sopenharmony_ci} 29b8a62b91Sopenharmony_ci 30b8a62b91Sopenharmony_ci#[inline] 31b8a62b91Sopenharmony_cipub(super) fn borrowed_fd(fd: BorrowedFd<'_>) -> LibcFd { 32b8a62b91Sopenharmony_ci fd.as_raw_fd() as LibcFd 33b8a62b91Sopenharmony_ci} 34b8a62b91Sopenharmony_ci 35b8a62b91Sopenharmony_ci#[inline] 36b8a62b91Sopenharmony_cipub(super) fn owned_fd(fd: OwnedFd) -> LibcFd { 37b8a62b91Sopenharmony_ci fd.into_raw_fd() as LibcFd 38b8a62b91Sopenharmony_ci} 39b8a62b91Sopenharmony_ci 40b8a62b91Sopenharmony_ci#[inline] 41b8a62b91Sopenharmony_cipub(super) fn ret(raw: c::c_int) -> io::Result<()> { 42b8a62b91Sopenharmony_ci if raw == 0 { 43b8a62b91Sopenharmony_ci Ok(()) 44b8a62b91Sopenharmony_ci } else { 45b8a62b91Sopenharmony_ci Err(io::Errno::last_os_error()) 46b8a62b91Sopenharmony_ci } 47b8a62b91Sopenharmony_ci} 48b8a62b91Sopenharmony_ci 49b8a62b91Sopenharmony_ci#[inline] 50b8a62b91Sopenharmony_cipub(super) fn syscall_ret(raw: c::c_long) -> io::Result<()> { 51b8a62b91Sopenharmony_ci if raw == 0 { 52b8a62b91Sopenharmony_ci Ok(()) 53b8a62b91Sopenharmony_ci } else { 54b8a62b91Sopenharmony_ci Err(io::Errno::last_os_error()) 55b8a62b91Sopenharmony_ci } 56b8a62b91Sopenharmony_ci} 57b8a62b91Sopenharmony_ci 58b8a62b91Sopenharmony_ci#[inline] 59b8a62b91Sopenharmony_cipub(super) fn nonnegative_ret(raw: c::c_int) -> io::Result<()> { 60b8a62b91Sopenharmony_ci if raw >= 0 { 61b8a62b91Sopenharmony_ci Ok(()) 62b8a62b91Sopenharmony_ci } else { 63b8a62b91Sopenharmony_ci Err(io::Errno::last_os_error()) 64b8a62b91Sopenharmony_ci } 65b8a62b91Sopenharmony_ci} 66b8a62b91Sopenharmony_ci 67b8a62b91Sopenharmony_ci#[inline] 68b8a62b91Sopenharmony_cipub(super) unsafe fn ret_infallible(raw: c::c_int) { 69b8a62b91Sopenharmony_ci debug_assert_eq!(raw, 0, "unexpected error: {:?}", io::Errno::last_os_error()); 70b8a62b91Sopenharmony_ci} 71b8a62b91Sopenharmony_ci 72b8a62b91Sopenharmony_ci#[inline] 73b8a62b91Sopenharmony_cipub(super) fn ret_c_int(raw: c::c_int) -> io::Result<c::c_int> { 74b8a62b91Sopenharmony_ci if raw == -1 { 75b8a62b91Sopenharmony_ci Err(io::Errno::last_os_error()) 76b8a62b91Sopenharmony_ci } else { 77b8a62b91Sopenharmony_ci Ok(raw) 78b8a62b91Sopenharmony_ci } 79b8a62b91Sopenharmony_ci} 80b8a62b91Sopenharmony_ci 81b8a62b91Sopenharmony_ci#[inline] 82b8a62b91Sopenharmony_cipub(super) fn ret_u32(raw: c::c_int) -> io::Result<u32> { 83b8a62b91Sopenharmony_ci if raw == -1 { 84b8a62b91Sopenharmony_ci Err(io::Errno::last_os_error()) 85b8a62b91Sopenharmony_ci } else { 86b8a62b91Sopenharmony_ci Ok(raw as u32) 87b8a62b91Sopenharmony_ci } 88b8a62b91Sopenharmony_ci} 89b8a62b91Sopenharmony_ci 90b8a62b91Sopenharmony_ci#[inline] 91b8a62b91Sopenharmony_cipub(super) fn ret_ssize_t(raw: c::ssize_t) -> io::Result<c::ssize_t> { 92b8a62b91Sopenharmony_ci if raw == -1 { 93b8a62b91Sopenharmony_ci Err(io::Errno::last_os_error()) 94b8a62b91Sopenharmony_ci } else { 95b8a62b91Sopenharmony_ci Ok(raw) 96b8a62b91Sopenharmony_ci } 97b8a62b91Sopenharmony_ci} 98b8a62b91Sopenharmony_ci 99b8a62b91Sopenharmony_ci#[inline] 100b8a62b91Sopenharmony_cipub(super) fn syscall_ret_ssize_t(raw: c::c_long) -> io::Result<c::ssize_t> { 101b8a62b91Sopenharmony_ci if raw == -1 { 102b8a62b91Sopenharmony_ci Err(io::Errno::last_os_error()) 103b8a62b91Sopenharmony_ci } else { 104b8a62b91Sopenharmony_ci Ok(raw as c::ssize_t) 105b8a62b91Sopenharmony_ci } 106b8a62b91Sopenharmony_ci} 107b8a62b91Sopenharmony_ci 108b8a62b91Sopenharmony_ci#[cfg(any(target_os = "android", target_os = "linux"))] 109b8a62b91Sopenharmony_ci#[inline] 110b8a62b91Sopenharmony_cipub(super) fn syscall_ret_u32(raw: c::c_long) -> io::Result<u32> { 111b8a62b91Sopenharmony_ci if raw == -1 { 112b8a62b91Sopenharmony_ci Err(io::Errno::last_os_error()) 113b8a62b91Sopenharmony_ci } else { 114b8a62b91Sopenharmony_ci let r32 = raw as u32; 115b8a62b91Sopenharmony_ci 116b8a62b91Sopenharmony_ci // Converting `raw` to `u32` should be lossless. 117b8a62b91Sopenharmony_ci debug_assert_eq!(r32 as c::c_long, raw); 118b8a62b91Sopenharmony_ci 119b8a62b91Sopenharmony_ci Ok(r32) 120b8a62b91Sopenharmony_ci } 121b8a62b91Sopenharmony_ci} 122b8a62b91Sopenharmony_ci 123b8a62b91Sopenharmony_ci#[cfg(not(windows))] 124b8a62b91Sopenharmony_ci#[cfg(feature = "fs")] 125b8a62b91Sopenharmony_ci#[inline] 126b8a62b91Sopenharmony_cipub(super) fn ret_off_t(raw: libc_off_t) -> io::Result<libc_off_t> { 127b8a62b91Sopenharmony_ci if raw == -1 { 128b8a62b91Sopenharmony_ci Err(io::Errno::last_os_error()) 129b8a62b91Sopenharmony_ci } else { 130b8a62b91Sopenharmony_ci Ok(raw) 131b8a62b91Sopenharmony_ci } 132b8a62b91Sopenharmony_ci} 133b8a62b91Sopenharmony_ci 134b8a62b91Sopenharmony_ci#[cfg(not(windows))] 135b8a62b91Sopenharmony_ci#[inline] 136b8a62b91Sopenharmony_cipub(super) fn ret_pid_t(raw: c::pid_t) -> io::Result<c::pid_t> { 137b8a62b91Sopenharmony_ci if raw == -1 { 138b8a62b91Sopenharmony_ci Err(io::Errno::last_os_error()) 139b8a62b91Sopenharmony_ci } else { 140b8a62b91Sopenharmony_ci Ok(raw) 141b8a62b91Sopenharmony_ci } 142b8a62b91Sopenharmony_ci} 143b8a62b91Sopenharmony_ci 144b8a62b91Sopenharmony_ci/// Convert a `c_int` returned from a libc function to an `OwnedFd`, if valid. 145b8a62b91Sopenharmony_ci/// 146b8a62b91Sopenharmony_ci/// # Safety 147b8a62b91Sopenharmony_ci/// 148b8a62b91Sopenharmony_ci/// The caller must ensure that this is the return value of a libc function 149b8a62b91Sopenharmony_ci/// which returns an owned file descriptor. 150b8a62b91Sopenharmony_ci#[inline] 151b8a62b91Sopenharmony_cipub(super) unsafe fn ret_owned_fd(raw: LibcFd) -> io::Result<OwnedFd> { 152b8a62b91Sopenharmony_ci if raw == !0 { 153b8a62b91Sopenharmony_ci Err(io::Errno::last_os_error()) 154b8a62b91Sopenharmony_ci } else { 155b8a62b91Sopenharmony_ci Ok(OwnedFd::from_raw_fd(raw as RawFd)) 156b8a62b91Sopenharmony_ci } 157b8a62b91Sopenharmony_ci} 158b8a62b91Sopenharmony_ci 159b8a62b91Sopenharmony_ci#[inline] 160b8a62b91Sopenharmony_cipub(super) fn ret_discarded_fd(raw: LibcFd) -> io::Result<()> { 161b8a62b91Sopenharmony_ci if raw == !0 { 162b8a62b91Sopenharmony_ci Err(io::Errno::last_os_error()) 163b8a62b91Sopenharmony_ci } else { 164b8a62b91Sopenharmony_ci Ok(()) 165b8a62b91Sopenharmony_ci } 166b8a62b91Sopenharmony_ci} 167b8a62b91Sopenharmony_ci 168b8a62b91Sopenharmony_ci#[inline] 169b8a62b91Sopenharmony_cipub(super) fn ret_discarded_char_ptr(raw: *mut c::c_char) -> io::Result<()> { 170b8a62b91Sopenharmony_ci if raw.is_null() { 171b8a62b91Sopenharmony_ci Err(io::Errno::last_os_error()) 172b8a62b91Sopenharmony_ci } else { 173b8a62b91Sopenharmony_ci Ok(()) 174b8a62b91Sopenharmony_ci } 175b8a62b91Sopenharmony_ci} 176b8a62b91Sopenharmony_ci 177b8a62b91Sopenharmony_ci/// Convert a `c_long` returned from `syscall` to an `OwnedFd`, if valid. 178b8a62b91Sopenharmony_ci/// 179b8a62b91Sopenharmony_ci/// # Safety 180b8a62b91Sopenharmony_ci/// 181b8a62b91Sopenharmony_ci/// The caller must ensure that this is the return value of a `syscall` call 182b8a62b91Sopenharmony_ci/// which returns an owned file descriptor. 183b8a62b91Sopenharmony_ci#[cfg(not(windows))] 184b8a62b91Sopenharmony_ci#[inline] 185b8a62b91Sopenharmony_cipub(super) unsafe fn syscall_ret_owned_fd(raw: c::c_long) -> io::Result<OwnedFd> { 186b8a62b91Sopenharmony_ci if raw == -1 { 187b8a62b91Sopenharmony_ci Err(io::Errno::last_os_error()) 188b8a62b91Sopenharmony_ci } else { 189b8a62b91Sopenharmony_ci Ok(OwnedFd::from_raw_fd(raw as RawFd)) 190b8a62b91Sopenharmony_ci } 191b8a62b91Sopenharmony_ci} 192b8a62b91Sopenharmony_ci 193b8a62b91Sopenharmony_ci/// Convert the buffer-length argument value of a `send` or `recv` call. 194b8a62b91Sopenharmony_ci#[cfg(not(windows))] 195b8a62b91Sopenharmony_ci#[inline] 196b8a62b91Sopenharmony_cipub(super) fn send_recv_len(len: usize) -> usize { 197b8a62b91Sopenharmony_ci len 198b8a62b91Sopenharmony_ci} 199b8a62b91Sopenharmony_ci 200b8a62b91Sopenharmony_ci/// Convert the buffer-length argument value of a `send` or `recv` call. 201b8a62b91Sopenharmony_ci#[cfg(windows)] 202b8a62b91Sopenharmony_ci#[inline] 203b8a62b91Sopenharmony_cipub(super) fn send_recv_len(len: usize) -> i32 { 204b8a62b91Sopenharmony_ci // On Windows, the length argument has type `i32`; saturate the length, 205b8a62b91Sopenharmony_ci // since `send` and `recv` are allowed to send and recv less data than 206b8a62b91Sopenharmony_ci // requested. 207b8a62b91Sopenharmony_ci len.try_into().unwrap_or(i32::MAX) 208b8a62b91Sopenharmony_ci} 209b8a62b91Sopenharmony_ci 210b8a62b91Sopenharmony_ci/// Convert the return value of a `send` or `recv` call. 211b8a62b91Sopenharmony_ci#[cfg(not(windows))] 212b8a62b91Sopenharmony_ci#[inline] 213b8a62b91Sopenharmony_cipub(super) fn ret_send_recv(len: isize) -> io::Result<c::ssize_t> { 214b8a62b91Sopenharmony_ci ret_ssize_t(len) 215b8a62b91Sopenharmony_ci} 216b8a62b91Sopenharmony_ci 217b8a62b91Sopenharmony_ci/// Convert the return value of a `send` or `recv` call. 218b8a62b91Sopenharmony_ci#[cfg(windows)] 219b8a62b91Sopenharmony_ci#[inline] 220b8a62b91Sopenharmony_cipub(super) fn ret_send_recv(len: i32) -> io::Result<c::ssize_t> { 221b8a62b91Sopenharmony_ci ret_ssize_t(len as isize) 222b8a62b91Sopenharmony_ci} 223