4 ms·
I test for these things when building open source software. • 64-bit compiles and applications have a 64-bit time_t in Linux. If your distro and binaries are
by strenholme 5y ago
I test for these things when building open source software.
• 64-bit compiles and applications have a 64-bit time_t in Linux. If your distro and binaries are 64-bit, there isn’t a problem.
• 32-bit compiles and applications still have a 32-bit time_t in mainstream Linux libraries, so that old binaries still run. The timestamp is a rolling one; once Y2038 is hit, the timestamp will be a negative one, but one which is updated and is off by 136 years. The workaround is code like this (this is real production code in my Lua fork, Lunacy[1]):
time_t t;
int64_t tt;
if (lua_isnoneornil(L, 1)) /* called without args? */
t = time(NULL); /* get current time */
else {
// Lunacy only supports getting the current time
lua_pushnil(L);
return 1;
}
if(t < -1) {
tt = (int64_t)t + 4294967296ULL;
} else {
tt = (int64_t)t;
}
if (t == (time_t)(-1))
lua_pushnil(L);
else
lua_pushnumber(L, (lua_Number)tt);
return 1;
This gives us accurate timestamps until 2106. If post 2106 compatibility is needed, we can add 2 ^ 32 again for timestamps with a positive value once the Y2038 rollover happens.
• Legacy 32-bit Windows applications using the Posix compatibility layer are not Y2038 compliant. Once Y2038 hits us, the timestamp will always return -1 (in Windows XP, the behavior was to return a number off by 136 years, but this changed in Windows 10). The workaround is to use Windows’ proprietary API for post-Y2038 timestamps. Again, from Lunacy which has a Win32 port:
/* Convert Windows "filetime" in to Lua number */
uint64_t t;
FILETIME win_time = { 0, 0 };
GetSystemTimeAsFileTime(&win_time);
t = win_time.dwHighDateTime & 0xffffffff;
t <<= 32;
t |= (win_time.dwLowDateTime & 0xffffffff);
t /= 10000000;
t -= 11644473600LL;
lua_pushnumber(L, (lua_Number)t);
return 1;
Now, last time I researched this, there wasn’t a “int64_t time_64bit()” style system call in the Linux API so that newly compiled 32-bit binaries can be Y2038 compliant without breaking the ABI by using “time_64bit()” instead of “time()”. This was based on some digging around Stackoverflow just last year, and simple Google searches are still not returning pages saying, in big bold letters “-D_TIME_BITS=64 when building 32-bit apps”.
https://sourceware.org/glibc/wiki/Y2038ProofnessDesign https://sourceware.org/glibc/wiki/Y2038ProofnessDesign talks about 64-bit support on 32-bit systems as if it’s a future pipe dream, but apparently -D_TIME_BITS=64 works right now.
[1] https://github.com/samboy/lunacy https://github.com/samboy/lunacy
[2] https://en.wikipedia.org/wiki/Time_in_Indiana https://en.wikipedia.org/wiki/Time_in_Indiana
[3] To ruin a classic sadistic interview question for sys admin roles, Linux these days returns both the modification time and the mostly useless “status change” timestamp. Facebook once decided to not move forward because I said that file timestamp was “modification time” and not “status change”; if Facebook is still asking that question, their knowledge is out of date.