I need to detect the triggering of an auto-mount operation when accessing the path to a formerly unknown mount point at the file system (BSD, POSIX, NSURL) level, and how to wait for it to finish the operation.
Network shares can have sub-volumes on them
Consider a Windows server. Let's say there's a SMB sharepoint at C:\Shared. It has some folders, one of which is at C:\Shared\More. Furthermore, there's another partition (volume) on the PC, which is mounted at C:\Shared\More\OtherVol.
If you mount the initial share on a Mac with a recent macOS, macOS initially only sees a single mount point at /Volumes/Shared,
which can be checked with the "mount" command.
Now, if you use Finder to dive into the Shared/More folder, Finder will trigger an auto-mount action on the containing OtherVol folder, and after that, the "mount" command will list two mount points from this server, the second being at /Volumes/Shared/More/OtherVol
.
(This was a bit surprising to me - I'd have thought that Windows or SMB would hide the fact that the share has sub-volumes, and simply show them as directories - and that's what it did in older macOS versions indeed, e.g. in High Sierra. But in Sequoia, these sub-volumes on the Windows side are mirrored on the Mac side, and they behave accordingly)
Browse the volume, including its sub-volumes
Now, I have a program that tries to dive into all the folders of this Shared volume, even if it was just freshly mounted and there's no mountpoint at /Volumes/Shared/More/OtherVol
known yet (i.e. the user didn't use Finder to explore it).
This means, that if my program, e.g. using a simple recursive directory scan, reaches /Volumes/Shared/More/OtherVol
, the item will not appear as a volume but as an empty folder. E.g, if I get the NSURLIsVolumeKey value, it'll be false. Only once I try to enter the empty dir, listing its contents, which will return no items, an auto-mount action will get triggered, which will add the mountpoint at the path.
So, in order to browse the actual contents of the OtherVol directory, I'd have to detect this auto-mount operation somehow, wait for it to finish mounting, and then re-enter the same directory so that I now see the mounted content.
How do I do that? I.e. how do I tell that a dir is actually a auto-mount point and how do I wait for it to get auto-mounted before I continue to browse its contents?
Note that newer macOS versions do not use fstab any more, so that's of no help here.
Can the DA API help?
Do I need to use the old Disk Arbitration functions for this, somehow?
I have used the DA framework in the part to prevent auto-mounting, so I imagine I could hook into that handler, and if I get a callback for a mount operation, I could then queue the newly mounted volume for scanning. The problem, however, is that my scanning code may, having only seen an empty directory at the not-yet-mounted mountpoint, already decided that there's nothing there and finished its operation.
I'd need some reliable method that lets my recursive scanning code know whether an auto-mount has been triggered and it therefore needs to wait for the DA callback.
So, is there some signal that will let me know IMMEDIATELY after entering the empty mountpoint directory that an auto-mount op is on the way? Because I suspect that the DA callbacks come with a delay, and therefore would come too late if I used that as the notifier that I have to wait.
Ironically, the answer is found in a 10 year old post by myself
As an additional irony, I'd just finished writing all this up when I saw your own post. Filling in some details which may be helpful...
(This was a bit surprising to me - I'd have thought that Windows or SMB would hide the fact that the share has sub-volumes, and simply show them as directories - and that's what it did in older macOS versions indeed, e.g. in High Sierra. But in Sequoia, these sub-volumes on the Windows side are mirrored on the Mac side, and they behave accordingly)
This is actually done by something called "DFS" (Distributed File System), which is actually designed to allow an organization to present a unified hierarchy across multiple servers as well as shares. The broader protocol obviously handles much more that this specific volume case and I suspect they used it here because it handles standard edge cases better* and the work had already been done.
*For example, exposing the secondary volume as a separate share means that if the remote volume disappears while being browsed, the client receives that operation as the share itself becoming unavailable instead of as a chunk of the hierarchy just "vanishing".
How do I do that? I.e. how do I tell that a dir is actually a auto-mount point and how do I wait for it to get auto-mounted before I continue to browse its contents?
That is a great question that I'm not sure of the answer to. From looking at our code, I don't think the Finder itself is actually doing this, but that it's actually being done by the SMB client itself using something called a "trigger vnode". If you're curious, you can actually see the code here.
SO, just to confirm what you're saying here:
Only once I try to enter the empty dir, listing its contents, which will return no items, an auto-mount action will get triggered, which will add the mountpoint at the path.
The problem here is that while your code is triggering the automount, the problem is that you don't actually "know" that it will occur or when it's done, so you can't go back again and "check".
Assuming that's correct, then I think you could detect this case using "NSURLIsVolumeKey" or "kCFURLIsVolumeKey", both of which correspond to "ATTR_DIR_MOUNTSTATUS" of getattrlist. That's typically used to denote actual mount points, however, it looks like it was also used to mark trigger nodes (the case here).
Do I need to use the old Disk Arbitration functions for this, somehow?
First off, Disk Arb is well aged, like a fine wine, not "old". Having been at this long enough to remember using the older, private, API (which was MISERAGBLE) and then being thrilled when the public API was introduced in 10.4, I have to defend it's honor.
But yes, I think this is what I would do:
I have used the DA framework in the part to prevent auto-mounting, so I imagine I could hook into that handler, and if I get a callback for a mount operation, I could then queue the newly mounted volume for scanning.
The issue here isn't just detecting these nodes at the point you're scanning, it's thinking through how you want to handle broader edge cases. The basic case here is "you scanned a folder which triggered an automount", but the other cases are things like:
-
After your scan had "left" the directory, the user attached a new remote volume and then browsed into that directory through the Finder.
-
The user (or some other app) manually mounted a new volume within the hierarchy you're scanning.
-
Even in the "basic" case (you navigated in a particular directory which triggered and automount), the time that automount could take to finish is WILDLY unpredictable. The best case (local volume on a fast LAN server) is pretty "fast", but the worst case (totally different server with a very slow/high latency connection) is basically unbounded.
The broader issue here is that relying on DiskArb lets you avoid thinking about all those specific case. DiskArb will tell you if/when any mount occurs, which you can then address however you choose.
__
Kevin Elliott
DTS Engineer, CoreOS/Hardware