PDA

View Full Version : Struggling with DiskArbitration




NSUser
May 9, 2013, 11:43 AM
In my app I use DiskArbitration.framework to mount and unmount local drives.
The code to mount a volume looks like this:

CFAllocatorRef allocator = kCFAllocatorDefault;
DASessionRef session = DASessionCreate(kCFAllocatorDefault);
const char *name = [openVolume.volId UTF8String]; // open volume is an object that stores volume information

DADiskRef disk = DADiskCreateFromBSDName(allocator,
session,
name);

DASessionScheduleWithRunLoop(session, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode);

CFDictionaryRef diskDescription = DADiskCopyDescription(disk);
NSDictionary *diskData = (NSDictionary *)diskDescription;
BOOL mountable = [[diskData objectForKey:@"DAVolumeMountable"] boolValue];

if (mountable) {

if (debug) {NSLog(@"Open volume %@ with id %@", openVolume.volName, openVolume.volId);}

NSURL *url = NULL;
if (![openVolume.volPath isEqualToString:openVolume.mountPath]) {
url = [NSURL URLWithString:[[openVolume.mountPath stringByExpandingTildeInPath] stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]];
if (debug) {NSLog(@"Open volume at URL: %@", url);}
}

DADiskMount(disk,
(CFURLRef) url,
kDADiskMountOptionDefault,
OnDiskMounted,
message);

} // is mountable
if (disk) {CFRelease(disk);}
if (session) {CFRelease(session);

and the code to umount a volume looks like this:

CFAllocatorRef allocator = kCFAllocatorDefault;
DASessionRef session = DASessionCreate(kCFAllocatorDefault);
NSURL *url = [NSURL URLWithString:[unmountVolume.volPath stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]];
NSLog(@"Unmount volume at URL: %@", url);

DADiskRef disk = DADiskCreateFromVolumePath(
allocator,
session,
(CFURLRef) url );
if (disk && debug) {NSLog(@"Got disk...");}
if (disk) {
DASessionScheduleWithRunLoop(session, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode);

DADiskUnmount(disk,
kDADiskMountOptionDefault,
OnDiskUnmounted,
message);

if (disk && debug) {NSLog(@"disk unmounted...");}
CFRelease(disk);
}
if (session) {CFRelease(session);}

Basically this works fine. The 'message' contains info for the callback functions to open a mounted or eject an unmounted volume, respectively.

But after mounting and unmounting a local usb drive several (2-3) times, I get a DADissenterRef in the 'OnDiskMounted' callback that I can not resolve from the info in the documentation (http://developer.apple.com/library/mac/#documentation/DiskArbitration/Reference/DADissenter_header_reference/Reference/reference.html#//apple_ref/doc/uid/TP40011612):

DADissenterGetStatus(dissenter) = 49153

When I then attempt to mount the volume again, directly after sending DADiskMount(), I get a notice that the disk description changed (usually this callback is called after succesfull mount/unmount because the path changed).
For some reason, the 'DAVolumeName' key and - sooner or later - even the 'DAVolumeUUID' key get copied from the startup disk. The info of the respective DADiskRef remains corrupted even after physically removing and reconnecting the usb drive. In DiskUtility.app, the wrong name (of the startup disk) is displayed in the sidebar, while the correct name is used when testing the volume. The Finder also displayes the correct name. After restarting the computer everything works fine again. Until I mount and unmount the volume...

What am I doing wrong? Is there anything I need to do in the mount/unmount callbacks? Do I have to unschedule the DASession from the current run loop? And if so, how owuld I do that?
Or do I need to claim the disk for mount/unmount?

I'd really appreciate any advice! Thanks!



NSUser
May 9, 2013, 04:21 PM
NSURL *url = NULL;
if (![openVolume.volPath isEqualToString:openVolume.mountPath]) {
url = [NSURL URLWithString:[[openVolume.mountPath stringByExpandingTildeInPath] stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]];
if (debug) {NSLog(@"Open volume at URL: %@", url);}
}

DADiskMount(disk,
(CFURLRef) url,
kDADiskMountOptionDefault,
OnDiskMounted,
message);



Solved: I sent '/Volumes' as mountpath to DADiskMount...