Skip to main content

Module times

Module times 

Source
Expand description

Per-file Unix timestamps shared across the create / import / export paths, plus the format-specific encoders every non-Unix driver needs to write those same times into its own on-disk shape.

The goal is date-preservation on copy: when rb-cli copies a file from a host folder, a tar archive, or another disk image into a filesystem, the destination should record the source’s mtime, not “now”. And a tar_export (or any host-side extract) of that image should carry the same mtime back out.

§The rule

create_file / create_directory / create_symlink use these times when options.unix_times.is_some(); otherwise they stamp now. So:

  • Genuine new file (user typed put, GUI created a blank file) — caller leaves unix_times = None, driver stamps now.
  • Copy / extract / import — caller (dir_import / tar_import / Commander stage_copy) captures the source’s mtime and passes it through; the destination inode records it verbatim.

§Why per-field Options

Different sources carry different subsets: a tar Header has only mtime, an HFS entry has creation + modification + backup dates, an EFS inode has all three (atime/mtime/ctime). Missing fields aren’t fabricated — the driver falls back to now (or mtime where sensible) for each.

Values are u64 seconds since UNIX epoch 1970-01-01. Sub-second precision is intentionally dropped: FAT is 2-second granular, EFS/AFFS/PFS3 are 1- second, only ext/xfs/jfs carry nanoseconds — and the tar exporter only writes seconds anyway, so nanos wouldn’t round-trip end-to-end.

§Format encoders

Every filesystem below rusty-backup edits carries dates in some shape: DOS packed (FAT / exFAT / Human68k), NTFS FILETIME, Mac epoch (HFS / HFS+ / MFS), ProDOS packed, UCSD packed, ADFS 40-bit centiseconds, OS-9 Y-M-D bytes, QDOS 1961 epoch. Each encoder in this module turns a Unix u64 seconds value into that shape; each decoder is the inverse and returns None on the format’s “no date set” sentinel (usually a literal zero on disk).

Encoders clamp to the format’s earliest representable date rather than underflowing — a FAT file dated 1975 becomes 1980-01-01, not garbage. Decoders return None for zero and for values that would land before 1970, so a modified_unix never carries a suspicious 1969 / 1970-01-01 for what is on disk actually “no timestamp”.

Structs§

UnixTimes
A snapshot of a file’s Unix timestamps, in seconds since 1970-01-01.

Constants§

EXFAT_UTC_OFFSET_VALID
exFAT UtcOffset bit 7: the low 7 bits hold a valid offset in 15-minute steps.

Functions§

adfs_time_to_unix
Decode an ADFS (load_addr, exec_addr) pair to Unix seconds. Returns None when load_addr’s high 12 bits aren’t 0xFFF (which means the pair is a real load/exec address, not a datestamp) or when the resulting timestamp would land before 1970.
dos_datetime_to_unix
Decode a FAT (date, time) pair back to Unix seconds. Returns None for a zero date (the “no date set” sentinel every DOS filesystem tool uses) or for a date field whose components don’t make sense (month 0, day 0, day > days-in-month, etc). Raw and zone-less: the words are read as UTC. FAT stores local wall-clock time, so drivers use dos_local_to_unix.
dos_local_now
The current wall clock as FAT (date, time) words.
dos_local_to_unix
FAT’s local wall-clock (date, time) words back to Unix seconds (UTC).
exfat_local_now
The current wall clock as an exFAT (timestamp, UtcOffset) pair.
exfat_local_to_unix
An exFAT (timestamp, UtcOffset) pair back to Unix seconds. With no valid offset the stamp is the local wall clock of an unknown zone, read as this host’s (as Linux does).
exfat_timestamp_to_unix
Inverse of unix_to_exfat_timestamp. Raw and zone-less like the DOS pair; drivers use exfat_local_to_unix, which honours the UtcOffset byte.
filetime_to_unix
Decode an NTFS FILETIME back to Unix seconds. Returns None for a zero FILETIME (NTFS’s “unset” sentinel) or for a FILETIME that would land before 1970 (the tar oracle would render those as 1969 either way, and no real NTFS volume dates a file before 1970).
local_utc_offset_secs
Seconds this host’s local time is ahead of UTC, for the filesystems that store wall-clock time with no zone (HFS, MFS, FAT, Human68k, ProDOS). The current offset, not the date’s.
mac_epoch_to_unix
Decode a Mac epoch u32 back to Unix seconds. Mirrors hfs_common::mac_date_to_unix — returns None for zero (the “no date” sentinel) and for pre-1970 Mac dates (which would tar out as 1969).
mac_local_now
The current wall clock as a classic-Mac local-time stamp.
mac_local_to_unix
A classic-Mac local-time stamp back to Unix seconds (UTC).
now
Current wall-clock time as seconds since UNIX epoch. Clamped to 0 on the (impossible) pre-1970 system clock. Replaces every driver’s SystemTime::now().duration_since(UNIX_EPOCH).unwrap_or_default().as_secs() dance with one function.
now_u32
now() clamped into a u32 (used by drivers with 32-bit time fields — EFS, UFS-v1, XFS-v4, FAT/exFAT date halves). u32 overflows in 2106; we document but do not guard against it (no user has a 2106-vintage disk).
os9_dat_to_unix
Decode an OS-9 FD.DAT to Unix seconds. Returns None for all-zero (unwritten) or nonsensical component values.
os9_dcr_to_unix
Decode an OS-9 FD.DCR (creation date only) to Unix seconds. Returns None for all-zero or pre-1970 dates.
prodos_datetime_to_unix
Decode a ProDOS (date, time) pair back to Unix seconds. Returns None for a zero date (“no date set” — ProDOS Technical Note #28 formalises this). Raw and zone-less; drivers use prodos_local_to_unix.
prodos_local_now
The current wall clock as a ProDOS (date, time) pair.
prodos_local_to_unix
A ProDOS local wall-clock (date, time) pair back to Unix seconds (UTC).
qdos_date_to_unix
Decode a QDOS timestamp to Unix seconds. Returns None for zero (the “no date set” sentinel) or for QDOS values that would land before 1970.
resolve_or_now
The now-fallback rule the drivers use in one place: return the given UnixTimes if any field is set, otherwise a fresh all-fields now.
ucsd_date_to_unix
Decode a UCSD Pascal packed date to Unix seconds (00:00:00 of that day). Returns None for zero, and for pre-1970 dates (which would round-trip through tar as 1969 anyway; the year field’s 1900..1999 range means any UCSD-native date can be pre-1970, so this guard matters).
unix_to_adfs_time
Encode Unix seconds as an ADFS timestamped (load_addr, exec_addr) pair carrying the given RISC OS filetype (12 bits: 0xFFF = Data, 0xFEB = Obey, etc.). load_addr = 0xFFF_00000 | ((ft & 0xFFF) << 8) | ((cs40 >> 32) as u8); exec_addr = cs40 as u32. The 0xFFF-in- high-12-bits pattern is the “this is a datestamp, not a load address” marker every RISC OS tool checks for.
unix_to_dos_datetime
Encode Unix seconds as (fat_date, fat_time) — the two 16-bit words FAT dirent slots hold. fat_date layout: year_since_1980 (7) | month (4) | day (5); fat_time layout: hour (5) | minute (6) | second/2 (5).
unix_to_dos_local
Unix seconds to FAT’s (date, time) words as the local wall clock, as DOS and Windows write them.
unix_to_exfat_local
Unix seconds to an exFAT (timestamp, UtcOffset) pair: local time tagged with the host offset. A host offset exFAT cannot express (not whole quarter hours) is written as UTC, offset 0.
unix_to_exfat_timestamp
exFAT packs the two 16-bit DOS words into a single u32 (date in the upper half, time in the lower). Layer over unix_to_dos_datetime.
unix_to_filetime
Encode Unix seconds as an NTFS FILETIME (100-nanosecond intervals since 1601-01-01). Sub-second precision is lost, which is fine — every other source in the import chain (host stat, tar Header, cross-fs copy) is second-granular anyway.
unix_to_lif_bcd
Encode Unix seconds as HP LIF’s 6-byte BCD YYMMDDhhmmss; years outside 1970-2069 clamp.
unix_to_mac_epoch
Encode Unix seconds as a Mac epoch u32, clamping at both ends: a bogus future mtime on an extracted archive used to wrap into 1904..1970.
unix_to_mac_local
Unix seconds to a classic-Mac local-time stamp: the wall clock the Mac shows.
unix_to_os9_dat
Encode Unix seconds as OS-9 FD.DAT (5 bytes: year-1900, month, day, hour, minute). OS-9’s year is a single unsigned byte — 1900..2155 representable. Pre-1900 clamps to 1900-01-01; post-2155 clamps to 2155-12-31.
unix_to_os9_dcr
Encode Unix seconds as OS-9 FD.DCR (3 bytes: year-1900, month, day).
unix_to_prodos_datetime
Encode Unix seconds as a ProDOS (date, time) pair. Date layout: year (7) | month (4) | day (5) where year is year - 2000 when < 40 else year - 1900 (ProDOS’s own two-digit convention — years 40..99 mean 1940..1999, years 0..39 mean 2000..2039). Time layout: hour (5) | minute (6) (no seconds — ProDOS is minute-granular).
unix_to_prodos_local
Unix seconds to a ProDOS (date, time) pair on the local wall clock an Apple II clock card keeps.
unix_to_qdos_date
Encode Unix seconds as a QDOS timestamp (u32 seconds since 1961-01-01, big-endian on disk — but the encoding is byte-order-agnostic here). Pre-1961 clamps to 0 (1961-01-01); post-2097-02-06 truncates by u32 wraparound. No QDOS tool guards against either.
unix_to_ucsd_date
Encode Unix seconds as a UCSD Pascal packed date. Layout (little-endian as it sits in the dirent, but treated here as a plain u16): year (7) | month (4) | day (5) — years are 2-digit like ProDOS, but UCSD’s convention is different: 0..99 all map to 1900..1999.