将USB磁盘BSD名称映射到OSX中的实际安装的驱动器

时间:2014-11-01 11:03:24

标签: usb-drive mount-point diskarbitration

我正试图从USB设备BSD Name获取该设备的实际安装卷,例如设备有BSD名称" disk2"并使用BSD名称安装单个卷" disk2s1" at" / Volumes / USBSTICK"。

这是我到目前为止所做的事情。使用

NSNotificationCenter NSWorkspaceDidMountNotification

我检测到添加了驱动器的时间。然后我扫描所有USB设备并使用

IORegistryEntrySearchCFProperty kIOBSDNameKey

获取设备的BSD名称。

对于我的USB记忆棒,它会返回" disk2"。运行

system_profiler SPUSBDataTypesystem_profiler SPUSBDataType

显示

      Product ID: 0x5607
      Vendor ID: 0x03f0  (Hewlett Packard)
      Serial Number: AA04012700008687
      Speed: Up to 480 Mb/sec
      Manufacturer: HP
      Location ID: 0x14200000 / 25
      Current Available (mA): 500
      Current Required (mA): 500
      Capacity: 16.04 GB (16,039,018,496 bytes)
      Removable Media: Yes
      Detachable Drive: Yes
      BSD Name: disk2
      Partition Map Type: MBR (Master Boot Record)
      S.M.A.R.T. status: Not Supported
      Volumes:
        USBSTICK:
          Capacity: 16.04 GB (16,037,879,808 bytes)
          Available: 5.22 GB (5,224,095,744 bytes)
          Writable: Yes
          File System: MS-DOS FAT32
          BSD Name: disk2s1
          Mount Point: /Volumes/USBSTICK
          Content: Windows_FAT_32

这是有道理的,因为单个USB设备可能有多个卷。

我假设我可以使用DiskArbitration来查找实际的卷,但是

DASessionRef session = DASessionCreate(NULL);
if (session)
{
    DADiskRef disk = DADiskCreateFromBSDName(NULL,session,"disk2");
    if (disk)
    {
        CFDictionaryRef dict = DADiskCopyDescription(disk);
        if (dict)

总是返回一个NULL字典。

那么,如何从USB设备的BSD名称到该设备的实际安装卷?我想应该可以迭代所有卷,获取他们的BSD名称并检查它是否以字符串开头,例如上面的/ Volumes / USBSTICK是" disk2s1",但这很糟糕,如果有磁盘等等怎么办。

1 个答案:

答案 0 :(得分:2)

使用IOBSDNameMatching找到解决方案将创建一个字典,以使服务与给定的BSD名称相匹配。然后可以搜索该服务的子节点以查找其BSD名称。 注意:这是我第一次在OSX上做任何事情。此外,由于bug,上面代码中的'dict'为NULL,但是该字典对此无用。

这里是一些没有错误检查等的减少代码。

CFMutableDictionaryRef  matchingDict;

matchingDict = IOBSDNameMatching(kIOMasterPortDefault, 0, "disk2");
io_iterator_t itr;
// Might only ever be one service so, MatchingService could be used. No sure though
IOServiceGetMatchingServices(kIOMasterPortDefault, matchingDict, &itr);
io_object_t service;
while ((service = IOIteratorNext(itr)))
{
    io_iterator_t children;
    io_registry_entry_t child;

    // Obtain the service's children.
    IORegistryEntryGetChildIterator(service, kIOServicePlane, &children);
    while ((child = IOIteratorNext(children)))
    {
        CFTypeRef name = IORegistryEntrySearchCFProperty(child,
                                                      kIOServicePlane,
                                                      CFSTR(kIOBSDNameKey),
                                                      kCFAllocatorDefault,
                                                      kIORegistryIterateRecursively);
        if (name)
        {
            // Got child BSD Name e.g. "disk2s1"
        }
    }
}