Cocoa in the Shell

Prevent a disk from mounting on the filesystem

Today I will show you how to prevent a disk (physical or virtual) to mount on the filesystem.
In order to do that, we will use the Disk Arbitration framework. There is very few documentation for this framework, the best is to read the header files, which are very well commented.

Let’s begin, first open Xcode and create a new Foundation Command line tool project. Name it as you like.
Once the project created link with DiskArbitration.framework, right click –> Add existing frameworks.

Now let’s code, first import the framework header :

#import <diskArbitration/DiskArbitration.h>

Now, we need a DASessionRef object that we initialize like this :

DASessionRef session = DASessionCreate(kCFAllocatorDefault);

At this point, it becomes really interesting to read the header we just imported.
By traversing it, we can see a function that could correspond as what we are looking for :

extern void DARegisterDiskMountApprovalCallback(DAApprovalSessionRef session, CFDictionaryRef match, DADiskMountApprovalCallback callback, void* context);

As I said before, all the comments are very explicit.
the most important parameter is the third, it’s a pointer to the function which will be called when a disk will want to mount, here is its definition.

typedef DADissenterRef (*DADiskMountApprovalCallback)(DADiskRef disk, void* context);

So, we need to create an handler function, name it diskDidMount.

DADissenterRef diskDidMount(DADiskRef dsk, void* context)
{
    DADissenterRef ref = DADissenterCreate(kCFAllocatorDefault, kDAReturnNotPermitted, NULL);
    return ref;
}

For what we want to do, all the parameters are useless, we just have to create a DADissenterRef object which is the return value of the function. The interesting parameter here is the second, which is a flag that indicates the action to do. The flag list is available in the documentation.

All we have to do now, is create a loop to let the program run. The best would be to make this program a daemon, which is the object of a future post.

Here is the full code :

#import <foundation/Foundation.h>
#import <diskArbitration/DiskArbitration.h>

DADissenterRef diskDidMount(DADiskRef dsk, void* context)
{
    DADissenterRef ref = DADissenterCreate(kCFAllocatorDefault, kDAReturnNotPermitted, NULL);
    return ref;
}

int main(int argc, const char* argv[])
{
    NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
    DASessionRef session = DASessionCreate(kCFAllocatorDefault);
    DARegisterDiskMountApprovalCallback(session, NULL, diskDidMount, NULL);
    DASessionScheduleWithRunLoop(session, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode);
    CFRunLoopRun();
    [pool drain];
    return 0;
}