Skip to content

Commit 676a29c

Browse files
authored
Avoid using glibc-style time64 functions on non-glibc platforms. (#745)
Following up on #742, this avoids using the glibc weak references on non-glibc platforms, and fixes the y2038 support on Android.
1 parent a86efbc commit 676a29c

File tree

4 files changed

+322
-245
lines changed

4 files changed

+322
-245
lines changed

build.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,7 @@ fn main() {
126126
&& (apple
127127
|| os == "android"
128128
|| os == "emscripten"
129+
|| os == "haiku"
129130
|| env == "gnu"
130131
|| (env == "musl" && arch == "x86"))
131132
{

src/backend/libc/fs/syscalls.rs

Lines changed: 47 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -54,13 +54,10 @@ 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(fix_y2038)]
57+
#[cfg(all(target_env = "gnu", fix_y2038))]
5858
use crate::timespec::LibcTimespec;
5959
#[cfg(not(target_os = "wasi"))]
6060
use crate::ugid::{Gid, Uid};
61-
#[cfg(not(fix_y2038))]
62-
#[cfg(not(target_os = "espidf"))]
63-
use crate::utils::as_ptr;
6461
#[cfg(apple)]
6562
use alloc::vec;
6663
use core::mem::MaybeUninit;
@@ -77,9 +74,9 @@ use {
7774
core::ptr::null,
7875
};
7976

80-
#[cfg(fix_y2038)]
77+
#[cfg(all(target_env = "gnu", fix_y2038))]
8178
weak!(fn __utimensat64(c::c_int, *const c::c_char, *const LibcTimespec, c::c_int) -> c::c_int);
82-
#[cfg(fix_y2038)]
79+
#[cfg(all(target_env = "gnu", fix_y2038))]
8380
weak!(fn __futimens64(c::c_int, *const LibcTimespec) -> c::c_int);
8481

8582
/// Use a direct syscall (via libc) for `open`.
@@ -706,31 +703,36 @@ pub(crate) fn utimensat(
706703
times: &Timestamps,
707704
flags: AtFlags,
708705
) -> io::Result<()> {
709-
// 32-bit gnu version: libc has `utimensat` but it is not y2038 safe by
710-
// default.
706+
// Old 32-bit version: libc has `utimensat` but it is not y2038 safe by
707+
// default. But there may be a `__utimensat16` we can use.
711708
#[cfg(fix_y2038)]
712-
unsafe {
709+
{
710+
#[cfg(target_env = "gnu")]
713711
if let Some(libc_utimensat) = __utimensat64.get() {
714712
let libc_times: [LibcTimespec; 2] = [
715713
times.last_access.clone().into(),
716714
times.last_modification.clone().into(),
717715
];
718716

719-
ret(libc_utimensat(
720-
borrowed_fd(dirfd),
721-
c_str(path),
722-
libc_times.as_ptr(),
723-
bitflags_bits!(flags),
724-
))
725-
} else {
726-
utimensat_old(dirfd, path, times, flags)
717+
unsafe {
718+
return ret(libc_utimensat(
719+
borrowed_fd(dirfd),
720+
c_str(path),
721+
libc_times.as_ptr(),
722+
bitflags_bits!(flags),
723+
));
724+
}
727725
}
726+
727+
utimensat_old(dirfd, path, times, flags)
728728
}
729729

730730
// Main version: libc is y2038 safe and has `utimensat`. Or, the platform
731731
// is not y2038 safe and there's nothing practical we can do.
732732
#[cfg(not(any(apple, fix_y2038)))]
733733
unsafe {
734+
use crate::utils::as_ptr;
735+
734736
// Assert that `Timestamps` has the expected layout.
735737
let _ = core::mem::transmute::<Timestamps, [c::timespec; 2]>(times.clone());
736738

@@ -742,9 +744,11 @@ pub(crate) fn utimensat(
742744
))
743745
}
744746

745-
// `utimensat` was introduced in macOS 10.13.
747+
// Apple version: `utimensat` was introduced in macOS 10.13.
746748
#[cfg(apple)]
747749
unsafe {
750+
use crate::utils::as_ptr;
751+
748752
// ABI details
749753
weak! {
750754
fn utimensat(
@@ -859,7 +863,7 @@ pub(crate) fn utimensat(
859863
}
860864

861865
#[cfg(fix_y2038)]
862-
unsafe fn utimensat_old(
866+
fn utimensat_old(
863867
dirfd: BorrowedFd<'_>,
864868
path: &CStr,
865869
times: &Timestamps,
@@ -883,12 +887,14 @@ unsafe fn utimensat_old(
883887
tv_nsec: times.last_modification.tv_nsec,
884888
},
885889
];
886-
ret(c::utimensat(
887-
borrowed_fd(dirfd),
888-
c_str(path),
889-
old_times.as_ptr(),
890-
bitflags_bits!(flags),
891-
))
890+
unsafe {
891+
ret(c::utimensat(
892+
borrowed_fd(dirfd),
893+
c_str(path),
894+
old_times.as_ptr(),
895+
bitflags_bits!(flags),
896+
))
897+
}
892898
}
893899

894900
#[cfg(not(target_os = "wasi"))]
@@ -1349,34 +1355,42 @@ fn libc_statvfs_to_statvfs(from: c::statvfs) -> StatVfs {
13491355

13501356
#[cfg(not(target_os = "espidf"))]
13511357
pub(crate) fn futimens(fd: BorrowedFd<'_>, times: &Timestamps) -> io::Result<()> {
1352-
// 32-bit gnu version: libc has `futimens` but it is not y2038 safe by default.
1358+
// Old 32-bit version: libc has `futimens` but it is not y2038 safe by
1359+
// default. But there may be a `__futimens64` we can use.
13531360
#[cfg(fix_y2038)]
1354-
unsafe {
1361+
{
1362+
#[cfg(target_env = "gnu")]
13551363
if let Some(libc_futimens) = __futimens64.get() {
13561364
let libc_times: [LibcTimespec; 2] = [
13571365
times.last_access.clone().into(),
13581366
times.last_modification.clone().into(),
13591367
];
13601368

1361-
ret(libc_futimens(borrowed_fd(fd), libc_times.as_ptr()))
1362-
} else {
1363-
futimens_old(fd, times)
1369+
unsafe {
1370+
return ret(libc_futimens(borrowed_fd(fd), libc_times.as_ptr()));
1371+
}
13641372
}
1373+
1374+
futimens_old(fd, times)
13651375
}
13661376

13671377
// Main version: libc is y2038 safe and has `futimens`. Or, the platform
13681378
// is not y2038 safe and there's nothing practical we can do.
13691379
#[cfg(not(any(apple, fix_y2038)))]
13701380
unsafe {
1381+
use crate::utils::as_ptr;
1382+
13711383
// Assert that `Timestamps` has the expected layout.
13721384
let _ = core::mem::transmute::<Timestamps, [c::timespec; 2]>(times.clone());
13731385

13741386
ret(c::futimens(borrowed_fd(fd), as_ptr(times).cast()))
13751387
}
13761388

1377-
// `futimens` was introduced in macOS 10.13.
1389+
// Apple version: `futimens` was introduced in macOS 10.13.
13781390
#[cfg(apple)]
13791391
unsafe {
1392+
use crate::utils::as_ptr;
1393+
13801394
// ABI details.
13811395
weak! {
13821396
fn futimens(c::c_int, *const c::timespec) -> c::c_int
@@ -1413,7 +1427,7 @@ pub(crate) fn futimens(fd: BorrowedFd<'_>, times: &Timestamps) -> io::Result<()>
14131427
}
14141428

14151429
#[cfg(fix_y2038)]
1416-
unsafe fn futimens_old(fd: BorrowedFd<'_>, times: &Timestamps) -> io::Result<()> {
1430+
fn futimens_old(fd: BorrowedFd<'_>, times: &Timestamps) -> io::Result<()> {
14171431
let old_times = [
14181432
c::timespec {
14191433
tv_sec: times
@@ -1433,7 +1447,7 @@ unsafe fn futimens_old(fd: BorrowedFd<'_>, times: &Timestamps) -> io::Result<()>
14331447
},
14341448
];
14351449

1436-
ret(c::futimens(borrowed_fd(fd), old_times.as_ptr()))
1450+
unsafe { ret(c::futimens(borrowed_fd(fd), old_times.as_ptr())) }
14371451
}
14381452

14391453
#[cfg(not(any(

0 commit comments

Comments
 (0)