Description
The GNU libc (glibc) provides alternative 64bit entry points for many of the file and time related functions on 32bit platforms. For C programs these are activated by setting the -D_TIME_BITS=64
and -D_FILE_OFFSET_BITS=64
preprocessor flags. What happens is that all the relevant types (time_t
, blksize_t
, ...) are defined as 64bit integers and the called symbols are redirected from the standard 32-bit variant like gmtime
to a 64bit variant like __gmtime64
.
In many ways this is the same as -D_LARGEFILE_SOURCE
flag except that this will not add new types and symbols but replace the existing ones. Note that it is possible to use -D_LARGEFILE_SOURCE
and -D_FILE_OFFSET_BITS=64
at the same time.
For full 64bit time support on llnux you also need a kernel newer than 5.6, but the 64bit glibc functions should be safe to use anyway and no worse than the 32bit versions.
The 64bit time support is needed when building embedded linux systems on 32bit platforms that are expected to live for 10 to 15 years.
Activity
snogge commentedon Apr 25, 2023
I've submitted #3175 as a possible solution.
safinaskar commentedon May 10, 2023
If somebody needs something like crate libc, but without time32 and lfs problems, I suggest using crate rustix. You can read its code and see that rustix put a lot of effort to deal with time32 and lfs problems
snogge commentedon May 10, 2023
I can see how that would work if I control which crates I want to use. But I'm not designing these projects from scratch, I'm trying to build existing projects with plenty of dependencies that use the libc crate.
But if there is a way to drop rustix in as a replacement I'm all ears.
If it is not obvious: I don't know much about rust, I'm approaching this from a distro building perspective using the Yocto project.
nekopsykose commentedon May 10, 2023
regardless of whether rustix works or not, libc has to be fixed anyway (i.e. this is lacking platform support and a goal of
libc
), so that is more of an offtopic suggestion, even if it's what somebody wants to use for a usecase.lvella commentedon Jun 20, 2023
I think the sensible solution here is to simply use 64 bits version of these types in every platform that supports them. In this time and age, I think it makes no sense for Rust's
libc
to support 32 bitsoff_t
,time_t
, etc.It is not like we have to worry about not breaking a huge ecosystem of 30 years old code that assumes these types to be 32 bits, like they have to in C.
snogge commentedon Jun 21, 2023
Will this be part of the 0.3 release? I see a lot of talk about the same problem on musl.
JohnTitor commentedon Jun 21, 2023
cc @joshtriplett as you facilitate the libc 0.3 here: #3248
Amanieu commentedon Jun 21, 2023
The main concern here is compatibility with C code that we link to using FFI. If some C code uses
time_t
, we want to ensure that our FFI bindings in Rust use the same definition oftime_t
as the C code. The general policy for the libc crate is to match the behavior of C with no preprocessor options defined. In the case of musl 1.2 this would default to 64-bit time but for glibc it would default to 32-bit time.This is similar to the situation with 64-bit
off_t
: we default to 32-bitoff_t
but also expose LFS types and functions such asstat64
. This won't work for 64-bit time since there are no alternate type/function names, but one possible solution would be to expose the 64-bittime_t
types and functions under atime64
module.snogge commentedon Jun 22, 2023
I understand your concern. But won't that be just as big a problem if the library has been built with the 64-bit flags set even if that is not the default for that library?
I suspect that these flags will be set on a distro level on Linux. How would Rust applications that use libc handle that?
Note that as long as the C library does not use any of the affected types such as
time_t
in their ABI, there is no conflict.My usecase is an embedded linux distribution created with Yocto. Everything is built from source and I control all the compiler settings. I need to make any Rust app build against 64-bit libs, and right now it seems my only option is to patch all uses of libc. For this, I would be happy with a switch I could set globally but I can see how that is not usable by everyone.
Amanieu commentedon Jun 23, 2023
Unfortunately there is just no way for Rust to know what flags any particular C code was compiled with. My recommendation would be to expose the time64 APIs in a
time64
module, and only for glibc. Then Rust programs using thelibc
crate can choose which API to use depending on the flags use to compile the C code (e.g. using thecc
crate from build scripts).Most Rust programs will not interact with the
libc
crate directly though: most will use the standard library'sSystemTime
instead. This already supports 64-bit time APIs on glibc by calling symbols such as__clock_gettime64
directly.kanavin commentedon Aug 25, 2023
SystemTime and libc crate aren't using musl correctly either. I got the following on a 32 bit musl system after setting the system clock to 2040.
I didn't yet look into details of what is happening, but please take this seriously: rust simply can't be used on 32 bit systems as of today, not if you want them to keep working after 2038:
snogge commentedon Aug 25, 2023
Wouldn't using a
time64
module require source code changes to all users of thelibc
crate?Is there any way we can use a configuration option to the libc crate and make it use only 64bit time?
kanavin commentedon Aug 25, 2023
kanavin commentedon Aug 25, 2023
After some poking at musl code, I think it has the same ABI as as glibc: clock_gettime() is the 32 bit version, and if you want 64 bits, you must call into __clock_gettime64(). C headers would take care of this automatically, but rust won't use them, so 🤷
musl's version of _TIME_BITS define is _REDIR_TIME64, and it's set to 1 by default in its headers (unlike glibc where you need to opt into 64 bit time via externally set -DTIME_BITS=64).
20 remaining items
snogge commentedon Apr 22, 2024
I could update the PR to check the
CFLAGS
environment variable, but wouldn't that only work in distro-like builders? Most users wont haveCFLAGS
set in their environments. And the correct flags might not be inCFLAGS
anyway. The Yocto Projects puts them in theCC
variable.kanavin commentedon Apr 22, 2024
This is correct, CFLAGS is not the canonical place to put these, and I was confused about where yocto puts them. There are various way to prescribe what ends up in C preprocessor, e.g. environment variables with command line flags, Makefiles, per-project config includes etc.
That said, I would really appreciate at least having some environment variable that can be set by distro builders to force 64 bit time in rust libc in a complete system build. You can name it RUST_LIBC_USE_64BIT_TIME. We (the yocto project) willl take care of setting it as appropriate.
sdroege commentedon Apr 22, 2024
AFAICS the most user-friendly way would be to check the target triplet, and Linux distro version from build.rs and based on that and a table auto-detect the variant of
time_t
(andoff_t
) that should be used. Plus an override for the auto-detection.That probably won't work for Yocto though as there it's actually a configuration (can that be retrieved somehow easily?) and not a simple matter of checking a version.
snogge commentedon Apr 22, 2024
Isn't that what cargo is doing by passing the various CARGO_CFG variables? See the
is_gnu_time64_abi
function in build.rs.I don't think it is reasonable for the libc crate to carry a list of all distro/triplet combinations that should configure things one way or another. Auto-detect by cargo with a possibility to override sounds OK.
kanavin commentedon Apr 22, 2024
I'm also not keen on the hardcoded distro/version table idea. As far as I understand, the only remaining binary distro that has any interest at all in 32 bit computing (and fixing y2038 in it) is Debian. For yocto such auto-detection is not useful as it is a generator of custom distros, and especially if build.rs would try to read things in /etc to determine 'distro (and its version) it would make completely incorrect decisions.
is_gnu_time64_abi() as it is has two problems:
I'd consider not trying to guess this at all, and just setting from environment variable only, as an opt-in.
snogge commentedon Apr 23, 2024
The riscv32 variant does not look at the gnu_time64 config option, or does so in a safe way, so is_gnu_time_64 does not have to handle it.
An override to force either variant seems like a good idea to me.
snogge commentedon May 8, 2024
I've updated #3175 to handle the cases listed above.
RUST_LIBC_TIME_BITS
can be set to 32 to force 32-bittime_t
gnu_time64_abi
is not set forriscv32
.safinaskar commentedon Dec 8, 2024
Possible solution to "how to distinguish 32 and 64" problem: rust-lang/rfcs#3716 ("[RFC] Target Modifiers")
tgross35 commentedon Dec 13, 2024
As proposed, isn't this only for things that
rustc
is aware of via flags? I don't think it will know which time ABI is in use.safinaskar commentedon Apr 11, 2025
Discussion about off_t and time_t in 32-bit archs happens here right now: https://rust-lang.zulipchat.com/#narrow/channel/219381-t-libs/topic/Questions.20and.20polls.20about.20.60libc.60.201.2E0
martinetd commentedon Jun 13, 2025
Hi all, thank you for working on this issue.
I'm coming in late to the party and have read what I could find, but I'm not quite clear on the status of 64 bit time_t on 32bit arches.
On the libc 1.0 tracking I'm reading between the lines that it'd be ok to break the ABI for 1.0, so finishing the musl upgrade in #3068 and merging into the main branch would be acceptable (even if it won't actually yield any result until the actual libc 1.0 release)?
But the last bit of the zulipchat link said we might not want to wait for 1.0 because distros have been doing a lot of work around 64-bit time_t on 32bit arches, and concluded with adding libc 1.0 to the all-hands agenda, but as far as I understand the all-hands is over and I've not seen any recap or movement since (but then again it's only been a few weeks).
Has there been any sort of consensus?
My work isn't giving me quite enough time to be highly active on this, but our customers are asking about y2038 regularly and I'll be happy to lend a hand where I can reach -- alternatively if there's a known workaround I'd be more than happy to try, but I couldn't find any navigating this and related issues (for an axum web server running on armhf alpine -- this is our last component that hasn't supported 64 bit time for a while...)
Cheers