5

我正在尝试对 Mac 上的磁盘分区表进行细微修改;特别是,我需要更改分区的类型。diskutil不支持这个,所以我不能使用它。gpt如果磁盘不在使用中,它可以正常工作(例如,通过修改的命令行实用程序)。如果是,则打开设备文件时失败:

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

fd为 -1 并errno指示错误“资源繁忙”。

我意识到我可以从另一个驱动器重新启动机器,从那里修改原始磁盘,然后重新启动。然而,从我的应用程序内部实现自动化/可靠并不容易。此外,diskutil编辑直播设备的分区表没有问题,训练营安装程序也没有。

有没有已知的方法可以做到这一点?最坏的情况,我可以尝试在内核中进行,但 kext 并不是真正为一次性的事情而设计的,我需要做的实际上是在用户空间中非常简单,但在内核中却很难。

有任何想法吗?

注意:我用 运行所有东西sudo,所以它不应该是权限问题。

4

2 回答 2

8

苹果是如何做到的

在与otool反汇编程序进行了一些调查之后,我确定 Applediskutil使用了一些私有框架来完成这项工作。(我查看了命令行版本,但 GUI Disk Utility的功能集和状态/错误消息非常匹配,我怀疑有区别) 特别是,Objective-CDiskManagement.framework包含映射 1 的类和方法:1 到diskutil命令。很多错误消息似乎来自 .MediaKit.framework它不是基于 Objective-C 的,所以它的 API 在otool.

简单看一下部分函数的拆解,似乎Mach Ports和MIG用的比较多。我不知道逆向工程的兔子洞有多深,以及它是否会导致任何有用的地方。毕竟,DiskManagement.framework似乎只是做了什么diskutil,仅此而已,因此不包括直接编辑分区表。即使我知道它是如何在幕后完成的,也可能无法帮助我解决问题。

我是怎么做的

因此,为了避免在成功机会可疑的活动上浪费更多时间,我最终通过内核扩展来完成,这正是我试图避免的。我基本上构建了一个通用IOService子类和一个IOUserClient伴随子类。这向以 root 身份运行的用户空间进程公开了一些用新分区表替换现有分区表的方法。它搜索IOMedia与设备名称相对应的对象,并使用一些技巧,直接对其进行读/写操作。我将旧的分区表传递给它,以便它可以验证它确实在更新正确的东西。在用户空间方面,我修改了gpt实用程序使用用户空间 I/O 工具包库与 kext 对话。我只是暂时加载 kext 进行更改,然后再次卸载它。我花了 2 天的时间,但效果很好。

于 2012-02-19T12:09:35.593 回答
-1

您需要使用原始磁盘设备 - 在您的情况下是/dev/rdisk1. 此外,显然,您需要root.

于 2012-02-09T21:54:09.837 回答