diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 58ab02e02..8b02189db 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -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 < 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 < 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 diff --git a/meson.build b/meson.build new file mode 100644 index 000000000..521cfa609 --- /dev/null +++ b/meson.build @@ -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, +) diff --git a/src/backend/libc/c.rs b/src/backend/libc/c.rs index 5eeff953f..c9819520a 100644 --- a/src/backend/libc/c.rs +++ b/src/backend/libc/c.rs @@ -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( diff --git a/src/backend/libc/fs/syscalls.rs b/src/backend/libc/fs/syscalls.rs index 8cbd3a2c1..f5cd9a86e 100644 --- a/src/backend/libc/fs/syscalls.rs +++ b/src/backend/libc/fs/syscalls.rs @@ -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); } diff --git a/src/backend/libc/thread/futex.rs b/src/backend/libc/thread/futex.rs index 5e836a9ab..5e38222e7 100644 --- a/src/backend/libc/thread/futex.rs +++ b/src/backend/libc/thread/futex.rs @@ -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`]. /// @@ -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; /// const _ = !0; } @@ -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; diff --git a/src/backend/libc/thread/syscalls.rs b/src/backend/libc/thread/syscalls.rs index 84356fee4..2649ce5e2 100644 --- a/src/backend/libc/thread/syscalls.rs +++ b/src/backend/libc/thread/syscalls.rs @@ -341,13 +341,13 @@ pub(crate) fn setns(fd: BorrowedFd<'_>, nstype: c::c_int) -> io::Result 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, @@ -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, @@ -666,8 +666,9 @@ pub(crate) fn futex_waitv( timeout: Option<&Timespec>, clockid: ClockId, ) -> io::Result { + 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, diff --git a/src/fs/statx.rs b/src/fs/statx.rs index f8be29f7d..ac858f916 100644 --- a/src/fs/statx.rs +++ b/src/fs/statx.rs @@ -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; @@ -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; +} diff --git a/src/ioctl/mod.rs b/src/ioctl/mod.rs index 70c690530..b6d8fe423 100644 --- a/src/ioctl/mod.rs +++ b/src/ioctl/mod.rs @@ -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::::new(*data), + )?) + } + }; +} + +/// Convenience macro for Rustix's ioctl read +#[macro_export] +macro_rules! ioctl_readwrite { + ($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::::new(data), + )?) + } + }; +} + #[cfg(linux_raw_dep)] #[cfg(not(any(target_arch = "sparc", target_arch = "sparc64")))] #[cfg(test)] diff --git a/src/thread/mod.rs b/src/thread/mod.rs index 26d1de427..b5e7e844a 100644 --- a/src/thread/mod.rs +++ b/src/thread/mod.rs @@ -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"))] @@ -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::*; diff --git a/subprojects/bitflags-2-rs.wrap b/subprojects/bitflags-2-rs.wrap new file mode 100644 index 000000000..75f73f9ef --- /dev/null +++ b/subprojects/bitflags-2-rs.wrap @@ -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 diff --git a/subprojects/errno-0.3-rs.wrap b/subprojects/errno-0.3-rs.wrap new file mode 100644 index 000000000..92ccf9706 --- /dev/null +++ b/subprojects/errno-0.3-rs.wrap @@ -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 diff --git a/subprojects/libc-0.2-rs.wrap b/subprojects/libc-0.2-rs.wrap new file mode 100644 index 000000000..dccc394c2 --- /dev/null +++ b/subprojects/libc-0.2-rs.wrap @@ -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 diff --git a/subprojects/packagefiles/bitflags-2-rs/meson.build b/subprojects/packagefiles/bitflags-2-rs/meson.build new file mode 100644 index 000000000..e9a6007af --- /dev/null +++ b/subprojects/packagefiles/bitflags-2-rs/meson.build @@ -0,0 +1,21 @@ +# Copyright © 2026 Google +# SPDX-License-Identifier: MIT + +project( + 'bitflags', + 'rust', + version : '2.9.1', + license : 'MIT OR Apache-2.0', + meson_version : '>= 1.3.0', +) + +lib = static_library( + 'bitflags', + 'src/lib.rs', + override_options : ['rust_std=2021', 'build.rust_std=2021', 'warning_level=0'], + rust_abi : 'rust', +) + +dep_bitflags = declare_dependency( + link_with : [lib] +) diff --git a/subprojects/packagefiles/errno-0.3-rs/meson.build b/subprojects/packagefiles/errno-0.3-rs/meson.build new file mode 100644 index 000000000..2f853656f --- /dev/null +++ b/subprojects/packagefiles/errno-0.3-rs/meson.build @@ -0,0 +1,28 @@ +# Copyright © 2026 Google +# SPDX-License-Identifier: MIT + +project( + 'errno', + 'rust', + version : '0.3.12', + license : 'MIT OR Apache-2.0', + meson_version : '>= 1.3.0', +) + +os_deps = [] +libc = subproject('libc-0.2-rs').get_variable('lib') +if host_machine.system() == 'windows' + os_deps += subproject('windows-sys-0.6-rs').get_variable('lib') +endif + +lib = static_library( + 'libc_errno', + 'src/lib.rs', + override_options : ['rust_std=2018', 'build.rust_std=2018', 'warning_level=0'], + link_with: [libc] + os_deps, + rust_abi : 'rust', +) + +dep_errno = declare_dependency( + link_with : [lib] +) diff --git a/subprojects/packagefiles/libc-0.2-rs/meson.build b/subprojects/packagefiles/libc-0.2-rs/meson.build new file mode 100644 index 000000000..cfc50f148 --- /dev/null +++ b/subprojects/packagefiles/libc-0.2-rs/meson.build @@ -0,0 +1,44 @@ +# Copyright © 2026 Google +# SPDX-License-Identifier: MIT + +project( + 'libc', + 'rust', + version : '0.2.177', + license : 'MIT OR Apache-2.0', + meson_version : '>= 1.3.0', +) + +libc_args = [ + '--cfg', 'feature="default"', + '--cfg', 'feature="extra_traits"', + '--cfg', 'feature="std"', + '--cfg', 'freebsd11', + '--cfg', 'freebsd11', + '--cfg', 'freebsd11', + '--cfg', 'libc_align', + '--cfg', 'libc_cfg_target_vendor', + '--cfg', 'libc_const_extern_fn', + '--cfg', 'libc_const_size_of', + '--cfg', 'libc_core_cvoid', + '--cfg', 'libc_int128', + '--cfg', 'libc_long_array', + '--cfg', 'libc_non_exhaustive', + '--cfg', 'libc_packedN', + '--cfg', 'libc_priv_mod_use', + '--cfg', 'libc_ptr_addr_of', + '--cfg', 'libc_underscore_const_names', + '--cfg', 'libc_union', +] + +lib = static_library( + 'libc', + 'src/lib.rs', + rust_abi : 'rust', + override_options : ['rust_std=2021', 'build.rust_std=2021', 'warning_level=0'], + rust_args: libc_args, +) + +dep_libc = declare_dependency( + link_with : [lib] +)