Skip to content

time_t is the wrong size on 32bit linux #4307

Closed as duplicate of#1848
Closed as duplicate of#1848
@WhyNotHugo

Description

@WhyNotHugo

On almost all 32bit platforms, this crate defines time_t = i32: https://docs.rs/libc/0.2.170/src/libc/unix/linux_like/linux/gnu/b64/mod.rs.html#19

At least on Linux/musl, libc defines time_t = i64: https://git.musl-libc.org/cgit/musl/tree/include/alltypes.h.in#n12

See also: https://musl.libc.org/time64.html

Examples

The following sample compiles in 64bit but does not compile on 32bit:

fn main() {
    let tv_sec: i64 = 1741340955;
    let mut tm = unsafe { std::mem::zeroed() };

    if unsafe { libc::localtime_r(&tv_sec, &mut tm) }.is_null() {
        panic!("Failed to determine local time via localtime_r");
    }

    println!(
        "Today is {}-{:02}-{:02}",
        tm.tm_year + 1900,
        tm.tm_mon + 1,
        tm.tm_mday
    );
}

The equivalent C code, compiles and produces the correct result on both 64bit and 32bit:

int main() {
    int64_t tv_sec = 1741340955;
    struct tm tm;

    if (localtime_r(&tv_sec, &tm) == NULL) {
        perror("Failed to determine local time via localtime_r");
        exit(EXIT_FAILURE);
    }

    printf("Today is %d-%02d-%02d\n",
           tm.tm_year + 1900,
           tm.tm_mon + 1,
           tm.tm_mday);

    return 0;
}

Context

This becomes a problem when using other crates which interact with the same underlying type from libc (the implementation itself, not the libc crate).

The following works fine on 64bit:

    let Timespec { tv_sec, tv_nsec } = rustix::clock_gettime(ClockId::Realtime);

    // SAFETY: This is safe as long as tm is fully overwritten before use, which localtime_r does.
    let mut tm = unsafe { std::mem::zeroed() };
    // SAFETY: localtime_r is called with a valid pointer to secs and a mutable reference to tm.
    if unsafe { localtime_r(&tv_sec, &mut tm) }.is_null() {
        bail!("Failed to determine local time via localtime_r");
    }

But on 32bit platforms it fails with:

error[E0308]: mismatched types
    --> src/paths.rs:44:29
     |
44   |     if unsafe { localtime_r(&tv_sec, &mut tm) }.is_null() {
     |                 ----------- ^^^^^^^ expected `*const i32`, found `&i64`
     |                 |
     |                 arguments to this function are incorrect
     |
     = note: expected raw pointer `*const i32`
                  found reference `&i64`
note: function defined here
    --> /home/buildozer/.cargo/registry/src/index.crates.io-1cd66030c949c28d/libc-0.2.170/src/unix/mod.rs:1328:12
     |
1328 |     pub fn localtime_r(time_p: *const time_t, result: *mut tm) -> *mut tm;
     |            ^^^^^^^^^^^

Metadata

Metadata

Assignees

No one assigned

    Labels

    C-bugCategory: bug

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions