我正在尝试对Mac上的磁盘分区表进行微妙的修改;特别是,我需要更改分区的类型。 diskutil
不支持此功能,因此我无法使用它。如果磁盘未使用,它可以正常工作(例如,通过修改后的gpt
命令行实用程序)。如果是,则在打开设备文件时失败:
int fd = open("/dev/disk1", O_RDWR);
fd
为-1,errno
表示错误“资源忙”。
我意识到我可以从另一个驱动器重启机器,从那里修改原始磁盘,然后重新启动。但是,从我的应用程序内部实现自动化/可靠性并不容易。此外,diskutil
编辑实时设备的分区表没有问题,也没有bootcamp安装程序。
有没有一种已知的方法可以做到这一点?最糟糕的情况是,我可以尝试在内核中执行此操作,但是kexts并非真正用于执行一次性操作,而我需要做的事情在用户空间中非常简单,但在内核中非常困难。
有什么想法吗?
注意:我正在使用sudo
运行所有内容,因此它不应该是权限问题。
答案 0 :(得分:6)
在使用otool
和反汇编程序进行一些调查之后,我确定Apple的diskutil
使用了一些私有框架来完成这项工作。 (我查看了命令行版本,但GUI 磁盘工具的功能集和状态/错误消息与它如此匹配,我怀疑是否存在差异)特别是Objective-C DiskManagement.framework
包含将1:1映射到diskutil
命令的类和方法。很多错误消息似乎来自MediaKit.framework
,它不是基于Objective-C的,因此otool
中的API无法显示。
简要地看一下这些函数的反汇编,似乎Mach Ports和 MIG 被大量使用。我不知道逆向工程的兔子孔有多深,以及它是否有用。毕竟,DiskManagement.framework
似乎与diskutil
完全相同,而不是更多,因此不包括直接编辑分区表。即使我弄清楚它是如何做到的,但这可能无法解决我的问题。
因此,为了避免在有可疑成功机会的活动上浪费更多时间,我最终通过内核扩展来实现,正是我试图避免的。我基本上构建了一个通用IOService
子类以及一个IOUserClient
伴随子类。这暴露了一些方法,用于将现有分区表替换为以root身份运行的用户空间进程。它搜索与设备名称对应的IOMedia
对象,并且通过一些技巧,直接读取/写入操作。我将旧的分区表传递给它,以便它可以验证它确实正在更新正确的东西。在用户空间方面,我修改了gpt
实用程序以使用用户空间I / O Kit库与kext进行通信。我只是临时加载kext进行更改,然后再次卸载它。它花了我2天的最佳时间,但效果很好。
答案 1 :(得分:-1)
您需要使用原始磁盘设备 - 在您的情况下为/dev/rdisk1
。另外,显然,您需要root
。