-
-
Notifications
You must be signed in to change notification settings - Fork 828
Description
Borg has still some support code for 32bit timestamps (but also supports 64bit timestamps). The remaining question was whether we can get rid of the 32bit compatibility code.
This is also mentioned in #6602, but let's focus on that here exclusively.
I had an exchange with claude.ai, see below:
Y2038 and BorgBackup: Summary
What is Y2038?
The Y2038 problem affects systems that store Unix timestamps as 32-bit signed integers.
These overflow on January 19, 2038 (Unix time 2,147,483,647), potentially corrupting
time-based data.
Python 3 and 64-bit Platforms: Largely Safe
Python 3 uses 64-bit integers for timestamps internally. On 64-bit operating systems:
time.time()returns a 64-bit float — no overflow.datetimeobjects use 64-bit internally.- Python
intis arbitrary precision — timestamp arithmetic is safe. os.stat()wraps the OSstruct stat, which uses 64-bittime_ton all modern 64-bit platforms.
The os.stat() float precision caveat
st_mtime is returned as a Python float (C double, 53-bit mantissa). For post-2038
timestamps, sub-millisecond precision can be lost. Solution: use st_mtime_ns
(available since Python 3.3), which returns a plain Python int with full nanosecond
precision and no size limit. Borg already does this.
Where the Real Risk Is: Your Own Archive Format
The most significant Y2038 risk for Borg is not at the OS or Python level — it is in
how timestamps are serialized to disk in archive metadata.
- Borg uses msgpack for metadata. msgpack integers are variable-width and can hold
64-bit values, but you must ensure timestamps are written as 64-bit when values
exceed the 32-bit range. - Any
struct.pack('i', ts)orstruct.pack('l', ts)call on a timestamp will overflow
post-2038. Use'q'(64-bit signed) instead. - Recommendation: audit the archive format, test with synthetic post-2038 dates
(e.g.touch -t 203901010000), and ensure 64-bit storage throughout.
32-bit Platforms
OS/libc Y2038 fixes (already shipped)
| System | Fixed in | Details |
|---|---|---|
| Linux glibc | glibc 2.31 (2020) | _FILE_OFFSET_BITS=64 now default on 32-bit |
| musl libc | musl 1.2 (2020) | 64-bit time_t on all arches |
| FreeBSD | FreeBSD 12 (2018) | 64-bit time_t on 32-bit arches |
| NetBSD | NetBSD 10 (2024) | 64-bit time_t on 32-bit arches |
Which 32-bit systems with ≥1 GB RAM still have meaningful user bases?
Applying a practical filter (≥1 GB RAM, real user base, capable of running Borg):
- 32-bit Raspberry Pi OS on Pi 2 (1 GB RAM) — real user base, but ships glibc 2.31+ → already safe
- armhf Debian/Ubuntu — supported arch, can run on ≥1 GB hardware, but modern glibc → already safe
- Genuinely broken
time_tsystems are too old to run a current Borg release in practice.
Conclusion on 32-bit
Essentially no platform with a meaningful Borg user base has an outstanding OS-level
Y2038 problem. The ecosystem fixed 32-bit time_t between 2018 and 2024. Any system
old enough to still be affected is also too old to realistically run current Borg.
If you wish to document a requirement: Borg requires 64-bit time_t at the OS/libc
level; on 32-bit platforms ensure glibc ≥ 2.31, musl ≥ 1.2, or FreeBSD ≥ 12.
Recommendations for BorgBackup Developers
- Audit archive format — verify all timestamps are serialized as 64-bit (msgpack
int64or nanosecondtimespecpairs). This is the highest-priority item. - Use
st_mtime_nsinstead ofst_mtimefor file metadata — already done in Borg,
but worth confirming throughout. - Search for
struct.packcalls using'i'or'l'format codes on timestamps;
replace with'q'. - Test with post-2038 synthetic dates to verify correct store/restore behavior.
- No special action needed for 64-bit platforms or modern 32-bit platforms at the
OS level — the problem has been solved upstream.