macOS & FAT directories

Previously, I wrote about things you probably didn’t know about FAT. Now, let’s continue the story!

In FAT12/16/32 file systems, each directory (except the root directory) contains two special entries:

  • dot (“.”);
  • dot-dot (“..”).

The first one (dot) refers to the directory itself, while the second one (dot-dot) refers to the parent directory. Apparently, these entries were introduced to keep file system implementations simple, so there is no need to generate those entries on the fly (this is what happens to file systems not wasting their space to store dot and dot-dot entries in every directory).

Since two special entries are regular 8.3 directory entries, they contain timestamps (Created, Modified, Last Accessed). According to Microsoft, these timestamps should be set like this:

[…] and all of the date and time fields in both of these entries are set to the same values as they were in the directory entry for the directory that you just created.

FATGEN, 1.03 (DOC)

So, the timestamps in the dot-dot directory entry have no connection to the parent directory of that directory (they aren’t copied from the corresponding timestamp fields of the parent directory). Both special entries have their timestamps set to the same values as in the directory itself.

For example, all these entries are expected to share the same timestamps:

  • E:\test
  • E:\test\.
  • E:\test\..

But are these timestamps always synchronized?

The Linux kernel doesn’t keep the timestamps in two special entries synchronized with their parent directory. Here is an example:

The timestamps for the dot and dot-dot entries are different from the timestamps of their parent directory

This is why we need the dot and dot-dot entries when building timelines!

But the craziest implementation is found in the macOS operating system (its FAT driver is called msdosfs).

In 2007, Apple released Mac OS X Leopard, which contained some new code in the msdosfs driver. Here it is:

/*
 * Read in the directory entry to be updated.
 * For files, this is just the file's directory entry (in its parent).
 * For directories, this is the "." entry inside the directory.
 * For the root, this is the volume label's directory entry.
 */
if (dep->de_Attributes & ATTR_DIRECTORY)
{
	if (isRoot)
	{
		dirclust = pmp->pm_label_cluster;
		diroffset = pmp->pm_label_offset;
	}
	else
	{
		dirclust = dep->de_StartCluster;
		diroffset = 0;
	}
}
else
{
	dirclust = dep->de_dirclust;
	diroffset = dep->de_diroffset;
}
error = readep(pmp, dirclust, diroffset, &bp, &dirp, context);

This code could be found here and here (this is the current version of the driver). Basically, any updates to timestamps of directories go to their dot entries! But not to the 8.3 directory entries of those directories. (This doesn’t affect timestamps of files, they are stored as usual.)

Here is an example:

Timestamps shown when using the stat tool (macOS Monterey), note the Modify timestamp (Jan 12 10:00:34 2022)
Timestamps extracted from 8.3 directory entries, note that the proper Modified timestamp (the same as shown above: Jan 12 10:00:34 2022) is stored in the “/test_dir/.” entry only

Also, here is a comment from the source code:

 * - Directory entries for directories are never changed once they are created
 *   (except when removed).  The size stays 0, and the last modification time
 *   is never changed.  This is because so many directory entries can point to
 *   the physical clusters that make up a directory.  It would lead to an
 *   update nightmare.
 * - For the POSIX/BSD APIs, the dates for a directory come from the "." entry
 *   in the directory.

It’s worth to mention that the latter point appeared before its implementation, while the first one is also present in the FreeBSD driver. (FreeBSD uses the usual way to store timestamps of directories.)

Based on this and further testing of multiple open-source and commercial forensics tools, I can state that many of them don’t support this unusual way of storing timestamps of directories, because dot and dot-dot entries inside directories are often ignored.

And a test image is here (it’s a gzipped raw image). The timestamps related to the issue were shown above.

One thought on “macOS & FAT directories

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s