Skip to content

Commit 1595eea

Browse files
authored
Ensure Secs is 64-bit on sparc and android. (#742)
This is needed for y2038 compatibility. Factor out the predicate for replacing libc::time_t into a `fix_y2038` config, and add 32-bit sparc and android too it. Also, add a layout testcase for the `Timespec` type.
1 parent 2c99002 commit 1595eea

File tree

8 files changed

+138
-283
lines changed

8 files changed

+138
-283
lines changed

build.rs

Lines changed: 35 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -22,9 +22,10 @@ fn main() {
2222

2323
// Gather target information.
2424
let arch = var("CARGO_CFG_TARGET_ARCH").unwrap();
25+
let env = var("CARGO_CFG_TARGET_ENV").unwrap();
2526
let inline_asm_name = format!("{}/{}.rs", ASM_PATH, arch);
2627
let inline_asm_name_present = std::fs::metadata(inline_asm_name).is_ok();
27-
let target_os = var("CARGO_CFG_TARGET_OS").unwrap();
28+
let os = var("CARGO_CFG_TARGET_OS").unwrap();
2829
let pointer_width = var("CARGO_CFG_TARGET_POINTER_WIDTH").unwrap();
2930
let endian = var("CARGO_CFG_TARGET_ENDIAN").unwrap();
3031

@@ -59,15 +60,15 @@ fn main() {
5960
// For now Android uses the libc backend; in theory it could use the
6061
// linux_raw backend, but to do that we'll need to figure out how to
6162
// install the toolchain for it.
62-
if feature_use_libc
63+
let libc = feature_use_libc
6364
|| cfg_use_libc
64-
|| target_os != "linux"
65+
|| os != "linux"
6566
|| !inline_asm_name_present
6667
|| is_unsupported_abi
6768
|| miri
6869
|| ((arch == "powerpc64" || arch == "mips" || arch == "mips64")
69-
&& !rustix_use_experimental_asm)
70-
{
70+
&& !rustix_use_experimental_asm);
71+
if libc {
7172
// Use the libc backend.
7273
use_feature("libc");
7374
} else {
@@ -86,43 +87,52 @@ fn main() {
8687

8788
// Rust's libc crate groups some OS's together which have similar APIs;
8889
// create similarly-named features to make `cfg` tests more concise.
89-
if target_os == "freebsd" || target_os == "dragonfly" {
90+
let freebsdlike = os == "freebsd" || os == "dragonfly";
91+
if freebsdlike {
9092
use_feature("freebsdlike");
9193
}
92-
if target_os == "openbsd" || target_os == "netbsd" {
94+
let netbsdlike = os == "openbsd" || os == "netbsd";
95+
if netbsdlike {
9396
use_feature("netbsdlike");
9497
}
95-
if target_os == "macos" || target_os == "ios" || target_os == "tvos" || target_os == "watchos" {
98+
let apple = os == "macos" || os == "ios" || os == "tvos" || os == "watchos";
99+
if apple {
96100
use_feature("apple");
97101
}
98-
if target_os == "linux"
99-
|| target_os == "l4re"
100-
|| target_os == "android"
101-
|| target_os == "emscripten"
102-
{
102+
if os == "linux" || os == "l4re" || os == "android" || os == "emscripten" {
103103
use_feature("linux_like");
104104
}
105-
if target_os == "solaris" || target_os == "illumos" {
105+
if os == "solaris" || os == "illumos" {
106106
use_feature("solarish");
107107
}
108-
if target_os == "macos"
109-
|| target_os == "ios"
110-
|| target_os == "tvos"
111-
|| target_os == "watchos"
112-
|| target_os == "freebsd"
113-
|| target_os == "dragonfly"
114-
|| target_os == "openbsd"
115-
|| target_os == "netbsd"
116-
{
108+
if apple || freebsdlike || netbsdlike {
117109
use_feature("bsd");
118110
}
119111

120112
// Add some additional common target combinations.
121-
if target_os == "android" || target_os == "linux" {
113+
114+
// Android and "regular" Linux both use the Linux kernel.
115+
if os == "android" || os == "linux" {
122116
use_feature("linux_kernel");
123117
}
124118

125-
if target_os == "wasi" {
119+
// These platforms have a 32-bit `time_t`.
120+
if libc
121+
&& (arch == "arm"
122+
|| arch == "mips"
123+
|| arch == "sparc"
124+
|| arch == "x86"
125+
|| (arch == "wasm32" && os == "emscripten"))
126+
&& (apple
127+
|| os == "android"
128+
|| os == "emscripten"
129+
|| env == "gnu"
130+
|| (env == "musl" && arch == "x86"))
131+
{
132+
use_feature("fix_y2038");
133+
}
134+
135+
if os == "wasi" {
126136
use_feature_or_nothing("wasi_ext");
127137
}
128138

src/backend/libc/fs/syscalls.rs

Lines changed: 10 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -54,17 +54,11 @@ use crate::fs::{Mode, OFlags, SeekFrom, Stat};
5454
#[cfg(not(any(target_os = "haiku", target_os = "redox", target_os = "wasi")))]
5555
use crate::fs::{StatVfs, StatVfsMountFlags};
5656
use crate::io;
57-
#[cfg(all(
58-
any(target_arch = "arm", target_arch = "mips", target_arch = "x86"),
59-
target_env = "gnu",
60-
))]
57+
#[cfg(fix_y2038)]
6158
use crate::timespec::LibcTimespec;
6259
#[cfg(not(target_os = "wasi"))]
6360
use crate::ugid::{Gid, Uid};
64-
#[cfg(not(all(
65-
any(target_arch = "arm", target_arch = "mips", target_arch = "x86"),
66-
target_env = "gnu",
67-
)))]
61+
#[cfg(not(fix_y2038))]
6862
#[cfg(not(target_os = "espidf"))]
6963
use crate::utils::as_ptr;
7064
#[cfg(apple)]
@@ -83,15 +77,9 @@ use {
8377
core::ptr::null,
8478
};
8579

86-
#[cfg(all(
87-
any(target_arch = "arm", target_arch = "mips", target_arch = "x86"),
88-
target_env = "gnu",
89-
))]
80+
#[cfg(fix_y2038)]
9081
weak!(fn __utimensat64(c::c_int, *const c::c_char, *const LibcTimespec, c::c_int) -> c::c_int);
91-
#[cfg(all(
92-
any(target_arch = "arm", target_arch = "mips", target_arch = "x86"),
93-
target_env = "gnu",
94-
))]
82+
#[cfg(fix_y2038)]
9583
weak!(fn __futimens64(c::c_int, *const LibcTimespec) -> c::c_int);
9684

9785
/// Use a direct syscall (via libc) for `open`.
@@ -720,10 +708,7 @@ pub(crate) fn utimensat(
720708
) -> io::Result<()> {
721709
// 32-bit gnu version: libc has `utimensat` but it is not y2038 safe by
722710
// default.
723-
#[cfg(all(
724-
any(target_arch = "arm", target_arch = "mips", target_arch = "x86"),
725-
target_env = "gnu",
726-
))]
711+
#[cfg(fix_y2038)]
727712
unsafe {
728713
if let Some(libc_utimensat) = __utimensat64.get() {
729714
let libc_times: [LibcTimespec; 2] = [
@@ -744,13 +729,7 @@ pub(crate) fn utimensat(
744729

745730
// Main version: libc is y2038 safe and has `utimensat`. Or, the platform
746731
// is not y2038 safe and there's nothing practical we can do.
747-
#[cfg(not(any(
748-
apple,
749-
all(
750-
any(target_arch = "arm", target_arch = "mips", target_arch = "x86"),
751-
target_env = "gnu",
752-
)
753-
)))]
732+
#[cfg(not(any(apple, fix_y2038)))]
754733
unsafe {
755734
// Assert that `Timestamps` has the expected layout.
756735
let _ = core::mem::transmute::<Timestamps, [c::timespec; 2]>(times.clone());
@@ -879,10 +858,7 @@ pub(crate) fn utimensat(
879858
}
880859
}
881860

882-
#[cfg(all(
883-
any(target_arch = "arm", target_arch = "mips", target_arch = "x86"),
884-
target_env = "gnu",
885-
))]
861+
#[cfg(fix_y2038)]
886862
unsafe fn utimensat_old(
887863
dirfd: BorrowedFd<'_>,
888864
path: &CStr,
@@ -1374,10 +1350,7 @@ fn libc_statvfs_to_statvfs(from: c::statvfs) -> StatVfs {
13741350
#[cfg(not(target_os = "espidf"))]
13751351
pub(crate) fn futimens(fd: BorrowedFd<'_>, times: &Timestamps) -> io::Result<()> {
13761352
// 32-bit gnu version: libc has `futimens` but it is not y2038 safe by default.
1377-
#[cfg(all(
1378-
any(target_arch = "arm", target_arch = "mips", target_arch = "x86"),
1379-
target_env = "gnu",
1380-
))]
1353+
#[cfg(fix_y2038)]
13811354
unsafe {
13821355
if let Some(libc_futimens) = __futimens64.get() {
13831356
let libc_times: [LibcTimespec; 2] = [
@@ -1393,13 +1366,7 @@ pub(crate) fn futimens(fd: BorrowedFd<'_>, times: &Timestamps) -> io::Result<()>
13931366

13941367
// Main version: libc is y2038 safe and has `futimens`. Or, the platform
13951368
// is not y2038 safe and there's nothing practical we can do.
1396-
#[cfg(not(any(
1397-
apple,
1398-
all(
1399-
any(target_arch = "arm", target_arch = "mips", target_arch = "x86"),
1400-
target_env = "gnu",
1401-
)
1402-
)))]
1369+
#[cfg(not(any(apple, fix_y2038)))]
14031370
unsafe {
14041371
// Assert that `Timestamps` has the expected layout.
14051372
let _ = core::mem::transmute::<Timestamps, [c::timespec; 2]>(times.clone());
@@ -1445,10 +1412,7 @@ pub(crate) fn futimens(fd: BorrowedFd<'_>, times: &Timestamps) -> io::Result<()>
14451412
}
14461413
}
14471414

1448-
#[cfg(all(
1449-
any(target_arch = "arm", target_arch = "mips", target_arch = "x86"),
1450-
target_env = "gnu",
1451-
))]
1415+
#[cfg(fix_y2038)]
14521416
unsafe fn futimens_old(fd: BorrowedFd<'_>, times: &Timestamps) -> io::Result<()> {
14531417
let old_times = [
14541418
c::timespec {

src/backend/libc/fs/types.rs

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1087,10 +1087,16 @@ pub type FsWord = u32;
10871087
pub type FsWord = u64;
10881088

10891089
/// `__fsword_t`
1090-
// s390x uses `u32` for `statfs` entries, even though `__fsword_t` is `u64`.
1091-
#[cfg(all(target_os = "linux", target_arch = "s390x"))]
1090+
// s390x uses `u32` for `statfs` entries on glibc, even though `__fsword_t` is
1091+
// `u64`.
1092+
#[cfg(all(target_os = "linux", target_arch = "s390x", target_env = "gnu"))]
10921093
pub type FsWord = u32;
10931094

1095+
/// `__fsword_t`
1096+
// s390x uses `u64` for `statfs` entries on musl.
1097+
#[cfg(all(target_os = "linux", target_arch = "s390x", target_env = "musl"))]
1098+
pub type FsWord = u64;
1099+
10941100
/// `copyfile_state_t`—State for use with [`fcopyfile`].
10951101
///
10961102
/// [`fcopyfile`]: crate::fs::fcopyfile

src/backend/libc/thread/syscalls.rs

Lines changed: 15 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,7 @@ use crate::backend::conv::ret;
55
use crate::io;
66
#[cfg(not(target_os = "redox"))]
77
use crate::thread::{NanosleepRelativeResult, Timespec};
8-
#[cfg(all(
9-
any(target_arch = "arm", target_arch = "mips", target_arch = "x86"),
10-
target_env = "gnu",
11-
))]
8+
#[cfg(fix_y2038)]
129
use crate::timespec::LibcTimespec;
1310
use core::mem::MaybeUninit;
1411
#[cfg(linux_kernel)]
@@ -30,15 +27,10 @@ use {
3027
)))]
3128
use {crate::thread::ClockId, core::ptr::null_mut};
3229

33-
#[cfg(all(
34-
any(target_arch = "arm", target_arch = "mips", target_arch = "x86"),
35-
target_env = "gnu",
36-
))]
30+
#[cfg(fix_y2038)]
31+
#[cfg(not(target_os = "emscripten"))]
3732
weak!(fn __clock_nanosleep_time64(c::clockid_t, c::c_int, *const LibcTimespec, *mut LibcTimespec) -> c::c_int);
38-
#[cfg(all(
39-
any(target_arch = "arm", target_arch = "mips", target_arch = "x86"),
40-
target_env = "gnu",
41-
))]
33+
#[cfg(fix_y2038)]
4234
weak!(fn __nanosleep64(*const LibcTimespec, *mut LibcTimespec) -> c::c_int);
4335

4436
#[cfg(not(any(
@@ -58,10 +50,7 @@ pub(crate) fn clock_nanosleep_relative(id: ClockId, request: &Timespec) -> Nanos
5850

5951
// 32-bit gnu version: libc has `clock_nanosleep` but it is not y2038 safe
6052
// by default.
61-
#[cfg(all(
62-
any(target_arch = "arm", target_arch = "mips", target_arch = "x86"),
63-
target_env = "gnu",
64-
))]
53+
#[cfg(fix_y2038)]
6554
unsafe {
6655
let mut remain = MaybeUninit::<LibcTimespec>::uninit();
6756

@@ -84,10 +73,7 @@ pub(crate) fn clock_nanosleep_relative(id: ClockId, request: &Timespec) -> Nanos
8473
}
8574

8675
// Main version: libc is y2038 safe and has `clock_nanosleep`.
87-
#[cfg(not(all(
88-
any(target_arch = "arm", target_arch = "mips", target_arch = "x86"),
89-
target_env = "gnu",
90-
)))]
76+
#[cfg(not(fix_y2038))]
9177
unsafe {
9278
let mut remain = MaybeUninit::<Timespec>::uninit();
9379

@@ -101,10 +87,8 @@ pub(crate) fn clock_nanosleep_relative(id: ClockId, request: &Timespec) -> Nanos
10187
}
10288
}
10389

104-
#[cfg(all(
105-
any(target_arch = "arm", target_arch = "mips", target_arch = "x86"),
106-
target_env = "gnu",
107-
))]
90+
#[cfg(fix_y2038)]
91+
#[cfg(not(target_os = "emscripten"))]
10892
unsafe fn clock_nanosleep_relative_old(id: ClockId, request: &Timespec) -> NanosleepRelativeResult {
10993
let tv_sec = match request.tv_sec.try_into() {
11094
Ok(tv_sec) => tv_sec,
@@ -154,10 +138,7 @@ pub(crate) fn clock_nanosleep_absolute(id: ClockId, request: &Timespec) -> io::R
154138

155139
// 32-bit gnu version: libc has `clock_nanosleep` but it is not y2038 safe
156140
// by default.
157-
#[cfg(all(
158-
any(target_arch = "arm", target_arch = "mips", target_arch = "x86"),
159-
target_env = "gnu",
160-
))]
141+
#[cfg(fix_y2038)]
161142
{
162143
if let Some(libc_clock_nanosleep) = __clock_nanosleep_time64.get() {
163144
match unsafe {
@@ -177,20 +158,15 @@ pub(crate) fn clock_nanosleep_absolute(id: ClockId, request: &Timespec) -> io::R
177158
}
178159

179160
// Main version: libc is y2038 safe and has `clock_nanosleep`.
180-
#[cfg(not(all(
181-
any(target_arch = "arm", target_arch = "mips", target_arch = "x86"),
182-
target_env = "gnu",
183-
)))]
161+
#[cfg(not(fix_y2038))]
184162
match unsafe { c::clock_nanosleep(id as c::clockid_t, flags as _, request, null_mut()) } {
185163
0 => Ok(()),
186164
err => Err(io::Errno(err)),
187165
}
188166
}
189167

190-
#[cfg(all(
191-
any(target_arch = "arm", target_arch = "mips", target_arch = "x86"),
192-
target_env = "gnu",
193-
))]
168+
#[cfg(fix_y2038)]
169+
#[cfg(not(target_os = "emscripten"))]
194170
fn clock_nanosleep_absolute_old(id: ClockId, request: &Timespec) -> io::Result<()> {
195171
let flags = c::TIMER_ABSTIME;
196172

@@ -209,10 +185,7 @@ fn clock_nanosleep_absolute_old(id: ClockId, request: &Timespec) -> io::Result<(
209185
pub(crate) fn nanosleep(request: &Timespec) -> NanosleepRelativeResult {
210186
// 32-bit gnu version: libc has `nanosleep` but it is not y2038 safe by
211187
// default.
212-
#[cfg(all(
213-
any(target_arch = "arm", target_arch = "mips", target_arch = "x86"),
214-
target_env = "gnu",
215-
))]
188+
#[cfg(fix_y2038)]
216189
unsafe {
217190
let mut remain = MaybeUninit::<LibcTimespec>::uninit();
218191

@@ -230,10 +203,7 @@ pub(crate) fn nanosleep(request: &Timespec) -> NanosleepRelativeResult {
230203
}
231204

232205
// Main version: libc is y2038 safe and has `nanosleep`.
233-
#[cfg(not(all(
234-
any(target_arch = "arm", target_arch = "mips", target_arch = "x86"),
235-
target_env = "gnu",
236-
)))]
206+
#[cfg(not(fix_y2038))]
237207
unsafe {
238208
let mut remain = MaybeUninit::<Timespec>::uninit();
239209

@@ -245,10 +215,7 @@ pub(crate) fn nanosleep(request: &Timespec) -> NanosleepRelativeResult {
245215
}
246216
}
247217

248-
#[cfg(all(
249-
any(target_arch = "arm", target_arch = "mips", target_arch = "x86"),
250-
target_env = "gnu",
251-
))]
218+
#[cfg(fix_y2038)]
252219
unsafe fn nanosleep_old(request: &Timespec) -> NanosleepRelativeResult {
253220
let tv_sec = match request.tv_sec.try_into() {
254221
Ok(tv_sec) => tv_sec,

0 commit comments

Comments
 (0)