Skip to content
Open
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
72 changes: 72 additions & 0 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -865,3 +865,75 @@ jobs:
cargo test --verbose --features=all-apis --release --workspace -- --nocapture
env:
RUST_BACKTRACE: full

meson-musl:
name: Meson Musl
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
submodules: true
- uses: ./.github/actions/install-rust
with:
toolchain: stable
- name: Install target
run: rustup target add x86_64-unknown-linux-musl
- name: Install Meson and Ninja
run: sudo apt-get update && sudo apt-get install -y meson ninja-build musl-tools
- name: Create cross file
run: |
cat <<EOF > cross_file_musl_ci.txt
[binaries]
c = 'gcc'
rust = ['rustc', '--target', 'x86_64-unknown-linux-musl']

[host_machine]
system = 'linux'
cpu_family = 'x86_64'
cpu = 'x86_64'
endian = 'little'
EOF
- name: Meson setup
run: meson setup build-musl --cross-file cross_file_musl_ci.txt
- name: Meson compile
run: meson compile -C build-musl

meson-android:
name: Meson Android
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
submodules: true
- uses: ./.github/actions/install-rust
with:
toolchain: stable
- name: Install target
run: rustup target add x86_64-linux-android
- name: Install Meson and Ninja
run: sudo apt-get update && sudo apt-get install -y meson ninja-build
- name: Setup NDK
uses: nttld/setup-ndk@v1
id: setup-ndk
with:
ndk-version: r27b
- name: Create cross file
run: |
cat <<EOF > cross_file_android_ci.txt
[binaries]
c = '${{ steps.setup-ndk.outputs.ndk-path }}/toolchains/llvm/prebuilt/linux-x86_64/bin/x86_64-linux-android30-clang'
cpp = '${{ steps.setup-ndk.outputs.ndk-path }}/toolchains/llvm/prebuilt/linux-x86_64/bin/x86_64-linux-android30-clang++'
ar = '${{ steps.setup-ndk.outputs.ndk-path }}/toolchains/llvm/prebuilt/linux-x86_64/bin/llvm-ar'
strip = '${{ steps.setup-ndk.outputs.ndk-path }}/toolchains/llvm/prebuilt/linux-x86_64/bin/llvm-strip'
rust = ['rustc', '--target', 'x86_64-linux-android']

[host_machine]
system = 'android'
cpu_family = 'x86_64'
cpu = 'x86_64'
endian = 'little'
EOF
- name: Meson setup
run: meson setup build-android --cross-file cross_file_android_ci.txt
- name: Meson compile
run: meson compile -C build-android
46 changes: 46 additions & 0 deletions meson.build
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
# Copyright © 2026 Google
# SPDX-License-Identifier: MIT

project(
'rustix',
'rust',
version : '1.1.3',
license : 'Apache-2.0 WITH LLVM-exception OR Apache-2.0 OR MIT',
)

dep_errno = dependency('errno-0.3-rs', fallback: ['errno-0.3-rs', 'dep_errno'])
dep_libc = dependency('libc-0.2-rs', fallback: ['libc-0.2-rs', 'dep_libc'])
dep_bitflags = dependency('bitflags-2-rs', fallback: ['bitflags-2-rs', 'dep_bitflags'])

rustix_args = [
'--cfg', 'libc',
'--cfg', 'feature="use-libc"',
]

os_deps = []
if host_machine.system() == 'linux' or host_machine.system() == 'android'
rustix_args += [
'--cfg', 'linux_like',
'--cfg', 'linux_kernel',
'--cfg', 'feature="std"',
'--cfg', 'feature="alloc"',
'--cfg', 'feature="event"',
'--cfg', 'feature="fs"',
'--cfg', 'feature="mm"',
'--cfg', 'feature="net"',
'--cfg', 'feature="param"',
'--cfg', 'feature="pipe"',
'--cfg', 'feature="thread"',
]
elif host_machine.system() == 'windows'
os_deps += [dependency('windows-sys-0.6-rs', fallback: ['windows-sys-0.6-rs', 'dep_windows_sys'])]
endif

lib = static_library(
'rustix',
'src/lib.rs',
override_options : ['rust_std=2021', 'build.rust_std=2021'],
dependencies : [dep_errno, dep_libc, dep_bitflags] + os_deps,
rust_abi : 'rust',
rust_args: rustix_args,
)
8 changes: 8 additions & 0 deletions src/backend/libc/c.rs
Original file line number Diff line number Diff line change
Expand Up @@ -515,6 +515,14 @@ pub(crate) use statx_flags::*;
#[cfg(target_os = "android")]
pub(crate) use __fsid_t as fsid_t;

// Android's libc crate is missing some constants.
#[cfg(target_os = "android")]
pub(crate) const CLONE_NEWTIME: c_int = 0x00000080;
#[cfg(target_os = "android")]
pub(crate) const FUTEX_WAITERS: u32 = 0x80000000;
#[cfg(target_os = "android")]
pub(crate) const FUTEX_OWNER_DIED: u32 = 0x40000000;

// FreeBSD added `timerfd_*` in FreeBSD 14. NetBSD added then in NetBSD 10.
#[cfg(all(feature = "time", any(target_os = "freebsd", target_os = "netbsd")))]
syscall!(pub(crate) fn timerfd_create(
Expand Down
4 changes: 2 additions & 2 deletions src/backend/libc/fs/syscalls.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2053,10 +2053,10 @@ pub(crate) fn statx(
// doesn't represent all the known flags.
//
// [it's deprecated]: https://patchwork.kernel.org/project/linux-fsdevel/patch/20200505095915.11275-7-mszeredi@redhat.com/
#[cfg(any(not(linux_raw_dep), not(target_env = "musl")))]
#[cfg(not(target_env = "musl"))]
const STATX__RESERVED: u32 = c::STATX__RESERVED as u32;
#[cfg(target_env = "musl")]
const STATX__RESERVED: u32 = linux_raw_sys::general::STATX__RESERVED;
const STATX__RESERVED: u32 = 0x80000000;
if (mask.bits() & STATX__RESERVED) == STATX__RESERVED {
return Err(io::Errno::INVAL);
}
Expand Down
29 changes: 17 additions & 12 deletions src/backend/libc/thread/futex.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,14 @@ bitflags::bitflags! {
}
}

const FUTEX2_SIZE_U8: u32 = 0;
const FUTEX2_SIZE_U16: u32 = 1;
const FUTEX2_SIZE_U32: u32 = 2;
const FUTEX2_SIZE_U64: u32 = 3;
const FUTEX2_SIZE_MASK: u32 = 3;
const FUTEX2_NUMA: u32 = 4;
const FUTEX2_PRIVATE: u32 = 128;

bitflags::bitflags! {
/// `FUTEX2_*` flags for use with the functions in [`Waitv`].
///
Expand All @@ -29,22 +37,19 @@ bitflags::bitflags! {
#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
pub struct WaitFlags: u32 {
/// `FUTEX_U8`
const SIZE_U8 = linux_raw_sys::general::FUTEX2_SIZE_U8;
const SIZE_U8 = FUTEX2_SIZE_U8;
/// `FUTEX_U16`
const SIZE_U16 = linux_raw_sys::general::FUTEX2_SIZE_U16;
const SIZE_U16 = FUTEX2_SIZE_U16;
/// `FUTEX_U32`
const SIZE_U32 = linux_raw_sys::general::FUTEX2_SIZE_U32;
const SIZE_U32 = FUTEX2_SIZE_U32;
/// `FUTEX_U64`
const SIZE_U64 = linux_raw_sys::general::FUTEX2_SIZE_U64;
const SIZE_U64 = FUTEX2_SIZE_U64;
/// `FUTEX_SIZE_MASK`
const SIZE_MASK = linux_raw_sys::general::FUTEX2_SIZE_MASK;

const SIZE_MASK = FUTEX2_SIZE_MASK;
/// `FUTEX2_NUMA`
const NUMA = linux_raw_sys::general::FUTEX2_NUMA;

const NUMA = FUTEX2_NUMA;
/// `FUTEX2_PRIVATE`
const PRIVATE = linux_raw_sys::general::FUTEX2_PRIVATE;

const PRIVATE = FUTEX2_PRIVATE;
/// <https://docs.rs/bitflags/*/bitflags/#externally-defined-flags>
const _ = !0;
}
Expand Down Expand Up @@ -85,7 +90,7 @@ pub(crate) enum Operation {
}

/// `FUTEX_WAITERS`
pub const WAITERS: u32 = linux_raw_sys::general::FUTEX_WAITERS;
pub const WAITERS: u32 = c::FUTEX_WAITERS;

/// `FUTEX_OWNER_DIED`
pub const OWNER_DIED: u32 = linux_raw_sys::general::FUTEX_OWNER_DIED;
pub const OWNER_DIED: u32 = c::FUTEX_OWNER_DIED;
9 changes: 5 additions & 4 deletions src/backend/libc/thread/syscalls.rs
Original file line number Diff line number Diff line change
Expand Up @@ -341,13 +341,13 @@ pub(crate) fn setns(fd: BorrowedFd<'_>, nstype: c::c_int) -> io::Result<c::c_int
unsafe { ret_c_int(setns(borrowed_fd(fd), nstype)) }
}

#[cfg(linux_kernel)]
#[cfg(all(linux_kernel, linux_raw_dep))]
#[inline]
pub(crate) unsafe fn unshare(flags: crate::thread::UnshareFlags) -> io::Result<()> {
ret(c::unshare(flags.bits() as i32))
}

#[cfg(linux_kernel)]
#[cfg(all(linux_kernel, linux_raw_dep))]
#[inline]
pub(crate) fn capget(
header: &mut linux_raw_sys::general::__user_cap_header_struct,
Expand All @@ -369,7 +369,7 @@ pub(crate) fn capget(
}
}

#[cfg(linux_kernel)]
#[cfg(all(linux_kernel, linux_raw_dep))]
#[inline]
pub(crate) fn capset(
header: &mut linux_raw_sys::general::__user_cap_header_struct,
Expand Down Expand Up @@ -666,8 +666,9 @@ pub(crate) fn futex_waitv(
timeout: Option<&Timespec>,
clockid: ClockId,
) -> io::Result<usize> {
use crate::backend::c::clockid_t;
use futex::Wait as FutexWait;
use linux_raw_sys::general::__kernel_clockid_t as clockid_t;

syscall! {
fn futex_waitv(
waiters: *const FutexWait,
Expand Down
32 changes: 32 additions & 0 deletions src/fs/statx.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
use crate::fd::AsFd;
use crate::fs::AtFlags;
use crate::{backend, io, path};
#[cfg(any(linux_raw_dep, not(target_env = "musl")))]
use backend::c;
use bitflags::bitflags;

Expand Down Expand Up @@ -275,3 +276,34 @@ mod compat {
}
}
}

// These are the actual values for the constants, needed for the fallback implementation.
#[cfg(all(not(linux_raw_dep), target_env = "musl"))]
mod c {
pub const STATX_TYPE: u32 = 0x00000001;
pub const STATX_MODE: u32 = 0x00000002;
pub const STATX_NLINK: u32 = 0x00000004;
pub const STATX_UID: u32 = 0x00000008;
pub const STATX_GID: u32 = 0x00000010;
pub const STATX_ATIME: u32 = 0x00000020;
pub const STATX_MTIME: u32 = 0x00000040;
pub const STATX_CTIME: u32 = 0x00000080;
pub const STATX_INO: u32 = 0x00000100;
pub const STATX_SIZE: u32 = 0x00000200;
pub const STATX_BLOCKS: u32 = 0x00000400;
pub const STATX_BASIC_STATS: u32 = 0x000007ff;
pub const STATX_BTIME: u32 = 0x00000800;
pub const STATX_MNT_ID: u32 = 0x00001000;
pub const STATX_DIOALIGN: u32 = 0x00002000; // Deprecated, but here for completeness
pub const STATX_ALL: u32 = 0x00000fff; // Note: Doesn't include newer flags

pub const STATX_ATTR_COMPRESSED: u64 = 0x00000004;
pub const STATX_ATTR_IMMUTABLE: u64 = 0x00000010;
pub const STATX_ATTR_APPEND: u64 = 0x00000020;
pub const STATX_ATTR_NODUMP: u64 = 0x00000040;
pub const STATX_ATTR_ENCRYPTED: u64 = 0x00000800;
pub const STATX_ATTR_AUTOMOUNT: u64 = 0x00001000;
pub const STATX_ATTR_MOUNT_ROOT: u64 = 0x00020000;
pub const STATX_ATTR_VERITY: u64 = 0x00100000;
pub const STATX_ATTR_DAX: u64 = 0x00200000;
}
30 changes: 30 additions & 0 deletions src/ioctl/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -344,6 +344,36 @@ type _Opcode = c::c_uint;
#[cfg(windows)]
type _Opcode = i32;

/// Convenience macro for Rustix's ioctl write
#[macro_export]
macro_rules! ioctl_write_ptr {
($name:ident, $ioty:expr, $nr:expr, $ty:ty) => {
pub unsafe fn $name(fd: std::os::fd::BorrowedFd, data: &$ty) -> std::io::Result<()> {
const OPCODE: $crate::ioctl::Opcode =
$crate::ioctl::opcode::write::<$ty>($ioty as u8, $nr as u8);
Ok(rustix::ioctl::ioctl(
fd,
$crate::ioctl::Setter::<OPCODE, $ty>::new(*data),
)?)
}
};
}

/// Convenience macro for Rustix's ioctl read
#[macro_export]
macro_rules! ioctl_readwrite {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These seem like weird inclusions for the public API.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

so nix has them too:

https://github.com/nix-rust/nix/blob/master/src/sys/ioctl/mod.rs#L652

I know of two places that are duplicating this logic:

https://github.com/Smithay/drm-rs/blob/develop/drm-ffi/src/ioctl.rs#L6
https://github.com/magma-gpu/rutabaga_gfx/blob/main/third_party/mesa3d/src/magma/sys/linux/amdgpu.rs#L43 (the project I work on)

Anything particularly wrong with these APIs? Otherwise, people have to excessively define things like ioctl::Updater and ioctl::opcode::read_write.

($name:ident, $ioty:expr, $nr:expr, $ty:ty) => {
pub unsafe fn $name(fd: std::os::fd::BorrowedFd, data: &mut $ty) -> std::io::Result<()> {
const OPCODE: $crate::ioctl::Opcode =
$crate::ioctl::opcode::read_write::<$ty>($ioty as u8, $nr as u8);
Ok($crate::ioctl::ioctl(
fd,
$crate::ioctl::Updater::<OPCODE, $ty>::new(data),
)?)
}
};
}

#[cfg(linux_raw_dep)]
#[cfg(not(any(target_arch = "sparc", target_arch = "sparc64")))]
#[cfg(test)]
Expand Down
11 changes: 6 additions & 5 deletions src/thread/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,16 +6,16 @@ mod clock;
pub mod futex;
#[cfg(linux_kernel)]
mod id;
#[cfg(linux_kernel)]
#[cfg(all(linux_kernel, linux_raw_dep))]
mod libcap;
#[cfg(linux_kernel)]
mod membarrier;
#[cfg(linux_kernel)]
#[cfg(all(linux_kernel, linux_raw_dep))]
mod prctl;
#[cfg(any(freebsdlike, linux_kernel, target_os = "fuchsia"))]
mod sched;
mod sched_yield;
#[cfg(linux_kernel)]
#[cfg(all(linux_kernel, linux_raw_dep))]
mod setns;

#[cfg(not(target_os = "redox"))]
Expand All @@ -25,13 +25,14 @@ pub use id::*;
#[cfg(linux_kernel)]
// #[expect(deprecated, reason = "CapabilityFlags is deprecated")]
#[allow(deprecated)]
#[cfg(all(linux_kernel, linux_raw_dep))]
pub use libcap::{capabilities, set_capabilities, CapabilityFlags, CapabilitySet, CapabilitySets};
#[cfg(linux_kernel)]
pub use membarrier::*;
#[cfg(linux_kernel)]
#[cfg(all(linux_kernel, linux_raw_dep))]
pub use prctl::*;
#[cfg(any(freebsdlike, linux_kernel, target_os = "fuchsia"))]
pub use sched::*;
pub use sched_yield::sched_yield;
#[cfg(linux_kernel)]
#[cfg(all(linux_kernel, linux_raw_dep))]
pub use setns::*;
6 changes: 6 additions & 0 deletions subprojects/bitflags-2-rs.wrap
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
[wrap-file]
directory = bitflags-2.9.1
source_url = https://crates.io/api/v1/crates/bitflags/2.9.1/download
source_filename = bitflags-2.9.1.tar.gz
source_hash = 1b8e56985ec62d17e9c1001dc89c88ecd7dc08e47eba5ec7c29c7b5eeecde967
patch_directory = bitflags-2-rs
6 changes: 6 additions & 0 deletions subprojects/errno-0.3-rs.wrap
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
[wrap-file]
directory = errno-0.3.12
source_url = https://crates.io/api/v1/crates/errno/0.3.12/download
source_filename = errno-0.3.12.tar.gz
source_hash = cea14ef9355e3beab063703aa9dab15afd25f0667c341310c1e5274bb1d0da18
patch_directory = errno-0.3-rs
6 changes: 6 additions & 0 deletions subprojects/libc-0.2-rs.wrap
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
[wrap-file]
directory = libc-0.2.177
source_url = https://crates.io/api/v1/crates/libc/0.2.177/download
source_filename = libc-0.2.177.tar.gz
source_hash = 2874a2af47a2325c2001a6e6fad9b16a53b802102b528163885171cf92b15976
patch_directory = libc-0.2-rs
Loading
Loading