rentzsch.com: tales from the red shed

Assessing and Accessing Access Dates

Mac OS X

Did you know Mac OS X 10.4 stores and maintains two distinct “access dates” for files? I didn’t until today.

In Mac OS 9, we just had creation date and modification date (to use AppleScript’s terminology). When Mac OS X came on the scene, we gained the additional common unix attribute of “access date” (obtainable via the stat(2) system call).

A problem with Unix access date is that it’s really volatile. For example, simply single-clicking on a file the Finder thinks it can preview (like a .txt file) will be enough for it to read that file, bumping its access date.

For better or worse, 10.4 added an additional “access date” that’s maintained by Spotlight’s metadata subsystem (obtainable via MDItemCopyAttribute(item, kMDItemLastUsedDate) call).*

In a vain attempt to maintain sanity, I’ll dub the older stat(2)-obtained access date “unix access date” and the newer Spotlight-obtained one “metadata access date”.

Unlike unix access date, metadata access date isn’t modified merely by browsing in the Finder — you have to “open” the file. That makes it a lot less volatile. The downside is that shell tools like cat or even touch don’t bump the metadata access date, even though they probably should.

Perhaps a better name for metadata access date would be gui access date, but I’m hesitant to use that label since I don’t know the intent of the attribute. For all I know this will be “fixed” in 10.5. However, I know I’m not wrong if I name it after the API (versus the intent).

The backstory on this discovery is that I’m trying to automate archiving a few thousand files. I’d like to reduce a scary-deep tree (where I’m in danger of PATH_MAX blackholing) into a shallow flattened-by-year+weeknumber hierarchy.

Problem: AppleScript doesn’t offer a native way to obtain either the unix access date or metadata access date. Solution: write an access date AppleScript addition (source code).

The heuristic I’m using is that I trust the unix access date unless it’s inside a minute of now. If it is, I assume that timestamp was blown away by a Finder preview and then fall back to the metadata access date. This seems to be a good compromise between honoring shell tools but not getting tripped up by mere previewing.

* It gets a little more interesting: there’s also kMDItemUsedDates, which houses an array of access dates. I don’t know how deep this array goes, but it’s a cool built-in auditing feature.

Update May 26: Teletubby writes:

These dates have actually been a part of HFS+ from the get go. I remember using the attribute mode date in 10.1.x (possibly even in 10.0.x, I don’t remember since 10.0.x wasn’t around for too long).

I remember the attribute mod and access date pissed me off because every time I’d get one of the dates, these things would be modified, making them completely useless. Curse you, quantum mechanics!

If you look in Files.h, you see the below. These dates have been there for what seems like forever. It’s possible these dates were even in Mac OS 9 when the HFS+ APIs were first added.

I mention this only because it seemed from your post you were implying attribute mod dates didn’t exist/weren’t set before 10.4, which isn’t the case. So you can get the dates using FSGetCatalogInfo(). However, there might have been a change after the last time I used it in 10.1 or 10.2 that made the dates not update every freakin single time you asked for them.

Sorry if I left the impression unix access dates didn’t exist before 10.4. As the rotund preschool hero points out, they were very much alive (even in 10.0).

Drew Thaler chimes in:

There are other dates too. The filesystem itself supports five different ones — see getattrlist(2):

ATTR_CMN_CRTIME - set once at file creation ATTR_CMN_MODTIME - updated at file content modification (write, ftruncate, etc) ATTR_CMN_CHGTIME - updated at filesystem attribute modification (utimes, setattrlist, chown, etc) ATTR_CMN_ACCTIME - updated at open ATTR_CMN_BKUPTIME - only set via API

Everything else is a layer added by Spotlight and kept in your metadata store. The fact that LaunchServices updates the LastUsedDate value for Spotlight is still pretty interesting, though.

From Apple’s docs, it sounds like the property is only measuring Launch Services opens — i.e. LSOpenCFURLRef and family. That’s mostly just opening via the Finder (double-click, drag onto app icon) but also includes the open(1) shell command and things like Safari’s open-after-download.

I’m guessing that this date probably wouldn’t be updated if you opened the item manually from inside the application via File->Open or Recent Documents. Unless of course NavServices, Cocoa, and CarbonCore are all in on the conspiracy. ;-)

As Drew knows, I always suspect conspiracy. The created/modified/backed-up dates are old news to any File Manager oldtymer but the dedicated attribute modification date field (ATTR_CMN_CHGTIME) is news to me. Now I just need to figure out how I can abuse it…

Saturday, May 26, 2007
12:00 AM