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.
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.
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.
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.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With