在 Mac OS X 上打开磁盘设备文件进行写访问

发布于 2025-01-04 05:33:49 字数 589 浏览 6 评论 0原文

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

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

fd为-1,errno表示错误“资源忙”。

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

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

有什么想法吗?

注意:我正在使用 sudo 运行所有内容,因此这不应该是权限问题。

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.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

如何视而不见 2025-01-11 05:33:49

Apple 是如何做到的

在使用 otool 和反汇编程序进行一些调查之后,我确定 Apple 的 diskutil 使用一些私有框架来完成这项工作。 (我查看了命令行版本,但是 GUI 磁盘工具 的功能集和状态/错误消息与它非常匹配,我怀疑是否存在差异)特别是 Objective-C DiskManagement.framework 包含将 1:1 映射到 diskutil 命令的类和方法。许多错误消息似乎来自 MediaKit.framework,它不是基于 Objective-C 的,因此它的 API 在 otool 中不可见。

简单看一下一些功能的反汇编,似乎Mach Ports和MIG被大量使用。我不知道逆向工程的兔子洞有多深,也不知道它是否会带来任何有用的东西。毕竟,DiskManagement.framework 似乎完全执行了 diskutil 的操作,仅此而已,因此不包括直接编辑分区表。即使我弄清楚它在幕后是如何工作的,这也可能无法帮助我解决我的问题。

我是如何做到的

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

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.

浮光之海 2025-01-11 05:33:49

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

You need to use the raw disk device - in your case that would be /dev/rdisk1. Also, obviously, you'll need to be root.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文