src/lib.rs
src/lib.rs, line 110-215
pub mod cmsg_macros {
use crate::ctypes::{c_long, c_uchar, c_uint};
use crate::net::{cmsghdr, msghdr};
use core::mem::size_of;
use core::ptr;
pub const unsafe fn CMSG_ALIGN(len: c_uint) -> c_uint {
let c_long_size = size_of::<c_long>() as c_uint;
(len + c_long_size - 1) & !(c_long_size - 1)
}
pub const unsafe fn CMSG_DATA(cmsg: *const cmsghdr) -> *mut c_uchar {
(cmsg as *mut c_uchar).add(size_of::<cmsghdr>())
}
pub const unsafe fn CMSG_SPACE(len: c_uint) -> c_uint {
size_of::<cmsghdr>() as c_uint + CMSG_ALIGN(len)
}
pub const unsafe fn CMSG_LEN(len: c_uint) -> c_uint {
size_of::<cmsghdr>() as c_uint + len
}
pub const unsafe fn CMSG_FIRSTHDR(mhdr: *const msghdr) -> *mut cmsghdr {
if (*mhdr).msg_controllen < size_of::<cmsghdr>() as _ {
return ptr::null_mut();
}
(*mhdr).msg_control as *mut cmsghdr
}
pub unsafe fn CMSG_NXTHDR(mhdr: *const msghdr, cmsg: *const cmsghdr) -> *mut cmsghdr {
// We convert from raw pointers to usize here, which may not be sound in a
// future version of Rust. Once the provenance rules are set in stone,
// it will be a good idea to give this function a once-over.
let cmsg_len = (*cmsg).cmsg_len;
let next_cmsg = (cmsg as *mut u8).add(CMSG_ALIGN(cmsg_len as _) as usize) as *mut cmsghdr;
let max = ((*mhdr).msg_control as usize) + ((*mhdr).msg_controllen as usize);
if cmsg_len < size_of::<cmsghdr>() as _ {
return ptr::null_mut();
}
if next_cmsg.add(1) as usize > max
|| next_cmsg as usize + CMSG_ALIGN((*next_cmsg).cmsg_len as _) as usize > max
{
return ptr::null_mut();
}
next_cmsg
}
}
#[cfg(feature = "general")]
pub mod select_macros {
use crate::ctypes::c_int;
use crate::general::__kernel_fd_set;
use core::mem::size_of;
pub unsafe fn FD_CLR(fd: c_int, set: *mut __kernel_fd_set) {
let bytes = set as *mut u8;
if fd >= 0 {
*bytes.add((fd / 8) as usize) &= !(1 << (fd % 8));
}
}
pub unsafe fn FD_SET(fd: c_int, set: *mut __kernel_fd_set) {
let bytes = set as *mut u8;
if fd >= 0 {
*bytes.add((fd / 8) as usize) |= 1 << (fd % 8);
}
}
pub unsafe fn FD_ISSET(fd: c_int, set: *const __kernel_fd_set) -> bool {
let bytes = set as *const u8;
if fd >= 0 {
*bytes.add((fd / 8) as usize) & (1 << (fd % 8)) != 0
} else {
false
}
}
pub unsafe fn FD_ZERO(set: *mut __kernel_fd_set) {
let bytes = set as *mut u8;
core::ptr::write_bytes(bytes, 0, size_of::<__kernel_fd_set>());
}
}
#[cfg(feature = "general")]
pub mod signal_macros {
pub const SIG_DFL: super::general::__kernel_sighandler_t = None;
/// Rust doesn't currently permit us to use `transmute` to convert the
/// `SIG_IGN` value into a function pointer in a `const` initializer, so
/// we make it a function instead.
///
#[inline]
pub const fn sig_ign() -> super::general::__kernel_sighandler_t {
// Safety: This creates an invalid pointer, but the pointer type
// includes `unsafe`, which covers the safety of calling it.
Some(unsafe {
core::mem::transmute::<usize, unsafe extern "C" fn(crate::ctypes::c_int)>(1)
})
}
}
The cmsg_macros, select_macros, and signal_macros modules in lib.rs contain the only hand-authored unsafe code in the crate. cmsg_macros implements POSIX CMSG_* socket control-message helpers using raw pointer arithmetic; CMSG_NXTHDR includes a comment noting the usize-from-pointer conversion may need revisiting once Rust provenance rules are finalised. select_macros implements FD_CLR, FD_SET, FD_ISSET, and FD_ZERO via byte-pointer arithmetic bounded by the fd index check (fd >= 0). signal_macros::sig_ign uses transmute to produce the SIG_IGN sentinel function pointer value (1), documented inline. Justifies uses-unsafe and is-benign.