Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I prevent ejection of a disk during an operation on Mac OS X?

I have a long-running task that performs a series of file operations on mounted USB drives and I want to prevent users from ejecting the drive from Finder (or elsewhere) while this happens. There is a Cancel button that allows the task to be ended at any time.

I had assumed that keeping a file handle open on the mounted volume for the duration of the task would do the trick, but it hasn't worked.

This is what I tried (error handling removed):

NSString *tempFilePath = @"/Volumes/myVolume/.myTempFile";
if ([[NSFileManager defaultManager] fileExistsAtPath:tempFilePath] == NO) {
    [[NSFileManager defaultManager] createFileAtPath:tempFilePath contents:nil attributes:nil]
}

_tempFile = [NSFileHandle fileHandleForWritingAtPath:tempFilePath];

Any ideas about what I can do to ensure that the volume is prevented from ejecting?

like image 379
mcsheffrey Avatar asked Sep 15 '10 18:09

mcsheffrey


People also ask

Why does my external hard drive keep ejecting Mac?

There are a few other instances that can cause random ejection of an external drive: Defective external drive cable. Defective external desktop drive power supply. Defective computer USB or Thunderbolt port.

Why does my external hard drive keeps ejecting itself?

Your issue may be that your hard drive keeps disconnecting because of bad sectors in the drive. If that's the case, those sectors will lead to corruption and poor connectivity. If you're operating on Windows, there's a built-in driver check to help rid the disk of bad sectors.

Can Mac force eject?

On your Mac, choose Apple menu > Log Out, then log in again. Try to eject the disc again. If you still can't eject the CD or DVD, choose Apple menu > Restart. While your computer restarts, press and hold the mouse or trackpad button until the disc is ejected.


1 Answers

You'll need to use the Disk Arbitration API, more specifically the DARegisterDiskUnmountApprovalCallback.

You can create a DADiskRef via the functions avaliable in DADisk.h

When the callback is called, you can then decide whether you want to block the unmount or not. For a contrived example:

DADissenterRef myUnmountApprovalCallback(DADiskRef disk, void *context)
{
    DADissenterRef result = NULL; // NULL means approval
    if (stillWorking) {
        // This is released by the caller, according to the docs
        result = DADissenterCreate(kCFAllocatorDefault, kDAReturnBusy, CFSTR("<Your App> is busy writing to this device. Please cancel the operation first.");
    }
    return result;
}

As noted in the comments, this doesn't prevent anyone from just pulling the plug, but it will give you notification of explicit unmounts.

like image 133
bobDevil Avatar answered Sep 20 '22 00:09

bobDevil