Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Opening disk device file for write access on Mac OS X

Tags:

posix

macos

iokit

I'm trying to make a subtle modification to the partition table of a disk on the Mac; in particular, I need to change the type of a partition. diskutil doesn't support this, so I can't use it. It works fine (e.g. via a modified gpt command-line utility) if the disk isn't in use. If it is, it fails when opening the device file:

int fd = open("/dev/disk1", O_RDWR);

fd is -1 and errno indicates the error "resource busy".

I realise I can reboot the machine from a different drive, modify the original disk from there, then boot back. This is, however, not exactly easy to automate/reliable from inside my application. Besides, diskutil has no problem editing the partition table of the live device, and neither has the bootcamp installer.

Is there a known way to do this? Worst case, I can try to do it in the kernel, but kexts aren't really designed for doing one-off things, and what I need to do is really quite conceptually simple in userspace but quite hard in the kernel.

Any ideas?

Note: I'm running everything with sudo, so it should not be a permissions problem.

like image 854
pmdj Avatar asked Feb 09 '12 16:02

pmdj


People also ask

How do I get write access on my external hard drive Mac?

Select the drive in the Finder. Press Command-I to display the Get Info window. At the bottom of the window, click the arrow next to Sharing & Permissions to display permissions. Click on the Privilege menu next to your username and choose Read & Write.

How do I access a disk in OSX?

On your Mac, use one of the following methods to open Disk Utility: Use Launchpad: Click Launchpad in the Dock, type Disk Utility in the search field, then click the Disk Utility icon. Use the Finder: In the Finder , choose Go > Utilities, then double-click the Disk Utility icon.


1 Answers

How Apple does it

After some sleuthing with otool and a disassembler, I determined that Apple's diskutil uses some private frameworks to do the job. (I looked at the command-line version, but the feature set and status/error messages of the GUI Disk Utility match it so closely, I doubt there is a difference) In particular, the Objective-C DiskManagement.framework contains classes and methods that map 1:1 to diskutil commands. A lot of error messages seem to come out of the MediaKit.framework, which isn't Objective-C based, so its API isn't visible right there in otool.

Briefly looking at the disassembly of some of the functions, it seems that Mach Ports and MIG are used heavily. I have no idea how deep the rabbit hole of reverse engineering that goes, and whether it leads anywhere useful. After all, the DiskManagement.framework seems to do exactly what diskutil does, and no more, so that doesn't include direct editing of the partition table. Even if I figured out how it does it under the hood, that may not help me fix my problem.

How I'm doing it

So, to avoid wasting any more time on activities with questionable chances of success, I ended up doing it via a kernel extension, just what I was trying to avoid. I basically built a general IOService subclass along with an IOUserClient companion subclass. This exposes some methods for replacing an existing partition table with a new one to user space processes running as root. It searches for the IOMedia object corresponding to the device name and with some trickery, does the read/write operations directly on that. I pass the old partition table to it so it can verify that it is indeed updating the right thing. On the user-space side, I modified the gpt utility to use the user-space I/O Kit libraries to talk to the kext. I only temporarily load the kext for making the changes and then unload it again. It took me the best part of 2 days but it works well.

like image 177
pmdj Avatar answered Oct 08 '22 15:10

pmdj