Do researchers handle exFAT volumes correctly?

Let’s conduct a simple experiment. In the Ext4 file system, I create two files (“1.txt” and “2.txt”).

touch 1.txt 2.txt

Then, I gather file system metadata (including timestamps) for these files:

sudo debugfs -R 'stat /path_to/the_file/1.txt' /dev/block_device
sudo debugfs -R 'stat /path_to/the_file/2.txt' /dev/block_device

In my case, the output is:

For “1.txt”:

Inode: 23918802   Type: regular    Mode:  0644   Flags: 0x80000
Generation: 2882061095    Version: 0x00000000:00000001
User:  1000   Group:  1000   Project:     0   Size: 0
File ACL: 0
Links: 1   Blockcount: 0
Fragment:  Address: 0    Number: 0    Size: 0
 ctime: 0x6399ee07:e1dbba28 -- Wed Dec 14 18:38:47 2022
 atime: 0x6399ee07:e1dbba28 -- Wed Dec 14 18:38:47 2022
 mtime: 0x6399ee07:e1dbba28 -- Wed Dec 14 18:38:47 2022
crtime: 0x6399ee07:e1dbba28 -- Wed Dec 14 18:38:47 2022
Size of extra inode fields: 32
Inode checksum: 0x9906b43e
EXTENTS:

For “2.txt”:

Inode: 23921678   Type: regular    Mode:  0644   Flags: 0x80000
Generation: 2369567438    Version: 0x00000000:00000001
User:  1000   Group:  1000   Project:     0   Size: 0
File ACL: 0
Links: 1   Blockcount: 0
Fragment:  Address: 0    Number: 0    Size: 0
 ctime: 0x6399ee07:e1dbba28 -- Wed Dec 14 18:38:47 2022
 atime: 0x6399ee07:e1dbba28 -- Wed Dec 14 18:38:47 2022
 mtime: 0x6399ee07:e1dbba28 -- Wed Dec 14 18:38:47 2022
crtime: 0x6399ee07:e1dbba28 -- Wed Dec 14 18:38:47 2022
Size of extra inode fields: 32
Inode checksum: 0x9b052019
EXTENTS:

Now, I’m going to store something in these files. I will use the bash shell to append some text to the first file (using the output redirection syntax) and the gedit text editor to modify the second one.

echo 123 >> 1.txt
gedit 2.txt # In the gedit window, I will type "456" and hit Ctrl-S.

And let’s get the timestamps for these files again…

For “1.txt”:

Inode: 23918802   Type: regular    Mode:  0644   Flags: 0x80000
Generation: 2882061095    Version: 0x00000000:00000001
User:  1000   Group:  1000   Project:     0   Size: 4
File ACL: 0
Links: 1   Blockcount: 8
Fragment:  Address: 0    Number: 0    Size: 0
 ctime: 0x6399eed2:68debfb8 -- Wed Dec 14 18:42:10 2022
 atime: 0x6399ee07:e1dbba28 -- Wed Dec 14 18:38:47 2022
 mtime: 0x6399eed2:68debfb8 -- Wed Dec 14 18:42:10 2022
crtime: 0x6399ee07:e1dbba28 -- Wed Dec 14 18:38:47 2022
Size of extra inode fields: 32
Inode checksum: 0x4a517d18
EXTENTS:
(0):95716043

For “2.txt”:

Inode: 23860507   Type: regular    Mode:  0644   Flags: 0x80000
Generation: 534549923    Version: 0x00000000:00000001
User:  1000   Group:  1000   Project:     0   Size: 4
File ACL: 0
Links: 1   Blockcount: 8
Fragment:  Address: 0    Number: 0    Size: 0
 ctime: 0x6399eed8:16d4b85c -- Wed Dec 14 18:42:16 2022
 atime: 0x6399eed8:14ec7284 -- Wed Dec 14 18:42:16 2022
 mtime: 0x6399eed8:16d4b85c -- Wed Dec 14 18:42:16 2022
crtime: 0x6399eed8:14ec7284 -- Wed Dec 14 18:42:16 2022
Size of extra inode fields: 32
Inode checksum: 0x2b67e3c3
EXTENTS:
(0):96358507

Do you see anything unusual?

Continue reading “Do researchers handle exFAT volumes correctly?”

exFAT: orphan file name entries

The exFAT file system was designed with Unicode file names and optional vendor-specific extensions in mind. To keep things simple, the file system specification allows the usage of multiple directory entries to describe a single file (so, additional file metadata is described in additional directory entries). This solution is similar to the VFAT extension for the FAT12/16/32 file systems, which was designed as a hack to the original file system format (originally, only one directory entry was used to describe a single file, so long file names were implemented as additional directory entries, which are “invisible” to operating systems without the VFAT support).

In the exFAT file system, a typical file consists of these entries (in this order, with no other entries between):

  • one file entry,
  • one stream extension entry,
  • one or more file name entries (as needed to store the file name),
  • zero, one or more vendor-specific entries (which can be ignored if not supported).

The first two entries describe all file metadata (its attributes, timestamps, data size, first cluster, etc.), while the file name entries contain strings to form the file name (each file name entry stores no more than 15 Unicode characters and the file name is no longer than 255 characters). Together, these entries are called a directory entry set (and it must contain at least three entries).

When a file is deleted, its directory entry set is marked as free. This process is very similar to what happens to a deleted file in the FAT12/16/32 file systems: the first byte of a directory entry is changed to mark it as free.

And, of course, it is possible to recover a deleted file when its directory set and data clusters are not overwritten. If the directory entry set is partially overwritten (with new directory entries), the following can be observed:

Continue reading “exFAT: orphan file name entries”

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?

Continue reading “macOS & FAT directories”