I'm writing a read-only filesystem extension.
I see that the documentation for loadResource(resource:options:replyHandler:) claims that the --rdonly option is supported, which suggests that this should be possible. However, I have never seen this option provided to my filesystem extension, even if I return usableButLimited as a probe result (where it doesn't mount at all - FB19241327) or pass the -r or -o rdonly options to the mount(8) command. Instead I see those options on the volume's activate call.
But other than saving that "readonly" state (which, in my case, is always the case) and then throwing on all write-related calls I'm not sure how to actually mark the filesystem as "read-only." Without such an indicator, the user is still offered the option to do things like trash items in Finder (although of course those operations do not succeed since I throw an EROFS error in the relevant calls).
It also seems like the FSKit extensions that come with the system handle read-only strangely as well. For example, for a FAT32 filesystem, if I mount it like
mount -r -F -t msdos /dev/disk15s1 /tmp/mnt
Then it acts... weirdly. For example, Finder doesn't know that the volume is read-only, and lets me do some operations like making new folders, although they never actually get written to disk. Writing may or may not lead to errors and/or the change just disappearing immediately (or later), which is pretty much what I'm seeing in my own filesystem extension. If I remove the -F option (thus using the kernel extension version of msdos), this doesn't happen.
Are read-only filesystems currently supported by FSKit? The fact that extensions like Apple's own msdos also seem to act weirdly makes me think this is just a current FSKit limitation, although maybe I'm missing something. It's not necessarily a hard blocker given that I can prevent writes from happening in my FSKit module code (or, in my case, just not implement such features at all), but it does make for a strange experience.
(I reported this as FB21068845, although I'm mostly asking here because I'm not 100% sure this is not just me missing something.)
Are read-only filesystems currently supported by FSKit?
I think the tricky part here is what "support" here actually means. Let me start by what this actually "does":
pass the -r or -o rdonly options to the mount(8) command.
Passing that to mount should mean that the VFS layer itself is prevented from writing to the device. In FSKit terms, that means "FSBlockDeviceResource.writable" should be false and that all write methods should fail. If either of those behave differently, then that's a HUGE bug that we'd need to fix ASAP.
However, the confusing point here is that mounting a volume "readonly" doesn't necessarily define/change how the file system "presents" itself to the higher level system. That is, strictly speaking, nothing prevents a volume being mounted "readonly"... but that file system itself allowing itself to be fully modifiable.
That might sound a bit strange, but as a concrete example, you could implement a "resettable" file system by using the on-disk file system as the starting structure, routing all writes to secondary storage, and then discarding that storage on unmount. That's just one example, but the broader point is that the data "source" and lower-level VFS system aren't designed to control/constrain the file system that's actually presented to the system.
That leads to here:
Then it acts... weirdly. For example, Finder doesn't know that the volume is read-only, and lets me do some operations like making new folders, although they never actually get written to disk.
So, FYI, this is what happens when the high-level system presents operations as "possible" when it can't actually perform those operations. You can actually get exactly the same thing to happen to any of our kernel drivers, though it takes a KEXT*.
*More specifically, having written a KEXT that did this earlier in my career, if the IOMedia driver (the top level of the IOKit storage stack) "flips" itself to read-only AFTER the volume has mounted, you basically get exactly the behavior you're describing.
In terms of what your extension should do (and why msdosfs is failing), I think the best approach here is to support permissions (FSItemAttributeMode), and then ALWAYS return a configuration for all objects that prevents writing and fail any attempt to modify mode. You could also implement FSVolumeAccessCheckOperations; however, I'm not sure that will actually behave the way you want, and the mode operation is the more important check. The mode configuration means that the system (particularly the Finder) "knows" that the object is read-only before it attempts any operation, which means it never bothers trying.
That leads to here:
It also seems like the FSKit extensions that come with the system handle read-only strangely as well. For example, for a FAT32 filesystem,
It also seems like the FSKit extensions that come with the system handle read-only strangely as well.
Please file a bug on this (specifically, msdosfs's behavior) and post the bug number once it's filed.
What's going on here is that we're returning FSVolumeSupportedCapabilities.doesNotSupportSettingFilePermissions because, in fact, FAT does not support file permissions. However, that also means that it can't "tell" the higher-level system that it's read-only because it's disabled file permissions. In any case, I think it could solve all this by removing "doesNotSupportSettingFilePermissions" on read-only volumes and using exactly the same approach I'm suggesting above... and if it can’t, then this is an edge case we should probably solve. Either way, it's worth a bug.
__
Kevin Elliott
DTS Engineer, CoreOS/Hardware