VirtualBox

Ignore:
Timestamp:
Aug 28, 2020 2:40:55 PM (4 years ago)
Author:
vboxsync
Message:

Main: bugref:9224: Main+VBoxManageDisk+doc part

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Main/src-server/darwin/iokit.cpp

    r85272 r85929  
    3131#include <mach/mach.h>
    3232#include <Carbon/Carbon.h>
     33#include <CoreFoundation/CFBase.h>
    3334#include <IOKit/IOKitLib.h>
     35#include <IOKit/IOBSD.h>
    3436#include <IOKit/storage/IOStorageDeviceCharacteristics.h>
     37#include <IOKit/storage/IOBlockStorageDevice.h>
     38#include <IOKit/storage/IOMedia.h>
     39#include <IOKit/storage/IOCDMedia.h>
    3540#include <IOKit/scsi/SCSITaskLib.h>
    3641#include <SystemConfiguration/SystemConfiguration.h>
    3742#include <mach/mach_error.h>
     43#include <sys/param.h>
     44#include <paths.h>
    3845#ifdef VBOX_WITH_USB
    3946# include <IOKit/usb/IOUSBLib.h>
    4047# include <IOKit/IOCFPlugIn.h>
    41 # include <IOKit/storage/IOMedia.h>
    4248#endif
    4349
     
    15701576
    15711577    IOObjectRelease(DVDServices);
     1578
     1579    return pHead;
     1580}
     1581
     1582
     1583/**
     1584 * Enumerate the fixed drives (HDDs, SSD, ++) returning a FIFO of device paths
     1585 * strings and model strings separated by ':'.
     1586 *
     1587 * @returns Pointer to the head.
     1588 *          The caller is responsible for calling RTMemFree() on each of the nodes.
     1589 */
     1590PDARWINFIXEDDRIVE DarwinGetFixedDrives(void)
     1591{
     1592    AssertReturn(darwinOpenMasterPort(), NULL);
     1593
     1594    /*
     1595     * Create a matching dictionary for searching drives in the IOKit.
     1596     *
     1597     * The idea is to find all the IOMedia objects with "Whole"="True" which identify the disks but
     1598     * not partitions.
     1599     */
     1600    CFMutableDictionaryRef RefMatchingDict = IOServiceMatching("IOMedia");
     1601    AssertReturn(RefMatchingDict, NULL);
     1602    CFDictionaryAddValue(RefMatchingDict, CFSTR(kIOMediaWholeKey), kCFBooleanTrue);
     1603
     1604    /*
     1605     * Perform the search and get a collection of IOMedia objects.
     1606     */
     1607    io_iterator_t MediaServices = IO_OBJECT_NULL;
     1608    IOReturn rc = IOServiceGetMatchingServices(g_MasterPort, RefMatchingDict, &MediaServices);
     1609    AssertMsgReturn(rc == kIOReturnSuccess, ("rc=%d\n", rc), NULL);
     1610    RefMatchingDict = NULL; /* the reference is consumed by IOServiceGetMatchingServices. */
     1611
     1612    /*
     1613     * Enumerate the matching services.
     1614     * (This enumeration must be identical to the one performed in DrvHostBase.cpp.)
     1615     */
     1616    PDARWINFIXEDDRIVE pHead = NULL;
     1617    PDARWINFIXEDDRIVE pTail = NULL;
     1618    unsigned i = 0;
     1619    io_object_t MediaService;
     1620    while ((MediaService = IOIteratorNext(MediaServices)) != IO_OBJECT_NULL)
     1621    {
     1622        DARWIN_IOKIT_DUMP_OBJ(MediaService);
     1623
     1624        /*
     1625         * Find the IOMedia parents having the IOBlockStorageDevice type and check they have "device-type" = "Generic".
     1626         * If the IOMedia object hasn't IOBlockStorageDevices with such device-type in parents the one is not general
     1627         * disk but either CDROM-like device or some another device which has no interest for the function.
     1628         */
     1629
     1630        /*
     1631         * Just avoid parents enumeration if the IOMedia is IOCDMedia, i.e. CDROM-like disk
     1632         */
     1633        if (IOObjectConformsTo(MediaService, kIOCDMediaClass))
     1634        {
     1635            IOObjectRelease(MediaService);
     1636            continue;
     1637        }
     1638
     1639        bool fIsGenericStorage = false;
     1640        io_registry_entry_t ChildEntry = MediaService;
     1641        io_registry_entry_t ParentEntry = IO_OBJECT_NULL;
     1642        kern_return_t krc = KERN_SUCCESS;
     1643        while (   !fIsGenericStorage
     1644               && (krc = IORegistryEntryGetParentEntry(ChildEntry, kIOServicePlane, &ParentEntry)) == KERN_SUCCESS)
     1645        {
     1646            if (!IOObjectIsEqualTo(ChildEntry, MediaService))
     1647                IOObjectRelease(ChildEntry);
     1648
     1649            DARWIN_IOKIT_DUMP_OBJ(ParentEntry);
     1650            if (IOObjectConformsTo(ParentEntry, kIOBlockStorageDeviceClass))
     1651            {
     1652                CFTypeRef DeviceTypeValueRef = IORegistryEntryCreateCFProperty(ParentEntry,
     1653                                                                               CFSTR("device-type"),
     1654                                                                               kCFAllocatorDefault, 0);
     1655                if (   DeviceTypeValueRef
     1656                    && CFGetTypeID(DeviceTypeValueRef) == CFStringGetTypeID()
     1657                    && CFStringCompare((CFStringRef)DeviceTypeValueRef, CFSTR("Generic"),
     1658                                       kCFCompareCaseInsensitive) == kCFCompareEqualTo)
     1659                    fIsGenericStorage = true;
     1660
     1661                if (DeviceTypeValueRef != NULL)
     1662                    CFRelease(DeviceTypeValueRef);
     1663            }
     1664            ChildEntry = ParentEntry;
     1665        }
     1666        if (ChildEntry != IO_OBJECT_NULL && !IOObjectIsEqualTo(ChildEntry, MediaService))
     1667            IOObjectRelease(ChildEntry);
     1668
     1669        if (!fIsGenericStorage)
     1670        {
     1671            IOObjectRelease(MediaService);
     1672            continue;
     1673        }
     1674
     1675        CFTypeRef DeviceName;
     1676        DeviceName = IORegistryEntryCreateCFProperty(MediaService,
     1677                                                     CFSTR(kIOBSDNameKey),
     1678                                                     kCFAllocatorDefault,0);
     1679        if (DeviceName)
     1680        {
     1681            char szDeviceFilePath[MAXPATHLEN];
     1682            strcpy(szDeviceFilePath, _PATH_DEV);
     1683            size_t cchPathSize = strlen(szDeviceFilePath);
     1684            if (CFStringGetCString((CFStringRef)DeviceName,
     1685                                   &szDeviceFilePath[cchPathSize],
     1686                                   (CFIndex)(sizeof(szDeviceFilePath) - cchPathSize),
     1687                                   kCFStringEncodingUTF8))
     1688            {
     1689                PDARWINFIXEDDRIVE pDuplicate = pHead;
     1690                while (pDuplicate && strcmp(szDeviceFilePath, pDuplicate->szName) != 0)
     1691                    pDuplicate = pDuplicate->pNext;
     1692                if (pDuplicate == NULL)
     1693                {
     1694                    /* Get model for the IOMedia object.
     1695                     *
     1696                     * Due to vendor and product property names are different and
     1697                     * depend on interface and device type, the best way to get a drive
     1698                     * model is get IORegistry name for the IOMedia object. Usually,
     1699                     * it takes "<vendor> <product> <revision> Media" form. Noticed,
     1700                     * such naming are used by only IOMedia objects having
     1701                     * "Whole" = True and "BSDName" properties set.
     1702                     */
     1703                    io_name_t szEntryName = { 0 };
     1704                    if ((krc = IORegistryEntryGetName(MediaService, szEntryName)) == KERN_SUCCESS)
     1705                    {
     1706                        /* remove " Media" from the end of the name */
     1707                        char *pszMedia = strrchr(szEntryName, ' ');
     1708                        if (   pszMedia != NULL
     1709                            && (uintptr_t)pszMedia < (uintptr_t)&szEntryName[sizeof(szEntryName)]
     1710                            && strcmp(pszMedia, " Media") == 0)
     1711                        {
     1712                            *pszMedia = '\0';
     1713                            RTStrPurgeEncoding(szEntryName);
     1714                        }
     1715                    }
     1716                    /* Create the device path and model name in form "/device/path:model". */
     1717                    cchPathSize = strlen(szDeviceFilePath);
     1718                    size_t const cchModelSize = strlen(szEntryName);
     1719                    size_t const cbExtra = cchPathSize + 1 + cchModelSize + !!cchModelSize;
     1720                    PDARWINFIXEDDRIVE pNew = (PDARWINFIXEDDRIVE)RTMemAlloc(RT_UOFFSETOF_DYN(DARWINFIXEDDRIVE, szName[cbExtra]));
     1721                    if (pNew)
     1722                    {
     1723                        pNew->pNext = NULL;
     1724                        memcpy(pNew->szName, szDeviceFilePath, cchPathSize + 1);
     1725                        pNew->pszModel = NULL;
     1726                        if (cchModelSize)
     1727                            pNew->pszModel = (const char *)memcpy(&pNew->szName[cchPathSize + 1], szEntryName, cchModelSize + 1);
     1728
     1729                        if (pTail)
     1730                            pTail = pTail->pNext = pNew;
     1731                        else
     1732                            pTail = pHead = pNew;
     1733                    }
     1734                }
     1735            }
     1736            CFRelease(DeviceName);
     1737        }
     1738        IOObjectRelease(MediaService);
     1739        i++;
     1740    }
     1741    IOObjectRelease(MediaServices);
    15721742
    15731743    return pHead;
Note: See TracChangeset for help on using the changeset viewer.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette