VirtualBox

Changeset 85929 in vbox


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

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

Location:
trunk
Files:
2 added
19 edited

Legend:

Unmodified
Added
Removed
  • trunk/doc/manual/en_US/user_AdvancedTopics.xml

    r84012 r85929  
    14211421        </para>
    14221422
    1423 <screen>$ VBoxManage internalcommands createrawvmdk -filename \
    1424 /path/to/file.vmdk -rawdisk /dev/sda</screen>
     1423<screen>$ VBoxManage createmedium disk --filename /path/to/file.vmdk --format=VMDK
     1424 --variant RawDisk --property RawDrive=/dev/sda</screen>
    14251425
    14261426        <para>
     
    14351435          for example use <filename>\\.\PhysicalDrive0</filename>. On a
    14361436          Mac OS X host, instead of the above device specification use
    1437           for example <filename>/dev/disk1</filename>. Note that on Mac
    1438           OS X you can only get access to an entire disk if no volume is
     1437          for example <filename>/dev/rdisk1</filename>. Note that on Mac
     1438          OS X you can only get access to entire disk if no volume is
    14391439          mounted from it.
    14401440        </para>
     
    14881488        </para>
    14891489
    1490 <screen>$ VBoxManage internalcommands createrawvmdk -filename \
    1491 /path/to/file.vmdk -rawdisk /dev/sda -partitions 1,5</screen>
     1490<screen>$ VBoxManage createmedium disk --filename /path/to/file.vmdk --format=VMDK
     1491--variant RawDisk --property RawDrive=/dev/sda --property Partitions=1,5</screen>
    14921492
    14931493        <para>
    14941494          The command is identical to the one for full hard disk access,
    1495           except for the additional <option>-partitions</option>
     1495          except for the additional
     1496          <option>--property Partitions=1,5</option>
    14961497          parameter. This example would create the image
    1497           <filename>/<replaceable>path-to-file</replaceable>.vmdk</filename>,
     1498          <filename>/path/to/file.vmdk</filename>,
    14981499          which must be absolute, and partitions 1 and 5 of
    14991500          <filename>/dev/sda</filename> would be made accessible to the
     
    15121513          use for example <filename>\\.\PhysicalDrive0</filename>. On a
    15131514          Mac OS X host, instead of the above device specification use
    1514           <filename>/dev/disk1</filename>, for example. Note that on OS
    1515           X you can only use partitions which are not mounted. Eject the
    1516           respective volume first. Partition numbers are the same on
    1517           Linux, Windows, and Mac OS X hosts.
     1515          <filename>/dev/rdisk1</filename>, for example. Note that on OS
     1516          X you can only use partitions which are not mounted. Unmount
     1517          the respective disk first using
     1518          <emphasis>diskutil unmountDisk <filename>/dev/diskX</filename></emphasis>.
     1519          Partition numbers are the same on Linux, Windows, and Mac OS X hosts.
    15181520        </para>
    15191521
     
    15231525        </para>
    15241526
    1525 <screen>$ VBoxManage internalcommands listpartitions -rawdisk /dev/sda</screen>
    1526 
    1527         <para>
    1528           The output lists the partition types and sizes to give the
    1529           user enough information to identify the partitions necessary
    1530           for the guest.
     1527<screen>$ VBoxManage list hostdrives</screen>
     1528
     1529        <para>
     1530          The output lists available drives and their partitions with
     1531          the partition types and sizes to give the user enough information
     1532          to identify the partitions necessary for the guest.
    15311533        </para>
    15321534
     
    15481550        </para>
    15491551
    1550 <screen>$ VBoxManage internalcommands createrawvmdk -filename \
    1551 /path/to/file.vmdk -rawdisk /dev/sda -partitions 1,5 -relative</screen>
     1552<screen>$ VBoxManage createmedium disk --filename /path/to/file.vmdk --format=VMDK
     1553--variant RawDisk --property RawDrive=/dev/sda --property Partitions=1,5
     1554--property Relative=1</screen>
    15521555
    15531556        <para>
     
    15681571          This enables for example the guest to boot directly to
    15691572          Windows, while the host boots Linux from the "same" disk. For
    1570           this purpose the <option>-mbr</option> option is provided. It
    1571           specifies a file name from which to take the MBR code. The
    1572           partition table is not modified at all, so a MBR file from a
    1573           system with totally different partitioning can be used. An
    1574           example of this is:
    1575         </para>
    1576 
    1577 <screen>$ VBoxManage internalcommands createrawvmdk -filename
    1578 /path/to/file.vmdk -rawdisk /dev/sda -partitions 1,5 -mbr winxp.mbr</screen>
     1573          this purpose the <option>--property-file
     1574          BootSector=/path/to/file/with/boot_sector</option>
     1575          parameter is provided. It specifies a file name from which to
     1576          take the MBR code. The partition table is not modified at all,
     1577          so a MBR file from a system with totally different
     1578          partitioning can be used. An example of this is:
     1579        </para>
     1580
     1581<screen>$ VBoxManage createmedium disk --filename /path/to/file.vmdk --format=VMDK
     1582--variant RawDisk --property RawDrive=/dev/sda --property Partitions=1,5
     1583--property-file BootSector=winxp.mbr</screen>
    15791584
    15801585        <para>
  • trunk/doc/manual/en_US/user_VBoxManage.xml

    r85770 r85929  
    480480          Cloud profiles are used when exporting VMs to a cloud service.
    481481          See <xref linkend="cloud-export-oci"/>.
     482        </para>
     483      </listitem>
     484
     485      <listitem>
     486        <para>
     487          <command>hostdrives</command>: Displays a list of host fixed
     488          drives with their partitions.  If you also specify
     489          <option>--long</option> or <option>-l</option> the sizes and
     490          offsets will be in bytes.
    482491        </para>
    483492      </listitem>
     
    52945303                            [--diffparent &lt;uuid&gt;|&lt;filename&gt;
    52955304                            [--format VDI|VMDK|VHD] (default: VDI)
    5296                             [--variant Standard,Fixed,Split2G,Stream,ESX]</screen>
     5305                            [--variant Standard,Fixed,Split2G,Stream,ESX,RawDisk]
     5306                            [[--property &lt;name&gt;=&lt;value&gt;]
     5307                             --property &lt;name&gt;=&lt;value&gt;]...
     5308                            [[--property-file &lt;name&gt;=&lt;/path/to/file/with/value&gt;]
     5309                             --property-file &lt;name&gt;=&lt;/path/to/file/with/value&gt;]...</screen>
    52975310
    52985311    <para>
     
    53695382            combinations are supported, and specifying mutually
    53705383            incompatible flags results in an error message. Optional.
     5384          </para>
     5385        </listitem>
     5386      </varlistentry>
     5387
     5388      <varlistentry>
     5389        <term>
     5390          <computeroutput>--property &lt;name&gt;=&lt;value&gt;</computeroutput>
     5391        </term>
     5392
     5393        <listitem>
     5394          <para>
     5395            Specifies any required file format dependent parameters in
     5396            <literal>key=value</literal> form. Optional.
     5397          </para>
     5398        </listitem>
     5399      </varlistentry>
     5400
     5401      <varlistentry>
     5402        <term>
     5403          <computeroutput>--property-file &lt;name&gt;=&lt;/path/to/file/with/value&gt;</computeroutput>
     5404        </term>
     5405
     5406        <listitem>
     5407          <para>
     5408            Specifies any required file format dependent parameters in
     5409            <literal>key=file/with/value</literal> form. The value is
     5410            taken from the file. Optional.
    53715411          </para>
    53725412        </listitem>
  • trunk/include/VBox/com/Guid.h

    r82968 r85929  
    324324    bool operator<(const RTUUID &guid) const { return ::RTUuidCompare(&mUuid, &guid) < 0; }
    325325
     326    /** Compare with a UUID string representation.
     327     * @note Not an operator as that could lead to confusion.  */
     328    bool equalsString(const char *pszUuid2) const { return ::RTUuidCompareStr(&mUuid, pszUuid2) == 0; }
     329
    326330    /**
    327331     * To directly copy the contents to a GUID, or for passing it as an input
  • trunk/include/VBox/log.h

    r85841 r85929  
    477477    /** Main group, IHost. */
    478478    LOG_GROUP_MAIN_HOST,
     479    /** Main group, IHostDrive. */
     480    LOG_GROUP_MAIN_HOSTDRIVE,
     481    /** Main group, IHostDriveList. */
     482    LOG_GROUP_MAIN_HOSTDRIVELIST,
     483    /** Main group, IHostDrivePartition. */
     484    LOG_GROUP_MAIN_HOSTDRIVEPARTITION,
    479485    /** Main group, IHostNetworkInterface. */
    480486    LOG_GROUP_MAIN_HOSTNETWORKINTERFACE,
     
    981987    "MAIN_GUESTSESSIONEVENT", \
    982988    "MAIN_HOST", \
     989    "MAIN_HOSTDRIVE", \
     990    "MAIN_HOSTDRIVELIST", \
     991    "MAIN_HOSTDRIVEPARTITION", \
    983992    "MAIN_HOSTNETWORKINTERFACE", \
    984993    "MAIN_HOSTUPDATE", \
  • trunk/src/VBox/Frontends/VBoxManage/VBoxManageDisk.cpp

    r82968 r85929  
    2929
    3030#include <iprt/asm.h>
     31#include <iprt/base64.h>
    3132#include <iprt/file.h>
    3233#include <iprt/path.h>
     
    3839#include <VBox/log.h>
    3940#include <VBox/vd.h>
     41
     42#include <list>
    4043
    4144#include "VBoxManage.h"
     
    9699            else if (!RTStrNICmp(psz, "formatted", len))
    97100                uMediumVariant |= MediumVariant_Formatted;
     101            else if (   !RTStrNICmp(psz, "raw", len)
     102                     || !RTStrNICmp(psz, "rawdisk", len))
     103                uMediumVariant |= MediumVariant_VmdkRawDisk;
    98104            else
    99105                rc = VERR_PARSE_ERROR;
     
    244250    { "--variant",      'm', RTGETOPT_REQ_STRING },
    245251    { "-variant",       'm', RTGETOPT_REQ_STRING },     // deprecated
    246     { "--property",     'p', RTGETOPT_REQ_STRING }
     252    { "--property",     'p', RTGETOPT_REQ_STRING },
     253    { "--property-file",'P', RTGETOPT_REQ_STRING },
    247254};
    248255
    249256RTEXITCODE handleCreateMedium(HandlerArg *a)
    250257{
     258    class MediumProperty
     259    {
     260    public:
     261        const char *m_pszKey;
     262        const char *m_pszValue; /**< Can be binary too. */
     263        size_t      m_cbValue;
     264        char       *m_pszFreeValue;
     265        MediumProperty() : m_pszKey(NULL), m_pszValue(NULL), m_cbValue(0), m_pszFreeValue(NULL) { }
     266        MediumProperty(MediumProperty const &a_rThat)
     267            : m_pszKey(a_rThat.m_pszKey)
     268            , m_pszValue(a_rThat.m_pszValue)
     269            , m_cbValue(a_rThat.m_cbValue)
     270            , m_pszFreeValue(NULL)
     271        {
     272            Assert(a_rThat.m_pszFreeValue == NULL); /* not expected here! */
     273        }
     274        ~MediumProperty()
     275        {
     276            RTMemFree(m_pszFreeValue);
     277            m_pszFreeValue = NULL;
     278        }
     279
     280    private:
     281        MediumProperty &operator=(MediumProperty const &a_rThat)
     282        {
     283            m_pszKey = a_rThat.m_pszKey;
     284            m_pszValue = a_rThat.m_pszValue;
     285            m_cbValue = a_rThat.m_cbValue;
     286            m_pszFreeValue = a_rThat.m_pszFreeValue;
     287            if (a_rThat.m_pszFreeValue != NULL)
     288            {
     289                m_pszFreeValue = (char *)RTMemAlloc(m_cbValue + 1);
     290                if (m_pszFreeValue)
     291                {
     292                    memcpy(m_pszFreeValue, m_pszValue, m_cbValue + 1);
     293                    m_pszValue = m_pszFreeValue;
     294                }
     295                else
     296                    RTMsgError("Out of memory copying '%s'", m_pszValue);
     297            }
     298            return *this;
     299        }
     300    };
     301    std::list<MediumProperty> lstProperties;
     302
    251303    HRESULT rc;
    252304    int vrc;
     
    254306    const char *diffparent = NULL;
    255307    uint64_t size = 0;
    256     typedef struct MEDIUMPROPERTY_LIST
    257     {
    258         struct MEDIUMPROPERTY_LIST *next;
    259         const char *key;
    260         const char *value;
    261     } MEDIUMPROPERTY, *PMEDIUMPROPERTY;
    262     PMEDIUMPROPERTY pMediumProps = NULL;
    263308    enum
    264309    {
     
    322367
    323368            case 'p':   // --property
     369            case 'P':   // --property-file
    324370            {
    325371                /* allocate property kvp, parse, and append to end of singly linked list */
    326 # define PROP_MAXLEN 256
    327                 PMEDIUMPROPERTY pNewProp = (PMEDIUMPROPERTY)RTMemAlloc(sizeof(MEDIUMPROPERTY));
    328                 if (!pNewProp)
    329                     return errorArgument("Can't allocate memory for property '%s'", ValueUnion.psz);
    330                 size_t cchKvp = RTStrNLen(ValueUnion.psz, PROP_MAXLEN);
    331                 char *pszEqual = (char *)memchr(ValueUnion.psz, '=', cchKvp);
    332                 if (pszEqual)
     372                char *pszValue = (char *)strchr(ValueUnion.psz, '=');
     373                if (!pszValue)
     374                    return RTMsgErrorExitFailure("Invalid key value pair: No '='.");
     375
     376                lstProperties.push_back(MediumProperty());
     377                MediumProperty &rNewProp = lstProperties.back();
     378                *pszValue++ = '\0';       /* Warning! Modifies argument string. */
     379                rNewProp.m_pszKey = ValueUnion.psz;
     380                if (c == 'p')
    333381                {
    334                     *pszEqual = '\0';       /* Warning! Modifies argument string. */
    335                     pNewProp->next = NULL;
    336                     pNewProp->key = (char *)ValueUnion.psz;
    337                     pNewProp->value = pszEqual + 1;
     382                    rNewProp.m_pszValue = pszValue;
     383                    rNewProp.m_cbValue  = strlen(pszValue);
    338384                }
    339                 if (pMediumProps)
     385                else // 'P'
    340386                {
    341                     PMEDIUMPROPERTY pProp;
    342                     for (pProp = pMediumProps; pProp->next; pProp = pProp->next)
    343                         continue;
    344                     pProp->next = pNewProp;
     387                    RTFILE hValueFile = NIL_RTFILE;
     388                    vrc = RTFileOpen(&hValueFile, pszValue, RTFILE_O_READ | RTFILE_O_OPEN | RTFILE_O_DENY_WRITE);
     389                    if (RT_FAILURE(vrc))
     390                        return RTMsgErrorExitFailure("Cannot open replacement value file '%s': %Rrc", pszValue, vrc);
     391
     392                    uint64_t cbValue = 0;
     393                    vrc = RTFileQuerySize(hValueFile, &cbValue);
     394                    if (RT_SUCCESS(vrc))
     395                    {
     396                        if (cbValue <= _16M)
     397                        {
     398                            rNewProp.m_cbValue  = (size_t)cbValue;
     399                            rNewProp.m_pszValue = rNewProp.m_pszFreeValue = (char *)RTMemAlloc(rNewProp.m_cbValue + 1);
     400                            if (rNewProp.m_pszFreeValue)
     401                            {
     402                                vrc = RTFileReadAt(hValueFile, 0, rNewProp.m_pszFreeValue, cbValue, NULL);
     403                                if (RT_SUCCESS(vrc))
     404                                    rNewProp.m_pszFreeValue[rNewProp.m_cbValue] = '\0';
     405                                else
     406                                    RTMsgError("Error reading replacement MBR file '%s': %Rrc", pszValue, vrc);
     407                            }
     408                            else
     409                                vrc = RTMsgErrorRc(VERR_NO_MEMORY, "Out of memory reading '%s': %Rrc", pszValue, vrc);
     410                        }
     411                        else
     412                            vrc = RTMsgErrorRc(VERR_OUT_OF_RANGE, "Replacement value file '%s' is to big: %Rhcb, max 16MiB", pszValue, cbValue);
     413                    }
     414                    else
     415                        RTMsgError("Cannot get the size of the value file '%s': %Rrc", pszValue, vrc);
     416                    RTFileClose(hValueFile);
     417                    if (RT_FAILURE(vrc))
     418                        return RTEXITCODE_FAILURE;
    345419                }
    346                 else
    347                     pMediumProps = pNewProp;
    348420                break;
    349421            }
     
    389461    if (fBase)
    390462    {
    391         if (   !filename
    392             || !*filename
    393             || size == 0)
    394             return errorSyntax(USAGE_CREATEMEDIUM, "Parameters --filename and --size are required");
     463        if (!filename || !*filename)
     464            return errorSyntax(USAGE_CREATEMEDIUM, "Parameters --filename is required");
     465        if ((enmMediumVariant & MediumVariant_VmdkRawDisk) == 0 && size == 0)
     466            return errorSyntax(USAGE_CREATEMEDIUM, "Parameters --size is required");
    395467        if (!format || !*format)
    396468        {
     
    482554    if (SUCCEEDED(rc) && pMedium)
    483555    {
    484         if (pMediumProps)
    485             for (PMEDIUMPROPERTY pProp = pMediumProps; pProp;)
     556        if (lstProperties.size() > 0)
     557        {
     558            ComPtr<IMediumFormat> pMediumFormat;
     559            CHECK_ERROR2I_RET(pMedium, COMGETTER(MediumFormat)(pMediumFormat.asOutParam()), RTEXITCODE_FAILURE);
     560            com::SafeArray<BSTR> propertyNames;
     561            com::SafeArray<BSTR> propertyDescriptions;
     562            com::SafeArray<DataType_T> propertyTypes;
     563            com::SafeArray<ULONG> propertyFlags;
     564            com::SafeArray<BSTR> propertyDefaults;
     565            CHECK_ERROR2I_RET(pMediumFormat,
     566                              DescribeProperties(ComSafeArrayAsOutParam(propertyNames),
     567                                                 ComSafeArrayAsOutParam(propertyDescriptions),
     568                                                 ComSafeArrayAsOutParam(propertyTypes),
     569                                                 ComSafeArrayAsOutParam(propertyFlags),
     570                                                 ComSafeArrayAsOutParam(propertyDefaults)),
     571                              RTEXITCODE_FAILURE);
     572
     573            for (std::list<MediumProperty>::iterator it = lstProperties.begin();
     574                 it != lstProperties.end();
     575                 ++it)
    486576            {
    487                 CHECK_ERROR(pMedium, SetProperty(Bstr(pProp->key).raw(), Bstr(pProp->value).raw()));
    488                 PMEDIUMPROPERTY next = pProp->next;
    489                 RTMemFree(pProp);
    490                 pProp = next;
     577                const char * const pszKey = it->m_pszKey;
     578                bool fBinary = true;
     579                for (size_t i = 0; i < propertyNames.size(); ++i)
     580                    if (RTUtf16CmpUtf8(propertyNames[i], pszKey) == 0)
     581                    {
     582                        fBinary = propertyTypes[i] == DataType_Int8;
     583                        break;
     584                    }
     585                if (!fBinary)
     586                    CHECK_ERROR2I_RET(pMedium, SetProperty(Bstr(pszKey).raw(), Bstr(it->m_pszValue).raw()),
     587                                      RTEXITCODE_FAILURE);
     588                else
     589                {
     590                    com::Bstr bstrBase64Value;
     591                    HRESULT hrc = bstrBase64Value.base64Encode(it->m_pszValue, it->m_cbValue);
     592                    if (FAILED(hrc))
     593                        return RTMsgErrorExit(RTEXITCODE_FAILURE, "Base64 encoding of the property %s failed. (%Rhrc)",
     594                                              pszKey, hrc);
     595                    CHECK_ERROR2I_RET(pMedium, SetProperty(Bstr(pszKey).raw(), bstrBase64Value.raw()), RTEXITCODE_FAILURE);
     596                }
    491597            }
     598        }
    492599
    493600        ComPtr<IProgress> pProgress;
  • trunk/src/VBox/Frontends/VBoxManage/VBoxManageHelp.cpp

    r85778 r85929  
    480480                     "                            groups|webcams|screenshotformats|cloudproviders|\n"
    481481#if defined(VBOX_WITH_CLOUD_NET)
    482                      "                            cloudprofiles|cloudnets|cpu-profiles\n"
     482                     "                            cloudprofiles|cloudnets|cpu-profiles|hostdrives\n"
    483483#else
    484                      "                            cloudprofiles|cpu-profiles\n"
     484                     "                            cloudprofiles|cpu-profiles|hostdrives\n"
    485485#endif
    486486                     "\n", SEP);
     
    10111011                     "                            [--format VDI|VMDK|VHD] (default: VDI)]\n"
    10121012                     "                            [--variant Standard,Fixed,Split2G,Stream,ESX,\n"
    1013                      "                                       Formatted]\n"
    1014                      "                            [[--property <name>=<value>] --property <name>=<value]...\n"
     1013                     "                                       Formatted,RawDisk]\n"
     1014                     "                            [[--property <name>=<value>] --property <name>=<value>\n"
     1015                     "                              --property-file <name>=</path/to/file/with/value>]...\n"
    10151016                     "\n", SEP);
    10161017
  • trunk/src/VBox/Frontends/VBoxManage/VBoxManageList.cpp

    r85769 r85929  
    14151415
    14161416/**
     1417 * Translates PartitionType_T to a string if possible.
     1418 * @returns read-only string if known value, @a pszUnknown if not.
     1419 */
     1420static const char *PartitionTypeToString(PartitionType_T enmType, const char *pszUnknown)
     1421{
     1422#define MY_CASE_STR(a_Type) case RT_CONCAT(PartitionType_,a_Type): return #a_Type
     1423    switch (enmType)
     1424    {
     1425        MY_CASE_STR(Empty);
     1426        MY_CASE_STR(FAT12);
     1427        MY_CASE_STR(FAT16);
     1428        MY_CASE_STR(FAT);
     1429        MY_CASE_STR(IFS);
     1430        MY_CASE_STR(FAT32CHS);
     1431        MY_CASE_STR(FAT32LBA);
     1432        MY_CASE_STR(FAT16B);
     1433        MY_CASE_STR(Extended);
     1434        MY_CASE_STR(WindowsRE);
     1435        MY_CASE_STR(LinuxSwapOld);
     1436        MY_CASE_STR(LinuxOld);
     1437        MY_CASE_STR(DragonFlyBSDSlice);
     1438        MY_CASE_STR(LinuxSwap);
     1439        MY_CASE_STR(Linux);
     1440        MY_CASE_STR(LinuxExtended);
     1441        MY_CASE_STR(LinuxLVM);
     1442        MY_CASE_STR(BSDSlice);
     1443        MY_CASE_STR(AppleUFS);
     1444        MY_CASE_STR(AppleHFS);
     1445        MY_CASE_STR(Solaris);
     1446        MY_CASE_STR(GPT);
     1447        MY_CASE_STR(EFI);
     1448        MY_CASE_STR(Unknown);
     1449        MY_CASE_STR(MBR);
     1450        MY_CASE_STR(iFFS);
     1451        MY_CASE_STR(SonyBoot);
     1452        MY_CASE_STR(LenovoBoot);
     1453        MY_CASE_STR(WindowsMSR);
     1454        MY_CASE_STR(WindowsBasicData);
     1455        MY_CASE_STR(WindowsLDMMeta);
     1456        MY_CASE_STR(WindowsLDMData);
     1457        MY_CASE_STR(WindowsRecovery);
     1458        MY_CASE_STR(WindowsStorageSpaces);
     1459        MY_CASE_STR(WindowsStorageReplica);
     1460        MY_CASE_STR(IBMGPFS);
     1461        MY_CASE_STR(LinuxData);
     1462        MY_CASE_STR(LinuxRAID);
     1463        MY_CASE_STR(LinuxRootX86);
     1464        MY_CASE_STR(LinuxRootAMD64);
     1465        MY_CASE_STR(LinuxRootARM32);
     1466        MY_CASE_STR(LinuxRootARM64);
     1467        MY_CASE_STR(LinuxHome);
     1468        MY_CASE_STR(LinuxSrv);
     1469        MY_CASE_STR(LinuxPlainDmCrypt);
     1470        MY_CASE_STR(LinuxLUKS);
     1471        MY_CASE_STR(LinuxReserved);
     1472        MY_CASE_STR(FreeBSDBoot);
     1473        MY_CASE_STR(FreeBSDData);
     1474        MY_CASE_STR(FreeBSDSwap);
     1475        MY_CASE_STR(FreeBSDUFS);
     1476        MY_CASE_STR(FreeBSDVinum);
     1477        MY_CASE_STR(FreeBSDZFS);
     1478        MY_CASE_STR(FreeBSDUnknown);
     1479        MY_CASE_STR(AppleHFSPlus);
     1480        MY_CASE_STR(AppleAPFS);
     1481        MY_CASE_STR(AppleRAID);
     1482        MY_CASE_STR(AppleRAIDOffline);
     1483        MY_CASE_STR(AppleBoot);
     1484        MY_CASE_STR(AppleLabel);
     1485        MY_CASE_STR(AppleTvRecovery);
     1486        MY_CASE_STR(AppleCoreStorage);
     1487        MY_CASE_STR(SoftRAIDStatus);
     1488        MY_CASE_STR(SoftRAIDScratch);
     1489        MY_CASE_STR(SoftRAIDVolume);
     1490        MY_CASE_STR(SoftRAIDCache);
     1491        MY_CASE_STR(AppleUnknown);
     1492        MY_CASE_STR(SolarisBoot);
     1493        MY_CASE_STR(SolarisRoot);
     1494        MY_CASE_STR(SolarisSwap);
     1495        MY_CASE_STR(SolarisBackup);
     1496        MY_CASE_STR(SolarisUsr);
     1497        MY_CASE_STR(SolarisVar);
     1498        MY_CASE_STR(SolarisHome);
     1499        MY_CASE_STR(SolarisAltSector);
     1500        MY_CASE_STR(SolarisReserved);
     1501        MY_CASE_STR(SolarisUnknown);
     1502        MY_CASE_STR(NetBSDSwap);
     1503        MY_CASE_STR(NetBSDFFS);
     1504        MY_CASE_STR(NetBSDLFS);
     1505        MY_CASE_STR(NetBSDRAID);
     1506        MY_CASE_STR(NetBSDConcatenated);
     1507        MY_CASE_STR(NetBSDEncrypted);
     1508        MY_CASE_STR(NetBSDUnknown);
     1509        MY_CASE_STR(ChromeOSKernel);
     1510        MY_CASE_STR(ChromeOSRootFS);
     1511        MY_CASE_STR(ChromeOSFuture);
     1512        MY_CASE_STR(ContLnxUsr);
     1513        MY_CASE_STR(ContLnxRoot);
     1514        MY_CASE_STR(ContLnxReserved);
     1515        MY_CASE_STR(ContLnxRootRAID);
     1516        MY_CASE_STR(HaikuBFS);
     1517        MY_CASE_STR(MidntBSDBoot);
     1518        MY_CASE_STR(MidntBSDData);
     1519        MY_CASE_STR(MidntBSDSwap);
     1520        MY_CASE_STR(MidntBSDUFS);
     1521        MY_CASE_STR(MidntBSDVium);
     1522        MY_CASE_STR(MidntBSDZFS);
     1523        MY_CASE_STR(MidntBSDUnknown);
     1524        MY_CASE_STR(OpenBSDData);
     1525        MY_CASE_STR(QNXPowerSafeFS);
     1526        MY_CASE_STR(Plan9);
     1527        MY_CASE_STR(VMWareVMKCore);
     1528        MY_CASE_STR(VMWareVMFS);
     1529        MY_CASE_STR(VMWareReserved);
     1530        MY_CASE_STR(VMWareUnknown);
     1531        MY_CASE_STR(AndroidX86Bootloader);
     1532        MY_CASE_STR(AndroidX86Bootloader2);
     1533        MY_CASE_STR(AndroidX86Boot);
     1534        MY_CASE_STR(AndroidX86Recovery);
     1535        MY_CASE_STR(AndroidX86Misc);
     1536        MY_CASE_STR(AndroidX86Metadata);
     1537        MY_CASE_STR(AndroidX86System);
     1538        MY_CASE_STR(AndroidX86Cache);
     1539        MY_CASE_STR(AndroidX86Data);
     1540        MY_CASE_STR(AndroidX86Persistent);
     1541        MY_CASE_STR(AndroidX86Vendor);
     1542        MY_CASE_STR(AndroidX86Config);
     1543        MY_CASE_STR(AndroidX86Factory);
     1544        MY_CASE_STR(AndroidX86FactoryAlt);
     1545        MY_CASE_STR(AndroidX86Fastboot);
     1546        MY_CASE_STR(AndroidX86OEM);
     1547        MY_CASE_STR(AndroidARMMeta);
     1548        MY_CASE_STR(AndroidARMExt);
     1549        MY_CASE_STR(ONIEBoot);
     1550        MY_CASE_STR(ONIEConfig);
     1551        MY_CASE_STR(PowerPCPrep);
     1552        MY_CASE_STR(XDGShrBootConfig);
     1553        MY_CASE_STR(CephBlock);
     1554        MY_CASE_STR(CephBlockDB);
     1555        MY_CASE_STR(CephBlockDBDmc);
     1556        MY_CASE_STR(CephBlockDBDmcLUKS);
     1557        MY_CASE_STR(CephBlockDmc);
     1558        MY_CASE_STR(CephBlockDmcLUKS);
     1559        MY_CASE_STR(CephBlockWALog);
     1560        MY_CASE_STR(CephBlockWALogDmc);
     1561        MY_CASE_STR(CephBlockWALogDmcLUKS);
     1562        MY_CASE_STR(CephDisk);
     1563        MY_CASE_STR(CephDiskDmc);
     1564        MY_CASE_STR(CephJournal);
     1565        MY_CASE_STR(CephJournalDmc);
     1566        MY_CASE_STR(CephJournalDmcLUKS);
     1567        MY_CASE_STR(CephLockbox);
     1568        MY_CASE_STR(CephMultipathBlock1);
     1569        MY_CASE_STR(CephMultipathBlock2);
     1570        MY_CASE_STR(CephMultipathBlockDB);
     1571        MY_CASE_STR(CephMultipathBLockWALog);
     1572        MY_CASE_STR(CephMultipathJournal);
     1573        MY_CASE_STR(CephMultipathOSD);
     1574        MY_CASE_STR(CephOSD);
     1575        MY_CASE_STR(CephOSDDmc);
     1576        MY_CASE_STR(CephOSDDmcLUKS);
     1577#ifdef VBOX_WITH_XPCOM_CPP_ENUM_HACK
     1578        case PartitionType_32BitHack: break;
     1579#endif
     1580        /* no default! */
     1581    }
     1582#undef MY_CASE_STR
     1583    return pszUnknown;
     1584}
     1585
     1586
     1587/**
     1588 * List all available host drives with their partitions.
     1589 *
     1590 * @returns See produceList.
     1591 * @param   pVirtualBox         Reference to the IVirtualBox pointer.
     1592 * @param   fOptLong            Long listing or human readable.
     1593 */
     1594static HRESULT listHostDrives(const ComPtr<IVirtualBox> pVirtualBox, bool fOptLong)
     1595{
     1596    HRESULT rc = S_OK;
     1597    ComPtr<IHost> pHost;
     1598    CHECK_ERROR2I_RET(pVirtualBox, COMGETTER(Host)(pHost.asOutParam()), hrcCheck);
     1599    com::SafeIfaceArray<IHostDrive> apHostDrives;
     1600    CHECK_ERROR2I_RET(pHost, COMGETTER(HostDrives)(ComSafeArrayAsOutParam(apHostDrives)), hrcCheck);
     1601    for (size_t i = 0; i < apHostDrives.size(); ++i)
     1602    {
     1603        ComPtr<IHostDrive> pHostDrive = apHostDrives[i];
     1604
     1605        com::Bstr bstrDrivePath;
     1606        CHECK_ERROR(pHostDrive,COMGETTER(DrivePath)(bstrDrivePath.asOutParam()));
     1607        RTPrintf("%sDrive:       %ls\n", i > 0 ? "\n" : "", bstrDrivePath.raw());
     1608
     1609        com::Bstr bstrModel;
     1610        com::Bstr bstrUuidDisk;
     1611        ULONG cbSectorSize = 0;
     1612        LONG64 cbSize = 0;
     1613        PartitioningType_T partitioningType;
     1614        HRESULT hrc;
     1615        if (   SUCCEEDED(hrc = pHostDrive->COMGETTER(Model)(bstrModel.asOutParam()))
     1616            && SUCCEEDED(hrc = pHostDrive->COMGETTER(Uuid)(bstrUuidDisk.asOutParam()))
     1617            && SUCCEEDED(hrc = pHostDrive->COMGETTER(SectorSize)(&cbSectorSize))
     1618            && SUCCEEDED(hrc = pHostDrive->COMGETTER(Size)(&cbSize))
     1619            && SUCCEEDED(hrc = pHostDrive->COMGETTER(PartitioningType)(&partitioningType)))
     1620        {
     1621            if (bstrModel.isNotEmpty())
     1622                RTPrintf("Model:       %ls\n", bstrModel.raw());
     1623            else
     1624                RTPrintf("Model:       Unknown\n");
     1625
     1626            if (partitioningType == PartitioningType_GPT || com::Guid(bstrUuidDisk).isZero())
     1627                RTPrintf("UUID:        %ls\n", bstrUuidDisk.raw());
     1628            if (fOptLong)
     1629                RTPrintf("Size:        %llu bytes (%Rhcb)\n", cbSize, cbSize);
     1630            else
     1631                RTPrintf("Size:        %Rhcb\n", cbSize);
     1632            RTPrintf("Sector Size: %u bytes\n", cbSectorSize);
     1633            RTPrintf("Scheme:      %s\n", partitioningType == PartitioningType_MBR ? "MBR" : "GPT");
     1634
     1635            com::SafeIfaceArray<IHostDrivePartition> apHostDrivesPartitions;
     1636            CHECK_ERROR(pHostDrive, COMGETTER(Partitions)(ComSafeArrayAsOutParam(apHostDrivesPartitions)));
     1637
     1638            if (partitioningType == PartitioningType_MBR)
     1639            {
     1640                if (fOptLong)
     1641                    RTPrintf("Partitions:                              First         Last\n"
     1642                             "##  Type      Byte Size     Byte Offset  Cyl/Head/Sec  Cyl/Head/Sec Active\n");
     1643                else
     1644                    RTPrintf("Partitions:                   First         Last\n"
     1645                             "##  Type  Size      Start     Cyl/Head/Sec  Cyl/Head/Sec Active\n");
     1646                for (size_t j = 0; j < apHostDrivesPartitions.size(); ++j)
     1647                {
     1648                    ComPtr<IHostDrivePartition> pHostDrivePartition = apHostDrivesPartitions[j];
     1649
     1650                    ULONG idx = 0;
     1651                    CHECK_ERROR(pHostDrivePartition, COMGETTER(Number)(&idx));
     1652                    ULONG uType = 0;
     1653                    CHECK_ERROR(pHostDrivePartition, COMGETTER(TypeMBR)(&uType));
     1654                    ULONG uStartCylinder = 0;
     1655                    CHECK_ERROR(pHostDrivePartition, COMGETTER(StartCylinder)(&uStartCylinder));
     1656                    ULONG uStartHead = 0;
     1657                    CHECK_ERROR(pHostDrivePartition, COMGETTER(StartHead)(&uStartHead));
     1658                    ULONG uStartSector = 0;
     1659                    CHECK_ERROR(pHostDrivePartition, COMGETTER(StartSector)(&uStartSector));
     1660                    ULONG uEndCylinder = 0;
     1661                    CHECK_ERROR(pHostDrivePartition, COMGETTER(EndCylinder)(&uEndCylinder));
     1662                    ULONG uEndHead = 0;
     1663                    CHECK_ERROR(pHostDrivePartition, COMGETTER(EndHead)(&uEndHead));
     1664                    ULONG uEndSector = 0;
     1665                    CHECK_ERROR(pHostDrivePartition, COMGETTER(EndSector)(&uEndSector));
     1666                    cbSize = 0;
     1667                    CHECK_ERROR(pHostDrivePartition, COMGETTER(Size)(&cbSize));
     1668                    LONG64 offStart = 0;
     1669                    CHECK_ERROR(pHostDrivePartition, COMGETTER(Start)(&offStart));
     1670                    BOOL fActive = 0;
     1671                    CHECK_ERROR(pHostDrivePartition, COMGETTER(Active)(&fActive));
     1672                    PartitionType_T enmType = PartitionType_Unknown;
     1673                    CHECK_ERROR(pHostDrivePartition, COMGETTER(Type)(&enmType));
     1674
     1675                    /* Max size & offset  here is around 16TiB with 4KiB sectors. */
     1676                    if (fOptLong) /* cb/off: max 16TiB; idx: max 64. */
     1677                        RTPrintf("%2u   %02x  %14llu  %14llu  %4u/%3u/%2u   %4u/%3u/%2u    %s   %s\n",
     1678                                 idx, uType, cbSize, offStart,
     1679                                 uStartCylinder, uStartHead, uStartSector, uEndCylinder, uEndHead, uEndSector,
     1680                                 fActive ? "yes" : "no", PartitionTypeToString(enmType, ""));
     1681                    else
     1682                        RTPrintf("%2u   %02x   %8Rhcb  %8Rhcb  %4u/%3u/%2u   %4u/%3u/%2u   %s   %s\n",
     1683                                 idx, uType, (uint64_t)cbSize, (uint64_t)offStart,
     1684                                 uStartCylinder, uStartHead, uStartSector, uEndCylinder, uEndHead, uEndSector,
     1685                                 fActive ? "yes" : "no", PartitionTypeToString(enmType, ""));
     1686                }
     1687            }
     1688            else /* GPT */
     1689            {
     1690                /* Determin the max partition type length to try reduce the table width: */
     1691                size_t cchMaxType = 0;
     1692                for (size_t j = 0; j < apHostDrivesPartitions.size(); ++j)
     1693                {
     1694                    ComPtr<IHostDrivePartition> pHostDrivePartition = apHostDrivesPartitions[j];
     1695                    PartitionType_T enmType = PartitionType_Unknown;
     1696                    CHECK_ERROR(pHostDrivePartition, COMGETTER(Type)(&enmType));
     1697                    size_t const cchTypeNm = strlen(PartitionTypeToString(enmType, "e530bf6d-2754-4e9d-b260-60a5d0b80457"));
     1698                    cchMaxType = RT_MAX(cchTypeNm, cchMaxType);
     1699                }
     1700                cchMaxType = RT_MIN(cchMaxType, RTUUID_STR_LENGTH);
     1701
     1702                if (fOptLong)
     1703                    RTPrintf("Partitions:\n"
     1704                             "## %-*s Uuid                                           Byte Size         Byte Offset Active Name\n",
     1705                             (int)cchMaxType, "Type");
     1706                else
     1707                    RTPrintf("Partitions:\n"
     1708                             "##  %-*s  Uuid                                   Size      Start   Active Name\n",
     1709                             (int)cchMaxType, "Type");
     1710
     1711                for (size_t j = 0; j < apHostDrivesPartitions.size(); ++j)
     1712                {
     1713                    ComPtr<IHostDrivePartition> pHostDrivePartition = apHostDrivesPartitions[j];
     1714
     1715                    ULONG idx = 0;
     1716                    CHECK_ERROR(pHostDrivePartition, COMGETTER(Number)(&idx));
     1717                    com::Bstr bstrUuidType;
     1718                    CHECK_ERROR(pHostDrivePartition, COMGETTER(TypeUuid)(bstrUuidType.asOutParam()));
     1719                    com::Bstr bstrUuidPartition;
     1720                    CHECK_ERROR(pHostDrivePartition, COMGETTER(Uuid)(bstrUuidPartition.asOutParam()));
     1721                    cbSize = 0;
     1722                    CHECK_ERROR(pHostDrivePartition, COMGETTER(Size)(&cbSize));
     1723                    LONG64 offStart = 0;
     1724                    CHECK_ERROR(pHostDrivePartition, COMGETTER(Start)(&offStart));
     1725                    BOOL fActive = 0;
     1726                    CHECK_ERROR(pHostDrivePartition, COMGETTER(Active)(&fActive));
     1727                    com::Bstr bstrName;
     1728                    CHECK_ERROR(pHostDrivePartition, COMGETTER(Name)(bstrName.asOutParam()));
     1729
     1730                    PartitionType_T enmType = PartitionType_Unknown;
     1731                    CHECK_ERROR(pHostDrivePartition, COMGETTER(Type)(&enmType));
     1732
     1733                    Utf8Str strTypeConv;
     1734                    const char *pszTypeNm = PartitionTypeToString(enmType, NULL);
     1735                    if (!pszTypeNm)
     1736                        pszTypeNm = (strTypeConv = bstrUuidType).c_str();
     1737                    else if (strlen(pszTypeNm) >= RTUUID_STR_LENGTH /* includes '\0' */)
     1738                        pszTypeNm -= RTUUID_STR_LENGTH - 1 - strlen(pszTypeNm);
     1739
     1740                    if (fOptLong)
     1741                        RTPrintf("%2u %-*s %36ls %19llu %19llu   %-3s  %ls\n", idx, cchMaxType, pszTypeNm,
     1742                                 bstrUuidPartition.raw(), cbSize, offStart, fActive ? "on" : "off", bstrName.raw());
     1743                    else
     1744                        RTPrintf("%2u  %-*s  %36ls  %8Rhcb  %8Rhcb  %-3s   %ls\n", idx, cchMaxType, pszTypeNm,
     1745                                 bstrUuidPartition.raw(), cbSize, offStart, fActive ? "on" : "off", bstrName.raw());
     1746                }
     1747            }
     1748        }
     1749        else
     1750            RTPrintf("Partitions and disk info for the drive %ls are not available. Error %Rhrc (%#RX32)\n",
     1751                     bstrDrivePath.raw(), hrc, hrc);
     1752    }
     1753    return rc;
     1754}
     1755
     1756
     1757/**
    14171758 * The type of lists we can produce.
    14181759 */
     
    14501791    kListCloudProviders,
    14511792    kListCloudProfiles,
    1452     kListCPUProfiles
     1793    kListCPUProfiles,
     1794    kListHostDrives
    14531795};
    14541796
     
    18072149            break;
    18082150
     2151        case kListHostDrives:
     2152            rc = listHostDrives(pVirtualBox, fOptLong);
     2153            break;
    18092154        /* No default here, want gcc warnings. */
    18102155
     
    18652210        { "cloudprofiles",      kListCloudProfiles,      RTGETOPT_REQ_NOTHING },
    18662211        { "cpu-profiles",       kListCPUProfiles,        RTGETOPT_REQ_NOTHING },
     2212        { "hostdrives",         kListHostDrives,         RTGETOPT_REQ_NOTHING },
    18672213    };
    18682214
     
    19222268            case kListCloudProfiles:
    19232269            case kListCPUProfiles:
     2270            case kListHostDrives:
    19242271                enmOptCommand = (enum ListType_T)ch;
    19252272                if (fOptMultiple)
  • trunk/src/VBox/Main/Makefile.kmk

    r85737 r85929  
    582582        src-server/HostUpdateImpl.cpp \
    583583        src-server/HostVideoInputDeviceImpl.cpp \
     584        src-server/HostDrivePartitionImpl.cpp \
     585        src-server/HostDriveImpl.cpp \
    584586        src-server/MachineImpl.cpp \
    585587        src-all/MachineLaunchVMCommonWorker.cpp \
     
    653655        src-server/freebsd/HostHardwareFreeBSD.cpp \
    654656        src-server/HostDnsServiceResolvConf.cpp
     657
     658VBoxSVC_LDFLAGS.freebsd += -lcam
    655659
    656660
  • trunk/src/VBox/Main/idl/VirtualBox.xidl

    r85769 r85929  
    15351535    </const>
    15361536  </enum>
     1537
     1538  <enum
     1539    name="PartitioningType"
     1540    uuid="64c4c806-8908-4c0b-9a51-2d7a0151321f"
     1541    >
     1542    <desc>
     1543      The type of the disk partition.
     1544    </desc>
     1545
     1546    <const name="MBR"     value="0"/>
     1547    <const name="GPT"     value="1"/>
     1548  </enum>
     1549
     1550  <enum
     1551    name="PartitionType"
     1552    uuid="84a6629c-8e9c-474c-adbb-21995671597f"
     1553    >
     1554    <desc></desc>
     1555
     1556    <!-- MBR partition IDs using the same value: -->
     1557    <const name="Empty"                 value="0"><desc>Empty partition entry</desc></const>
     1558    <const name="FAT12"                 value="1">  <desc>FAT12 if partition size less than 65536 sectors</desc></const>
     1559    <const name="FAT16"                 value="4">  <desc>FAT16 if partition size less than 65536 sectors</desc></const>
     1560    <const name="FAT"                   value="6">  <desc>FAT12 or FAT16 if partition size greater or equal than 65536 sectors</desc></const>
     1561    <const name="IFS"                   value="7">  <desc>NT and OS/2 installable file system, e.g. NTFS, exFAT, HPFS.</desc></const>
     1562    <const name="FAT32CHS"              value="11"> <desc>The FAT32 with CHS addressing.</desc></const>
     1563    <const name="FAT32LBA"              value="12"> <desc>The FAT32 with LBA addressing.</desc></const>
     1564    <const name="FAT16B"                value="14"> <desc>The FAT16 with LBA addressing.</desc></const>
     1565    <const name="Extended"              value="15"> <desc>The extended partition with LBA addressing.</desc></const>
     1566    <const name="WindowsRE"             value="39"> <desc>Windows Recovery Environment (RE) partition (hidden NTFS partition).</desc></const>
     1567    <const name="LinuxSwapOld"          value="66"> <desc>The linux swap partition (old versions).</desc></const>
     1568    <const name="LinuxOld"              value="67"> <desc>The linux native partition (old versions).</desc></const>
     1569    <const name="DragonFlyBSDSlice"     value="108"><desc>The BSD slice.</desc></const>
     1570    <const name="LinuxSwap"             value="130"><desc>The linux swap partition.</desc></const>
     1571    <const name="Linux"                 value="131"><desc>The linux native partition.</desc></const>
     1572    <const name="LinuxExtended"         value="133"><desc>The linux extended partition.</desc></const>
     1573    <const name="LinuxLVM"              value="142"><desc>The linux LVM partition.</desc></const>
     1574    <const name="BSDSlice"              value="165"><desc>The BSD slice.</desc></const>
     1575    <const name="AppleUFS"              value="168"><desc>The Apple UFS partition.</desc></const>
     1576    <const name="AppleHFS"              value="175"><desc>The Apple HFS partition.</desc></const>
     1577    <const name="Solaris"               value="191"><desc>The Apple HFS partition.</desc></const>
     1578    <const name="GPT"                   value="238"><desc>The GPT protective MBR partition.</desc></const>
     1579    <const name="EFI"                   value="239"><desc>The EFI system partition.</desc></const>
     1580
     1581    <!-- Dummy value: -->
     1582    <const name="Unknown"               value="256"><desc>Unknown partition type.</desc></const>
     1583
     1584    <!-- GPT partition types: -->
     1585    <const name="MBR"                   value="257"><desc>MBR partition scheme.</desc></const>
     1586    <const name="iFFS"                  value="258"><desc>Intel Fast Flash (iFFS) partition.</desc></const>
     1587    <const name="SonyBoot"              value="259"><desc>Sony boot partition.</desc></const>
     1588    <const name="LenovoBoot"            value="260"><desc>Lenovo boot partition.</desc></const>
     1589
     1590    <const name="WindowsMSR"            value="270"><desc>Microsoft Reserved Partition (MSR).</desc></const>
     1591    <const name="WindowsBasicData"      value="271"><desc>Windows Basic data partition</desc></const>
     1592    <const name="WindowsLDMMeta"        value="272"><desc>Windows Logical Disk Manager (LDM) metadata partition.</desc></const>
     1593    <const name="WindowsLDMData"        value="273"><desc>Windows Logical Disk Manager data partition.</desc></const>
     1594    <const name="WindowsRecovery"       value="274"><desc>Windows Recovery Environment.</desc></const>
     1595    <const name="WindowsStorageSpaces"  value="276"><desc>Windows Storage Spaces partition.</desc></const>
     1596    <const name="WindowsStorageReplica" value="277"><desc>Windows Storage Replica partition.</desc></const>
     1597    <const name="IBMGPFS"               value="275"><desc>IBM General Parallel File System (GPFS) partition.</desc></const>
     1598
     1599    <const name="LinuxData"             value="300"><desc>Linux filesystem data.</desc></const>
     1600    <const name="LinuxRAID"             value="301"><desc>Linux RAID partition.</desc></const>
     1601    <const name="LinuxRootX86"          value="302"><desc>Linux root partition for x86.</desc></const>
     1602    <const name="LinuxRootAMD64"        value="303"><desc>Linux root partition for AMD64.</desc></const>
     1603    <const name="LinuxRootARM32"        value="304"><desc>Linux root partition for ARM32.</desc></const>
     1604    <const name="LinuxRootARM64"        value="305"><desc>Linux root partition for ARM64 / AArch64.</desc></const>
     1605    <const name="LinuxHome"             value="306"><desc>Linux /home partition.</desc></const>
     1606    <const name="LinuxSrv"              value="307"><desc>Linux /srv partition..</desc></const>
     1607    <const name="LinuxPlainDmCrypt"     value="308"><desc>Linux plain dm-crypt partition.</desc></const>
     1608    <const name="LinuxLUKS"             value="309"><desc>Linux unitified key setup (LUKS) partition.</desc></const>
     1609    <const name="LinuxReserved"         value="310"><desc>Linux reserved partition.</desc></const>
     1610
     1611    <const name="FreeBSDBoot"           value="330"><desc>FreeBSD boot partition.</desc></const>
     1612    <const name="FreeBSDData"           value="331"><desc>FreeBSD data partition.</desc></const>
     1613    <const name="FreeBSDSwap"           value="332"><desc>FreeBSD swap partition.</desc></const>
     1614    <const name="FreeBSDUFS"            value="333"><desc>FreeBSD unix file system (UFS) partition.</desc></const>
     1615    <const name="FreeBSDVinum"          value="334"><desc>FreeBSD Vinum volume manager partition.</desc></const>
     1616    <const name="FreeBSDZFS"            value="335"><desc>FreeBSD ZFS partition.</desc></const>
     1617    <const name="FreeBSDUnknown"        value="359"><desc>Unknown FreeBSD partition.</desc></const>
     1618
     1619    <const name="AppleHFSPlus"          value="360"><desc>Apple hierarchical file system plus (HFS+) partition.</desc></const>
     1620    <const name="AppleAPFS"             value="361"><desc>Apple APFS/FileFault container partition.</desc></const>
     1621    <const name="AppleRAID"             value="362"><desc>Apple RAID partition.</desc></const>
     1622    <const name="AppleRAIDOffline"      value="363"><desc>Apple RAID partition, offline.</desc></const>
     1623    <const name="AppleBoot"             value="364"><desc>Apple boot partition.</desc></const>
     1624    <const name="AppleLabel"            value="365"><desc>Apple label.</desc></const>
     1625    <const name="AppleTvRecovery"       value="366"><desc>Apple TV recovery partition.</desc></const>
     1626    <const name="AppleCoreStorage"      value="367"><desc>Apple Core Storage Containe.</desc></const>
     1627    <const name="SoftRAIDStatus"        value="370"><desc>SoftRAID status.</desc></const>
     1628    <const name="SoftRAIDScratch"       value="371"><desc>SoftRAID scratch.</desc></const>
     1629    <const name="SoftRAIDVolume"        value="372"><desc>SoftRAID volume.</desc></const>
     1630    <const name="SoftRAIDCache"         value="373"><desc>SoftRAID cache.</desc></const>
     1631    <const name="AppleUnknown"          value="389"><desc>Unknown Apple partition.</desc></const>
     1632
     1633    <const name="SolarisBoot"           value="390"><desc>Solaris boot partition.</desc></const>
     1634    <const name="SolarisRoot"           value="391"><desc>Solaris root partition.</desc></const>
     1635    <const name="SolarisSwap"           value="392"><desc>Solaris swap partition.</desc></const>
     1636    <const name="SolarisBackup"         value="393"><desc>Solaris backup partition.</desc></const>
     1637    <const name="SolarisUsr"            value="394"><desc>Solaris /usr partition.</desc></const>
     1638    <const name="SolarisVar"            value="395"><desc>Solaris /var partition.</desc></const>
     1639    <const name="SolarisHome"           value="396"><desc>Solaris /home partition.</desc></const>
     1640    <const name="SolarisAltSector"      value="397"><desc>Solaris alternate sector.</desc></const>
     1641    <const name="SolarisReserved"       value="398"><desc>Solaris reserved partition.</desc></const>
     1642    <const name="SolarisUnknown"        value="419"><desc>Unknown Solaris partition.</desc></const>
     1643
     1644    <const name="NetBSDSwap"            value="420"><desc>NetBSD swap partition.</desc></const>
     1645    <const name="NetBSDFFS"             value="421"><desc>NetBSD fast file system (FFS) partition.</desc></const>
     1646    <const name="NetBSDLFS"             value="422"><desc>NetBSD log structured file system (LFS) partition.</desc></const>
     1647    <const name="NetBSDRAID"            value="423"><desc>NetBSD RAID partition.</desc></const>
     1648    <const name="NetBSDConcatenated"    value="424"><desc>NetBSD concatenated partition.</desc></const>
     1649    <const name="NetBSDEncrypted"       value="425"><desc>NetBSD encrypted partition.</desc></const>
     1650    <const name="NetBSDUnknown"         value="449"><desc>Unknown NetBSD partition.</desc></const>
     1651
     1652    <const name="ChromeOSKernel"        value="450"><desc>Chrome OS kernel partition.</desc></const>
     1653    <const name="ChromeOSRootFS"        value="451"><desc>Chrome OS root file system partition.</desc></const>
     1654    <const name="ChromeOSFuture"        value="452"><desc>Chrome OS partition reserved for future.</desc></const>
     1655
     1656    <const name="ContLnxUsr"            value="480"><desc>Container Linux /usr partition.</desc></const>
     1657    <const name="ContLnxRoot"           value="481"><desc>Container Linux resizable root filesystem partition.</desc></const>
     1658    <const name="ContLnxReserved"       value="482"><desc>Container Linux OEM customization partition.</desc></const>
     1659    <const name="ContLnxRootRAID"       value="483"><desc>Container Linux root filesystem on RAID partition.</desc></const>
     1660
     1661    <const name="HaikuBFS"              value="510"><desc>Haiku BFS</desc></const>
     1662
     1663    <const name="MidntBSDBoot"          value="540"><desc>MidnightBSD boot partition.</desc></const>
     1664    <const name="MidntBSDData"          value="541"><desc>MidnightBSD data partition.</desc></const>
     1665    <const name="MidntBSDSwap"          value="542"><desc>MidnightBSD swap partition.</desc></const>
     1666    <const name="MidntBSDUFS"           value="543"><desc>MidnightBSD unix file system (UFS) partition.</desc></const>
     1667    <const name="MidntBSDVium"          value="544"><desc>MidnightBSD Vinum volume manager partition.</desc></const>
     1668    <const name="MidntBSDZFS"           value="545"><desc>MidnightBSD ZFS partition.</desc></const>
     1669    <const name="MidntBSDUnknown"       value="569"><desc>Unknown MidnightBSD partition.</desc></const>
     1670
     1671    <const name="OpenBSDData"           value="570"><desc>OpenBSD data partition.</desc></const>
     1672
     1673    <const name="QNXPowerSafeFS"        value="600"><desc>QNX power-safe file system partition.</desc></const>
     1674
     1675    <const name="Plan9"                 value="630"><desc>Plan 9 partition.</desc></const>
     1676
     1677    <const name="VMWareVMKCore"         value="660"><desc>VMWare ESX coredump partition.</desc></const>
     1678    <const name="VMWareVMFS"            value="661"><desc>VMWare ESX virtual machine file system (VMFS) partition.</desc></const>
     1679    <const name="VMWareReserved"        value="662"><desc>VMWare ESX reserved partition.</desc></const>
     1680    <const name="VMWareUnknown"         value="689"><desc>Unknown VMWare partition.</desc></const>
     1681
     1682    <const name="AndroidX86Bootloader"  value="690"><desc>Android x86 bootloader partition.</desc></const>
     1683    <const name="AndroidX86Bootloader2" value="691"><desc>Android x86 bootloader2 partition.</desc></const>
     1684    <const name="AndroidX86Boot"        value="692"><desc>Android x86 boot partition.</desc></const>
     1685    <const name="AndroidX86Recovery"    value="693"><desc>Android x86 recovery partition.</desc></const>
     1686    <const name="AndroidX86Misc"        value="694"><desc>Android x86 misc partition.</desc></const>
     1687    <const name="AndroidX86Metadata"    value="695"><desc>Android x86 metadata partition.</desc></const>
     1688    <const name="AndroidX86System"      value="696"><desc>Android x86 system partition.</desc></const>
     1689    <const name="AndroidX86Cache"       value="697"><desc>Android x86 cache partition.</desc></const>
     1690    <const name="AndroidX86Data"        value="698"><desc>Android x86 data partition.</desc></const>
     1691    <const name="AndroidX86Persistent"  value="699"><desc>Android x86 persistent data partition.</desc></const>
     1692    <const name="AndroidX86Vendor"      value="700"><desc>Android x86 vendor partition.</desc></const>
     1693    <const name="AndroidX86Config"      value="701"><desc>Android x86 config partition.</desc></const>
     1694    <const name="AndroidX86Factory"     value="702"><desc>Android x86 factory partition.</desc></const>
     1695    <const name="AndroidX86FactoryAlt"  value="703"><desc>Android x86 alternative factory partition.</desc></const>
     1696    <const name="AndroidX86Fastboot"    value="704"><desc>Android x86 fastboot partition.</desc></const>
     1697    <const name="AndroidX86OEM"         value="705"><desc>Android x86 OEM partition.</desc></const>
     1698
     1699    <const name="AndroidARMMeta"        value="720"><desc>Android ARM meta partition.</desc></const>
     1700    <const name="AndroidARMExt"         value="721"><desc>Android ARM EXT partition.</desc></const>
     1701
     1702    <const name="ONIEBoot"              value="750"><desc>Open Network Install Environment (ONIE) boot partition.</desc></const>
     1703    <const name="ONIEConfig"            value="751"><desc>Open Network Install Environment (ONIE) config partition.</desc></const>
     1704
     1705    <const name="PowerPCPrep"           value="780"><desc>PowerPC PReP boot partition.</desc></const>
     1706
     1707    <const name="XDGShrBootConfig"      value="810"><desc>freedesktop.org shared boot loader configuration partition.</desc></const>
     1708
     1709    <const name="CephBlock"             value="830"><desc>Ceph block partition.</desc></const>
     1710    <const name="CephBlockDB"           value="831"><desc>Ceph block DB partition.</desc></const>
     1711    <const name="CephBlockDBDmc"        value="832"><desc>Ceph dm-crypt block DB partition.</desc></const>
     1712    <const name="CephBlockDBDmcLUKS"    value="833"><desc>Ceph dm-crypt Linux unitified key setup (LUKS) block DB partition.</desc></const>
     1713    <const name="CephBlockDmc"          value="834"><desc>Ceph dm-crypt block partition.</desc></const>
     1714    <const name="CephBlockDmcLUKS"      value="835"><desc>Ceph dm-crypt Linux unitified key setup (LUKS) block partition.</desc></const>
     1715    <const name="CephBlockWALog"        value="836"><desc>Ceph block write-ahead log partition.</desc></const>
     1716    <const name="CephBlockWALogDmc"     value="837"><desc>Ceph dm-crypt block write-ahead log partition.</desc></const>
     1717    <const name="CephBlockWALogDmcLUKS" value="838"><desc>Ceph dm-crypt Linux unitified key setup (LUKS) block write-ahead log partition.</desc></const>
     1718    <const name="CephDisk"              value="839"><desc>Ceph disk in creation partition.</desc></const>
     1719    <const name="CephDiskDmc"           value="840"><desc>Ceph dm-crypt disk in creation partition.</desc></const>
     1720    <const name="CephJournal"           value="841"><desc>Ceph Journal partition.</desc></const>
     1721    <const name="CephJournalDmc"        value="842"><desc>Ceph dm-crypt journal partition.</desc></const>
     1722    <const name="CephJournalDmcLUKS"    value="843"><desc>Ceph dm-crypt Linux unitified key setup (LUKS) journal partition.</desc></const>
     1723    <const name="CephLockbox"           value="844"><desc>Ceph Lockbox for dm-crypt keys partition.</desc></const>
     1724    <const name="CephMultipathBlock1"   value="845"><desc>Ceph multipath block 1 partition.</desc></const>
     1725    <const name="CephMultipathBlock2"   value="846"><desc>Ceph multipath block 2 partition.</desc></const>
     1726    <const name="CephMultipathBlockDB"  value="847"><desc>Ceph multipath block DB partition.</desc></const>
     1727    <const name="CephMultipathBLockWALog" value="848"><desc>Ceph multipath block write-ahead log partition.</desc></const>
     1728    <const name="CephMultipathJournal"  value="849"><desc>Ceph multipath journal partition.</desc></const>
     1729    <const name="CephMultipathOSD"      value="851"><desc>Ceph multipath object storage deamon (OSD) partition.</desc></const>
     1730    <const name="CephOSD"               value="852"><desc>Ceph object storage deamon (OSD) partition.</desc></const>
     1731    <const name="CephOSDDmc"            value="853"><desc>Ceph dm-crypt object storage deamon (OSD) partition.</desc></const>
     1732    <const name="CephOSDDmcLUKS"        value="854"><desc>Ceph dm-crypt Linux unitified key setup (LUKS) object storage deamon (OSD) partition.</desc></const>
     1733  </enum>
     1734
    15371735
    15381736  <!--
     
    1030010498
    1030110499  <interface
     10500    name="IHostDrivePartition" extends="$unknown"
     10501    uuid="4f529a14-ace3-407c-9c49-066e8e8027f0"
     10502    wsmap="struct"
     10503    >
     10504    <desc>
     10505      The IHostDrivePartition interface represents the partition of the host drive.
     10506      To enumerate all available drives partitions in the host, use the
     10507      <link to="IHost::hostDrives"/> attribute.
     10508    </desc>
     10509
     10510    <attribute name="number" type="unsigned long" readonly="yes">
     10511      <desc>
     10512        The number of the partition.
     10513        <!-- @todo r=bird: This is weird numbering scheme for MBR disk as it goes 1,2,3,4,5,7,9,11,...
     10514             And has no practical use.  It would be better to use the system specific device node numbering here. -->
     10515      </desc>
     10516    </attribute>
     10517
     10518    <attribute name="size" type="long long" readonly="yes">
     10519      <desc>
     10520        The partition size in bytes.
     10521      </desc>
     10522    </attribute>
     10523
     10524    <attribute name="start" type="long long" readonly="yes">
     10525      <desc>
     10526        The start byte offset of this partition in bytes relative to the
     10527        beginning of the hard disk.
     10528      </desc>
     10529    </attribute>
     10530
     10531    <attribute name="type" type="PartitionType" readonly="yes">
     10532      <desc>
     10533        A translation of <link to="IHostDrivePartition::typeMBR"/> and
     10534        <link to="IHostDrivePartition::typeUuid"/> when possible, otherwise
     10535        set to <link to="PartitionType::Unknown" />.
     10536      </desc>
     10537    </attribute>
     10538
     10539    <attribute name="active" type="boolean" readonly="yes">
     10540      <desc>
     10541        The partition is bootable when TRUE.
     10542      </desc>
     10543    </attribute>
     10544
     10545    <!-- MBR: -->
     10546
     10547    <attribute name="typeMBR" type="unsigned long" readonly="yes">
     10548      <desc>
     10549        The raw MBR partition type, 0 for non-MBR disks.
     10550      </desc>
     10551    </attribute>
     10552
     10553    <attribute name="startCylinder" type="unsigned long" readonly="yes">
     10554      <desc>
     10555        The cylinder (0..1023) of the first sector in the partition on an MBR disk, zero for not an MBR disk.
     10556      </desc>
     10557    </attribute>
     10558
     10559    <attribute name="startHead" type="unsigned long" readonly="yes">
     10560      <desc>
     10561        The head (0..255) of the first sector in the partition on an MBR disk, zero for not an MBR disk.
     10562      </desc>
     10563    </attribute>
     10564
     10565    <attribute name="startSector" type="unsigned long" readonly="yes">
     10566      <desc>
     10567        The sector (0..63) of the first sector in the partition on an MBR disk, zero for not an MBR disk.
     10568      </desc>
     10569    </attribute>
     10570
     10571    <attribute name="endCylinder" type="unsigned long" readonly="yes">
     10572      <desc>
     10573        The cylinder (0..1023) of the last sector (inclusive) in the partition on an MBR disk, zero for not an MBR disk.
     10574      </desc>
     10575    </attribute>
     10576
     10577    <attribute name="endHead" type="unsigned long" readonly="yes">
     10578      <desc>
     10579        The head (0..255) of the last sector (inclusive) in the partition on an MBR disk, zero for not an MBR disk.
     10580      </desc>
     10581    </attribute>
     10582
     10583    <attribute name="endSector" type="unsigned long" readonly="yes">
     10584      <desc>
     10585        The sector (1..63) of the last sector (inclusive) in the partition on an MBR disk, zero for not an MBR disk.
     10586      </desc>
     10587    </attribute>
     10588
     10589    <!-- GPT: -->
     10590    <attribute name="typeUuid" type="uuid" mod="string" readonly="yes">
     10591    <!-- @todo r=bird: Not sure about the casing here. typeUUID Klaus? -->
     10592      <desc>
     10593        The partition type when GUID partitioning scheme is used, NULL UUID value for not a GPT disks.
     10594      </desc>
     10595    </attribute>
     10596
     10597    <attribute name="uuid" type="uuid" mod="string" readonly="yes">
     10598      <desc>
     10599        The GUID of the partition when GUID partitioning scheme is used, NULL UUID value for not a GPT disks.
     10600      </desc>
     10601    </attribute>
     10602
     10603    <attribute name="name" type="wstring" readonly="yes">
     10604      <desc>
     10605        The name of the partition if GPT partitioning is used, empty if not a GPT disk.
     10606      </desc>
     10607    </attribute>
     10608
     10609  </interface>
     10610
     10611  <interface
     10612    name="IHostDrive" extends="$unknown"
     10613    uuid="70e2e0c3-332c-4d72-b822-2db16e2cb31b"
     10614    wsmap="managed"
     10615    >
     10616    <desc>
     10617      The IHostDrive interface represents the drive of the physical machine.
     10618      It is not complete medium description and, therefore, it is not IMedium
     10619      based. The interface is used just for getting a host drive partitions info.
     10620    </desc>
     10621
     10622    <attribute name="drivePath" type="wstring" readonly="yes" wrap-hint-server="limitedcaller">
     10623      <desc>
     10624        The path of the drive. Platform dependent.
     10625      </desc>
     10626    </attribute>
     10627
     10628    <attribute name="partitioningType" type="PartitioningType" readonly="yes">
     10629     <desc>
     10630       The scheme of the partitions the disk has.
     10631     </desc>
     10632    </attribute>
     10633
     10634    <attribute name="uuid" type="uuid" mod="string" readonly="yes">
     10635      <desc>
     10636        The GUID of the disk.
     10637      </desc>
     10638    </attribute>
     10639
     10640    <attribute name="sectorSize" type="unsigned long" readonly="yes">
     10641     <desc>
     10642       The size of the sector in bytes.
     10643     </desc>
     10644    </attribute>
     10645
     10646    <attribute name="size" type="long long" readonly="yes">
     10647     <desc>
     10648       The size of the disk in bytes.
     10649     </desc>
     10650    </attribute>
     10651
     10652    <attribute name="model" type="wstring" readonly="yes">
     10653     <desc>
     10654       The model string of the drive if available.
     10655     </desc>
     10656    </attribute>
     10657
     10658    <attribute name="partitions" type="IHostDrivePartition" readonly="yes" safearray="yes">
     10659      <desc>List of partitions available on the host drive.</desc>
     10660    </attribute>
     10661
     10662  </interface>
     10663
     10664  <interface
    1030210665    name="IHost" extends="$unknown"
    10303     uuid="16ced992-5fdc-4aba-aff5-6a39bbd7c38b"
     10666    uuid="fc0759a6-a5e2-41e1-93ca-64776335eb2d"
    1030410667    wsmap="managed"
    1030510668    reservedMethods="6" reservedAttributes="12"
     
    1039110754    <attribute name="processorOnlineCoreCount" type="unsigned long" readonly="yes">
    1039210755      <desc>Number of physical processor cores online in the host system.</desc>
     10756    </attribute>
     10757
     10758    <attribute name="hostDrives" type="IHostDrive" readonly="yes" safearray="yes">
     10759      <desc>List of the host drive available to use in the VirtualBox.</desc>
    1039310760    </attribute>
    1039410761
  • trunk/src/VBox/Main/include/AutoCaller.h

    r82968 r85929  
    333333
    334334    /**
     335     * Sets the initialization status to Succeeded to indicate limited
     336     * (partly successful) initialization but also adds the initialization
     337     * error if required for further reporting. The AutoInitSpan destructor
     338     * will place the managed VirtualBoxBase object to the Limited state.
     339     */
     340    void setLimited(HRESULT rc)
     341    {
     342        mResult = Limited;
     343        mFailedRC = rc;
     344        mpFailedEI = new ErrorInfo();
     345    }
     346
     347    /**
    335348     * Sets the initialization status to Failure to indicates failed
    336349     * initialization. The AutoInitSpan destructor will place the managed
  • trunk/src/VBox/Main/include/HostHardwareLinux.h

    r82968 r85929  
    6969     * @returns iprt status code
    7070     */
    71     int updateFloppies();
     71    int updateFloppies() RT_NOEXCEPT;
    7272
    7373    /**
     
    7676     * @returns iprt status code
    7777     */
    78     int updateDVDs();
     78    int updateDVDs() RT_NOEXCEPT;
     79
     80    /**
     81     * Search for fixed disks (HDDs) and rebuild the list, which remains empty until
     82     * the first time this method is called.
     83     * @returns iprt status code
     84     */
     85    int updateFixedDrives() RT_NOEXCEPT;
    7986
    8087    /** Get the first element in the list of floppy drives. */
     
    101108        return mDVDList.end();
    102109    }
     110
     111    /** Get the first element in the list of fixed drives. */
     112    DriveInfoList::const_iterator FixedDriveBegin()
     113    {
     114        return mFixedDriveList.begin();
     115    }
     116
     117    /** Get the last element in the list of fixed drives. */
     118    DriveInfoList::const_iterator FixedDriveEnd()
     119    {
     120        return mFixedDriveList.end();
     121    }
    103122private:
    104123    /** The list of currently available floppy drives */
     
    106125    /** The list of currently available DVD drives */
    107126    DriveInfoList mDVDList;
     127    /** The list of currently available fixed drives */
     128    DriveInfoList mFixedDriveList;
    108129};
    109130
  • trunk/src/VBox/Main/include/HostImpl.h

    r85683 r85929  
    2929class Progress;
    3030class PerformanceCollector;
     31class HostDrive;
     32class HostDrivePartition;
    3133
    3234namespace settings
     
    109111    HRESULT getProcessorCoreCount(ULONG *aProcessorCoreCount);
    110112    HRESULT getProcessorOnlineCoreCount(ULONG *aProcessorOnlineCoreCount);
     113    HRESULT getHostDrives(std::vector<ComPtr<IHostDrive> > &aHostDrives);
    111114    HRESULT getMemorySize(ULONG *aMemorySize);
    112115    HRESULT getMemoryAvailable(ULONG *aMemoryAvailable);
     
    177180    bool i_getDVDInfoFromHal(std::list< ComObjPtr<Medium> > &list);
    178181    bool i_getFloppyInfoFromHal(std::list< ComObjPtr<Medium> > &list);
     182    HRESULT i_getFixedDrivesFromHal(std::list<std::pair<com::Utf8Str, com::Utf8Str> > &list) RT_NOEXCEPT;
    179183#endif
    180184
     
    183187    void i_parseMountTable(char *mountTable, std::list< ComObjPtr<Medium> > &list);
    184188    bool i_validateDevice(const char *deviceNode, bool isCDROM);
     189    HRESULT i_getFixedDrivesFromDevTree(std::list<std::pair<com::Utf8Str, com::Utf8Str> > &list) RT_NOEXCEPT;
    185190#endif
    186191
     
    199204#endif /* VBOX_WITH_RESOURCE_USAGE_API */
    200205
     206    HRESULT i_getDrivesPathsList(std::list<std::pair<com::Utf8Str, com::Utf8Str> > &aDriveList) RT_NOEXCEPT;
     207
    201208    struct Data;        // opaque data structure, defined in HostImpl.cpp
    202209    Data *m;
  • trunk/src/VBox/Main/src-all/AutoCaller.cpp

    r82968 r85929  
    294294    }
    295295
    296     if (aNewState == InitFailed)
     296    if (aNewState == InitFailed || aNewState == Limited)
    297297    {
    298298        mFailedRC = aFailedRC;
    299         /* apFailedEI may be NULL, when there is no explicit setFailed() call,
    300          * which also implies that aFailedRC is S_OK. This case is used by
    301          * objects (the majority) which don't want delayed error signalling. */
     299        /* apFailedEI may be NULL, when there is no explicit setFailed() or
     300         * setLimited() call, which also implies that aFailedRC is S_OK.
     301         * This case is used by objects (the majority) which don't want
     302         * delayed error signalling. */
    302303        mpFailedEI = apFailedEI;
    303304    }
  • trunk/src/VBox/Main/src-all/GlobalStatusConversion.cpp

    r82968 r85929  
    108108        case VERR_NOT_EQUAL:                    return VBOX_E_FILE_ERROR;
    109109        case VERR_FILE_NOT_FOUND:               return VBOX_E_OBJECT_NOT_FOUND;
     110        case VERR_IO_NOT_READY:                 return VBOX_E_INVALID_OBJECT_STATE;
    110111
    111112        /* Guest Control errors. */
  • trunk/src/VBox/Main/src-server/HostImpl.cpp

    r85769 r85929  
    113113typedef SOLARISDVD *PSOLARISDVD;
    114114
     115/** Solaris fixed drive (SSD, HDD, ++) descriptor list entry as returned by the
     116 * solarisWalkDeviceNodeForFixedDrive callback. */
     117typedef SOLARISDVD SOLARISFIXEDDISK;
     118/** Pointer to a Solaris fixed drive (SSD, HDD, ++) descriptor. */
     119typedef SOLARISFIXEDDISK *PSOLARISFIXEDDISK;
    115120
    116121
     
    136141
    137142#include <iprt/asm-amd64-x86.h>
    138 #include <iprt/string.h>
     143#ifdef RT_OS_SOLARIS
     144# include <iprt/ctype.h>
     145#endif
     146#if defined(RT_OS_SOLARIS) || defined(RT_OS_WINDOWS)
     147# include <iprt/file.h>
     148#endif
    139149#include <iprt/mp.h>
    140 #include <iprt/time.h>
    141 #include <iprt/param.h>
    142150#include <iprt/env.h>
    143151#include <iprt/mem.h>
     152#include <iprt/param.h>
     153#include <iprt/string.h>
    144154#include <iprt/system.h>
    145155#ifndef RT_OS_WINDOWS
    146156# include <iprt/path.h>
    147157#endif
    148 #ifdef RT_OS_SOLARIS
    149 # include <iprt/ctype.h>
    150 #endif
     158#include <iprt/time.h>
     159
    151160#ifdef VBOX_WITH_HOSTNETIF_API
    152161# include "netif.h"
     
    169178
    170179#include "HostDnsService.h"
     180#include "HostDriveImpl.h"
     181#include "HostDrivePartitionImpl.h"
    171182
    172183////////////////////////////////////////////////////////////////////////////////
     
    19711982
    19721983
     1984HRESULT  Host::getHostDrives(std::vector<ComPtr<IHostDrive> > &aHostDrives)
     1985{
     1986    std::list<std::pair<com::Utf8Str, com::Utf8Str> > llDrivesPathsList;
     1987    HRESULT hrc = i_getDrivesPathsList(llDrivesPathsList);
     1988    if (SUCCEEDED(hrc))
     1989    {
     1990        for (std::list<std::pair<com::Utf8Str, com::Utf8Str> >::const_iterator it = llDrivesPathsList.begin();
     1991             it != llDrivesPathsList.end();
     1992             ++it)
     1993        {
     1994            ComObjPtr<HostDrive> pHostDrive;
     1995            hrc = pHostDrive.createObject();
     1996            if (SUCCEEDED(hrc))
     1997                hrc = pHostDrive->initFromPathAndModel(it->first, it->second);
     1998            if (FAILED(hrc))
     1999                break;
     2000            aHostDrives.push_back(pHostDrive);
     2001        }
     2002    }
     2003    return hrc;
     2004}
     2005
     2006
    19732007// public methods only for internal purposes
    19742008////////////////////////////////////////////////////////////////////////////////
     
    25582592static char *solarisGetSliceFromPath(const char *pszDevLinkPath)
    25592593{
    2560     char *pszFound = NULL;
    2561     char *pszSlice = strrchr(pszDevLinkPath, 's');
    2562     char *pszDisk  = strrchr(pszDevLinkPath, 'd');
    2563     if (pszSlice && pszSlice > pszDisk)
     2594    char *pszSlice = (char *)strrchr(pszDevLinkPath, 's');
     2595    char *pszDisk  = (char *)strrchr(pszDevLinkPath, 'd');
     2596    char *pszFound;
     2597    if (pszSlice && (uintptr_t)pszSlice > (uintptr_t)pszDisk)
    25642598        pszFound = pszSlice;
    25652599    else
     
    25762610 *
    25772611 * @param   DevLink     Handle to the device link being walked.
    2578  * @param   pvArg       Opaque data containing the pointer to the path.
    2579  * @returns Pointer to an allocated device path string.
     2612 * @param   pvArg       Opaque pointer that we use to point to the return
     2613 *                      variable (char *).  Caller must call RTStrFree on it.
     2614 * @returns DI_WALK_TERMINATE to stop the walk.
    25802615 */
    25812616static int solarisWalkDevLink(di_devlink_t DevLink, void *pvArg)
    25822617{
    25832618    char **ppszPath = (char **)pvArg;
    2584     *ppszPath = strdup(di_devlink_path(DevLink));
     2619    *ppszPath = RTStrDup(di_devlink_path(DevLink));
    25852620    return DI_WALK_TERMINATE;
    25862621}
     
    26552690                                        RTStrPrintf(pDrive->szDescription, sizeof(pDrive->szDescription),
    26562691                                                    "%s %s", pszVendor, pszProduct);
     2692                                        RTStrPurgeEncoding(pDrive->szDescription);
    26572693                                        RTStrCopy(pDrive->szRawDiskPath, sizeof(pDrive->szRawDiskPath), pszDevLinkPath);
    26582694                                        if (*ppDrives)
     
    26612697
    26622698                                        /* We're not interested in any of the other slices, stop minor nodes traversal. */
    2663                                         free(pszDevLinkPath);
     2699                                        RTStrFree(pszDevLinkPath);
    26642700                                        break;
    26652701                                    }
    26662702                                }
    2667                                 free(pszDevLinkPath);
     2703                                RTStrFree(pszDevLinkPath);
    26682704                            }
    26692705                        }
     
    27032739}
    27042740
     2741
     2742/**
     2743 * Walk all devices in the system and enumerate fixed drives.
     2744 * @param   Node        Handle to the current node.
     2745 * @param   pvArg       Opaque data (holds list pointer).
     2746 * @returns Solaris specific code whether to continue walking or not.
     2747 */
     2748static int solarisWalkDeviceNodeForFixedDrive(di_node_t Node, void *pvArg) RT_NOEXCEPT
     2749{
     2750    PSOLARISFIXEDDISK *ppDrives = (PSOLARISFIXEDDISK *)pvArg;
     2751
     2752    int *pInt = NULL;
     2753    if (    di_prop_lookup_ints(DDI_DEV_T_ANY, Node, "inquiry-device-type", &pInt) > 0
     2754        && *pInt == DTYPE_DIRECT) /* Fixed drive */
     2755    {
     2756        char *pszProduct = NULL;
     2757        if (di_prop_lookup_strings(DDI_DEV_T_ANY, Node, "inquiry-product-id", &pszProduct) > 0)
     2758        {
     2759            char *pszVendor = NULL;
     2760            if (di_prop_lookup_strings(DDI_DEV_T_ANY, Node, "inquiry-vendor-id", &pszVendor) > 0)
     2761            {
     2762                /*
     2763                 * Found a fixed drive, we need to scan the minor nodes to find the correct
     2764                 * slice that represents the whole drive.
     2765                 */
     2766                int Major = di_driver_major(Node);
     2767                di_minor_t Minor = DI_MINOR_NIL;
     2768                di_devlink_handle_t DevLink = di_devlink_init(NULL /* name */, 0 /* flags */);
     2769                if (DevLink)
     2770                {
     2771                    /*
     2772                     * The device name we have to select depends on drive type. For fixed drives, the
     2773                     * name without slice or partition should be selected, for USB flash drive the
     2774                     * partition 0 should be selected and slice 0 for other cases.
     2775                     */
     2776                    char *pszDisk       = NULL;
     2777                    char *pszPartition0 = NULL;
     2778                    char *pszSlice0     = NULL;
     2779                    while ((Minor = di_minor_next(Node, Minor)) != DI_MINOR_NIL)
     2780                    {
     2781                        dev_t Dev = di_minor_devt(Minor);
     2782                        if (   Major != (int)major(Dev)
     2783                            || di_minor_spectype(Minor) == S_IFBLK
     2784                            || di_minor_type(Minor) != DDM_MINOR)
     2785                            continue;
     2786
     2787                        char *pszMinorPath = di_devfs_minor_path(Minor);
     2788                        if (!pszMinorPath)
     2789                            continue;
     2790
     2791                        char *pszDevLinkPath = NULL;
     2792                        di_devlink_walk(DevLink, NULL, pszMinorPath, DI_PRIMARY_LINK, &pszDevLinkPath, solarisWalkDevLink);
     2793                        di_devfs_path_free(pszMinorPath);
     2794
     2795                        if (pszDevLinkPath)
     2796                        {
     2797                            char const *pszCurSlice = strrchr(pszDevLinkPath, 's');
     2798                            char const *pszCurDisk  = strrchr(pszDevLinkPath, 'd');
     2799                            char const *pszCurPart  = strrchr(pszDevLinkPath, 'p');
     2800                            char **ppszDst  = NULL;
     2801                            if (pszCurSlice && (uintptr_t)pszCurSlice > (uintptr_t)pszCurDisk && !strcmp(pszCurSlice, "s0"))
     2802                                ppszDst = &pszSlice0;
     2803                            else if (pszCurPart && (uintptr_t)pszCurPart > (uintptr_t)pszCurDisk && !strcmp(pszCurPart, "p0"))
     2804                                ppszDst = &pszPartition0;
     2805                            else if (   (!pszCurSlice || (uintptr_t)pszCurSlice < (uintptr_t)pszCurDisk)
     2806                                     && (!pszCurPart  || (uintptr_t)pszCurPart  < (uintptr_t)pszCurDisk)
     2807                                     && *pszDevLinkPath != '\0')
     2808                                ppszDst = &pszDisk;
     2809                            else
     2810                                RTStrFree(pszDevLinkPath);
     2811                            if (ppszDst)
     2812                            {
     2813                                if (*ppszDst != NULL)
     2814                                    RTStrFree(*ppszDst);
     2815                                *ppszDst = pszDevLinkPath;
     2816                            }
     2817                        }
     2818                    }
     2819                    di_devlink_fini(&DevLink);
     2820                    if (pszDisk || pszPartition0 || pszSlice0)
     2821                    {
     2822                        PSOLARISFIXEDDISK pDrive = (PSOLARISFIXEDDISK)RTMemAllocZ(sizeof(*pDrive));
     2823                        if (RT_LIKELY(pDrive))
     2824                        {
     2825                            RTStrPrintf(pDrive->szDescription, sizeof(pDrive->szDescription), "%s %s", pszVendor, pszProduct);
     2826                            RTStrPurgeEncoding(pDrive->szDescription);
     2827
     2828                            const char *pszDevPath = pszDisk ? pszDisk : pszPartition0 ? pszPartition0 : pszSlice0;
     2829                            int rc = RTStrCopy(pDrive->szRawDiskPath, sizeof(pDrive->szRawDiskPath), pszDevPath);
     2830                            AssertRC(rc);
     2831
     2832                            if (*ppDrives)
     2833                                pDrive->pNext = *ppDrives;
     2834                            *ppDrives = pDrive;
     2835                        }
     2836                        RTStrFree(pszDisk);
     2837                        RTStrFree(pszPartition0);
     2838                        RTStrFree(pszSlice0);
     2839                    }
     2840                }
     2841            }
     2842        }
     2843    }
     2844    return DI_WALK_CONTINUE;
     2845}
     2846
     2847
     2848/**
     2849 * Solaris specific function to enumerate fixed drives via the device tree.
     2850 * Works on Solaris 10 as well as OpenSolaris without depending on libhal.
     2851 *
     2852 * @returns COM status, either S_OK or E_OUTOFMEMORY.
     2853 * @param   list        Reference to list where the the path/model pairs are to
     2854 *                      be returned.
     2855 */
     2856HRESULT Host::i_getFixedDrivesFromDevTree(std::list<std::pair<com::Utf8Str, com::Utf8Str> > &list) RT_NOEXCEPT
     2857{
     2858    PSOLARISFIXEDDISK pDrives = NULL;
     2859    di_node_t RootNode = di_init("/", DINFOCPYALL);
     2860    if (RootNode != DI_NODE_NIL)
     2861        di_walk_node(RootNode, DI_WALK_CLDFIRST, &pDrives, solarisWalkDeviceNodeForFixedDrive);
     2862    di_fini(RootNode);
     2863
     2864    HRESULT hrc = S_OK;
     2865    try
     2866    {
     2867        for (PSOLARISFIXEDDISK pCurDrv = pDrives; pCurDrv; pCurDrv = pCurDrv->pNext)
     2868            list.push_back(std::pair<com::Utf8Str, com::Utf8Str>(pCurDrv->szRawDiskPath, pCurDrv->szDescription));
     2869    }
     2870    catch (std::bad_alloc &)
     2871    {
     2872        LogRelFunc(("Out of memory!\n"));
     2873        list.clear();
     2874        hrc = E_OUTOFMEMORY;
     2875    }
     2876
     2877    while (pDrives)
     2878    {
     2879        PSOLARISFIXEDDISK pFreeMe = pDrives;
     2880        pDrives = pDrives->pNext;
     2881        ASMCompilerBarrier();
     2882        RTMemFree(pFreeMe);
     2883    }
     2884
     2885    return hrc;
     2886}
     2887
     2888
    27052889/* Solaris hosts, loading libhal at runtime */
    27062890
     
    27102894 *
    27112895 * @returns true if information was successfully obtained, false otherwise
    2712  * @retval  list drives found will be attached to this list
     2896 * @param   list        Reference to list where the DVDs drives are to be returned.
    27132897 */
    27142898bool Host::i_getDVDInfoFromHal(std::list<ComObjPtr<Medium> > &list)
     
    30213205    return halSuccess;
    30223206}
     3207
     3208
     3209/**
     3210 * Helper function to query the hal subsystem for information about fixed drives attached to the
     3211 * system.
     3212 *
     3213 * @returns COM status code. (setError is not called on failure as we only fail
     3214 *          with E_OUTOFMEMORY.)
     3215 * @retval  S_OK on success.
     3216 * @retval  S_FALSE if HAL cannot be used.
     3217 * @param   list        Reference to list to return the path/model string pairs.
     3218 */
     3219HRESULT Host::i_getFixedDrivesFromHal(std::list<std::pair<com::Utf8Str, com::Utf8Str> > &list) RT_NOEXCEPT
     3220{
     3221    HRESULT hrc = S_FALSE;
     3222    if (!gLibHalCheckPresence())
     3223        return hrc;
     3224
     3225    DBusError dbusError;
     3226    gDBusErrorInit(&dbusError);
     3227    DBusConnection *dbusConnection = gDBusBusGet(DBUS_BUS_SYSTEM, &dbusError);
     3228    if (dbusConnection != 0)
     3229    {
     3230        LibHalContext *halContext = gLibHalCtxNew();
     3231        if (halContext != 0)
     3232        {
     3233            if (gLibHalCtxSetDBusConnection(halContext, dbusConnection))
     3234            {
     3235                if (gLibHalCtxInit(halContext, &dbusError))
     3236                {
     3237                    int cDevices;
     3238                    char **halDevices = gLibHalFindDeviceStringMatch(halContext, "storage.drive_type", "disk",
     3239                                                                     &cDevices, &dbusError);
     3240                    if (halDevices != 0)
     3241                    {
     3242                        /* Hal is installed and working, so if no devices are reported, assume
     3243                           that there are none. */
     3244                        hrc = S_OK;
     3245                        for (int i = 0; i < cDevices && hrc == S_OK; i++)
     3246                        {
     3247                            char *pszDevNode = gLibHalDeviceGetPropertyString(halContext, halDevices[i], "block.device",
     3248                                                                              &dbusError);
     3249                            /* The fixed drive ioctls work only for raw device nodes. */
     3250                            char *pszTmp = getfullrawname(pszDevNode);
     3251                            gLibHalFreeString(pszDevNode);
     3252                            pszDevNode = pszTmp;
     3253                            if (pszDevNode != 0)
     3254                            {
     3255                                /* We do not check the error here, as this field may
     3256                                   not even exist. */
     3257                                char *pszVendor = gLibHalDeviceGetPropertyString(halContext, halDevices[i], "info.vendor", 0);
     3258                                char *pszProduct = gLibHalDeviceGetPropertyString(halContext, halDevices[i], "info.product",
     3259                                                                                  &dbusError);
     3260                                Utf8Str strDescription;
     3261                                if (pszProduct != NULL && pszProduct[0] != '\0')
     3262                                {
     3263                                    int rc;
     3264                                    if (pszVendor != NULL && pszVendor[0] != '\0')
     3265                                        vrc = strDescription.printfNoThrow("%s %s", pszVendor, pszProduct);
     3266                                    else
     3267                                        vrc = strDescription.assignNoThrow(pszProduct);
     3268                                    AssertRCStmt(vrc, hrc = E_OUTOFMEMORY);
     3269                                }
     3270                                if (pszVendor != NULL)
     3271                                    gLibHalFreeString(pszVendor);
     3272                                if (pszProduct != NULL)
     3273                                    gLibHalFreeString(pszProduct);
     3274
     3275                                /* Correct device/partition/slice already choosen. Just add it to the return list */
     3276                                if (hrc == S_OK)
     3277                                    try
     3278                                    {
     3279                                        list.push_back(std::pair<com::Utf8Str, com::Utf8Str>(pszDevNode, strDescription));
     3280                                    }
     3281                                    catch (std::bad_alloc &)
     3282                                    {
     3283                                        AssertFailedStmt(hrc = E_OUTOFMEMORY);
     3284                                    }
     3285                                gLibHalFreeString(pszDevNode);
     3286                            }
     3287                            else
     3288                            {
     3289                                LogRel(("Host::COMGETTER(HostDrives): failed to get property \"block.device\" for device %s.  dbus error: %s (%s)\n",
     3290                                        halDevices[i], dbusError.name, dbusError.message));
     3291                                gDBusErrorFree(&dbusError);
     3292                            }
     3293                        }
     3294                        gLibHalFreeStringArray(halDevices);
     3295                    }
     3296                    else
     3297                    {
     3298                        LogRel(("Host::COMGETTER(HostDrives): failed to get devices with capability \"storage.disk\".  dbus error: %s (%s)\n", dbusError.name, dbusError.message));
     3299                        gDBusErrorFree(&dbusError);
     3300                    }
     3301                    if (!gLibHalCtxShutdown(halContext, &dbusError))  /* what now? */
     3302                    {
     3303                        LogRel(("Host::COMGETTER(HostDrives): failed to shutdown the libhal context.  dbus error: %s (%s)\n",
     3304                                dbusError.name, dbusError.message));
     3305                        gDBusErrorFree(&dbusError);
     3306                    }
     3307                }
     3308                else
     3309                {
     3310                    LogRel(("Host::COMGETTER(HostDrives): failed to initialise libhal context.  dbus error: %s (%s)\n",
     3311                            dbusError.name, dbusError.message));
     3312                    gDBusErrorFree(&dbusError);
     3313                }
     3314                gLibHalCtxFree(halContext);
     3315            }
     3316            else
     3317                LogRel(("Host::COMGETTER(HostDrives): failed to set libhal connection to dbus.\n"));
     3318        }
     3319        else
     3320            LogRel(("Host::COMGETTER(HostDrives): failed to get a libhal context - out of memory?\n"));
     3321        gDBusConnectionUnref(dbusConnection);
     3322    }
     3323    else
     3324    {
     3325        LogRel(("Host::COMGETTER(HostDrives): failed to connect to dbus.  dbus error: %s (%s)\n",
     3326                dbusError.name, dbusError.message));
     3327        gDBusErrorFree(&dbusError);
     3328    }
     3329    return hrc;
     3330}
     3331
    30233332#endif  /* RT_OS_SOLARIS and VBOX_USE_HAL */
    30243333
     
    35743883}
    35753884
     3885/**
     3886 * @throws nothing
     3887 */
     3888HRESULT Host::i_getDrivesPathsList(std::list<std::pair<com::Utf8Str, com::Utf8Str> > &aDriveList) RT_NOEXCEPT
     3889{
     3890#ifdef RT_OS_WINDOWS
     3891    /** @todo r=bird: This approach is seriously flawed. The "Count" value refers to
     3892     * the registry entries next to it and as little if anything to do with
     3893     * PhysicalDriveX numbering.  The registry entries doesn't immediately give
     3894     * you the PhysicalDrive address either.
     3895     *
     3896     * One option would be to enumerate the \Device or \GLOBAL?? directories looking
     3897     * for Harddisk* directories and PhysicalDrive* symlinks respectively.  This can
     3898     * be explored using
     3899     *  - "out\win.amd64\debug\bin\tools\RTLs.exe -la \\:iprtnt:\Device"
     3900     *  - "out\win.amd64\debug\bin\tools\RTLs.exe -la \\:iprtnt:\GLOBAL??"
     3901     *  - WinObj from sysinternals.
     3902     *
     3903     * "wmic diskdrive list" somehow gets the info too.   There is more here:
     3904     * https://stackoverflow.com/questions/327718/how-to-list-physical-disks
     3905     *
     3906     * A third option would be to just be to go significantly higher than what
     3907     * "Count" indicates, to span gaps and stuff.
     3908     *
     3909     *
     3910     * How to create gaps in the PhysicalDriveX numbers:
     3911     *      1. Insert 2 USB sticks to you box.
     3912     *      2. Remove the first USB stick you inserted.
     3913     *      3. You've got a gap: RTLs -la \\:iprtnt:\GLOBAL?? | grep PhysicalDrive
     3914     */
     3915    HKEY hKeyEnum = (HKEY)INVALID_HANDLE_VALUE;
     3916    LONG lRc = RegOpenKeyExW(HKEY_LOCAL_MACHINE,
     3917                             L"SYSTEM\\CurrentControlSet\\Services\\Disk\\Enum",
     3918                             0,
     3919                             KEY_READ | KEY_QUERY_VALUE,
     3920                             &hKeyEnum);
     3921    if (lRc != ERROR_SUCCESS)
     3922        return setError(E_FAIL, tr("Failed to open key Disk\\Enum (error %u/%#x)"), lRc, lRc);
     3923
     3924    DWORD cCount = 0;
     3925    DWORD cBufSize = sizeof(cCount);
     3926    lRc = RegQueryValueExW(hKeyEnum, L"Count", NULL, NULL, (PBYTE)&cCount, &cBufSize);
     3927    RegCloseKey(hKeyEnum);
     3928    if (lRc != ERROR_SUCCESS)
     3929        return setError(E_FAIL, tr("Failed to get physical drives count (error %u/%#x)"), lRc, lRc);
     3930
     3931    for (uint32_t i = 0; i < cCount; ++i)
     3932    {
     3933        char szPhysicalDrive[64];
     3934        RTStrPrintf(szPhysicalDrive, sizeof(szPhysicalDrive), "\\\\.\\PhysicalDrive%d", i);
     3935
     3936        /** @todo r=bird: Why RTFILE_O_DENY_WRITE? */
     3937        RTFILE hRawFile = NIL_RTFILE;
     3938        int vrc = RTFileOpen(&hRawFile, szPhysicalDrive, RTFILE_O_READ | RTFILE_O_OPEN | RTFILE_O_DENY_WRITE);
     3939        if (RT_FAILURE(vrc))
     3940            continue; /** @todo r=bird: you might not be able to open all disks... */
     3941
     3942        DWORD   cbBytesReturned = 0;
     3943        uint8_t abBuffer[1024];
     3944        RT_ZERO(abBuffer);
     3945
     3946        STORAGE_PROPERTY_QUERY query;
     3947        RT_ZERO(query);
     3948        query.PropertyId = StorageDeviceProperty;
     3949        query.QueryType  = PropertyStandardQuery;
     3950
     3951        BOOL fRc = DeviceIoControl((HANDLE)RTFileToNative(hRawFile),
     3952                                   IOCTL_STORAGE_QUERY_PROPERTY, &query, sizeof(query),
     3953                                   abBuffer, sizeof(abBuffer), &cbBytesReturned, NULL);
     3954        RTFileClose(hRawFile);
     3955        char szModel[1024];
     3956        if (fRc)
     3957        {
     3958            PSTORAGE_DEVICE_DESCRIPTOR pDevDescriptor = (PSTORAGE_DEVICE_DESCRIPTOR)abBuffer;
     3959            char *pszProduct = pDevDescriptor->ProductIdOffset ? (char *)&abBuffer[pDevDescriptor->ProductIdOffset] : NULL;
     3960            if (pszProduct)
     3961            {
     3962                RTStrPurgeEncoding(pszProduct);
     3963                if (*pszProduct != '\0')
     3964                {
     3965                    char *pszVendor = pDevDescriptor->VendorIdOffset  ? (char *)&abBuffer[pDevDescriptor->VendorIdOffset] : NULL;
     3966                    if (pszVendor)
     3967                        RTStrPurgeEncoding(pszVendor);
     3968                    if (pszVendor && *pszVendor)
     3969                        RTStrPrintf(szModel, sizeof(szModel), "%s %s", pszVendor, pszProduct);
     3970                    else
     3971                        RTStrCopy(szModel, sizeof(szModel), pszProduct);
     3972                }
     3973            }
     3974        }
     3975        try
     3976        {
     3977            aDriveList.push_back(std::pair<com::Utf8Str, com::Utf8Str>(szPhysicalDrive, szModel));
     3978        }
     3979        catch (std::bad_alloc &)
     3980        {
     3981            aDriveList.clear();
     3982            return E_OUTOFMEMORY;
     3983        }
     3984    }
     3985
     3986    return S_OK;
     3987
     3988#elif defined(RT_OS_DARWIN)
     3989    /*
     3990     * Get the list of fixed drives from iokit.cpp and transfer it to aDriveList.
     3991     */
     3992    PDARWINFIXEDDRIVE pDrives = DarwinGetFixedDrives();
     3993    HRESULT hrc;
     3994    try
     3995    {
     3996        for (PDARWINFIXEDDRIVE pCurDrv = pDrives; pCurDrv; pCurDrv = pCurDrv->pNext)
     3997            aDriveList.push_back(std::pair<com::Utf8Str, com::Utf8Str>(pCurDrv->szName, pCurDrv->pszModel));
     3998        hrc = S_OK;
     3999    }
     4000    catch (std::bad_alloc &)
     4001    {
     4002        aDriveList.clear();
     4003        hrc = E_OUTOFMEMORY;
     4004    }
     4005
     4006    while (pDrives)
     4007    {
     4008        PDARWINFIXEDDRIVE pFreeMe = pDrives;
     4009        pDrives = pDrives->pNext;
     4010        ASMCompilerBarrier();
     4011        RTMemFree(pFreeMe);
     4012    }
     4013    return hrc;
     4014
     4015#elif defined(RT_OS_LINUX) || defined(RT_OS_FREEBSD)
     4016    /*
     4017     * The list of fixed drives is kept in the VBoxMainDriveInfo instance, so
     4018     * update it and tranfer the info to aDriveList.
     4019     *
     4020     * This obviously requires us to write lock the object!
     4021     */
     4022    AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
     4023    int vrc = m->hostDrives.updateFixedDrives(); /* nothrow */
     4024    if (RT_FAILURE(vrc))
     4025        return setErrorBoth(E_FAIL, vrc, tr("Failed to update fixed drive list (%Rrc)"), vrc);
     4026
     4027    try
     4028    {
     4029        for (DriveInfoList::const_iterator it = m->hostDrives.FixedDriveBegin(); it != m->hostDrives.FixedDriveEnd(); ++it)
     4030            aDriveList.push_back(std::pair<com::Utf8Str, com::Utf8Str>(it->mDevice, it->mDescription));
     4031    }
     4032    catch (std::bad_alloc &)
     4033    {
     4034        aDriveList.clear();
     4035        return E_OUTOFMEMORY;
     4036    }
     4037    return S_OK;
     4038
     4039#elif defined(RT_OS_SOLARIS)
     4040    /*
     4041     * We can get the info from HAL, if not present/working we'll get by
     4042     * walking the device tree.
     4043     */
     4044# ifdef VBOX_USE_LIBHAL
     4045    HRESULT hrc = i_getFixedDrivesFromHal(aDriveList);
     4046    if (hrc != S_FALSE)
     4047        return hrc;
     4048    aDriveList.clear(); /* just in case */
     4049# endif
     4050    return i_getFixedDrivesFromDevTree(aDriveList);
     4051
     4052#else
     4053    /* PORTME */
     4054    RT_NOREF(aDriveList);
     4055    return E_NOTIMPL;
     4056#endif
     4057}
     4058
    35764059/* vi: set tabstop=4 shiftwidth=4 expandtab: */
  • 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;
  • trunk/src/VBox/Main/src-server/darwin/iokit.h

    r82968 r85929  
    2424#include <iprt/cdefs.h>
    2525#include <iprt/types.h>
     26#include <iprt/cpp/ministring.h>
    2627#ifdef VBOX_WITH_USB
    2728# include <VBox/usb.h>
     
    4041/** Pointer to a Darwin DVD descriptor. */
    4142typedef DARWINDVD *PDARWINDVD;
     43
     44/** Darwin fixed drive (SSD, HDD, ++) descriptor as returned by
     45 *  DarwinGetFixedDrives(). */
     46typedef struct DARWINFIXEDDRIVE
     47{
     48    /** Pointer to the next DVD. */
     49    struct DARWINFIXEDDRIVE *pNext;
     50    /** Pointer to the model name, NULL if none.
     51     * This points after szName and needs not be freed separately. */
     52    const char *pszModel;
     53    /** Variable length name / identifier. */
     54    char szName[1];
     55} DARWINFIXEDDRIVE;
     56/** Pointer to a Darwin fixed drive. */
     57typedef DARWINFIXEDDRIVE *PDARWINFIXEDDRIVE;
    4258
    4359
     
    85101#endif /* VBOX_WITH_USB */
    86102PDARWINDVD      DarwinGetDVDDrives(void);
     103PDARWINFIXEDDRIVE DarwinGetFixedDrives(void);
    87104PDARWINETHERNIC DarwinGetEthernetControllers(void);
    88105RT_C_DECLS_END
  • trunk/src/VBox/Main/src-server/freebsd/HostHardwareFreeBSD.cpp

    r82968 r85929  
    11/* $Id$ */
    22/** @file
    3  * Classes for handling hardware detection under FreeBSD.
     3 * VirtualBox Main - Code for handling hardware detection under FreeBSD, VBoxSVC.
    44 */
    55
     
    1616 */
    1717
    18 #define LOG_GROUP LOG_GROUP_MAIN
    19 
    2018
    2119/*********************************************************************************************************************************
    2220*   Header Files                                                                                                                 *
    2321*********************************************************************************************************************************/
    24 
    25 #include <HostHardwareLinux.h>
     22#define LOG_GROUP LOG_GROUP_MAIN
     23#include "HostHardwareLinux.h"
    2624
    2725#include <VBox/log.h>
     
    3533#include <iprt/string.h>
    3634
    37 #ifdef RT_OS_FREEBSD
    38 # include <sys/param.h>
    39 # include <sys/types.h>
    40 # include <sys/stat.h>
    41 # include <unistd.h>
    42 # include <stdio.h>
    43 # include <sys/ioctl.h>
    44 # include <fcntl.h>
    45 # include <cam/cam.h>
    46 # include <cam/cam_ccb.h>
    47 # include <cam/scsi/scsi_pass.h>
    48 #endif /* RT_OS_FREEBSD */
     35#include <sys/param.h>
     36#include <sys/types.h>
     37#include <sys/stat.h>
     38#include <unistd.h>
     39#include <stdio.h>
     40#include <sys/ioctl.h>
     41#include <fcntl.h>
     42#include <cam/cam.h>
     43#include <cam/cam_ccb.h>
     44#include <camlib.h>
     45#include <cam/scsi/scsi_pass.h>
     46
    4947#include <vector>
    5048
     
    5351*   Typedefs and Defines                                                                                                         *
    5452*********************************************************************************************************************************/
    55 
    56 static int getDriveInfoFromEnv(const char *pcszVar, DriveInfoList *pList,
    57                                bool isDVD, bool *pfSuccess);
    58 static int getDVDInfoFromCAM(DriveInfoList *pList, bool *pfSuccess);
     53typedef enum DriveType_T
     54{
     55    Fixed,
     56    DVD,
     57    Any
     58} DriveType_T;
     59
     60
     61/*********************************************************************************************************************************
     62*   Internal Functions                                                                                                           *
     63*********************************************************************************************************************************/
     64static int getDriveInfoFromEnv(const char *pcszVar, DriveInfoList *pList, bool isDVD, bool *pfSuccess) RT_NOTHROW_PROTP;
     65static int getDriveInfoFromCAM(DriveInfoList *pList, DriveType_T enmDriveType, bool *pfSuccess) RT_NOTHROW_PROTP;
     66
    5967
    6068/** Find the length of a string, ignoring trailing non-ascii or control
    61  * characters */
    62 static size_t strLenStripped(const char *pcsz)
     69 * characters
     70 * @note Code duplicated in HostHardwareLinux.cpp  */
     71static size_t strLenStripped(const char *pcsz) RT_NOTHROW_DEF
    6372{
    6473    size_t cch = 0;
    6574    for (size_t i = 0; pcsz[i] != '\0'; ++i)
    66         if (pcsz[i] > 32 && pcsz[i] < 127)
     75        if (pcsz[i] > 32 /*space*/ && pcsz[i] < 127 /*delete*/)
    6776            cch = i;
    6877    return cch + 1;
    6978}
    7079
    71 static void strLenRemoveTrailingWhiteSpace(char *psz, size_t cchStr)
    72 {
    73     while (   (cchStr > 0)
    74            && (psz[cchStr -1] == ' '))
    75         psz[--cchStr] = '\0';
    76 }
    7780
    7881/**
    79  * Initialise the device description for a DVD drive based on
    80  * vendor and model name strings.
    81  * @param pcszVendor  the vendor ID string
    82  * @param pcszModel   the product ID string
    83  * @param pszDesc    where to store the description string (optional)
    84  * @param cchDesc    the size of the buffer in @pszDesc
     82 * Initialize the device description for a drive based on vendor and model name
     83 * strings.
     84 *
     85 * @param   pcszVendor  The raw vendor ID string.
     86 * @param   pcszModel   The raw product ID string.
     87 * @param   pszDesc     Where to store the description string (optional)
     88 * @param   cbDesc      The size of the buffer in @pszDesc
     89 *
     90 * @note    Used for disks as well as DVDs.
    8591 */
    8692/* static */
    87 void dvdCreateDeviceString(const char *pcszVendor, const char *pcszModel,
    88                             char *pszDesc, size_t cchDesc)
     93void dvdCreateDeviceString(const char *pcszVendor, const char *pcszModel, char *pszDesc, size_t cbDesc) RT_NOTHROW_DEF
    8994{
    9095    AssertPtrReturnVoid(pcszVendor);
    9196    AssertPtrReturnVoid(pcszModel);
    9297    AssertPtrNullReturnVoid(pszDesc);
    93     AssertReturnVoid(!pszDesc || cchDesc > 0);
     98    AssertReturnVoid(!pszDesc || cbDesc > 0);
    9499    size_t cchVendor = strLenStripped(pcszVendor);
    95100    size_t cchModel = strLenStripped(pcszModel);
     
    99104    {
    100105        if (cchVendor > 0)
    101             RTStrPrintf(pszDesc, cchDesc, "%.*s %s", cchVendor, pcszVendor,
     106            RTStrPrintf(pszDesc, cbDesc, "%.*s %s", cchVendor, pcszVendor,
    102107                        cchModel > 0 ? pcszModel : "(unknown drive model)");
    103108        else
    104             RTStrPrintf(pszDesc, cchDesc, "%s", pcszModel);
    105     }
    106 }
    107 
    108 
    109 int VBoxMainDriveInfo::updateDVDs ()
     109            RTStrPrintf(pszDesc, cbDesc, "%s", pcszModel);
     110        RTStrPurgeEncoding(pszDesc);
     111    }
     112}
     113
     114
     115int VBoxMainDriveInfo::updateDVDs() RT_NOEXCEPT
    110116{
    111117    LogFlowThisFunc(("entered\n"));
    112     int rc = VINF_SUCCESS;
    113     bool fSuccess = false;  /* Have we succeeded in finding anything yet? */
    114 
     118    int rc;
    115119    try
    116120    {
    117         mDVDList.clear ();
     121        mDVDList.clear();
    118122        /* Always allow the user to override our auto-detection using an
    119123         * environment variable. */
     124        bool fSuccess = false;  /* Have we succeeded in finding anything yet? */
     125        rc = getDriveInfoFromEnv("VBOX_CDROM", &mDVDList, true /* isDVD */, &fSuccess);
    120126        if (RT_SUCCESS(rc) && !fSuccess)
    121             rc = getDriveInfoFromEnv("VBOX_CDROM", &mDVDList, true /* isDVD */,
    122                                      &fSuccess);
    123         if (RT_SUCCESS(rc) && !fSuccess)
    124             rc = getDVDInfoFromCAM(&mDVDList, &fSuccess);
    125     }
    126     catch(std::bad_alloc &e)
     127            rc = getDriveInfoFromCAM(&mDVDList, DVD, &fSuccess);
     128    }
     129    catch (std::bad_alloc &)
    127130    {
    128131        rc = VERR_NO_MEMORY;
     
    132135}
    133136
    134 int VBoxMainDriveInfo::updateFloppies ()
     137int VBoxMainDriveInfo::updateFloppies() RT_NOEXCEPT
    135138{
    136139    LogFlowThisFunc(("entered\n"));
    137     int rc = VINF_SUCCESS;
    138     bool fSuccess = false;  /* Have we succeeded in finding anything yet? */
    139 
     140    int rc;
    140141    try
    141142    {
    142         mFloppyList.clear ();
    143         /* Always allow the user to override our auto-detection using an
    144          * environment variable. */
    145         if (RT_SUCCESS(rc) && !fSuccess)
    146             rc = getDriveInfoFromEnv("VBOX_FLOPPY", &mFloppyList, false /* isDVD */,
    147                                      &fSuccess);
    148     }
    149     catch(std::bad_alloc &e)
     143        /* Only got the enviornment variable here... */
     144        mFloppyList.clear();
     145        bool fSuccess = false;  /* ignored */
     146        rc = getDriveInfoFromEnv("VBOX_FLOPPY", &mFloppyList, false /* isDVD */, &fSuccess);
     147    }
     148    catch (std::bad_alloc &)
    150149    {
    151150        rc = VERR_NO_MEMORY;
     
    155154}
    156155
     156int VBoxMainDriveInfo::updateFixedDrives() RT_NOEXCEPT
     157{
     158    LogFlowThisFunc(("entered\n"));
     159    int rc;
     160    try
     161    {
     162        mFixedDriveList.clear();
     163        bool fSuccess = false;  /* ignored */
     164        rc = getDriveInfoFromCAM(&mFixedDriveList, Fixed, &fSuccess);
     165    }
     166    catch (std::bad_alloc &)
     167    {
     168        rc = VERR_NO_MEMORY;
     169    }
     170    LogFlowThisFunc(("rc=%Rrc\n", rc));
     171    return rc;
     172}
     173
     174static void strDeviceStringSCSI(device_match_result *pDevResult, char *pszDesc, size_t cbDesc) RT_NOTHROW_DEF
     175{
     176    char szVendor[128];
     177    cam_strvis((uint8_t *)szVendor, (const uint8_t *)pDevResult->inq_data.vendor,
     178               sizeof(pDevResult->inq_data.vendor), sizeof(szVendor));
     179    char szProduct[128];
     180    cam_strvis((uint8_t *)szProduct, (const uint8_t *)pDevResult->inq_data.product,
     181               sizeof(pDevResult->inq_data.product), sizeof(szProduct));
     182    dvdCreateDeviceString(szVendor, szProduct, pszDesc, cbDesc);
     183}
     184
     185static void strDeviceStringATA(device_match_result *pDevResult, char *pszDesc, size_t cbDesc) RT_NOTHROW_DEF
     186{
     187    char szProduct[256];
     188    cam_strvis((uint8_t *)szProduct, (const uint8_t *)pDevResult->ident_data.model,
     189               sizeof(pDevResult->ident_data.model), sizeof(szProduct));
     190    dvdCreateDeviceString("", szProduct, pszDesc, cbDesc);
     191}
     192
     193static void strDeviceStringSEMB(device_match_result *pDevResult, char *pszDesc, size_t cbDesc) RT_NOTHROW_DEF
     194{
     195    sep_identify_data *pSid = (sep_identify_data *)&pDevResult->ident_data;
     196
     197    char szVendor[128];
     198    cam_strvis((uint8_t *)szVendor, (const uint8_t *)pSid->vendor_id,
     199               sizeof(pSid->vendor_id), sizeof(szVendor));
     200    char szProduct[128];
     201    cam_strvis((uint8_t *)szProduct, (const uint8_t *)pSid->product_id,
     202               sizeof(pSid->product_id), sizeof(szProduct));
     203    dvdCreateDeviceString(szVendor, szProduct, pszDesc, cbDesc);
     204}
     205
     206static void strDeviceStringMMCSD(device_match_result *pDevResult, char *pszDesc, size_t cbDesc)  RT_NOTHROW_DEF
     207{
     208    struct cam_device *pDev = cam_open_btl(pDevResult->path_id, pDevResult->target_id,
     209                                           pDevResult->target_lun, O_RDWR, NULL);
     210    if (pDev == NULL)
     211    {
     212        Log(("Error while opening drive device. Error: %s\n", cam_errbuf));
     213        return;
     214    }
     215
     216    union ccb *pCcb = cam_getccb(pDev);
     217    if (pCcb != NULL)
     218    {
     219        struct mmc_params mmcIdentData;
     220        RT_ZERO(mmcIdentData);
     221
     222        struct ccb_dev_advinfo *pAdvi = &pCcb->cdai;
     223        pAdvi->ccb_h.flags = CAM_DIR_IN;
     224        pAdvi->ccb_h.func_code = XPT_DEV_ADVINFO;
     225        pAdvi->flags = CDAI_FLAG_NONE;
     226        pAdvi->buftype = CDAI_TYPE_MMC_PARAMS;
     227        pAdvi->bufsiz = sizeof(mmcIdentData);
     228        pAdvi->buf = (uint8_t *)&mmcIdentData;
     229
     230        if (cam_send_ccb(pDev, pCcb) >= 0)
     231        {
     232            if (strlen((char *)mmcIdentData.model) > 0)
     233                dvdCreateDeviceString("", (const char *)mmcIdentData.model, pszDesc, cbDesc);
     234            else
     235                dvdCreateDeviceString("", mmcIdentData.card_features & CARD_FEATURE_SDIO ? "SDIO card" : "Unknown card",
     236                                      pszDesc, cbDesc);
     237        }
     238        else
     239            Log(("error sending XPT_DEV_ADVINFO CCB\n"));
     240
     241        cam_freeccb(pCcb);
     242    }
     243    else
     244        Log(("Could not allocate CCB\n"));
     245    cam_close_device(pDev);
     246}
     247
     248/** @returns boolean success indicator (true/false). */
     249static int nvmeGetCData(struct cam_device *pDev, struct nvme_controller_data *pCData) RT_NOTHROW_DEF
     250{
     251    bool fSuccess = false;
     252    union ccb *pCcb = cam_getccb(pDev);
     253    if (pCcb != NULL)
     254    {
     255        struct ccb_dev_advinfo *pAdvi = &pCcb->cdai;
     256        pAdvi->ccb_h.flags = CAM_DIR_IN;
     257        pAdvi->ccb_h.func_code = XPT_DEV_ADVINFO;
     258        pAdvi->flags = CDAI_FLAG_NONE;
     259        pAdvi->buftype = CDAI_TYPE_NVME_CNTRL;
     260        pAdvi->bufsiz = sizeof(struct nvme_controller_data);
     261        pAdvi->buf = (uint8_t *)pCData;
     262        RT_BZERO(pAdvi->buf, pAdvi->bufsiz);
     263
     264        if (cam_send_ccb(pDev, pCcb) >= 0)
     265        {
     266            if (pAdvi->ccb_h.status == CAM_REQ_CMP)
     267                fSuccess = true;
     268            else
     269                Log(("Got CAM error %#x\n", pAdvi->ccb_h.status));
     270        }
     271        else
     272            Log(("Error sending XPT_DEV_ADVINFO CC\n"));
     273        cam_freeccb(pCcb);
     274    }
     275    else
     276        Log(("Could not allocate CCB\n"));
     277    return fSuccess;
     278}
     279
     280static void strDeviceStringNVME(device_match_result *pDevResult, char *pszDesc, size_t cbDesc) RT_NOTHROW_DEF
     281{
     282    struct cam_device *pDev = cam_open_btl(pDevResult->path_id, pDevResult->target_id,
     283                                           pDevResult->target_lun, O_RDWR, NULL);
     284    if (pDev)
     285    {
     286        struct nvme_controller_data CData;
     287        if (nvmeGetCData(pDev, &CData))
     288        {
     289            char szVendor[128];
     290            cam_strvis((uint8_t *)szVendor, CData.mn, sizeof(CData.mn), sizeof(szVendor));
     291            char szProduct[128];
     292            cam_strvis((uint8_t *)szProduct, CData.fr, sizeof(CData.fr), sizeof(szProduct));
     293            dvdCreateDeviceString(szVendor, szProduct, pszDesc, cbDesc);
     294        }
     295        else
     296            Log(("Error while getting NVME drive info\n"));
     297        cam_close_device(pDev);
     298    }
     299    else
     300        Log(("Error while opening drive device. Error: %s\n", cam_errbuf));
     301}
     302
     303
    157304/**
    158  * Search for available CD/DVD drives using the CAM layer.
     305 * Search for available drives using the CAM layer.
    159306 *
    160307 * @returns iprt status code
    161  * @param   pList      the list to append the drives found to
    162  * @param   pfSuccess  this will be set to true if we found at least one drive
    163  *                     and to false otherwise.  Optional.
     308 * @param   pList         the list to append the drives found to
     309 * @param   enmDriveType  search drives of specified type
     310 * @param   pfSuccess     this will be set to true if we found at least one drive
     311 *                        and to false otherwise.  Optional.
    164312 */
    165 static int getDVDInfoFromCAM(DriveInfoList *pList, bool *pfSuccess)
    166 {
    167     int rc = VINF_SUCCESS;
    168     RTFILE FileXpt;
    169 
    170     rc = RTFileOpen(&FileXpt, "/dev/xpt0", RTFILE_O_READWRITE | RTFILE_O_OPEN | RTFILE_O_DENY_NONE);
     313static int getDriveInfoFromCAM(DriveInfoList *pList, DriveType_T enmDriveType, bool *pfSuccess) RT_NOTHROW_DEF
     314{
     315    RTFILE hFileXpt = NIL_RTFILE;
     316    int rc = RTFileOpen(&hFileXpt, "/dev/xpt0", RTFILE_O_READWRITE | RTFILE_O_OPEN | RTFILE_O_DENY_NONE);
    171317    if (RT_SUCCESS(rc))
    172318    {
     
    196342 #define INQ_PAT inq_pat
    197343#endif
    198         DeviceMatchPattern.pattern.device_pattern.INQ_PAT.type = T_CDROM;
     344        DeviceMatchPattern.pattern.device_pattern.INQ_PAT.type = enmDriveType == Fixed ? T_DIRECT
     345                                                               : enmDriveType == DVD   ? T_CDROM : T_ANY;
    199346        DeviceMatchPattern.pattern.device_pattern.INQ_PAT.media_type  = SIP_MEDIA_REMOVABLE | SIP_MEDIA_FIXED;
    200347        DeviceMatchPattern.pattern.device_pattern.INQ_PAT.vendor[0]   = '*'; /* Matches anything */
     
    220367            do
    221368            {
    222                 rc = RTFileIoCtl(FileXpt, CAMIOCOMMAND, &DeviceCCB, sizeof(union ccb), NULL);
     369                rc = RTFileIoCtl(hFileXpt, CAMIOCOMMAND, &DeviceCCB, sizeof(union ccb), NULL);
    223370                if (RT_FAILURE(rc))
    224371                {
     
    231378                    if (paMatches[i].type == DEV_MATCH_DEVICE)
    232379                    {
     380                        /*
     381                         * The result list can contain some empty entries with DEV_RESULT_UNCONFIGURED
     382                         * flag set, e.g. in case of T_DIRECT. Ignore them.
     383                         */
     384                        if (   (paMatches[i].result.device_result.flags & DEV_RESULT_UNCONFIGURED)
     385                            == DEV_RESULT_UNCONFIGURED)
     386                            continue;
     387
    233388                        /* We have the drive now but need the appropriate device node */
    234389                        struct device_match_result *pDevResult = &paMatches[i].result.device_result;
     
    254409                        PeriphMatchPattern.pattern.periph_pattern.target_id  = paMatches[i].result.device_result.target_id;
    255410                        PeriphMatchPattern.pattern.periph_pattern.target_lun = paMatches[i].result.device_result.target_lun;
    256                         PeriphMatchPattern.pattern.periph_pattern.flags      = (periph_pattern_flags)(  PERIPH_MATCH_PATH | PERIPH_MATCH_TARGET
     411                        PeriphMatchPattern.pattern.periph_pattern.flags      = (periph_pattern_flags)(  PERIPH_MATCH_PATH
     412                                                                                                      | PERIPH_MATCH_TARGET
    257413                                                                                                      | PERIPH_MATCH_LUN);
    258414                        PeriphCCB.cdm.num_patterns    = 1;
     
    265421                        do
    266422                        {
    267                             rc = RTFileIoCtl(FileXpt, CAMIOCOMMAND, &PeriphCCB, sizeof(union ccb), NULL);
     423                            rc = RTFileIoCtl(hFileXpt, CAMIOCOMMAND, &PeriphCCB, sizeof(union ccb), NULL);
    268424                            if (RT_FAILURE(rc))
    269425                            {
     
    274430                            for (iPeriphMatch = 0; iPeriphMatch < PeriphCCB.cdm.num_matches; iPeriphMatch++)
    275431                            {
    276                                 if (   (aPeriphMatches[iPeriphMatch].type == DEV_MATCH_PERIPH)
    277                                     && (!strcmp(aPeriphMatches[iPeriphMatch].result.periph_result.periph_name, "cd")))
     432                                /* Ignore "passthrough mode" paths */
     433                                if (   aPeriphMatches[iPeriphMatch].type == DEV_MATCH_PERIPH
     434                                    && strcmp(aPeriphMatches[iPeriphMatch].result.periph_result.periph_name, "pass"))
    278435                                {
    279436                                    pPeriphResult = &aPeriphMatches[iPeriphMatch].result.periph_result;
     
    285442                                break;
    286443
    287                         } while (   (DeviceCCB.ccb_h.status == CAM_REQ_CMP)
    288                                  && (DeviceCCB.cdm.status == CAM_DEV_MATCH_MORE));
     444                        } while (   DeviceCCB.ccb_h.status == CAM_REQ_CMP
     445                                 && DeviceCCB.cdm.status == CAM_DEV_MATCH_MORE);
    289446
    290447                        if (pPeriphResult)
    291448                        {
    292449                            char szPath[RTPATH_MAX];
    293                             char szDesc[256];
    294 
    295450                            RTStrPrintf(szPath, sizeof(szPath), "/dev/%s%d",
    296451                                        pPeriphResult->periph_name, pPeriphResult->unit_number);
    297452
    298                             /* Remove trailing white space. */
    299                             strLenRemoveTrailingWhiteSpace(pDevResult->inq_data.vendor,
    300                                                             sizeof(pDevResult->inq_data.vendor));
    301                             strLenRemoveTrailingWhiteSpace(pDevResult->inq_data.product,
    302                                                             sizeof(pDevResult->inq_data.product));
    303 
    304                             dvdCreateDeviceString(pDevResult->inq_data.vendor,
    305                                                     pDevResult->inq_data.product,
    306                                                     szDesc, sizeof(szDesc));
    307 
    308                             pList->push_back(DriveInfo(szPath, "", szDesc));
     453                            char szDesc[256] = { 0 };
     454                            switch (pDevResult->protocol)
     455                            {
     456                                case PROTO_SCSI:  strDeviceStringSCSI( pDevResult, szDesc, sizeof(szDesc)); break;
     457                                case PROTO_ATA:   strDeviceStringATA(  pDevResult, szDesc, sizeof(szDesc)); break;
     458                                case PROTO_MMCSD: strDeviceStringMMCSD(pDevResult, szDesc, sizeof(szDesc)); break;
     459                                case PROTO_SEMB:  strDeviceStringSEMB( pDevResult, szDesc, sizeof(szDesc)); break;
     460                                case PROTO_NVME:  strDeviceStringNVME( pDevResult, szDesc, sizeof(szDesc)); break;
     461                                default: break;
     462                            }
     463
     464                            try
     465                            {
     466                                pList->push_back(DriveInfo(szPath, "", szDesc));
     467                            }
     468                            catch (std::bad_alloc &)
     469                            {
     470                                pList->clear();
     471                                rc = VERR_NO_MEMORY;
     472                                break;
     473                            }
    309474                            if (pfSuccess)
    310475                                *pfSuccess = true;
     
    312477                    }
    313478                }
    314             } while (   (DeviceCCB.ccb_h.status == CAM_REQ_CMP)
    315                      && (DeviceCCB.cdm.status == CAM_DEV_MATCH_MORE));
     479            } while (   DeviceCCB.ccb_h.status == CAM_REQ_CMP
     480                     && DeviceCCB.cdm.status == CAM_DEV_MATCH_MORE
     481                     && RT_SUCCESS(rc));
    316482
    317483            RTMemFree(paMatches);
     
    320486            rc = VERR_NO_MEMORY;
    321487
    322         RTFileClose(FileXpt);
     488        RTFileClose(hFileXpt);
    323489    }
    324490
    325491    return rc;
    326492}
     493
    327494
    328495/**
    329496 * Extract the names of drives from an environment variable and add them to a
    330497 * list if they are valid.
     498 *
    331499 * @returns iprt status code
    332500 * @param   pcszVar     the name of the environment variable.  The variable
     
    337505 * @param   pfSuccess  this will be set to true if we found at least one drive
    338506 *                     and to false otherwise.  Optional.
     507 *
     508 * @note    This is duplicated in HostHardwareLinux.cpp.
    339509 */
    340 static int getDriveInfoFromEnv(const char *pcszVar, DriveInfoList *pList,
    341                                bool isDVD, bool *pfSuccess)
     510static int getDriveInfoFromEnv(const char *pcszVar, DriveInfoList *pList, bool isDVD, bool *pfSuccess) RT_NOTHROW_DEF
    342511{
    343512    AssertPtrReturn(pcszVar, VERR_INVALID_POINTER);
    344513    AssertPtrReturn(pList, VERR_INVALID_POINTER);
    345514    AssertPtrNullReturn(pfSuccess, VERR_INVALID_POINTER);
    346     LogFlowFunc(("pcszVar=%s, pList=%p, isDVD=%d, pfSuccess=%p\n", pcszVar,
    347                  pList, isDVD, pfSuccess));
     515    LogFlowFunc(("pcszVar=%s, pList=%p, isDVD=%d, pfSuccess=%p\n", pcszVar, pList, isDVD, pfSuccess));
    348516    int rc = VINF_SUCCESS;
    349517    bool success = false;
     
    352520    try
    353521    {
    354         const char *pcszCurrent = pszFreeMe;
    355         while (pcszCurrent && *pcszCurrent != '\0')
     522        char *pszCurrent = pszFreeMe;
     523        while (pszCurrent && *pszCurrent != '\0')
    356524        {
    357             const char *pcszNext = strchr(pcszCurrent, ':');
    358             char szPath[RTPATH_MAX], szReal[RTPATH_MAX];
    359             char szDesc[256], szUdi[256];
    360             if (pcszNext)
    361                 RTStrPrintf(szPath, sizeof(szPath), "%.*s",
    362                             pcszNext - pcszCurrent - 1, pcszCurrent);
    363             else
    364                 RTStrPrintf(szPath, sizeof(szPath), "%s", pcszCurrent);
    365             if (RT_SUCCESS(RTPathReal(szPath, szReal, sizeof(szReal))))
     525            char *pszNext = strchr(pszCurrent, ':');
     526            if (pszNext)
     527                *pszNext++ = '\0';
     528
     529            char szReal[RTPATH_MAX];
     530            char szDesc[1] = "", szUdi[1] = ""; /* differs on freebsd because no devValidateDevice */
     531            if (   RT_SUCCESS(RTPathReal(pszCurrent, szReal, sizeof(szReal)))
     532                /*&& devValidateDevice(szReal, isDVD, NULL, szDesc, sizeof(szDesc), szUdi, sizeof(szUdi)) - linux only */)
    366533            {
    367                 szUdi[0] = '\0'; /** @todo r=bird: missing a call to devValidateDevice() here and szUdi wasn't
    368                                   *        initialized because of that.  Need proper fixing. */
    369534                pList->push_back(DriveInfo(szReal, szUdi, szDesc));
    370535                success = true;
    371536            }
    372             pcszCurrent = pcszNext ? pcszNext + 1 : NULL;
     537            pszCurrent = pszNext;
    373538        }
    374539        if (pfSuccess != NULL)
    375540            *pfSuccess = success;
    376541    }
    377     catch(std::bad_alloc &e)
     542    catch (std::bad_alloc &)
    378543    {
    379544        rc = VERR_NO_MEMORY;
     
    383548    return rc;
    384549}
     550
  • trunk/src/VBox/Main/src-server/linux/HostHardwareLinux.cpp

    r82968 r85929  
    11/* $Id$ */
    22/** @file
    3  * Classes for handling hardware detection under Linux.  Please feel free to
    4  * expand these to work for other systems (Solaris!) or to add new ones for
    5  * other systems.
     3 * VirtualBox Main - Code for handling hardware detection under Linux, VBoxSVC.
    64 */
    75
     
    1816 */
    1917
    20 #define LOG_GROUP LOG_GROUP_MAIN
    21 
    2218
    2319/*********************************************************************************************************************************
    2420*   Header Files                                                                                                                 *
    2521*********************************************************************************************************************************/
    26 
    27 #include <HostHardwareLinux.h>
    28 #include <vector.h>
     22#define LOG_GROUP LOG_GROUP_MAIN
     23#include "HostHardwareLinux.h"
    2924
    3025#include <VBox/err.h>
     
    7166*   Global Variables                                                                                                             *
    7267*********************************************************************************************************************************/
    73 
    7468#ifdef TESTCASE
    7569static bool testing() { return true; }
     
    8781*   Typedefs and Defines                                                                                                         *
    8882*********************************************************************************************************************************/
    89 
    90 static int getDriveInfoFromEnv(const char *pcszVar, DriveInfoList *pList,
    91                                bool isDVD, bool *pfSuccess);
    92 static int getDriveInfoFromSysfs(DriveInfoList *pList, bool isDVD,
    93                                  bool *pfSuccess);
     83typedef enum SysfsWantDevice_T
     84{
     85    DVD,
     86    Floppy,
     87    FixedDisk
     88} SysfsWantDevice_T;
     89
     90
     91/*********************************************************************************************************************************
     92*   Internal Functions                                                                                                           *
     93*********************************************************************************************************************************/
     94static int getDriveInfoFromEnv(const char *pcszVar, DriveInfoList *pList, bool isDVD, bool *pfSuccess) RT_NOTHROW_PROTO;
     95static int getDriveInfoFromSysfs(DriveInfoList *pList, SysfsWantDevice_T wantDevice, bool *pfSuccess) RT_NOTHROW_PROTO;
     96
    9497
    9598/** Find the length of a string, ignoring trailing non-ascii or control
    96  * characters */
    97 static size_t strLenStripped(const char *pcsz)
     99 * characters
     100 * @note Code duplicated in HostHardwareFreeBSD.cpp  */
     101static size_t strLenStripped(const char *pcsz) RT_NOTHROW_DEF
    98102{
    99103    size_t cch = 0;
    100104    for (size_t i = 0; pcsz[i] != '\0'; ++i)
    101         if (pcsz[i] > 32 && pcsz[i] < 127)
     105        if (pcsz[i] > 32 /*space*/ && pcsz[i] < 127 /*delete*/)
    102106            cch = i;
    103107    return cch + 1;
     
    114118 * @param  pszName   where to store the name retrieved
    115119 */
    116 static bool floppyGetName(const char *pcszNode, unsigned Number,
    117                           floppy_drive_name pszName)
     120static bool floppyGetName(const char *pcszNode, unsigned Number, floppy_drive_name pszName) RT_NOTHROW_DEF
    118121{
    119122    AssertPtrReturn(pcszNode, false);
     
    145148 *                       FDC 1)
    146149 * @param   pszDesc      where to store the device description (optional)
    147  * @param   cchDesc      the size of the buffer in @a pszDesc
     150 * @param   cbDesc       the size of the buffer in @a pszDesc
    148151 * @param   pszUdi       where to store the device UDI (optional)
    149  * @param   cchUdi       the size of the buffer in @a pszUdi
     152 * @param   cbUdi        the size of the buffer in @a pszUdi
    150153 */
    151 static void floppyCreateDeviceStrings(const floppy_drive_name pcszName,
    152                                       unsigned Number, char *pszDesc,
    153                                       size_t cchDesc, char *pszUdi,
    154                                       size_t cchUdi)
     154static void floppyCreateDeviceStrings(const floppy_drive_name pcszName, unsigned Number,
     155                                      char *pszDesc, size_t cbDesc, char *pszUdi, size_t cbUdi) RT_NOTHROW_DEF
    155156{
    156157    AssertPtrNullReturnVoid(pcszName);
    157158    AssertPtrNullReturnVoid(pszDesc);
    158     AssertReturnVoid(!pszDesc || cchDesc > 0);
     159    AssertReturnVoid(!pszDesc || cbDesc > 0);
    159160    AssertPtrNullReturnVoid(pszUdi);
    160     AssertReturnVoid(!pszUdi || cchUdi > 0);
     161    AssertReturnVoid(!pszUdi || cbUdi > 0);
    161162    AssertReturnVoid(Number <= 7);
    162163    if (pcszName)
     
    175176        }
    176177        if (pszDesc)
    177             RTStrPrintf(pszDesc, cchDesc, "%s %s K%s", pcszSize, &pcszName[1],
     178            RTStrPrintf(pszDesc, cbDesc, "%s %s K%s", pcszSize, &pcszName[1],
    178179                        Number > 3 ? ", FDC 2" : "");
    179180    }
     
    181182    {
    182183        if (pszDesc)
    183             RTStrPrintf(pszDesc, cchDesc, "FDD %d%s", (Number & 4) + 1,
     184            RTStrPrintf(pszDesc, cbDesc, "FDD %d%s", (Number & 4) + 1,
    184185                        Number > 3 ? ", FDC 2" : "");
    185186    }
    186187    if (pszUdi)
    187         RTStrPrintf(pszUdi, cchUdi,
     188        RTStrPrintf(pszUdi, cbUdi,
    188189                    "/org/freedesktop/Hal/devices/platform_floppy_%u_storage",
    189190                    Number);
     
    194195 * Check whether a device number might correspond to a CD-ROM device according
    195196 * to Documentation/devices.txt in the Linux kernel source.
     197 *
    196198 * @returns true if it might, false otherwise
    197199 * @param   Number  the device number (major and minor combination)
    198200 */
    199 static bool isCdromDevNum(dev_t Number)
     201static bool isCdromDevNum(dev_t Number) RT_NOTHROW_DEF
    200202{
    201203    int major = major(Number);
    202204    int minor = minor(Number);
    203     if ((major == IDE0_MAJOR) && !(minor & 0x3f))
     205    if (major == IDE0_MAJOR && !(minor & 0x3f))
    204206        return true;
    205207    if (major == SCSI_CDROM_MAJOR)
     
    215217    if (major == MITSUMI_X_CDROM_MAJOR)
    216218        return true;
    217     if ((major == IDE1_MAJOR) && !(minor & 0x3f))
     219    if (major == IDE1_MAJOR && !(minor & 0x3f))
    218220        return true;
    219221    if (major == MITSUMI_CDROM_MAJOR)
     
    235237    if (major == CM206_CDROM_MAJOR)
    236238        return true;
    237     if ((major == IDE3_MAJOR) && !(minor & 0x3f))
     239    if (major == IDE3_MAJOR && !(minor & 0x3f))
    238240        return true;
    239241    if (major == 46 /* Parallel port ATAPI CD-ROM */)  /* no #define */
    240242        return true;
    241     if ((major == IDE4_MAJOR) && !(minor & 0x3f))
    242         return true;
    243     if ((major == IDE5_MAJOR) && !(minor & 0x3f))
    244         return true;
    245     if ((major == IDE6_MAJOR) && !(minor & 0x3f))
    246         return true;
    247     if ((major == IDE7_MAJOR) && !(minor & 0x3f))
    248         return true;
    249     if ((major == IDE8_MAJOR) && !(minor & 0x3f))
    250         return true;
    251     if ((major == IDE9_MAJOR) && !(minor & 0x3f))
     243    if (major == IDE4_MAJOR && !(minor & 0x3f))
     244        return true;
     245    if (major == IDE5_MAJOR && !(minor & 0x3f))
     246        return true;
     247    if (major == IDE6_MAJOR && !(minor & 0x3f))
     248        return true;
     249    if (major == IDE7_MAJOR && !(minor & 0x3f))
     250        return true;
     251    if (major == IDE8_MAJOR && !(minor & 0x3f))
     252        return true;
     253    if (major == IDE9_MAJOR && !(minor & 0x3f))
    252254        return true;
    253255    if (major == 113 /* VIOCD_MAJOR */)
     
    259261/**
    260262 * Send an SCSI INQUIRY command to a device and return selected information.
     263 *
    261264 * @returns  iprt status code
    262  * @returns  VERR_TRY_AGAIN if the query failed but might succeed next time
     265 * @retval   VERR_TRY_AGAIN if the query failed but might succeed next time
    263266 * @param pcszNode    the full path to the device node
    264  * @param pu8Type    where to store the SCSI device type on success (optional)
    265  * @param pchVendor  where to store the vendor id string on success (optional)
    266  * @param cchVendor  the size of the @a pchVendor buffer
    267  * @param pchModel   where to store the product id string on success (optional)
    268  * @param cchModel   the size of the @a pchModel buffer
     267 * @param pbType     where to store the SCSI device type on success (optional)
     268 * @param pszVendor  where to store the vendor id string on success (optional)
     269 * @param cbVendor   the size of the @a pszVendor buffer
     270 * @param pszModel   where to store the product id string on success (optional)
     271 * @param cchModel   the size of the @a pszModel buffer
    269272 * @note check documentation on the SCSI INQUIRY command and the Linux kernel
    270273 *       SCSI headers included above if you want to understand what is going
    271274 *       on in this method.
    272275 */
    273 static int cdromDoInquiry(const char *pcszNode, uint8_t *pu8Type,
    274                           char *pchVendor, size_t cchVendor, char *pchModel,
    275                           size_t cchModel)
    276 {
    277     LogRelFlowFunc(("pcszNode=%s, pu8Type=%p, pchVendor=%p, cchVendor=%llu, pchModel=%p, cchModel=%llu\n",
    278                     pcszNode, pu8Type, pchVendor, cchVendor, pchModel,
    279                     cchModel));
     276static int cdromDoInquiry(const char *pcszNode, uint8_t *pbType, char *pszVendor, size_t cbVendor,
     277                          char *pszModel, size_t cbModel) RT_NOTHROW_DEF
     278{
     279    LogRelFlowFunc(("pcszNode=%s, pbType=%p, pszVendor=%p, cbVendor=%zu, pszModel=%p, cbModel=%zu\n",
     280                    pcszNode, pbType, pszVendor, cbVendor, pszModel, cbModel));
    280281    AssertPtrReturn(pcszNode, VERR_INVALID_POINTER);
    281     AssertPtrNullReturn(pu8Type, VERR_INVALID_POINTER);
    282     AssertPtrNullReturn(pchVendor, VERR_INVALID_POINTER);
    283     AssertPtrNullReturn(pchModel, VERR_INVALID_POINTER);
    284 
    285     RTFILE hFile;
     282    AssertPtrNullReturn(pbType, VERR_INVALID_POINTER);
     283    AssertPtrNullReturn(pszVendor, VERR_INVALID_POINTER);
     284    AssertPtrNullReturn(pszModel, VERR_INVALID_POINTER);
     285
     286    RTFILE hFile = NIL_RTFILE;
    286287    int rc = RTFileOpen(&hFile, pcszNode, RTFILE_O_READ | RTFILE_O_OPEN | RTFILE_O_DENY_NONE | RTFILE_O_NON_BLOCK);
    287288    if (RT_SUCCESS(rc))
    288289    {
    289         int                             rcIoCtl        = 0;
    290         unsigned char                   u8Response[96] = { 0 };
     290        int                             rcIoCtl          = 0;
     291        unsigned char                   auchResponse[96] = { 0 };
    291292        struct cdrom_generic_command    CdromCommandReq;
    292293        RT_ZERO(CdromCommandReq);
    293294        CdromCommandReq.cmd[0]         = INQUIRY;
    294         CdromCommandReq.cmd[4]         = sizeof(u8Response);
    295         CdromCommandReq.buffer         = u8Response;
    296         CdromCommandReq.buflen         = sizeof(u8Response);
     295        CdromCommandReq.cmd[4]         = sizeof(auchResponse);
     296        CdromCommandReq.buffer         = auchResponse;
     297        CdromCommandReq.buflen         = sizeof(auchResponse);
    297298        CdromCommandReq.data_direction = CGC_DATA_READ;
    298299        CdromCommandReq.timeout        = 5000;  /* ms */
     
    304305        if (RT_SUCCESS(rc))
    305306        {
    306             if (pu8Type)
    307                 *pu8Type = u8Response[0] & 0x1f;
    308             if (pchVendor)
    309                 RTStrPrintf(pchVendor, cchVendor, "%.8s",
    310                             &u8Response[8] /* vendor id string */);
    311             if (pchModel)
    312                 RTStrPrintf(pchModel, cchModel, "%.16s",
    313                             &u8Response[16] /* product id string */);
     307            if (pbType)
     308                *pbType = auchResponse[0] & 0x1f;
     309            if (pszVendor)
     310            {
     311                RTStrPrintf(pszVendor, cbVendor, "%.8s", &auchResponse[8] /* vendor id string */);
     312                RTStrPurgeEncoding(pszVendor);
     313            }
     314            if (pszModel)
     315            {
     316                RTStrPrintf(pszModel, cbModel, "%.16s", &auchResponse[16] /* product id string */);
     317                RTStrPurgeEncoding(pszModel);
     318            }
    314319            LogRelFlowFunc(("returning success: type=%u, vendor=%.8s, product=%.16s\n",
    315                             u8Response[0] & 0x1f, &u8Response[8], &u8Response[16]));
     320                            auchResponse[0] & 0x1f, &auchResponse[8], &auchResponse[16]));
    316321            return VINF_SUCCESS;
    317322        }
     
    328333 * @param pcszModel   the product ID string
    329334 * @param pszDesc    where to store the description string (optional)
    330  * @param cchDesc    the size of the buffer in @a pszDesc
     335 * @param cbDesc     the size of the buffer in @a pszDesc
    331336 * @param pszUdi     where to store the UDI string (optional)
    332  * @param cchUdi     the size of the buffer in @a pszUdi
     337 * @param cbUdi      the size of the buffer in @a pszUdi
     338 *
     339 * @note  Used for more than DVDs these days.
    333340 */
    334 /* static */
    335 void dvdCreateDeviceStrings(const char *pcszVendor, const char *pcszModel,
    336                             char *pszDesc, size_t cchDesc, char *pszUdi,
    337                             size_t cchUdi)
     341static void dvdCreateDeviceStrings(const char *pcszVendor, const char *pcszModel,
     342                                   char *pszDesc, size_t cbDesc, char *pszUdi, size_t cbUdi) RT_NOEXCEPT
    338343{
    339344    AssertPtrReturnVoid(pcszVendor);
    340345    AssertPtrReturnVoid(pcszModel);
    341346    AssertPtrNullReturnVoid(pszDesc);
    342     AssertReturnVoid(!pszDesc || cchDesc > 0);
     347    AssertReturnVoid(!pszDesc || cbDesc > 0);
    343348    AssertPtrNullReturnVoid(pszUdi);
    344     AssertReturnVoid(!pszUdi || cchUdi > 0);
    345     char szCleaned[128];
     349    AssertReturnVoid(!pszUdi || cbUdi > 0);
     350
    346351    size_t cchVendor = strLenStripped(pcszVendor);
    347352    size_t cchModel = strLenStripped(pcszModel);
    348353
    349354    /* Create a cleaned version of the model string for the UDI string. */
     355    char szCleaned[128];
    350356    for (unsigned i = 0; i < sizeof(szCleaned) && pcszModel[i] != '\0'; ++i)
    351357        if (   (pcszModel[i] >= '0' && pcszModel[i] <= '9')
     
    360366    {
    361367        if (cchVendor > 0)
    362             RTStrPrintf(pszDesc, cchDesc, "%.*s %s", cchVendor, pcszVendor,
    363                         cchModel > 0 ? pcszModel : "(unknown drive model)");
     368        {
     369            RTStrPrintf(pszDesc, cbDesc, "%.*s %s", cchVendor, pcszVendor, cchModel > 0 ? pcszModel : "(unknown drive model)");
     370            RTStrPurgeEncoding(pszDesc);
     371        }
    364372        else
    365             RTStrPrintf(pszDesc, cchDesc, "%s", pcszModel);
     373            RTStrCopy(pszDesc, cbDesc, pcszModel);
    366374    }
    367375    /* Construct the UDI string */
     
    369377    {
    370378        if (cchModel > 0)
    371             RTStrPrintf(pszUdi, cchUdi,
    372                         "/org/freedesktop/Hal/devices/storage_model_%s",
    373                         szCleaned);
     379            RTStrPrintf(pszUdi, cbUdi, "/org/freedesktop/Hal/devices/storage_model_%s", szCleaned);
    374380        else
    375381            pszUdi[0] = '\0';
     
    381387 * Check whether a device node points to a valid device and create a UDI and
    382388 * a description for it, and store the device number, if it does.
     389 *
    383390 * @returns true if the device is valid, false otherwise
    384391 * @param   pcszNode   the path to the device node
     
    386393 * @param   pDevice   where to store the device node (optional)
    387394 * @param   pszDesc   where to store the device description (optional)
    388  * @param   cchDesc   the size of the buffer in @a pszDesc
     395 * @param   cbDesc    the size of the buffer in @a pszDesc
    389396 * @param   pszUdi    where to store the device UDI (optional)
    390  * @param   cchUdi    the size of the buffer in @a pszUdi
     397 * @param   cbUdi     the size of the buffer in @a pszUdi
    391398 */
    392399static bool devValidateDevice(const char *pcszNode, bool isDVD, dev_t *pDevice,
    393                               char *pszDesc, size_t cchDesc, char *pszUdi,
    394                               size_t cchUdi)
     400                              char *pszDesc, size_t cbDesc, char *pszUdi, size_t cbUdi) RT_NOTHROW_DEF
    395401{
    396402    AssertPtrReturn(pcszNode, false);
    397403    AssertPtrNullReturn(pDevice, false);
    398404    AssertPtrNullReturn(pszDesc, false);
    399     AssertReturn(!pszDesc || cchDesc > 0, false);
     405    AssertReturn(!pszDesc || cbDesc > 0, false);
    400406    AssertPtrNullReturn(pszUdi, false);
    401     AssertReturn(!pszUdi || cchUdi > 0, false);
     407    AssertReturn(!pszUdi || cbUdi > 0, false);
     408
    402409    RTFSOBJINFO ObjInfo;
    403410    if (RT_FAILURE(RTPathQueryInfo(pcszNode, &ObjInfo, RTFSOBJATTRADD_UNIX)))
     
    407414    if (pDevice)
    408415        *pDevice = ObjInfo.Attr.u.Unix.Device;
     416
    409417    if (isDVD)
    410418    {
     
    419427        if (u8Type != TYPE_ROM)
    420428            return false;
    421         dvdCreateDeviceStrings(szVendor, szModel, pszDesc, cchDesc,
    422                                pszUdi, cchUdi);
     429        dvdCreateDeviceStrings(szVendor, szModel, pszDesc, cbDesc, pszUdi, cbUdi);
    423430    }
    424431    else
    425432    {
    426         /* Floppies on Linux are legacy devices with hardcoded majors and
    427          * minors */
    428         unsigned Number;
    429         floppy_drive_name szName;
     433        /* Floppies on Linux are legacy devices with hardcoded majors and minors */
    430434        if (major(ObjInfo.Attr.u.Unix.Device) != FLOPPY_MAJOR)
    431435            return false;
     436
     437        unsigned Number;
    432438        switch (minor(ObjInfo.Attr.u.Unix.Device))
    433439        {
     
    441447                return false;
    442448        }
     449
     450        floppy_drive_name szName;
    443451        if (!floppyGetName(pcszNode, Number, szName))
    444452            return false;
    445         floppyCreateDeviceStrings(szName, Number, pszDesc, cchDesc, pszUdi,
    446                                   cchUdi);
     453        floppyCreateDeviceStrings(szName, Number, pszDesc, cbDesc, pszUdi, cbUdi);
    447454    }
    448455    return true;
     
    450457
    451458
    452 int VBoxMainDriveInfo::updateDVDs ()
     459int VBoxMainDriveInfo::updateDVDs() RT_NOEXCEPT
    453460{
    454461    LogFlowThisFunc(("entered\n"));
    455     int rc = VINF_SUCCESS;
    456     bool success = false;  /* Have we succeeded in finding anything yet? */
     462    int rc;
    457463    try
    458464    {
    459         mDVDList.clear ();
     465        mDVDList.clear();
    460466        /* Always allow the user to override our auto-detection using an
    461467         * environment variable. */
    462         if (RT_SUCCESS(rc) && (!success || testing()))
    463             rc = getDriveInfoFromEnv ("VBOX_CDROM", &mDVDList, true /* isDVD */,
    464                                       &success);
     468        bool fSuccess = false;  /* Have we succeeded in finding anything yet? */
     469        rc = getDriveInfoFromEnv("VBOX_CDROM", &mDVDList, true /* isDVD */, &fSuccess);
    465470        setNoProbe(false);
    466         if (RT_SUCCESS(rc) && (!success || testing()))
    467             rc = getDriveInfoFromSysfs(&mDVDList, true /* isDVD */, &success);
     471        if (RT_SUCCESS(rc) && (!fSuccess || testing()))
     472            rc = getDriveInfoFromSysfs(&mDVDList, DVD, &fSuccess);
    468473        if (RT_SUCCESS(rc) && testing())
    469474        {
    470475            setNoProbe(true);
    471             rc = getDriveInfoFromSysfs(&mDVDList, true /* isDVD */, &success);
    472         }
    473     }
    474     catch(std::bad_alloc &e)
     476            rc = getDriveInfoFromSysfs(&mDVDList, DVD, &fSuccess);
     477        }
     478    }
     479    catch (std::bad_alloc &e)
    475480    {
    476481        rc = VERR_NO_MEMORY;
     
    480485}
    481486
    482 int VBoxMainDriveInfo::updateFloppies ()
     487int VBoxMainDriveInfo::updateFloppies() RT_NOEXCEPT
    483488{
    484489    LogFlowThisFunc(("entered\n"));
    485     int rc = VINF_SUCCESS;
    486     bool success = false;  /* Have we succeeded in finding anything yet? */
     490    int rc;
    487491    try
    488492    {
    489         mFloppyList.clear ();
    490         if (RT_SUCCESS(rc) && (!success || testing()))
    491             rc = getDriveInfoFromEnv("VBOX_FLOPPY", &mFloppyList,
    492                                      false /* isDVD */, &success);
     493        mFloppyList.clear();
     494        bool fSuccess = false;  /* Have we succeeded in finding anything yet? */
     495        rc = getDriveInfoFromEnv("VBOX_FLOPPY", &mFloppyList, false /* isDVD */, &fSuccess);
    493496        setNoProbe(false);
    494         if (   RT_SUCCESS(rc) && (!success || testing()))
    495             rc = getDriveInfoFromSysfs(&mFloppyList, false /* isDVD */,
    496                                        &success);
     497        if (RT_SUCCESS(rc) && (!fSuccess || testing()))
     498            rc = getDriveInfoFromSysfs(&mFloppyList, Floppy, &fSuccess);
    497499        if (RT_SUCCESS(rc) && testing())
    498500        {
    499501            setNoProbe(true);
    500             rc = getDriveInfoFromSysfs(&mFloppyList, false /* isDVD */, &success);
    501         }
    502     }
    503     catch(std::bad_alloc &e)
     502            rc = getDriveInfoFromSysfs(&mFloppyList, Floppy, &fSuccess);
     503        }
     504    }
     505    catch (std::bad_alloc &)
    504506    {
    505507        rc = VERR_NO_MEMORY;
     
    507509    LogFlowThisFunc(("rc=%Rrc\n", rc));
    508510    return rc;
     511}
     512
     513int VBoxMainDriveInfo::updateFixedDrives() RT_NOEXCEPT
     514{
     515    LogFlowThisFunc(("entered\n"));
     516    int vrc;
     517    try
     518    {
     519        mFixedDriveList.clear();
     520        setNoProbe(false);
     521        bool fSuccess = false;  /* Have we succeeded in finding anything yet? */
     522        vrc = getDriveInfoFromSysfs(&mFixedDriveList, FixedDisk, &fSuccess);
     523        if (RT_SUCCESS(vrc) && testing())
     524        {
     525            setNoProbe(true);
     526            vrc = getDriveInfoFromSysfs(&mFixedDriveList, FixedDisk, &fSuccess);
     527        }
     528    }
     529    catch (std::bad_alloc &)
     530    {
     531        vrc = VERR_NO_MEMORY;
     532    }
     533    LogFlowThisFunc(("vrc=%Rrc\n", vrc));
     534    return vrc;
    509535}
    510536
     
    513539 * Extract the names of drives from an environment variable and add them to a
    514540 * list if they are valid.
     541 *
    515542 * @returns iprt status code
    516543 * @param   pcszVar     the name of the environment variable.  The variable
     
    521548 * @param   pfSuccess  this will be set to true if we found at least one drive
    522549 *                     and to false otherwise.  Optional.
     550 *
     551 * @note    This is duplicated in HostHardwareFreeBSD.cpp.
    523552 */
    524 /* static */
    525 int getDriveInfoFromEnv(const char *pcszVar, DriveInfoList *pList,
    526                         bool isDVD, bool *pfSuccess)
     553static int getDriveInfoFromEnv(const char *pcszVar, DriveInfoList *pList, bool isDVD, bool *pfSuccess) RT_NOTHROW_DEF
    527554{
    528555    AssertPtrReturn(pcszVar, VERR_INVALID_POINTER);
    529556    AssertPtrReturn(pList, VERR_INVALID_POINTER);
    530557    AssertPtrNullReturn(pfSuccess, VERR_INVALID_POINTER);
    531     LogFlowFunc(("pcszVar=%s, pList=%p, isDVD=%d, pfSuccess=%p\n", pcszVar,
    532                  pList, isDVD, pfSuccess));
     558    LogFlowFunc(("pcszVar=%s, pList=%p, isDVD=%d, pfSuccess=%p\n", pcszVar, pList, isDVD, pfSuccess));
    533559    int rc = VINF_SUCCESS;
    534560    bool success = false;
     
    537563    try
    538564    {
    539         const char *pcszCurrent = pszFreeMe;
    540         while (pcszCurrent && *pcszCurrent != '\0')
    541         {
    542             const char *pcszNext = strchr(pcszCurrent, ':');
    543             char szPath[RTPATH_MAX], szReal[RTPATH_MAX];
     565        char *pszCurrent = pszFreeMe;
     566        while (pszCurrent && *pszCurrent != '\0')
     567        {
     568            char *pszNext = strchr(pszCurrent, ':');
     569            if (pszNext)
     570                *pszNext++ = '\0';
     571
     572            char szReal[RTPATH_MAX];
    544573            char szDesc[256], szUdi[256];
    545             if (pcszNext)
    546                 RTStrPrintf(szPath, sizeof(szPath), "%.*s",
    547                             pcszNext - pcszCurrent - 1, pcszCurrent);
    548             else
    549                 RTStrPrintf(szPath, sizeof(szPath), "%s", pcszCurrent);
    550             if (   RT_SUCCESS(RTPathReal(szPath, szReal, sizeof(szReal)))
    551                 && devValidateDevice(szReal, isDVD, NULL, szDesc,
    552                                      sizeof(szDesc), szUdi, sizeof(szUdi)))
     574            if (   RT_SUCCESS(RTPathReal(pszCurrent, szReal, sizeof(szReal)))
     575                && devValidateDevice(szReal, isDVD, NULL, szDesc, sizeof(szDesc), szUdi, sizeof(szUdi)))
    553576            {
    554577                pList->push_back(DriveInfo(szReal, szUdi, szDesc));
    555578                success = true;
    556579            }
    557             pcszCurrent = pcszNext ? pcszNext + 1 : NULL;
     580            pszCurrent = pszNext;
    558581        }
    559582        if (pfSuccess != NULL)
    560583            *pfSuccess = success;
    561584    }
    562     catch(std::bad_alloc &e)
     585    catch (std::bad_alloc &)
    563586    {
    564587        rc = VERR_NO_MEMORY;
     
    570593
    571594
    572 class sysfsBlockDev
     595class SysfsBlockDev
    573596{
    574597public:
    575     sysfsBlockDev(const char *pcszName, bool wantDVD)
    576             : mpcszName(pcszName), mwantDVD(wantDVD), misConsistent(true),
    577               misValid(false)
     598    SysfsBlockDev(const char *pcszName, SysfsWantDevice_T wantDevice) RT_NOEXCEPT
     599        : mpcszName(pcszName), mWantDevice(wantDevice), misConsistent(true), misValid(false)
    578600    {
    579601        if (findDeviceNode())
    580602        {
    581             if (mwantDVD)
    582                 validateAndInitForDVD();
    583             else
    584                 validateAndInitForFloppy();
     603            switch (mWantDevice)
     604            {
     605                case DVD:    validateAndInitForDVD(); break;
     606                case Floppy: validateAndInitForFloppy(); break;
     607                default:     validateAndInitForFixedDisk(); break;
     608            }
    585609        }
    586610    }
     
    588612    /** The name of the subdirectory of /sys/block for this device */
    589613    const char *mpcszName;
    590     /** Are we looking for a floppy or a DVD device? */
    591     bool mwantDVD;
     614    /** Are we looking for a floppy, a DVD or a fixed disk device? */
     615    SysfsWantDevice_T mWantDevice;
    592616    /** The device node for the device */
    593617    char mszNode[RTPATH_MAX];
     
    609633     * @returns boolean success value
    610634     */
    611     bool findDeviceNode()
     635    bool findDeviceNode() RT_NOEXCEPT
    612636    {
    613637        dev_t dev = 0;
     
    618642            return false;
    619643        }
    620         rc = RTLinuxCheckDevicePath(dev, RTFS_TYPE_DEV_BLOCK, mszNode,
    621                                     sizeof(mszNode), "%s", mpcszName);
    622         if (RT_FAILURE(rc))
    623             return false;
    624         return true;
     644        rc = RTLinuxCheckDevicePath(dev, RTFS_TYPE_DEV_BLOCK, mszNode, sizeof(mszNode), "%s", mpcszName);
     645        return RT_SUCCESS(rc);
    625646    }
    626647
     
    630651     * poking the device, and if that fails we fall back to an SCSI INQUIRY
    631652     * command. */
    632     void validateAndInitForDVD()
    633     {
    634         char szVendor[128], szModel[128];
     653    void validateAndInitForDVD() RT_NOEXCEPT
     654    {
    635655        int64_t type = 0;
    636656        int rc = RTLinuxSysFsReadIntFile(10, &type, "block/%s/device/type", mpcszName);
     
    639659        if (type == TYPE_ROM)
    640660        {
    641             rc = RTLinuxSysFsReadStrFile(szVendor, sizeof(szVendor), NULL,
    642                                         "block/%s/device/vendor", mpcszName);
     661            char szVendor[128];
     662            rc = RTLinuxSysFsReadStrFile(szVendor, sizeof(szVendor), NULL, "block/%s/device/vendor", mpcszName);
    643663            if (RT_SUCCESS(rc))
    644664            {
    645                 rc = RTLinuxSysFsReadStrFile(szModel, sizeof(szModel), NULL,
    646                                             "block/%s/device/model", mpcszName);
     665                char szModel[128];
     666                rc = RTLinuxSysFsReadStrFile(szModel, sizeof(szModel), NULL, "block/%s/device/model", mpcszName);
    647667                if (RT_SUCCESS(rc))
    648668                {
    649669                    misValid = true;
    650                     dvdCreateDeviceStrings(szVendor, szModel,
    651                                            mszDesc, sizeof(mszDesc),
    652                                            mszUdi, sizeof(mszUdi));
     670                    dvdCreateDeviceStrings(szVendor, szModel, mszDesc, sizeof(mszDesc), mszUdi, sizeof(mszUdi));
    653671                    return;
    654672                }
     
    663681     * data members for the object based on the returned data.
    664682     */
    665     void probeAndInitForDVD()
     683    void probeAndInitForDVD() RT_NOEXCEPT
    666684    {
    667685        AssertReturnVoid(mszNode[0] != '\0');
    668         uint8_t u8Type = 0;
     686        uint8_t bType = 0;
    669687        char szVendor[128] = "";
    670688        char szModel[128] = "";
    671         int rc = cdromDoInquiry(mszNode, &u8Type, szVendor,
    672                                 sizeof(szVendor), szModel,
    673                                 sizeof(szModel));
    674         if (RT_SUCCESS(rc) && (u8Type == TYPE_ROM))
     689        int rc = cdromDoInquiry(mszNode, &bType, szVendor, sizeof(szVendor), szModel, sizeof(szModel));
     690        if (RT_SUCCESS(rc) && bType == TYPE_ROM)
    675691        {
    676692            misValid = true;
    677             dvdCreateDeviceStrings(szVendor, szModel, mszDesc, sizeof(mszDesc),
    678                                    mszUdi, sizeof(mszUdi));
     693            dvdCreateDeviceStrings(szVendor, szModel, mszDesc, sizeof(mszDesc), mszUdi, sizeof(mszUdi));
    679694        }
    680695    }
     
    684699     * support floppies using the basic "floppy" driver, we check the driver
    685700     * using the entry name and a driver-specific ioctl. */
    686     void validateAndInitForFloppy()
    687     {
    688         bool haveName = false;
     701    void validateAndInitForFloppy() RT_NOEXCEPT
     702    {
    689703        floppy_drive_name szName;
    690704        char szDriver[8];
     
    695709            || mpcszName[3] != '\0')
    696710            return;
     711        bool fHaveName = false;
    697712        if (!noProbe())
    698             haveName = floppyGetName(mszNode, mpcszName[2] - '0', szName);
     713            fHaveName = floppyGetName(mszNode, mpcszName[2] - '0', szName);
    699714        int rc = RTLinuxSysFsGetLinkDest(szDriver, sizeof(szDriver), NULL, "block/%s/%s",
    700715                                         mpcszName, "device/driver");
     
    704719                return;
    705720        }
    706         else if (!haveName)
     721        else if (!fHaveName)
    707722            return;
    708         floppyCreateDeviceStrings(haveName ? szName : NULL,
     723        floppyCreateDeviceStrings(fHaveName ? szName : NULL,
    709724                                  mpcszName[2] - '0', mszDesc,
    710725                                  sizeof(mszDesc), mszUdi, sizeof(mszUdi));
     
    712727    }
    713728
     729    void validateAndInitForFixedDisk() RT_NOEXCEPT
     730    {
     731        /*
     732         * For current task only device path is needed. Therefore, device probing
     733         * is skipped and other fields are empty if there aren't files in the
     734         * device entry.
     735         */
     736        int64_t type = 0;
     737        int rc = RTLinuxSysFsReadIntFile(10, &type, "block/%s/device/type", mpcszName);
     738        if (RT_SUCCESS(rc) && type != TYPE_DISK)
     739            return;
     740        char szVendor[128];
     741        rc = RTLinuxSysFsReadStrFile(szVendor, sizeof(szVendor), NULL, "block/%s/device/vendor", mpcszName);
     742        if (RT_SUCCESS(rc))
     743        {
     744            char szModel[128];
     745            rc = RTLinuxSysFsReadStrFile(szModel, sizeof(szModel), NULL, "block/%s/device/model", mpcszName);
     746            if (RT_SUCCESS(rc))
     747            {
     748                misValid = true;
     749                dvdCreateDeviceStrings(szVendor, szModel, mszDesc, sizeof(mszDesc), mszUdi, sizeof(mszUdi));
     750                return;
     751            }
     752        }
     753    }
     754
    714755public:
    715     bool isConsistent()
     756    bool isConsistent() const RT_NOEXCEPT
    716757    {
    717758        return misConsistent;
    718759    }
    719     bool isValid()
     760    bool isValid() const RT_NOEXCEPT
    720761    {
    721762        return misValid;
    722763    }
    723     const char *getDesc()
     764    const char *getDesc() const RT_NOEXCEPT
    724765    {
    725766        return mszDesc;
    726767    }
    727     const char *getUdi()
     768    const char *getUdi() const RT_NOEXCEPT
    728769    {
    729770        return mszUdi;
    730771    }
    731     const char *getNode()
     772    const char *getNode() const RT_NOEXCEPT
    732773    {
    733774        return mszNode;
     
    739780 * drives attached to the system.
    740781 * @returns iprt status code
    741  * @param   pList      where to add information about the drives detected
    742  * @param   isDVD      are we looking for DVDs or floppies?
    743  * @param   pfSuccess  Did we find anything?
     782 * @param   pList       where to add information about the drives detected
     783 * @param   wantDevice  The kind of devices we're looking for.
     784 * @param   pfSuccess   Did we find anything?
    744785 *
    745786 * @returns IPRT status code
     787 * @throws  Nothing.
    746788 */
    747 /* static */
    748 int getDriveInfoFromSysfs(DriveInfoList *pList, bool isDVD, bool *pfSuccess)
     789static int getDriveInfoFromSysfs(DriveInfoList *pList, SysfsWantDevice_T wantDevice, bool *pfSuccess) RT_NOTHROW_DEF
    749790{
    750791    AssertPtrReturn(pList, VERR_INVALID_POINTER);
    751792    AssertPtrNullReturn(pfSuccess, VERR_INVALID_POINTER); /* Valid or Null */
    752     LogFlowFunc (("pList=%p, isDVD=%u, pfSuccess=%p\n",
    753                   pList, (unsigned) isDVD, pfSuccess));
    754     RTDIR hDir;
    755     int rc;
    756     bool fSuccess = false;
    757     unsigned cFound = 0;
    758 
     793    LogFlowFunc (("pList=%p, wantDevice=%u, pfSuccess=%p\n",
     794                  pList, (unsigned)wantDevice, pfSuccess));
    759795    if (!RTPathExists("/sys"))
    760796        return VINF_SUCCESS;
    761     rc = RTDirOpen(&hDir, "/sys/block");
     797
     798    bool fSuccess = true;
     799    unsigned cFound = 0;
     800    RTDIR hDir = NIL_RTDIR;
     801    int rc = RTDirOpen(&hDir, "/sys/block");
    762802    /* This might mean that sysfs semantics have changed */
    763803    AssertReturn(rc != VERR_FILE_NOT_FOUND, VINF_SUCCESS);
    764     fSuccess = true;
    765804    if (RT_SUCCESS(rc))
    766805    {
     
    774813            if (entry.szName[0] == '.')
    775814                continue;
    776             sysfsBlockDev dev(entry.szName, isDVD);
     815            SysfsBlockDev dev(entry.szName, wantDevice);
    777816            /* This might mean that sysfs semantics have changed */
    778817            AssertBreakStmt(dev.isConsistent(), fSuccess = false);
     
    783822                pList->push_back(DriveInfo(dev.getNode(), dev.getUdi(), dev.getDesc()));
    784823            }
    785             catch(std::bad_alloc &e)
     824            catch (std::bad_alloc &e)
    786825            {
    787826                rc = VERR_NO_MEMORY;
     
    794833    if (rc == VERR_NO_MORE_FILES)
    795834        rc = VINF_SUCCESS;
    796     if (RT_FAILURE(rc))
     835    else if (RT_FAILURE(rc))
    797836        /* Clean up again */
    798         for (unsigned i = 0; i < cFound; ++i)
     837        while (cFound-- > 0)
    799838            pList->pop_back();
    800839    if (pfSuccess)
    801840        *pfSuccess = fSuccess;
    802     LogFlow (("rc=%Rrc, fSuccess=%u\n", rc, (unsigned) fSuccess));
     841    LogFlow (("rc=%Rrc, fSuccess=%u\n", rc, (unsigned)fSuccess));
    803842    return rc;
    804843}
     
    807846/** Helper for readFilePathsFromDir().  Adds a path to the vector if it is not
    808847 * NULL and not a dotfile (".", "..", ".*"). */
    809 static int maybeAddPathToVector(const char *pcszPath, const char *pcszEntry,
    810                                 VECTOR_PTR(char *) *pvecpchDevs)
    811 {
    812     char *pszPath;
    813 
     848static int maybeAddPathToVector(const char *pcszPath, const char *pcszEntry, VECTOR_PTR(char *) *pvecpchDevs) RT_NOTHROW_DEF
     849{
    814850    if (!pcszPath)
    815851        return 0;
    816852    if (pcszEntry[0] == '.')
    817853        return 0;
    818     pszPath = RTStrDup(pcszPath);
    819     if (!pszPath)
    820         return ENOMEM;
    821     if (RT_FAILURE(VEC_PUSH_BACK_PTR(pvecpchDevs, char *, pszPath)))
    822         return ENOMEM;
    823     return 0;
    824 }
    825 
    826 /** Helper for readFilePaths().  Adds the entries from the open directory
    827  * @a pDir to the vector @a pvecpchDevs using either the full path or the
    828  * realpath() and skipping hidden files and files on which realpath() fails. */
    829 static int readFilePathsFromDir(const char *pcszPath, DIR *pDir,
    830                                 VECTOR_PTR(char *) *pvecpchDevs, int withRealPath)
     854    char *pszPath = RTStrDup(pcszPath);
     855    if (pszPath)
     856    {
     857        int vrc = VEC_PUSH_BACK_PTR(pvecpchDevs, char *, pszPath);
     858        if (RT_SUCCESS(vrc))
     859            return 0;
     860    }
     861    return ENOMEM;
     862}
     863
     864/**
     865 * Helper for readFilePaths().
     866 *
     867 * Adds the entries from the open directory @a pDir to the vector @a pvecpchDevs
     868 * using either the full path or the realpath() and skipping hidden files
     869 * and files on which realpath() fails.
     870 */
     871static int readFilePathsFromDir(const char *pcszPath, DIR *pDir, VECTOR_PTR(char *) *pvecpchDevs, int withRealPath) RT_NOTHROW_DEF
    831872{
    832873    struct dirent entry, *pResult;
     
    837878# pragma GCC diagnostic ignored "-Wdeprecated-declarations"
    838879#endif
    839     for (err = readdir_r(pDir, &entry, &pResult); pResult;
     880    for (err = readdir_r(pDir, &entry, &pResult);
     881         pResult /** @todo r=bird: && err == 0 ? */;
    840882         err = readdir_r(pDir, &entry, &pResult))
    841883#if RT_GNUC_PREREQ(4, 6)
     
    869911 * @param   withRealPath  whether to canonicalise the filename with realpath
    870912 */
    871 static int readFilePaths(const char *pcszPath, VECTOR_PTR(char *) *pvecpchDevs,
    872                          int withRealPath)
    873 {
    874     DIR *pDir;
    875     int err;
    876 
     913static int readFilePaths(const char *pcszPath, VECTOR_PTR(char *) *pvecpchDevs, int withRealPath) RT_NOTHROW_DEF
     914{
    877915    AssertPtrReturn(pvecpchDevs, EINVAL);
    878916    AssertReturn(VEC_SIZE_PTR(pvecpchDevs) == 0, EINVAL);
    879917    AssertPtrReturn(pcszPath, EINVAL);
    880918
    881     pDir = opendir(pcszPath);
     919    DIR *pDir = opendir(pcszPath);
    882920    if (!pDir)
    883921        return RTErrConvertFromErrno(errno);
    884     err = readFilePathsFromDir(pcszPath, pDir, pvecpchDevs, withRealPath);
     922    int err = readFilePathsFromDir(pcszPath, pDir, pvecpchDevs, withRealPath);
    885923    if (closedir(pDir) < 0 && !err)
    886924        err = errno;
     
    12621300        mImpl = new hotplugNullImpl(pcszDevicesRoot);
    12631301    }
    1264     catch(std::bad_alloc &e)
     1302    catch (std::bad_alloc &e)
    12651303    { }
    12661304}
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