From 91e8eb3fef7e5780fed26229d3ca6a0f16d7329d Mon Sep 17 00:00:00 2001 From: Jonah Petri Date: Tue, 7 Dec 2021 16:57:52 -0500 Subject: [PATCH] uclibc support --- .cirrus.yml | 3 +++ Cargo.toml | 2 +- README.md | 1 + bors.toml | 1 + src/sys/mod.rs | 2 +- src/sys/personality.rs | 4 ++-- src/sys/ptrace/linux.rs | 7 ++++--- src/sys/resource.rs | 10 +++++----- src/sys/signal.rs | 16 ++++++++++++---- src/sys/socket/addr.rs | 4 ++-- src/sys/statfs.rs | 34 +++++++++++++++++++++++++++++----- src/sys/uio.rs | 8 ++++++-- src/time.rs | 1 - test/sys/mod.rs | 3 ++- test/sys/test_aio_drop.rs | 1 + test/test_fcntl.rs | 5 +++++ 16 files changed, 75 insertions(+), 27 deletions(-) diff --git a/.cirrus.yml b/.cirrus.yml index c6f4e0b2d2..6cf1b976fc 100644 --- a/.cirrus.yml +++ b/.cirrus.yml @@ -280,6 +280,9 @@ task: - name: OpenBSD x86_64 env: TARGET: x86_64-unknown-openbsd + - name: Linux armv7 uclibceabihf + env: + TARGET: armv7-unknown-linux-uclibceabihf setup_script: - rustup component add rust-src << : *BUILD diff --git a/Cargo.toml b/Cargo.toml index dbe05683dd..af70a78f4d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -27,7 +27,7 @@ targets = [ ] [dependencies] -libc = { git = "https://github.com/rust-lang/libc", rev = "e470e3b6a1f940e0024d40d3b79fc73fe29c7f17", features = [ "extra_traits" ] } +libc = { version = "0.2.113", features = [ "extra_traits" ] } bitflags = "1.1" cfg-if = "1.0" diff --git a/README.md b/README.md index a8759f1ce8..342e6a5d10 100644 --- a/README.md +++ b/README.md @@ -83,6 +83,7 @@ Tier 3: * x86_64-unknown-linux-gnux32 * x86_64-unknown-openbsd * x86_64-unknown-redox + * armv7-unknown-linux-uclibceabihf ## Minimum Supported Rust Version (MSRV) diff --git a/bors.toml b/bors.toml index 03810b7e8e..ee43cf2923 100644 --- a/bors.toml +++ b/bors.toml @@ -14,6 +14,7 @@ status = [ "Linux arm gnueabi", "Linux arm-musleabi", "Linux armv7 gnueabihf", + "Linux armv7 uclibceabihf", "Linux i686 musl", "Linux i686", "Linux mipsel", diff --git a/src/sys/mod.rs b/src/sys/mod.rs index 0bd0bc9f88..2fd2a698ba 100644 --- a/src/sys/mod.rs +++ b/src/sys/mod.rs @@ -2,7 +2,7 @@ #[cfg(any(target_os = "dragonfly", target_os = "freebsd", target_os = "ios", - target_os = "linux", + all(target_os = "linux", not(target_env = "uclibc")), target_os = "macos", target_os = "netbsd"))] feature! { diff --git a/src/sys/personality.rs b/src/sys/personality.rs index b15956c469..e64c906d1a 100644 --- a/src/sys/personality.rs +++ b/src/sys/personality.rs @@ -11,13 +11,13 @@ libc_bitflags! { ADDR_NO_RANDOMIZE; ADDR_LIMIT_32BIT; ADDR_LIMIT_3GB; - #[cfg(not(target_env = "musl"))] + #[cfg(not(any(target_env = "musl", target_env = "uclibc")))] FDPIC_FUNCPTRS; MMAP_PAGE_ZERO; READ_IMPLIES_EXEC; SHORT_INODE; STICKY_TIMEOUTS; - #[cfg(not(target_env = "musl"))] + #[cfg(not(any(target_env = "musl", target_env = "uclibc")))] UNAME26; WHOLE_SECONDS; } diff --git a/src/sys/ptrace/linux.rs b/src/sys/ptrace/linux.rs index fb6ff1996d..24152d7d5a 100644 --- a/src/sys/ptrace/linux.rs +++ b/src/sys/ptrace/linux.rs @@ -20,7 +20,8 @@ use libc::user_regs_struct; cfg_if! { if #[cfg(any(all(target_os = "linux", target_arch = "s390x"), - all(target_os = "linux", target_env = "gnu")))] { + all(target_os = "linux", target_env = "gnu"), + target_env = "uclibc"))] { #[doc(hidden)] pub type RequestType = ::libc::c_uint; } else { @@ -30,8 +31,8 @@ cfg_if! { } libc_enum!{ - #[cfg_attr(not(any(target_env = "musl", target_os = "android")), repr(u32))] - #[cfg_attr(any(target_env = "musl", target_os = "android"), repr(i32))] + #[cfg_attr(not(any(target_env = "musl", target_env = "uclibc", target_os = "android")), repr(u32))] + #[cfg_attr(any(target_env = "musl", target_env = "uclibc", target_os = "android"), repr(i32))] /// Ptrace Request enum defining the action to be taken. #[non_exhaustive] pub enum Request { diff --git a/src/sys/resource.rs b/src/sys/resource.rs index 7f2927b4a0..ba206aa208 100644 --- a/src/sys/resource.rs +++ b/src/sys/resource.rs @@ -7,9 +7,9 @@ pub use libc::rlim_t; use std::mem; cfg_if! { - if #[cfg(all(target_os = "linux", target_env = "gnu"))]{ + if #[cfg(all(target_os = "linux", any(target_env = "gnu", target_env = "uclibc")))]{ use libc::{__rlimit_resource_t, rlimit, RLIM_INFINITY}; - }else if #[cfg(any( + } else if #[cfg(any( target_os = "freebsd", target_os = "openbsd", target_os = "netbsd", @@ -199,9 +199,9 @@ pub fn getrlimit(resource: Resource) -> Result<(Option, Option)> let mut old_rlim = mem::MaybeUninit::::uninit(); cfg_if! { - if #[cfg(all(target_os = "linux", target_env = "gnu"))]{ + if #[cfg(all(target_os = "linux", any(target_env = "gnu", target_env = "uclibc")))]{ let res = unsafe { libc::getrlimit(resource as __rlimit_resource_t, old_rlim.as_mut_ptr()) }; - }else{ + } else { let res = unsafe { libc::getrlimit(resource as c_int, old_rlim.as_mut_ptr()) }; } } @@ -253,7 +253,7 @@ pub fn setrlimit( rlim_max: hard_limit.unwrap_or(RLIM_INFINITY), }; cfg_if! { - if #[cfg(all(target_os = "linux", target_env = "gnu"))]{ + if #[cfg(all(target_os = "linux", any(target_env = "gnu", target_env = "uclibc")))]{ let res = unsafe { libc::setrlimit(resource as __rlimit_resource_t, &new_rlim as *const rlimit) }; }else{ let res = unsafe { libc::setrlimit(resource as c_int, &new_rlim as *const rlimit) }; diff --git a/src/sys/signal.rs b/src/sys/signal.rs index 9750d89080..ddc02483ed 100644 --- a/src/sys/signal.rs +++ b/src/sys/signal.rs @@ -11,6 +11,7 @@ use std::str::FromStr; #[cfg(any(target_os = "dragonfly", target_os = "freebsd"))] use std::os::unix::io::RawFd; use std::ptr; +use cfg_if::cfg_if; #[cfg(not(any(target_os = "openbsd", target_os = "redox")))] #[cfg(any(feature = "aio", feature = "signal"))] @@ -420,10 +421,15 @@ pub const SIGPOLL : Signal = SIGIO; /// Alias for [`SIGSYS`] pub const SIGUNUSED : Signal = SIGSYS; -#[cfg(not(target_os = "redox"))] -type SaFlags_t = libc::c_int; -#[cfg(target_os = "redox")] -type SaFlags_t = libc::c_ulong; +cfg_if! { + if #[cfg(target_os = "redox")] { + type SaFlags_t = libc::c_ulong; + } else if #[cfg(target_env = "uclibc")] { + type SaFlags_t = libc::c_ulong; + } else { + type SaFlags_t = libc::c_int; + } +} } #[cfg(feature = "signal")] @@ -1046,6 +1052,8 @@ mod sigevent { SigevNotify::SigevThreadId{..} => libc::SIGEV_THREAD_ID, #[cfg(all(target_os = "linux", target_env = "gnu", not(target_arch = "mips")))] SigevNotify::SigevThreadId{..} => libc::SIGEV_THREAD_ID, + #[cfg(all(target_os = "linux", target_env = "uclibc"))] + SigevNotify::SigevThreadId{..} => libc::SIGEV_THREAD_ID, #[cfg(any(all(target_os = "linux", target_env = "musl"), target_arch = "mips"))] SigevNotify::SigevThreadId{..} => 4 // No SIGEV_THREAD_ID defined }; diff --git a/src/sys/socket/addr.rs b/src/sys/socket/addr.rs index 67e5d6c64f..e9fe70ee72 100644 --- a/src/sys/socket/addr.rs +++ b/src/sys/socket/addr.rs @@ -120,10 +120,10 @@ pub enum AddressFamily { #[cfg(any(target_os = "android", target_os = "linux"))] #[cfg_attr(docsrs, doc(cfg(all())))] Llc = libc::AF_LLC, - #[cfg(target_os = "linux")] + #[cfg(all(target_os = "linux",not(target_env = "uclibc")))] #[cfg_attr(docsrs, doc(cfg(all())))] Ib = libc::AF_IB, - #[cfg(target_os = "linux")] + #[cfg(all(target_os = "linux",not(target_env = "uclibc")))] #[cfg_attr(docsrs, doc(cfg(all())))] Mpls = libc::AF_MPLS, #[cfg(any(target_os = "android", target_os = "linux"))] diff --git a/src/sys/statfs.rs b/src/sys/statfs.rs index e46733e703..838ca3ac98 100644 --- a/src/sys/statfs.rs +++ b/src/sys/statfs.rs @@ -31,7 +31,9 @@ type fs_type_t = libc::c_ulong; type fs_type_t = libc::c_uint; #[cfg(all(target_os = "linux", target_env = "musl"))] type fs_type_t = libc::c_ulong; -#[cfg(all(target_os = "linux", not(any(target_arch = "s390x", target_env = "musl"))))] +#[cfg(all(target_os = "linux", target_env = "uclibc"))] +type fs_type_t = libc::c_int; +#[cfg(all(target_os = "linux", not(any(target_arch = "s390x", target_env = "musl", target_env = "uclibc"))))] type fs_type_t = libc::__fsword_t; /// Describes the file system type as known by the operating system. @@ -71,7 +73,7 @@ pub const EXT3_SUPER_MAGIC: FsType = FsType(libc::EXT3_SUPER_MAGIC as fs_type_t) #[cfg(all(target_os = "linux", not(target_env = "musl")))] #[allow(missing_docs)] pub const EXT4_SUPER_MAGIC: FsType = FsType(libc::EXT4_SUPER_MAGIC as fs_type_t); -#[cfg(all(target_os = "linux", not(target_env = "musl")))] +#[cfg(all(target_os = "linux", not(any(target_env = "musl", target_env = "uclibc"))))] #[allow(missing_docs)] pub const FUSE_SUPER_MAGIC: FsType = FsType(libc::FUSE_SUPER_MAGIC as fs_type_t); #[cfg(all(target_os = "linux", not(target_env = "musl")))] @@ -192,12 +194,19 @@ impl Statfs { } /// Optimal transfer block size - #[cfg(all(target_os = "linux", not(any(target_arch = "s390x", target_env = "musl"))))] + #[cfg(all(target_os = "linux", not(any(target_arch = "s390x", target_env = "musl", target_env = "uclibc"))))] #[cfg_attr(docsrs, doc(cfg(all())))] pub fn optimal_transfer_size(&self) -> libc::__fsword_t { self.0.f_bsize } + /// Optimal transfer block size + #[cfg(all(target_os = "linux", target_env = "uclibc"))] + #[cfg_attr(docsrs, doc(cfg(all())))] + pub fn optimal_transfer_size(&self) -> libc::c_int { + self.0.f_bsize + } + /// Optimal transfer block size #[cfg(target_os = "dragonfly")] #[cfg_attr(docsrs, doc(cfg(all())))] @@ -237,7 +246,15 @@ impl Statfs { /// Size of a block // f_bsize on linux: https://github.com/torvalds/linux/blob/master/fs/nfs/super.c#L471 - #[cfg(all(target_os = "linux", not(any(target_arch = "s390x", target_env = "musl"))))] + #[cfg(all(target_os = "linux", target_env = "uclibc"))] + #[cfg_attr(docsrs, doc(cfg(all())))] + pub fn block_size(&self) -> libc::c_int { + self.0.f_bsize + } + + /// Size of a block + // f_bsize on linux: https://github.com/torvalds/linux/blob/master/fs/nfs/super.c#L471 + #[cfg(all(target_os = "linux", not(any(target_arch = "s390x", target_env = "musl", target_env = "uclibc"))))] #[cfg_attr(docsrs, doc(cfg(all())))] pub fn block_size(&self) -> libc::__fsword_t { self.0.f_bsize @@ -286,7 +303,14 @@ impl Statfs { } /// Maximum length of filenames - #[cfg(all(target_os = "linux", not(any(target_arch = "s390x", target_env = "musl"))))] + #[cfg(all(target_os = "linux", target_env = "uclibc"))] + #[cfg_attr(docsrs, doc(cfg(all())))] + pub fn maximum_name_length(&self) -> libc::c_int { + self.0.f_namelen + } + + /// Maximum length of filenames + #[cfg(all(target_os = "linux", not(any(target_arch = "s390x", target_env = "musl", target_env = "uclibc"))))] #[cfg_attr(docsrs, doc(cfg(all())))] pub fn maximum_name_length(&self) -> libc::__fsword_t { self.0.f_namelen diff --git a/src/sys/uio.rs b/src/sys/uio.rs index 125c2e6c30..a1fc8e5fea 100644 --- a/src/sys/uio.rs +++ b/src/sys/uio.rs @@ -34,6 +34,8 @@ pub fn readv(fd: RawFd, iov: &mut [IoVec<&mut [u8]>]) -> Result { #[cfg_attr(docsrs, doc(cfg(all())))] pub fn pwritev(fd: RawFd, iov: &[IoVec<&[u8]>], offset: off_t) -> Result { + #[cfg(target_env = "uclibc")] + let offset = offset as libc::off64_t; // uclibc doesn't use off_t let res = unsafe { libc::pwritev(fd, iov.as_ptr() as *const libc::iovec, iov.len() as c_int, offset) }; @@ -52,6 +54,8 @@ pub fn pwritev(fd: RawFd, iov: &[IoVec<&[u8]>], #[cfg_attr(docsrs, doc(cfg(all())))] pub fn preadv(fd: RawFd, iov: &[IoVec<&mut [u8]>], offset: off_t) -> Result { + #[cfg(target_env = "uclibc")] + let offset = offset as libc::off64_t; // uclibc doesn't use off_t let res = unsafe { libc::preadv(fd, iov.as_ptr() as *const libc::iovec, iov.len() as c_int, offset) }; @@ -127,7 +131,7 @@ feature! { /// [ptrace]: ../ptrace/index.html /// [`IoVec`]: struct.IoVec.html /// [`RemoteIoVec`]: struct.RemoteIoVec.html -#[cfg(target_os = "linux")] +#[cfg(all(target_os = "linux", not(target_env = "uclibc")))] pub fn process_vm_writev( pid: crate::unistd::Pid, local_iov: &[IoVec<&[u8]>], @@ -162,7 +166,7 @@ pub fn process_vm_writev( /// [`ptrace`]: ../ptrace/index.html /// [`IoVec`]: struct.IoVec.html /// [`RemoteIoVec`]: struct.RemoteIoVec.html -#[cfg(any(target_os = "linux"))] +#[cfg(all(target_os = "linux", not(target_env = "uclibc")))] pub fn process_vm_readv( pid: crate::unistd::Pid, local_iov: &[IoVec<&mut [u8]>], diff --git a/src/time.rs b/src/time.rs index 01a8fd0024..6a385b90bd 100644 --- a/src/time.rs +++ b/src/time.rs @@ -237,7 +237,6 @@ pub fn clock_gettime(clock_id: ClockId) -> Result { #[cfg(not(any( target_os = "macos", target_os = "ios", - target_env = "uclibc", target_os = "redox", target_os = "hermit", )))] diff --git a/test/sys/mod.rs b/test/sys/mod.rs index 60904bd174..b059521f38 100644 --- a/test/sys/mod.rs +++ b/test/sys/mod.rs @@ -7,7 +7,7 @@ mod test_signal; // cases on DragonFly. #[cfg(any(target_os = "freebsd", target_os = "ios", - target_os = "linux", + all(target_os = "linux", not(target_env = "uclibc")), target_os = "macos", target_os = "netbsd"))] mod test_aio; @@ -28,6 +28,7 @@ mod test_termios; #[cfg(not(any(target_os = "redox", target_os = "fuchsia")))] mod test_ioctl; mod test_wait; +#[cfg(not(target_env = "uclibc"))] mod test_uio; #[cfg(any(target_os = "android", target_os = "linux"))] diff --git a/test/sys/test_aio_drop.rs b/test/sys/test_aio_drop.rs index 71a2183bc1..f9ff97af6c 100644 --- a/test/sys/test_aio_drop.rs +++ b/test/sys/test_aio_drop.rs @@ -4,6 +4,7 @@ #[test] #[should_panic(expected = "Dropped an in-progress AioCb")] #[cfg(all(not(target_env = "musl"), + not(target_env = "uclibc"), any(target_os = "linux", target_os = "ios", target_os = "macos", diff --git a/test/test_fcntl.rs b/test/test_fcntl.rs index b24a49eef5..95e224e2d4 100644 --- a/test/test_fcntl.rs +++ b/test/test_fcntl.rs @@ -30,6 +30,9 @@ use std::os::unix::fs; #[test] #[cfg(not(target_os = "redox"))] +// QEMU does not handle openat well enough to satisfy this test +// https://gitlab.com/qemu-project/qemu/-/issues/829 +#[cfg_attr(qemu, ignore)] fn test_openat() { const CONTENTS: &[u8] = b"abcd"; let mut tmp = NamedTempFile::new().unwrap(); @@ -357,6 +360,7 @@ mod linux_android { #[test] #[cfg(all(target_os = "linux", not(target_env = "musl")))] + #[cfg_attr(target_env = "uclibc", ignore)] // uclibc doesn't support OFD locks, but the test should still compile fn test_ofd_write_lock() { use nix::sys::stat::fstat; use std::mem; @@ -394,6 +398,7 @@ mod linux_android { #[test] #[cfg(all(target_os = "linux", not(target_env = "musl")))] + #[cfg_attr(target_env = "uclibc", ignore)] // uclibc doesn't support OFD locks, but the test should still compile fn test_ofd_read_lock() { use nix::sys::stat::fstat; use std::mem;