Re: Finding out that a volume is going away before it does
Re: Finding out that a volume is going away before it does
- Subject: Re: Finding out that a volume is going away before it does
- From: Francis Devereux <email@hidden>
- Date: Mon, 27 Oct 2008 13:31:21 +0000
On 26 Oct 2008, at 16:37, Gregory Weston wrote:
Amusingly, when you register an unmount or eject approval function
with DiskArbitration, that function gets invoked *after* NSWorkspace
sends its didUnmount notification. How's that for a lead-in anecdote?
So anyway, I'm looking to react to the imminent or even potential
departure of a volume. Some way I can know that a volume will (or
probably will) be taken away from me in the near future but with
enough lead time that I can reliably make one or two quick function
calls against it. Any thoughts? I'm not worried about abrupt
disconnects like the user yanking the cable on an external drive.
Just looking for the tiniest smidgen of warning for orderly unmounts.
Specifically, I'm looking for the opportunity to call
FSGetCatalogInfo on the mount point and then FSGetVolumeInfo on the
volume reference number I got back from the first call.
Have you actually tried using DiskArbitration unmount approval
callbacks? I decided to give it a go and was able to successfully
call FSGetVolumeInfo in the callback. Tested with OS X 10.5.5 and
Xcode 3.1.1. The full project is at http://www.devrx.org/software/osx/DiskArbitrationTest.zip
, here's the important bits:
@implementation FDDAController
static DADissenterRef DiskUnmountApprovalCallback(DADiskRef disk, void
*context)
{
//FDDAController *self = (FDDAController *)context;
OSStatus status;
OSErr err;
CFDictionaryRef diskDescription = DADiskCopyDescription(disk);
NSLog(@"DiskUnmountApprovalCallback diskDescription = %@",
diskDescription);
NSDictionary *nsDiskDescription = (NSDictionary *)diskDescription;
NSURL *volumeURL = [nsDiskDescription valueForKey:@"DAVolumePath"];
if (![volumeURL isFileURL])
{
NSLog(@"Error: volume URL %@ is not a file URL!", volumeURL);
goto EXIT1;
}
NSString *volumePath = [volumeURL path];
const char *utf8VolumePath = [volumePath UTF8String];
FSRef volumeFSRef;
if ((status = FSPathMakeRef((UInt8 *)utf8VolumePath,
&volumeFSRef, (Boolean *)NULL)) != noErr)
{
NSLog(@"FDPathMakeRef error: %d", status);
goto EXIT1;
}
FSCatalogInfo catalogInfo;
if ((err = FSGetCatalogInfo(&volumeFSRef, kFSCatInfoVolume,
&catalogInfo, NULL, NULL, NULL)) != noErr)
{
NSLog(@"FSGetCatalogInfo error: %d", err);
goto EXIT1;
}
FSVolumeInfo volumeInfo;
if ((err = FSGetVolumeInfo(catalogInfo.volume,
0, NULL,
kFSVolInfoGettableInfo, &volumeInfo,
NULL,
NULL)) != noErr)
{
NSLog(@"FSGetVolumeInfo error: %d", err);
goto EXIT1;
}
NSLog(@"totalBytes = %llu, freeBytes = %llu, blockSize = %u",
volumeInfo.totalBytes, volumeInfo.freeBytes, volumeInfo.blockSize);
EXIT1:
CFRelease(diskDescription);
return NULL;
}
- (void)awakeFromNib
{
NSLog(@"FDDAController awakeFromNib");
daApprovalSession = DAApprovalSessionCreate(kCFAllocatorDefault);
DAApprovalSessionScheduleWithRunLoop(daApprovalSession,
[[NSRunLoop mainRunLoop]
getCFRunLoop],
kCFRunLoopCommonModes);
DARegisterDiskUnmountApprovalCallback(daApprovalSession,
NULL,
&DiskUnmountApprovalCallback,
(void *)self);
NSLog(@"finished registering callbacks");
}
- (void)dealloc
{
DAUnregisterApprovalCallback(daApprovalSession,
DiskUnmountApprovalCallback, self);
DAApprovalSessionUnscheduleFromRunLoop(daApprovalSession,
[[NSRunLoop mainRunLoop]
getCFRunLoop],
kCFRunLoopCommonModes);
CFRelease(daApprovalSession);
[super dealloc];
}
Francis
_______________________________________________
Cocoa-dev mailing list (email@hidden)
Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden