diff --git a/libc-test/tests/windows_time.rs b/libc-test/tests/windows_time.rs new file mode 100644 index 0000000000000..9b71fffde8de0 --- /dev/null +++ b/libc-test/tests/windows_time.rs @@ -0,0 +1,26 @@ +//! Ensures Windows `time`-related routines align with `libc`'s interface. By +//! default, both MSVC and GNU (under `mingw`) expose 64-bit symbols, but in +//! stable we need to cope with a 32-bit `time-t`, so the routines should link +//! to their 32-bit variants. + +#![cfg(windows)] + +/// Ensures a 64-bit write is performed on values that should always be 64 bits, +/// and that a corresponding 32-bit write is performed on values that should be +/// 32 bits. This basically makes sure `time_t`'s bit-width aligns with those of +/// functions that expect it as a parameter. +#[test] +fn test_bitwidth_store() { + #[cfg(all(target_arch = "x86", target_env = "gnu"))] + assert_eq!(size_of::(), 4); + #[cfg(not(all(target_arch = "x86", target_env = "gnu")))] + assert_eq!(size_of::(), 8); + + let mut time_values: [libc::time_t; 2] = [123, 456]; + let ptr = time_values.as_mut_ptr(); + + unsafe { libc::time(ptr) }; + + assert!(time_values[0] != 123); + assert_eq!(time_values[1], 456); +} diff --git a/src/windows/mod.rs b/src/windows/mod.rs index 2cfd1977d2799..bab730c7b1a19 100644 --- a/src/windows/mod.rs +++ b/src/windows/mod.rs @@ -390,10 +390,6 @@ extern "C" { pub fn raise(signum: c_int) -> c_int; pub fn clock() -> clock_t; - pub fn ctime(sourceTime: *const time_t) -> *mut c_char; - pub fn difftime(timeEnd: time_t, timeStart: time_t) -> c_double; - #[link_name = "_gmtime64_s"] - pub fn gmtime_s(destTime: *mut tm, srcTime: *const time_t) -> c_int; #[link_name = "_get_daylight"] pub fn get_daylight(hours: *mut c_int) -> errno_t; #[link_name = "_get_dstbias"] @@ -407,10 +403,6 @@ extern "C" { size_in_bytes: size_t, index: c_int, ) -> errno_t; - #[link_name = "_localtime64_s"] - pub fn localtime_s(tmDest: *mut tm, sourceTime: *const time_t) -> crate::errno_t; - #[link_name = "_time64"] - pub fn time(destTime: *mut time_t) -> time_t; #[link_name = "_tzset"] pub fn tzset(); #[link_name = "_chmod"] @@ -549,6 +541,33 @@ extern "C" { ) -> crate::errno_t; } +// By default, the following link to 64-bit variants where the expected `time_t` +// is also 64-bits. +#[cfg(not(all(target_arch = "x86", target_env = "gnu")))] +extern "C" { + pub fn ctime(sourceTime: *const time_t) -> *mut c_char; + pub fn difftime(timeEnd: time_t, timeStart: time_t) -> c_double; + pub fn gmtime_s(destTime: *mut tm, srcTime: *const time_t) -> c_int; + pub fn localtime_s(tmDest: *mut tm, sourceTime: *const time_t) -> crate::errno_t; + pub fn time(destTime: *mut time_t) -> time_t; +} + +// Under Windows x86 with GNU, `time_t` is still 32-bit wide on stable, so the +// above routines have to link with their 32-bit variants. +#[cfg(all(target_arch = "x86", target_env = "gnu"))] +extern "C" { + #[link_name = "_ctime32"] + pub fn ctime(sourceTime: *const time_t) -> *mut c_char; + #[link_name = "_difftime32"] + pub fn difftime(timeEnd: time_t, timeStart: time_t) -> c_double; + #[link_name = "_gmtime32_s"] + pub fn gmtime_s(destTime: *mut tm, srcTime: *const time_t) -> c_int; + #[link_name = "_localtime32_s"] + pub fn localtime_s(tmDest: *mut tm, sourceTime: *const time_t) -> crate::errno_t; + #[link_name = "_time32"] + pub fn time(destTime: *mut time_t) -> time_t; +} + extern "system" { pub fn listen(s: SOCKET, backlog: c_int) -> c_int; pub fn accept(s: SOCKET, addr: *mut crate::sockaddr, addrlen: *mut c_int) -> SOCKET;