Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Remove most linux-raw-sys types from the public API #1277

Merged
merged 4 commits into from
Jan 29, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 1 addition & 23 deletions examples/stdio.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,25 +18,6 @@ use {
rustix::stdio::{stderr, stdin, stdout},
};

#[cfg(feature = "termios")]
#[cfg(all(not(windows), feature = "stdio"))]
#[cfg(not(any(target_os = "espidf", target_os = "wasi")))]
struct DebugWinsize(rustix::termios::Winsize);

#[cfg(feature = "termios")]
#[cfg(all(not(windows), feature = "stdio"))]
#[cfg(not(any(target_os = "espidf", target_os = "wasi")))]
impl core::fmt::Debug for DebugWinsize {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
let mut d = f.debug_struct("Winsize");
d.field("ws_row", &self.0.ws_row);
d.field("ws_col", &self.0.ws_col);
d.field("ws_xpixel", &self.0.ws_xpixel);
d.field("ws_ypixel", &self.0.ws_ypixel);
d.finish()
}
}

#[cfg(all(not(windows), feature = "stdio"))]
fn main() -> io::Result<()> {
let (stdin, stdout, stderr) = (stdin(), stdout(), stderr());
Expand Down Expand Up @@ -74,10 +55,7 @@ fn show<Fd: AsFd>(fd: Fd) -> io::Result<()> {
println!(" - process group: {:?}", rustix::termios::tcgetpgrp(fd)?);

#[cfg(not(any(target_os = "espidf", target_os = "wasi")))]
println!(
" - winsize: {:?}",
DebugWinsize(rustix::termios::tcgetwinsize(fd)?)
);
println!(" - winsize: {:?}", rustix::termios::tcgetwinsize(fd)?);

#[cfg(not(any(target_os = "espidf", target_os = "wasi")))]
{
Expand Down
2 changes: 2 additions & 0 deletions src/backend/linux_raw/c.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ pub(crate) use linux_raw_sys::general::{
__kernel_pid_t as pid_t, __kernel_time64_t as time_t, __kernel_timespec as timespec, iovec,
O_CLOEXEC, O_NOCTTY, O_NONBLOCK, O_RDWR,
};
#[cfg(feature = "system")]
pub(crate) use linux_raw_sys::system::sysinfo;

#[cfg(feature = "event")]
#[cfg(test)]
Expand Down
3 changes: 1 addition & 2 deletions src/backend/linux_raw/fs/inotify.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
//! inotify support for working with inotify objects.

use crate::backend::c;
use crate::ffi;
use bitflags::bitflags;

Expand Down Expand Up @@ -84,7 +83,7 @@ bitflags! {
/// [`inotify::Reader`]: crate::fs::inotify::InotifyReader
#[repr(transparent)]
#[derive(Default, Copy, Clone, Eq, PartialEq, Hash, Debug)]
pub struct ReadFlags: c::c_uint {
pub struct ReadFlags: ffi::c_uint {
/// `IN_ACCESS`
const ACCESS = linux_raw_sys::general::IN_ACCESS;
/// `IN_ATTRIB`
Expand Down
37 changes: 36 additions & 1 deletion src/backend/linux_raw/system/types.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,39 @@
use crate::ffi;

/// `sysinfo`
pub type Sysinfo = linux_raw_sys::system::sysinfo;
#[non_exhaustive]
#[repr(C)]
pub struct Sysinfo {
/// Seconds since boot
pub uptime: ffi::c_long,
/// 1, 5, and 15 minute load averages
pub loads: [ffi::c_ulong; 3],
/// Total usable main memory size
pub totalram: ffi::c_ulong,
/// Available memory size
pub freeram: ffi::c_ulong,
/// Amount of shared memory
pub sharedram: ffi::c_ulong,
/// Memory used by buffers
pub bufferram: ffi::c_ulong,
/// Total swap space size
pub totalswap: ffi::c_ulong,
/// Swap space still available
pub freeswap: ffi::c_ulong,
/// Number of current processes
pub procs: ffi::c_ushort,

pub(crate) pad: ffi::c_ushort,

/// Total high memory size
pub totalhigh: ffi::c_ulong,
/// Available high memory size
pub freehigh: ffi::c_ulong,
/// Memory unit size in bytes
pub mem_unit: ffi::c_uint,

pub(crate) f:
[u8; 20 - 2 * core::mem::size_of::<ffi::c_long>() - core::mem::size_of::<ffi::c_int>()],
}

pub(crate) type RawUname = linux_raw_sys::system::new_utsname;
17 changes: 17 additions & 0 deletions src/check_types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,23 @@ macro_rules! check_struct_renamed_field {
};
}

/// The same as `check_struct_field`, but for when the struct is renamed
/// but the field is not.
macro_rules! check_renamed_struct_field {
($to_struct:ident, $from_struct:ident, $field:ident) => {
const_assert_eq!(
memoffset::offset_of!($to_struct, $field),
memoffset::offset_of!(c::$from_struct, $field)
);

// As above, this can't use `const_assert_eq`.
assert_eq!(
memoffset::span_of!($to_struct, $field),
memoffset::span_of!(c::$from_struct, $field)
);
};
}

/// The same as `check_struct_renamed_field`, but for when both the struct and
/// a field are renamed.
macro_rules! check_renamed_struct_renamed_field {
Expand Down
5 changes: 2 additions & 3 deletions src/event/epoll.rs
Original file line number Diff line number Diff line change
Expand Up @@ -73,8 +73,6 @@
#![allow(unused_qualifications)]

use super::epoll;
#[cfg(feature = "alloc")]
use crate::backend::c;
pub use crate::backend::event::epoll::*;
use crate::backend::event::syscalls;
use crate::fd::{AsFd, OwnedFd};
Expand Down Expand Up @@ -205,7 +203,7 @@ pub fn delete<EpollFd: AsFd, SourceFd: AsFd>(epoll: EpollFd, source: SourceFd) -
pub fn wait<EpollFd: AsFd>(
epoll: EpollFd,
event_list: &mut EventVec,
timeout: c::c_int,
timeout: crate::ffi::c_int,
) -> io::Result<()> {
// SAFETY: We're calling `epoll_wait` via FFI and we know how it
// behaves.
Expand Down Expand Up @@ -456,6 +454,7 @@ impl<'a> IntoIterator for &'a EventVec {
#[cfg(test)]
mod tests {
use super::*;
use crate::backend::c;

#[test]
fn test_epoll_layouts() {
Expand Down
99 changes: 99 additions & 0 deletions src/io_uring/bindgen_types.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
//! Local versions of types that bindgen would use.

/// This represents an incomplete array field at the end of a struct.
///
/// This is called `__IncompleteArrayField` in bindgen bindings.
#[repr(C)]
#[derive(Default)]
pub struct IncompleteArrayField<T>(::core::marker::PhantomData<T>, [T; 0]);

#[allow(missing_docs)]
impl<T> IncompleteArrayField<T> {
#[inline]
pub const fn new() -> Self {
IncompleteArrayField(::core::marker::PhantomData, [])
}

#[inline]
pub fn as_ptr(&self) -> *const T {
self as *const _ as *const T
}

#[inline]
pub fn as_mut_ptr(&mut self) -> *mut T {
self as *mut _ as *mut T
}

#[inline]
pub unsafe fn as_slice(&self, len: usize) -> &[T] {
::core::slice::from_raw_parts(self.as_ptr(), len)
}

#[inline]
pub unsafe fn as_mut_slice(&mut self, len: usize) -> &mut [T] {
::core::slice::from_raw_parts_mut(self.as_mut_ptr(), len)
}
}

impl<T> ::core::fmt::Debug for IncompleteArrayField<T> {
fn fmt(&self, fmt: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result {
fmt.write_str("IncompleteArrayField")
}
}

/// This represents a toplevel union field.
///
/// This is called `__BindgenUnionField` in bindgen bindings.
pub struct UnionField<T>(::core::marker::PhantomData<T>);

#[allow(missing_docs)]
impl<T> UnionField<T> {
#[inline]
pub const fn new() -> Self {
UnionField(::core::marker::PhantomData)
}

#[inline]
pub unsafe fn as_ref(&self) -> &T {
::core::mem::transmute(self)
}

#[inline]
pub unsafe fn as_mut(&mut self) -> &mut T {
::core::mem::transmute(self)
}
}

impl<T> ::core::default::Default for UnionField<T> {
#[inline]
fn default() -> Self {
Self::new()
}
}

impl<T> ::core::clone::Clone for UnionField<T> {
#[inline]
fn clone(&self) -> Self {
*self
}
}

impl<T> ::core::marker::Copy for UnionField<T> {}

impl<T> ::core::fmt::Debug for UnionField<T> {
fn fmt(&self, fmt: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result {
fmt.write_str("UnionField")
}
}

impl<T> ::core::hash::Hash for UnionField<T> {
fn hash<H: ::core::hash::Hasher>(&self, _state: &mut H) {}
}

impl<T> ::core::cmp::PartialEq for UnionField<T> {
fn eq(&self, _other: &UnionField<T>) -> bool {
true
}
}

impl<T> ::core::cmp::Eq for UnionField<T> {}
13 changes: 8 additions & 5 deletions src/io_uring.rs → src/io_uring/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,11 @@
//! [rustix-uring]: https://crates.io/crates/rustix-uring
#![allow(unsafe_code)]

mod bindgen_types;

use crate::fd::{AsFd, BorrowedFd, OwnedFd, RawFd};
use crate::{backend, io};
use bindgen_types::*;
use core::ffi::c_void;
use core::mem::MaybeUninit;
use core::ptr::{null_mut, write_bytes};
Expand Down Expand Up @@ -1210,7 +1213,7 @@ pub struct io_uring_cqe {
pub user_data: io_uring_user_data,
pub res: i32,
pub flags: IoringCqeFlags,
pub big_cqe: sys::__IncompleteArrayField<u64>,
pub big_cqe: IncompleteArrayField<u64>,
}

#[allow(missing_docs)]
Expand Down Expand Up @@ -1286,7 +1289,7 @@ pub struct io_uring_probe {
pub ops_len: u8,
pub resv: u16,
pub resv2: [u32; 3],
pub ops: sys::__IncompleteArrayField<io_uring_probe_op>,
pub ops: IncompleteArrayField<io_uring_probe_op>,
}

#[allow(missing_docs)]
Expand Down Expand Up @@ -1416,15 +1419,15 @@ pub struct buf_ring_tail_struct {
#[repr(C)]
#[derive(Debug, Default)]
pub struct buf_ring_bufs_struct {
pub bufs: sys::__IncompleteArrayField<io_uring_buf>,
pub bufs: IncompleteArrayField<io_uring_buf>,
}

#[allow(missing_docs)]
#[repr(C)]
#[derive(Debug, Default)]
pub struct tail_or_bufs_struct {
pub tail: sys::__BindgenUnionField<buf_ring_tail_struct>,
pub bufs: sys::__BindgenUnionField<buf_ring_bufs_struct>,
pub tail: UnionField<buf_ring_tail_struct>,
pub bufs: UnionField<buf_ring_bufs_struct>,
pub union_field: [u64; 2],
}

Expand Down
6 changes: 0 additions & 6 deletions src/process/wait.rs
Original file line number Diff line number Diff line change
Expand Up @@ -225,12 +225,6 @@ impl WaitIdStatus {
}
}

/// Returns a reference to the raw platform-specific `siginfo_t` struct.
#[inline]
pub const fn as_raw(&self) -> &backend::c::siginfo_t {
&self.0
}

#[cfg(linux_raw)]
fn si_code(&self) -> u32 {
self.0.si_code() as u32 // CLD_ consts are unsigned
Expand Down
36 changes: 34 additions & 2 deletions src/system.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
#![allow(unsafe_code)]

use crate::backend;
#[cfg(linux_kernel)]
#[cfg(target_os = "linux")]
use crate::backend::c;
use crate::ffi::CStr;
#[cfg(not(any(target_os = "espidf", target_os = "emscripten", target_os = "vita")))]
Expand All @@ -20,7 +20,7 @@ pub use backend::system::types::Sysinfo;
#[cfg(linux_kernel)]
use crate::fd::AsFd;
#[cfg(linux_kernel)]
use c::c_int;
use crate::ffi::c_int;

/// `uname()`—Returns high-level information about the runtime OS and
/// hardware.
Expand Down Expand Up @@ -282,3 +282,35 @@ pub fn finit_module<Fd: AsFd>(fd: Fd, param_values: &CStr, flags: c_int) -> io::
pub fn delete_module(name: &CStr, flags: c_int) -> io::Result<()> {
backend::system::syscalls::delete_module(name, flags)
}

#[cfg(test)]
mod tests {
#[allow(unused_imports)]
use super::*;
#[allow(unused_imports)]
use crate::backend::c;

#[cfg(linux_kernel)]
#[test]
fn test_sysinfo_layouts() {
// Don't assert the size for `Sysinfo` because `c::sysinfo` has a
// computed-size padding field at the end that bindgen doesn't support,
// and `c::sysinfo` may add fields over time.
assert_eq!(
core::mem::align_of::<Sysinfo>(),
core::mem::align_of::<c::sysinfo>()
);
check_renamed_struct_field!(Sysinfo, sysinfo, uptime);
check_renamed_struct_field!(Sysinfo, sysinfo, loads);
check_renamed_struct_field!(Sysinfo, sysinfo, totalram);
check_renamed_struct_field!(Sysinfo, sysinfo, freeram);
check_renamed_struct_field!(Sysinfo, sysinfo, sharedram);
check_renamed_struct_field!(Sysinfo, sysinfo, bufferram);
check_renamed_struct_field!(Sysinfo, sysinfo, totalswap);
check_renamed_struct_field!(Sysinfo, sysinfo, freeswap);
check_renamed_struct_field!(Sysinfo, sysinfo, procs);
check_renamed_struct_field!(Sysinfo, sysinfo, totalhigh);
check_renamed_struct_field!(Sysinfo, sysinfo, freehigh);
check_renamed_struct_field!(Sysinfo, sysinfo, mem_unit);
}
}
16 changes: 15 additions & 1 deletion src/termios/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1350,7 +1350,15 @@ pub enum Action {
///
/// [`tcgetwinsize`]: crate::termios::tcgetwinsize
#[doc(alias = "winsize")]
pub type Winsize = c::winsize;
#[repr(C)]
#[derive(Debug, Copy, Clone, Eq, Hash, PartialEq)]
#[allow(missing_docs)]
pub struct Winsize {
pub ws_row: u16,
pub ws_col: u16,
pub ws_xpixel: u16,
pub ws_ypixel: u16,
}

#[test]
fn termios_layouts() {
Expand All @@ -1361,6 +1369,12 @@ fn termios_layouts() {
assert_eq_size!(u8, libc::cc_t);
assert_eq_size!(types::tcflag_t, libc::tcflag_t);

check_renamed_type!(Winsize, winsize);
check_renamed_struct_field!(Winsize, winsize, ws_row);
check_renamed_struct_field!(Winsize, winsize, ws_col);
check_renamed_struct_field!(Winsize, winsize, ws_xpixel);
check_renamed_struct_field!(Winsize, winsize, ws_ypixel);

// On platforms with a termios/termios2 split, check `termios`.
#[cfg(linux_raw)]
{
Expand Down
Loading