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