O_NOATIME, which means reading it will not change its access time. Windows offers a similar option that works for individual file handles. macOS has neither of these features. The only way to control this on macOS is at the volume mount level, and a standard APFS volume updates its access time with every read. So on macOS, whether a file's access time remains unchanged after a read depends on how its volume was mounted.
We discovered this while preparing a remote triage demonstration. A substantial collection of evidence files was stored on a Mac. Another computer connected to it over the network and read through these files. Our software already uses the no-atime method when a shared volume is set to read-only, so we verified that the access times remained constant.
The test
Reading 4 KB from a file and comparing the access time before and after.
F=~/Evidence/SYSTEM
echo "before: $(stat -f '%a' "$F")"
head -c 4096 "$F" > /dev/null
echo "after: $(stat -f '%a' "$F")"
On a MacBook Pro running Darwin 25.5.0, APFS:
| Volume | Operation | atime |
|---|---|---|
| Plain APFS data volume | read 4 KB | moved, 1787149389 to 1787149481 |
Disk image, noatime | read 4 KB, then a full cat | held at 1787149516 |
Same noatime image, 24 files | sha256 every file | all 24 held |
The third row shows the most common use case. Hashing a set of files means reading every byte. On the noatime volume, all the files were processed with their access times unchanged, including one file dated back to January 1, 2024.
Linux and Windows offer a flag for each handle
Linux exposes O_NOATIME as an open flag. A process that owns the file, or has CAP_FOWNER permissions, can read it without the kernel updating the access time. This flag applies to each open operation, allowing one program to be careful while the rest of the system operates normally.
Windows provides the same control at the handle level, by writing a special value to the last-access field.
macOS has no open flag and no field per handle for this function. The decision is made only once, for the entire volume, when it is mounted.
Mounting a volume with noatime on macOS
A disk image is the easiest way to achieve this. The hdiutil attach command does not have a functional -mountoptions flag for this purpose, so you must attach it first and then remount it.
hdiutil create -size 30g -type SPARSE -fs APFS -volname Evidence -quiet ~/evidence.sparseimage
hdiutil attach -mountpoint ~/Evidence -nobrowse ~/evidence.sparseimage
mount -u -o noatime ~/Evidence
mount | grep Evidence
# /dev/disk3s1 on /Users/you/Evidence (apfs, local, nodev, nosuid, journaled, noatime, ...)
The last line is the check. Look for noatime in the list of flags. Without it, read operations will continue to write metadata.
A sparse image uses almost no space until it contains data. The mount does not persist after a reboot, so include the attach and remount commands in any script that sets up the machine.
Handling evidence on a Mac
Access time is fragile evidence. It is easy to accidentally change, many systems disable it for speed, and its meaning depends on mount options that are not always visible. That is why it is important to state this condition.
On a macOS computer, the claim carries a condition. Access times remain unchanged after a read if the volume containing them was mounted with the noatime option. On Linux and Windows, a careful program protects them on its own. On macOS, the mount option determines this, and the application software has no influence.
In KEIBIDROP, this functionality is contained within a single function. When a shared resource is marked as read-only, serving a peer's read opens the file using the no-atime method where the operating system supports it. The comment for that function explains that macOS has no per-handle equivalent, and the policy of the source mount controls this. We tested this before relying on it, which is how the evidence volume mentioned above was created.
Limits
- We measured this on one machine running macOS Darwin 25.5.0 with APFS, on both the system data volume and an attached sparse image. We did not test HFS+, network volumes, or external media.
- The
noatimeoption stops the update from happening. An access time that has already moved will stay where it is. - Copying a file with a tool that does not carry access times, which is how most of them behave by default, gives the copy a fresh access time no matter what the source volume did. That behaviour comes from the copy program itself.
- Birth time and change time are separate questions. Birth time can be read back, but most systems do not allow you to set it. Change time is maintained by the kernel, and no tool can set it.