VirtualBox

Changeset 79965 in vbox


Ignore:
Timestamp:
Jul 24, 2019 8:32:32 PM (5 years ago)
Author:
vboxsync
Message:

Storage: Added a desired format parameter to VDGetFormat() so Main can pass along the device type. Bumped the RAW backend down after the CUE and VISO to prevent (impossible) mixups of tiny files. Extended rawProbe() to look for a valid ISO-9660/UDF descriptor sequence on the image if the caller doesn't say it should be a floppy or hdd, only if that fail go by the extension. Note! the pfnProbe callback should probably get a score return parameter to indicate how confient the backend is about the probe result, as this would prevent the RAW backend from accidentally grabbing images which belongs to a plug-in. bugref:9151

Location:
trunk
Files:
23 edited

Legend:

Unmodified
Added
Removed
  • trunk/include/VBox/vd-image-backend.h

    r76585 r79965  
    9696     * @param   pVDIfsDisk      Pointer to the per-disk VD interface list.
    9797     * @param   pVDIfsImage     Pointer to the per-image VD interface list.
     98     * @param   enmDesiredType  The desired image type, VDTYPE_INVALID if anything goes.
    9899     * @param   penmType        Returns the supported device type on success.
    99100     */
    100101    DECLR3CALLBACKMEMBER(int, pfnProbe, (const char *pszFilename, PVDINTERFACE pVDIfsDisk,
    101                                          PVDINTERFACE pVDIfsImage, VDTYPE *penmType));
     102                                         PVDINTERFACE pVDIfsImage, VDTYPE enmDesiredType, VDTYPE *penmType));
    102103
    103104    /**
  • trunk/include/VBox/vd.h

    r79742 r79965  
    592592 * @param   pVDIfsImage     Pointer to the per-image VD interface list.
    593593 * @param   pszFilename     Name of the image file for which the backend is queried.
     594 * @param   enmDesiredType  The desired image type, VDTYPE_INVALID if anything goes.
    594595 * @param   ppszFormat      Receives pointer of the UTF-8 string which contains the format name.
    595596 *                          The returned pointer must be freed using RTStrFree().
     
    597598 */
    598599VBOXDDU_DECL(int) VDGetFormat(PVDINTERFACE pVDIfsDisk, PVDINTERFACE pVDIfsImage,
    599                               const char *pszFilename, char **ppszFormat, VDTYPE *penmType);
     600                              const char *pszFilename, VDTYPE enmDesiredType,
     601                              char **ppszFormat, VDTYPE *penmType);
    600602
    601603/**
  • trunk/src/VBox/Frontends/VBoxManage/VBoxInternalManage.cpp

    r77595 r79965  
    656656    VDTYPE enmType = VDTYPE_INVALID;
    657657    int rc = VDGetFormat(NULL /* pVDIfsDisk */, NULL /* pVDIfsImage */,
    658                          argv[1], &pszFormat, &enmType);
     658                         argv[1], VDTYPE_INVALID, &pszFormat, &enmType);
    659659    if (RT_FAILURE(rc))
    660660        return RTMsgErrorExit(RTEXITCODE_FAILURE, "Format autodetect failed: %Rrc", rc);
     
    709709    VDTYPE enmType = VDTYPE_INVALID;
    710710    int rc = VDGetFormat(NULL /* pVDIfsDisk */, NULL /* pVDIfsImage */,
    711                          argv[0], &pszFormat, &enmType);
     711                         argv[0], VDTYPE_INVALID, &pszFormat, &enmType);
    712712    if (RT_FAILURE(rc))
    713713        return RTMsgErrorExit(RTEXITCODE_FAILURE, "Format autodetect failed: %Rrc", rc);
     
    20162016        VDTYPE enmType = VDTYPE_INVALID;
    20172017        vrc = VDGetFormat(NULL /* pVDIfsDisk */, NULL /* pVDIfsImage */,
    2018                           src.c_str(), &pszFormat, &enmType);
     2018                          src.c_str(), VDTYPE_INVALID, &pszFormat, &enmType);
    20192019        if (RT_FAILURE(vrc) || enmType != VDTYPE_HDD)
    20202020        {
     
    21642164            char *pszFormat = NULL;
    21652165            vrc = VDGetFormat(NULL /* pVDIfsDisk */, NULL /* pVDIfsImage */,
    2166                               src.c_str(), &pszFormat, &enmSrcType);
     2166                              src.c_str(), VDTYPE_HDD, &pszFormat, &enmSrcType);
    21672167            if (RT_FAILURE(vrc))
    21682168            {
     
    22822282
    22832283            vrc = VDGetFormat(NULL /* pVDIfsDisk */, NULL /* pVDIfsImage */,
    2284                               image.c_str(), &pszFormat, &enmSrcType);
     2284                              image.c_str(), VDTYPE_HDD, &pszFormat, &enmSrcType);
    22852285            if (RT_FAILURE(vrc) && (vrc != VERR_VD_IMAGE_CORRUPTED))
    22862286            {
  • trunk/src/VBox/ImageMounter/VBoxFUSE/VBoxFUSE.cpp

    r76553 r79965  
    521521    char *pszFormat;
    522522    VDTYPE enmType;
    523     rc = VDGetFormat(NULL /* pVDIIfsDisk */, NULL /* pVDIIfsImage*/, pszImage, &pszFormat, &enmType);
     523    rc = VDGetFormat(NULL /* pVDIIfsDisk */, NULL /* pVDIIfsImage*/, pszImage,  VDTYPE_INVALID,&pszFormat, &enmType);
    524524    if (RT_FAILURE(rc))
    525525    {
  • trunk/src/VBox/ImageMounter/vboximg-mount/vboximg-mount.cpp

    r77143 r79965  
    13721372     * Create HDD container to open base image and differencing images into
    13731373     */
    1374     rc = VDGetFormat(NULL /* pVDIIfsDisk */, NULL /* pVDIIfsImage*/,
     1374    rc = VDGetFormat(NULL /* pVDIIfsDisk */, NULL /* pVDIIfsImage*/, VDTYPE_INVALID,
    13751375            CSTR(pVDiskBaseImagePath), &pszFormat, &enmType);
    13761376
  • trunk/src/VBox/Main/src-server/MediumImpl.cpp

    r79961 r79965  
    76197619        if (isImport)
    76207620        {
     7621            VDTYPE const enmDesiredType = m->devType == DeviceType_Floppy   ? VDTYPE_FLOPPY
     7622                                        : m->devType == DeviceType_DVD      ? VDTYPE_OPTICAL_DISC
     7623                                        : m->devType == DeviceType_HardDisk ? VDTYPE_HDD : VDTYPE_INVALID;
    76217624            VDTYPE enmType = VDTYPE_INVALID;
    76227625            char *backendName = NULL;
     
    76347637            {
    76357638                vrc = VDGetFormat(NULL /* pVDIfsDisk */, NULL /* pVDIfsImage */,
    7636                                   locationFull.c_str(), &backendName, &enmType);
     7639                                  locationFull.c_str(), enmDesiredType, &backendName, &enmType);
    76377640            }
    76387641            else if (   vrc != VERR_FILE_NOT_FOUND
     
    76447647                locationFull = aLocation;
    76457648                vrc = VDGetFormat(NULL /* pVDIfsDisk */, NULL /* pVDIfsImage */,
    7646                                   locationFull.c_str(), &backendName, &enmType);
     7649                                  locationFull.c_str(), enmDesiredType, &backendName, &enmType);
    76477650            }
    76487651
  • trunk/src/VBox/Storage/CUE.cpp

    r78169 r79965  
    14321432/** @copydoc VDIMAGEBACKEND::pfnProbe */
    14331433static DECLCALLBACK(int) cueProbe(const char *pszFilename, PVDINTERFACE pVDIfsDisk,
    1434                                   PVDINTERFACE pVDIfsImage, VDTYPE *penmType)
    1435 {
    1436     RT_NOREF1(pVDIfsDisk);
     1434                                  PVDINTERFACE pVDIfsImage, VDTYPE enmDesiredType, VDTYPE *penmType)
     1435{
     1436    RT_NOREF(pVDIfsDisk, enmDesiredType);
    14371437    LogFlowFunc(("pszFilename=\"%s\" pVDIfsDisk=%#p pVDIfsImage=%#p\n", pszFilename, pVDIfsDisk, pVDIfsImage));
    14381438    int rc = VINF_SUCCESS;
  • trunk/src/VBox/Storage/DMG.cpp

    r76553 r79965  
    17421742/** @interface_method_impl{VDIMAGEBACKEND,pfnProbe} */
    17431743static DECLCALLBACK(int) dmgProbe(const char *pszFilename, PVDINTERFACE pVDIfsDisk,
    1744                                   PVDINTERFACE pVDIfsImage, VDTYPE *penmType)
    1745 {
    1746     RT_NOREF1(pVDIfsDisk);
     1744                                  PVDINTERFACE pVDIfsImage, VDTYPE enmDesiredType, VDTYPE *penmType)
     1745{
     1746    RT_NOREF(pVDIfsDisk, enmDesiredType);
    17471747    LogFlowFunc(("pszFilename=\"%s\" pVDIfsDisk=%#p pVDIfsImage=%#p penmType=%#p\n",
    17481748                 pszFilename, pVDIfsDisk, pVDIfsImage, penmType));
  • trunk/src/VBox/Storage/ISCSI.cpp

    r76553 r79965  
    47674767/** @copydoc VDIMAGEBACKEND::pfnProbe */
    47684768static DECLCALLBACK(int) iscsiProbe(const char *pszFilename, PVDINTERFACE pVDIfsDisk,
    4769                                     PVDINTERFACE pVDIfsImage, VDTYPE *penmType)
    4770 {
    4771     RT_NOREF4(pszFilename, pVDIfsDisk, pVDIfsImage, penmType);
     4769                                    PVDINTERFACE pVDIfsImage, VDTYPE enmDesiredType, VDTYPE *penmType)
     4770{
     4771    RT_NOREF(pszFilename, pVDIfsDisk, pVDIfsImage, enmDesiredType, penmType);
    47724772    LogFlowFunc(("pszFilename=\"%s\"\n", pszFilename));
    47734773
  • trunk/src/VBox/Storage/Parallels.cpp

    r77699 r79965  
    376376/** @copydoc VDIMAGEBACKEND::pfnProbe */
    377377static DECLCALLBACK(int) parallelsProbe(const char *pszFilename, PVDINTERFACE pVDIfsDisk,
    378                                         PVDINTERFACE pVDIfsImage, VDTYPE *penmType)
    379 {
    380     RT_NOREF1(pVDIfsDisk);
     378                                        PVDINTERFACE pVDIfsImage, VDTYPE enmDesiredType, VDTYPE *penmType)
     379{
     380    RT_NOREF(pVDIfsDisk, enmDesiredType);
    381381    int rc;
    382382    PVDIOSTORAGE pStorage;
  • trunk/src/VBox/Storage/QCOW.cpp

    r77924 r79965  
    15771577/** @copydoc VDIMAGEBACKEND::pfnProbe */
    15781578static DECLCALLBACK(int) qcowProbe(const char *pszFilename, PVDINTERFACE pVDIfsDisk,
    1579                                    PVDINTERFACE pVDIfsImage, VDTYPE *penmType)
    1580 {
    1581     RT_NOREF1(pVDIfsDisk);
     1579                                   PVDINTERFACE pVDIfsImage, VDTYPE enmDesiredType, VDTYPE *penmType)
     1580{
     1581    RT_NOREF(pVDIfsDisk, enmDesiredType);
    15821582    LogFlowFunc(("pszFilename=\"%s\" pVDIfsDisk=%#p pVDIfsImage=%#p\n", pszFilename, pVDIfsDisk, pVDIfsImage));
    15831583    PVDIOSTORAGE pStorage = NULL;
  • trunk/src/VBox/Storage/QED.cpp

    r77232 r79965  
    15031503/** @copydoc VDIMAGEBACKEND::pfnProbe */
    15041504static DECLCALLBACK(int) qedProbe(const char *pszFilename, PVDINTERFACE pVDIfsDisk,
    1505                                   PVDINTERFACE pVDIfsImage, VDTYPE *penmType)
    1506 {
    1507     RT_NOREF1(pVDIfsDisk);
     1505                                  PVDINTERFACE pVDIfsImage, VDTYPE enmDesiredType, VDTYPE *penmType)
     1506{
     1507    RT_NOREF(pVDIfsDisk, enmDesiredType);
    15081508    LogFlowFunc(("pszFilename=\"%s\" pVDIfsDisk=%#p pVDIfsImage=%#p\n", pszFilename, pVDIfsDisk, pVDIfsImage));
    15091509    PVDIOSTORAGE pStorage = NULL;
  • trunk/src/VBox/Storage/RAW.cpp

    r76553 r79965  
    2828#include <iprt/alloc.h>
    2929#include <iprt/path.h>
     30#include <iprt/formats/iso9660.h>
     31#include <iprt/formats/udf.h>
    3032
    3133#include "VDBackends.h"
     
    320322}
    321323
     324/**
     325 * Worker for rawProbe that checks if the file looks like it contains an ISO
     326 * 9660 or UDF descriptor sequence at the expected offset.
     327 *
     328 * Caller already checked if the size is suitable for ISOs.
     329 *
     330 * @returns IPRT status code.  Success if detected ISO 9660 or UDF, failure if
     331 *          not.
     332 *
     333 * @note Code is a modified version of rtFsIsoVolTryInit() IPRT (isovfs.cpp).
     334 */
     335static int rawProbeIsIso9660OrUdf(PVDINTERFACEIOINT pIfIo, PVDIOSTORAGE pStorage)
     336{
     337    PRTERRINFO                  pErrInfo = NULL;
     338    const uint32_t              cbSector = _2K;
     339
     340    union
     341    {
     342        uint8_t                 ab[_2K];
     343        ISO9660VOLDESCHDR       VolDescHdr;
     344    } Buf;
     345    Assert(cbSector <= sizeof(Buf));
     346    RT_ZERO(Buf);
     347
     348    uint8_t         uUdfLevel               = 0;
     349    uint64_t        offUdfBootVolDesc       = UINT64_MAX;
     350
     351    uint32_t        cPrimaryVolDescs        = 0;
     352    uint32_t        cSupplementaryVolDescs  = 0;
     353    uint32_t        cBootRecordVolDescs     = 0;
     354    uint32_t        offVolDesc              = 16 * cbSector;
     355    enum
     356    {
     357        kStateStart = 0,
     358        kStateNoSeq,
     359        kStateCdSeq,
     360        kStateUdfSeq
     361    }               enmState = kStateStart;
     362    for (uint32_t iVolDesc = 0; ; iVolDesc++, offVolDesc += cbSector)
     363    {
     364        if (iVolDesc > 32)
     365            return RTERRINFO_LOG_SET(pErrInfo, VERR_VFS_BOGUS_FORMAT, "More than 32 volume descriptors, doesn't seem right...");
     366
     367        /* Read the next one and check the signature. */
     368        int rc = vdIfIoIntFileReadSync(pIfIo, pStorage, offVolDesc, &Buf, cbSector);
     369        if (RT_FAILURE(rc))
     370            return RTERRINFO_LOG_SET_F(pErrInfo, rc, "Unable to read volume descriptor #%u", iVolDesc);
     371
     372#define MATCH_STD_ID(a_achStdId1, a_szStdId2) \
     373            (   (a_achStdId1)[0] == (a_szStdId2)[0] \
     374             && (a_achStdId1)[1] == (a_szStdId2)[1] \
     375             && (a_achStdId1)[2] == (a_szStdId2)[2] \
     376             && (a_achStdId1)[3] == (a_szStdId2)[3] \
     377             && (a_achStdId1)[4] == (a_szStdId2)[4] )
     378#define MATCH_HDR(a_pStd, a_bType2, a_szStdId2, a_bVer2) \
     379            (    MATCH_STD_ID((a_pStd)->achStdId, a_szStdId2) \
     380             && (a_pStd)->bDescType    == (a_bType2) \
     381             && (a_pStd)->bDescVersion == (a_bVer2) )
     382
     383        /*
     384         * ISO 9660 ("CD001").
     385         */
     386        if (   (   enmState == kStateStart
     387                || enmState == kStateCdSeq
     388                || enmState == kStateNoSeq)
     389            && MATCH_STD_ID(Buf.VolDescHdr.achStdId, ISO9660VOLDESC_STD_ID) )
     390        {
     391            enmState = kStateCdSeq;
     392
     393            /* Do type specific handling. */
     394            Log(("RAW/ISO9660: volume desc #%u: type=%#x\n", iVolDesc, Buf.VolDescHdr.bDescType));
     395            if (Buf.VolDescHdr.bDescType == ISO9660VOLDESC_TYPE_PRIMARY)
     396            {
     397                cPrimaryVolDescs++;
     398                if (Buf.VolDescHdr.bDescVersion != ISO9660PRIMARYVOLDESC_VERSION)
     399                    return RTERRINFO_LOG_SET_F(pErrInfo, VERR_VFS_UNSUPPORTED_FORMAT,
     400                                               "Unsupported primary volume descriptor version: %#x", Buf.VolDescHdr.bDescVersion);
     401                if (cPrimaryVolDescs == 1)
     402                { /*rc = rtFsIsoVolHandlePrimaryVolDesc(pThis, &Buf.PrimaryVolDesc, offVolDesc, &RootDir, &offRootDirRec, pErrInfo);*/ }
     403                else if (cPrimaryVolDescs == 2)
     404                    Log(("RAW/ISO9660: ignoring 2nd primary descriptor\n")); /* so we can read the w2k3 ifs kit */
     405                else
     406                    return RTERRINFO_LOG_SET(pErrInfo, VERR_VFS_UNSUPPORTED_FORMAT, "More than one primary volume descriptor");
     407            }
     408            else if (Buf.VolDescHdr.bDescType == ISO9660VOLDESC_TYPE_SUPPLEMENTARY)
     409            {
     410                cSupplementaryVolDescs++;
     411                if (Buf.VolDescHdr.bDescVersion != ISO9660SUPVOLDESC_VERSION)
     412                    return RTERRINFO_LOG_SET_F(pErrInfo, VERR_VFS_UNSUPPORTED_FORMAT,
     413                                               "Unsupported supplemental volume descriptor version: %#x", Buf.VolDescHdr.bDescVersion);
     414                /*rc = rtFsIsoVolHandleSupplementaryVolDesc(pThis, &Buf.SupVolDesc, offVolDesc, &bJolietUcs2Level, &JolietRootDir,
     415                                                          &offJolietRootDirRec, pErrInfo);*/
     416            }
     417            else if (Buf.VolDescHdr.bDescType == ISO9660VOLDESC_TYPE_BOOT_RECORD)
     418            {
     419                cBootRecordVolDescs++;
     420            }
     421            else if (Buf.VolDescHdr.bDescType == ISO9660VOLDESC_TYPE_TERMINATOR)
     422            {
     423                if (!cPrimaryVolDescs)
     424                    return RTERRINFO_LOG_SET(pErrInfo, VERR_VFS_BOGUS_FORMAT, "No primary volume descriptor");
     425                enmState = kStateNoSeq;
     426            }
     427            else
     428                return RTERRINFO_LOG_SET_F(pErrInfo, VERR_VFS_UNSUPPORTED_FORMAT,
     429                                           "Unknown volume descriptor: %#x", Buf.VolDescHdr.bDescType);
     430        }
     431        /*
     432         * UDF volume recognition sequence (VRS).
     433         */
     434        else if (   (   enmState == kStateNoSeq
     435                     || enmState == kStateStart)
     436                 && MATCH_HDR(&Buf.VolDescHdr, UDF_EXT_VOL_DESC_TYPE, UDF_EXT_VOL_DESC_STD_ID_BEGIN, UDF_EXT_VOL_DESC_VERSION) )
     437        {
     438            if (uUdfLevel == 0)
     439                enmState = kStateUdfSeq;
     440            else
     441                return RTERRINFO_LOG_SET_F(pErrInfo, VERR_VFS_BOGUS_FORMAT, "Only one BEA01 sequence is supported");
     442        }
     443        else if (   enmState == kStateUdfSeq
     444                 && MATCH_HDR(&Buf.VolDescHdr, UDF_EXT_VOL_DESC_TYPE, UDF_EXT_VOL_DESC_STD_ID_NSR_02, UDF_EXT_VOL_DESC_VERSION) )
     445            uUdfLevel = 2;
     446        else if (   enmState == kStateUdfSeq
     447                 && MATCH_HDR(&Buf.VolDescHdr, UDF_EXT_VOL_DESC_TYPE, UDF_EXT_VOL_DESC_STD_ID_NSR_03, UDF_EXT_VOL_DESC_VERSION) )
     448            uUdfLevel = 3;
     449        else if (   enmState == kStateUdfSeq
     450                 && MATCH_HDR(&Buf.VolDescHdr, UDF_EXT_VOL_DESC_TYPE, UDF_EXT_VOL_DESC_STD_ID_BOOT, UDF_EXT_VOL_DESC_VERSION) )
     451        {
     452            if (offUdfBootVolDesc == UINT64_MAX)
     453                offUdfBootVolDesc = iVolDesc * cbSector;
     454            else
     455                return RTERRINFO_LOG_SET_F(pErrInfo, VERR_VFS_BOGUS_FORMAT, "Only one BOOT2 descriptor is supported");
     456        }
     457        else if (   enmState == kStateUdfSeq
     458                 && MATCH_HDR(&Buf.VolDescHdr, UDF_EXT_VOL_DESC_TYPE, UDF_EXT_VOL_DESC_STD_ID_TERM, UDF_EXT_VOL_DESC_VERSION) )
     459        {
     460            if (uUdfLevel != 0)
     461                enmState = kStateNoSeq;
     462            else
     463                return RTERRINFO_LOG_SET_F(pErrInfo, VERR_VFS_BOGUS_FORMAT, "Found BEA01 & TEA01, but no NSR02 or NSR03 descriptors");
     464        }
     465        /*
     466         * Unknown, probably the end.
     467         */
     468        else if (enmState == kStateNoSeq)
     469            break;
     470        else if (enmState == kStateStart)
     471                return RTERRINFO_LOG_SET_F(pErrInfo, VERR_VFS_UNKNOWN_FORMAT,
     472                                           "Not ISO? Unable to recognize volume descriptor signature: %.5Rhxs", Buf.VolDescHdr.achStdId);
     473        else if (enmState == kStateCdSeq)
     474            return RTERRINFO_LOG_SET_F(pErrInfo, VERR_VFS_BOGUS_FORMAT,
     475                                       "Missing ISO 9660 terminator volume descriptor? (Found %.5Rhxs)", Buf.VolDescHdr.achStdId);
     476        else if (enmState == kStateUdfSeq)
     477            return RTERRINFO_LOG_SET_F(pErrInfo, VERR_VFS_BOGUS_FORMAT,
     478                                       "Missing UDF terminator volume descriptor? (Found %.5Rhxs)", Buf.VolDescHdr.achStdId);
     479        else
     480            return RTERRINFO_LOG_SET_F(pErrInfo, VERR_VFS_UNKNOWN_FORMAT,
     481                                       "Unknown volume descriptor signature found at sector %u: %.5Rhxs",
     482                                       16 + iVolDesc, Buf.VolDescHdr.achStdId);
     483    }
     484
     485    return VINF_SUCCESS;
     486}
     487
     488/**
     489 * Checks the given extension array for the given suffix and type.
     490 *
     491 * @returns true if found in the list, false if not.
     492 * @param   paExtensions        The extension array to check against.
     493 * @param   pszSuffix           The suffix to look for.  Can be NULL.
     494 * @param   enmType             The image type to look for.
     495 */
     496static bool rawProbeContainsExtension(const VDFILEEXTENSION *paExtensions, const char *pszSuffix, VDTYPE enmType)
     497{
     498    if (pszSuffix)
     499    {
     500        if (*pszSuffix == '.')
     501            pszSuffix++;
     502        if (*pszSuffix != '\0')
     503        {
     504            for (size_t i = 0;; i++)
     505            {
     506                if (!paExtensions[i].pszExtension)
     507                    break;
     508                if (   paExtensions[i].enmType == enmType
     509                    && RTStrICmpAscii(paExtensions[i].pszExtension, pszSuffix) == 0)
     510                    return true;
     511            }
     512        }
     513    }
     514    return false;
     515}
     516
    322517
    323518/** @copydoc VDIMAGEBACKEND::pfnProbe */
    324519static DECLCALLBACK(int) rawProbe(const char *pszFilename, PVDINTERFACE pVDIfsDisk,
    325                                   PVDINTERFACE pVDIfsImage, VDTYPE *penmType)
    326 {
    327     RT_NOREF1(pVDIfsDisk);
     520                                  PVDINTERFACE pVDIfsImage, VDTYPE enmDesiredType, VDTYPE *penmType)
     521{
     522    RT_NOREF(pVDIfsDisk, enmDesiredType);
    328523    LogFlowFunc(("pszFilename=\"%s\" pVDIfsDisk=%#p pVDIfsImage=%#p\n", pszFilename, pVDIfsDisk, pVDIfsImage));
    329524    PVDIOSTORAGE pStorage = NULL;
     
    343538    {
    344539        uint64_t cbFile;
    345         const char *pszSuffix = RTPathSuffix(pszFilename);
    346540        rc = vdIfIoIntFileGetSize(pIfIo, pStorage, &cbFile);
    347 
    348         /* Try to guess the image type based on the extension. */
    349         if (   RT_SUCCESS(rc)
    350             && pszSuffix)
     541        if (RT_SUCCESS(rc))
    351542        {
    352             if (   !RTStrICmp(pszSuffix, ".iso")
    353                 || !RTStrICmp(pszSuffix, ".cdr")) /* DVD images. */
     543            /*
     544             * Detecting raw ISO and floppy images and keeping them apart isn't all
     545             * that simple.
     546             *
     547             * - Both must be a multiple of their sector sizes, though
     548             *   that means that any ISO can also be a floppy, since 2048 is 512 * 4.
     549             * - The ISO images must be 32KB and floppies are generally not larger
     550             *   than 2.88MB, but that leaves quite a bit of size overlap,
     551             *
     552             * So, the size cannot conclusively say whether something is one or the other.
     553             *
     554             * - The content of a normal ISO image is detectable, but not all ISO
     555             *   images need to follow that spec to work in a DVD ROM drive.
     556             * - It is common for ISO images to start like a floppy with a boot sector
     557             *   at the very start of the image.
     558             * - Floppies doesn't need to contain a DOS-style boot sector, it depends
     559             *   on the system it is formatted and/or intended for.
     560             *
     561             * So, the content cannot conclusively determine the type either.
     562             *
     563             * However, there are a number of cases, especially for ISOs, where we can
     564             * say we a deal of confidence that something is an ISO image.
     565             */
     566            const char * const pszSuffix = RTPathSuffix(pszFilename);
     567
     568            /*
     569             * Start by checking for sure signs of an ISO 9660 / UDF image.
     570             */
     571            rc = VERR_VD_RAW_INVALID_HEADER;
     572            if (   (enmDesiredType == VDTYPE_INVALID || enmDesiredType == VDTYPE_OPTICAL_DISC)
     573                && (cbFile % 2048) == 0
     574                &&  cbFile > 32768)
    354575            {
    355                 /* Note that there are ISO images smaller than 1 MB; it is impossible to distinguish
    356                  * between raw floppy and CD images based on their size (and cannot be reliably done
    357                  * based on contents, either).
    358                  * bird: Not sure what this comment is mumbling about, the test below is 32KB not 1MB.
    359                  */
    360                 if (cbFile % 2048)
    361                     rc = VERR_VD_RAW_SIZE_MODULO_2048;
    362                 else if (cbFile <= 32768)
    363                     rc = VERR_VD_RAW_SIZE_OPTICAL_TOO_SMALL;
    364                 else
     576                int rc2 = rawProbeIsIso9660OrUdf(pIfIo, pStorage);
     577                if (RT_SUCCESS(rc2))
    365578                {
     579                    /* *puScore = VDPROBE_SCORE_HIGH; */
     580                    *penmType = VDTYPE_OPTICAL_DISC;
     581                    rc = VINF_SUCCESS;
     582                }
     583                /* If that didn't work out, check by extension (the old way): */
     584                else if (rawProbeContainsExtension(s_aRawFileExtensions, pszSuffix, VDTYPE_OPTICAL_DISC))
     585                {
     586                    /* *puScore = VDPROBE_SCORE_LOW; */
    366587                    *penmType = VDTYPE_OPTICAL_DISC;
    367588                    rc = VINF_SUCCESS;
    368589                }
    369590            }
    370             else if (   !RTStrICmp(pszSuffix, ".img")
    371                      || !RTStrICmp(pszSuffix, ".ima")
    372                      || !RTStrICmp(pszSuffix, ".dsk")
    373                      || !RTStrICmp(pszSuffix, ".flp")
    374                      || !RTStrICmp(pszSuffix, ".vfd")) /* Floppy images */
     591
     592            /*
     593             * We could do something similar for floppies, i.e. check for a
     594             * DOS'ish boot sector and thereby get a good match on most of the
     595             * relevant floppy images out there.
     596             */
     597            if (   RT_FAILURE(rc)
     598                && (enmDesiredType == VDTYPE_INVALID || enmDesiredType == VDTYPE_FLOPPY)
     599                && (cbFile % 512) == 0
     600                && cbFile > 512
     601                && cbFile <= RAW_MAX_FLOPPY_IMG_SIZE)
    375602            {
    376                 if (cbFile % 512)
    377                     rc = VERR_VD_RAW_SIZE_MODULO_512;
    378                 else if (cbFile > RAW_MAX_FLOPPY_IMG_SIZE)
    379                     rc = VERR_VD_RAW_SIZE_FLOPPY_TOO_BIG;
    380                 else
     603                /** @todo check if the content is DOSish.  */
     604                if (false)
    381605                {
     606                    /* *puScore = VDPROBE_SCORE_HIGH; */
     607                    *penmType = VDTYPE_FLOPPY;
     608                    rc = VINF_SUCCESS;
     609                }
     610                else if (rawProbeContainsExtension(s_aRawFileExtensions, pszSuffix, VDTYPE_FLOPPY))
     611                {
     612                    /* *puScore = VDPROBE_SCORE_LOW; */
    382613                    *penmType = VDTYPE_FLOPPY;
    383614                    rc = VINF_SUCCESS;
    384615                }
    385616            }
    386             else
    387                 rc = VERR_VD_RAW_INVALID_HEADER;
     617
     618            /*
     619             * No luck?  Go exclusively by extension like we've done since
     620             * for ever and complain about the size if it doesn't fit expectations.
     621             * We can get here if the desired type doesn't match the extension and such.
     622             */
     623            if (RT_FAILURE(rc))
     624            {
     625                if (rawProbeContainsExtension(s_aRawFileExtensions, pszSuffix, VDTYPE_OPTICAL_DISC))
     626                {
     627                    if (cbFile % 2048)
     628                        rc = VERR_VD_RAW_SIZE_MODULO_2048;
     629                    else if (cbFile <= 32768)
     630                        rc = VERR_VD_RAW_SIZE_OPTICAL_TOO_SMALL;
     631                    else
     632                    {
     633                        Assert(enmDesiredType != VDTYPE_OPTICAL_DISC);
     634                        *penmType = VDTYPE_OPTICAL_DISC;
     635                        rc = VINF_SUCCESS;
     636                    }
     637                }
     638                else if (rawProbeContainsExtension(s_aRawFileExtensions, pszSuffix, VDTYPE_FLOPPY))
     639                {
     640                    if (cbFile % 512)
     641                        rc = VERR_VD_RAW_SIZE_MODULO_512;
     642                    else if (cbFile > RAW_MAX_FLOPPY_IMG_SIZE)
     643                        rc = VERR_VD_RAW_SIZE_FLOPPY_TOO_BIG;
     644                    else
     645                    {
     646                        Assert(cbFile == 0 || enmDesiredType != VDTYPE_FLOPPY);
     647                        *penmType = VDTYPE_FLOPPY;
     648                        rc = VINF_SUCCESS;
     649                    }
     650                }
     651                else
     652                    rc = VERR_VD_RAW_INVALID_HEADER;
     653            }
    388654        }
    389655        else
  • trunk/src/VBox/Storage/VD.cpp

    r76553 r79965  
    54085408 * @param   pVDIfsImage     Pointer to the per-image VD interface list.
    54095409 * @param   pszFilename     Name of the image file for which the backend is queried.
     5410 * @param   enmDesiredType  The desired image type, VDTYPE_INVALID if anything goes.
    54105411 * @param   ppszFormat      Receives pointer of the UTF-8 string which contains the format name.
    54115412 *                          The returned pointer must be freed using RTStrFree().
     5413 * @param   penmType        Where to store the type of the image.
    54125414 */
    54135415VBOXDDU_DECL(int) VDGetFormat(PVDINTERFACE pVDIfsDisk, PVDINTERFACE pVDIfsImage,
    5414                               const char *pszFilename, char **ppszFormat, VDTYPE *penmType)
     5416                              const char *pszFilename, VDTYPE enmDesiredType,
     5417                              char **ppszFormat, VDTYPE *penmType)
    54155418{
    54165419    int rc = VERR_NOT_SUPPORTED;
     
    54305433                    ("penmType=%#p\n", penmType),
    54315434                    VERR_INVALID_PARAMETER);
     5435    AssertReturn(enmDesiredType >= VDTYPE_INVALID && enmDesiredType <= VDTYPE_FLOPPY, VERR_INVALID_PARAMETER);
    54325436
    54335437    if (!vdPluginIsInitialized())
     
    54645468    AssertRC(rc);
    54655469
     5470    /** @todo r=bird: Would be better to do a scoring approach here, where the
     5471     * backend that scores the highest is choosen.  That way we don't have to depend
     5472     * on registration order and filename suffixes to figure out what RAW should
     5473     * handle and not.   Besides, the registration order won't cut it for plug-ins
     5474     * anyway, as they end up after the builtin ones.
     5475     */
     5476
    54665477    /* Find the backend supporting this file format. */
    54675478    for (unsigned i = 0; i < vdGetImageBackendCount(); i++)
     
    54735484        if (pBackend->pfnProbe)
    54745485        {
    5475             rc = pBackend->pfnProbe(pszFilename, pVDIfsDisk, pVDIfsImage, penmType);
     5486            rc = pBackend->pfnProbe(pszFilename, pVDIfsDisk, pVDIfsImage, enmDesiredType, penmType);
    54765487            if (    RT_SUCCESS(rc)
    54775488                /* The correct backend has been found, but there is a small
  • trunk/src/VBox/Storage/VDI.cpp

    r79742 r79965  
    14101410/** @copydoc VDIMAGEBACKEND::pfnProbe */
    14111411static DECLCALLBACK(int) vdiProbe(const char *pszFilename, PVDINTERFACE pVDIfsDisk,
    1412                                   PVDINTERFACE pVDIfsImage, VDTYPE *penmType)
    1413 {
     1412                                  PVDINTERFACE pVDIfsImage, VDTYPE enmDesiredType, VDTYPE *penmType)
     1413{
     1414    RT_NOREF(enmDesiredType);
    14141415    LogFlowFunc(("pszFilename=\"%s\"\n", pszFilename));
    14151416    int rc = VINF_SUCCESS;
  • trunk/src/VBox/Storage/VDPlugin.cpp

    r76553 r79965  
    7777static RTLDRMOD *g_ahBackendPlugins = NULL;
    7878#endif
    79 /** Builtin image backends. */
     79/**
     80 * Builtin image backends.
     81 *
     82 * @note As long as the pfnProb() calls aren't scored, the ordering influences
     83 *       which backend take precedence.  In particular, the RAW backend should
     84 *       be thowards the end of the list.
     85 */
    8086static PCVDIMAGEBACKEND aStaticBackends[] =
    8187{
     
    8894    &g_QCowBackend,
    8995    &g_VhdxBackend,
    90     &g_RawBackend,
    9196    &g_CueBackend,
    9297    &g_VBoxIsoMakerBackend,
     98    &g_RawBackend,
    9399    &g_ISCSIBackend
    94100};
  • trunk/src/VBox/Storage/VDVfs.cpp

    r76553 r79965  
    714714    char  *pszFormat = NULL;
    715715    VDTYPE enmType   = VDTYPE_INVALID;
    716     int rc = VDGetFormat(NULL, NULL, pElement->paArgs[0].psz, &pszFormat, &enmType);
     716    int rc = VDGetFormat(NULL, NULL, pElement->paArgs[0].psz, VDTYPE_INVALID, &pszFormat, &enmType);
    717717    if (RT_SUCCESS(rc))
    718718    {
  • trunk/src/VBox/Storage/VHD.cpp

    r77780 r79965  
    12961296/** @interface_method_impl{VDIMAGEBACKEND,pfnProbe} */
    12971297static DECLCALLBACK(int) vhdProbe(const char *pszFilename, PVDINTERFACE pVDIfsDisk,
    1298                                   PVDINTERFACE pVDIfsImage, VDTYPE *penmType)
    1299 {
    1300     RT_NOREF1(pVDIfsDisk);
     1298                                  PVDINTERFACE pVDIfsImage, VDTYPE enmDesiredType, VDTYPE *penmType)
     1299{
     1300    RT_NOREF(pVDIfsDisk, enmDesiredType);
    13011301    LogFlowFunc(("pszFilename=\"%s\" pVDIfsDisk=%#p pVDIfsImage=%#p\n", pszFilename, pVDIfsDisk, pVDIfsImage));
    13021302    PVDIOSTORAGE pStorage;
  • trunk/src/VBox/Storage/VHDX.cpp

    r76553 r79965  
    17701770/** @copydoc VDIMAGEBACKEND::pfnProbe */
    17711771static DECLCALLBACK(int) vhdxProbe(const char *pszFilename, PVDINTERFACE pVDIfsDisk,
    1772                                    PVDINTERFACE pVDIfsImage, VDTYPE *penmType)
    1773 {
    1774     RT_NOREF1(pVDIfsDisk);
     1772                                   PVDINTERFACE pVDIfsImage, VDTYPE enmDesiredType, VDTYPE *penmType)
     1773{
     1774    RT_NOREF(pVDIfsDisk, enmDesiredType);
    17751775    LogFlowFunc(("pszFilename=\"%s\" pVDIfsDisk=%#p pVDIfsImage=%#p\n", pszFilename, pVDIfsDisk, pVDIfsImage));
    17761776    PVDIOSTORAGE pStorage = NULL;
  • trunk/src/VBox/Storage/VISO.cpp

    r76553 r79965  
    209209 * @interface_method_impl{VDIMAGEBACKEND,pfnProbe}
    210210 */
    211 static DECLCALLBACK(int) visoProbe(const char *pszFilename, PVDINTERFACE pVDIfsDisk, PVDINTERFACE pVDIfsImage, VDTYPE *penmType)
     211static DECLCALLBACK(int) visoProbe(const char *pszFilename, PVDINTERFACE pVDIfsDisk, PVDINTERFACE pVDIfsImage,
     212                                   VDTYPE enmDesiredType, VDTYPE *penmType)
    212213{
    213214    /*
     
    224225
    225226    RT_NOREF(pVDIfsDisk);
     227
     228    /*
     229     * We can only fake DVD stuff, so fail if the desired type doesn't match up
     230     */
     231    if (enmDesiredType != VDTYPE_OPTICAL_DISC && enmDesiredType != VDTYPE_INVALID)
     232        return VERR_VD_GEN_INVALID_HEADER; /* Caller has strict, though undocument, status code expectations. */
    226233
    227234    /*
  • trunk/src/VBox/Storage/VMDK.cpp

    r78399 r79965  
    52335233/** @copydoc VDIMAGEBACKEND::pfnProbe */
    52345234static DECLCALLBACK(int) vmdkProbe(const char *pszFilename, PVDINTERFACE pVDIfsDisk,
    5235                                    PVDINTERFACE pVDIfsImage, VDTYPE *penmType)
    5236 {
     5235                                   PVDINTERFACE pVDIfsImage, VDTYPE enmDesiredType, VDTYPE *penmType)
     5236{
     5237    RT_NOREF(enmDesiredType);
    52375238    LogFlowFunc(("pszFilename=\"%s\" pVDIfsDisk=%#p pVDIfsImage=%#p penmType=%#p\n",
    52385239                 pszFilename, pVDIfsDisk, pVDIfsImage, penmType));
  • trunk/src/VBox/Storage/testcase/tstVD.cpp

    r76553 r79965  
    544544        RTFileClose(File);
    545545        rc = VDGetFormat(NULL /* pVDIfsDisk */, NULL /* pVDIfsImage */,
    546                          pszBaseFilename, &pszFormat, &enmType);
     546                         pszBaseFilename, VDTYPE_INVALID, &pszFormat, &enmType);
    547547        RTPrintf("VDGetFormat() pszFormat=%s rc=%Rrc\n", pszFormat, rc);
    548548        if (RT_SUCCESS(rc) && strcmp(pszFormat, pszBackend))
  • trunk/src/VBox/Storage/testcase/vbox-img.cpp

    r76553 r79965  
    283283        /* Don't pass error interface, as that would triggers error messages
    284284         * because some backends fail to open the image. */
    285         rc = VDGetFormat(NULL, NULL, pszFilename, &pszFormat, &enmType);
     285        rc = VDGetFormat(NULL, NULL, pszFilename, VDTYPE_INVALID, &pszFormat, &enmType);
    286286        if (RT_FAILURE(rc))
    287287            return errorRuntime("Format autodetect failed: %Rrc\n", rc);
     
    419419        /* Don't pass error interface, as that would triggers error messages
    420420         * because some backends fail to open the image. */
    421         rc = VDGetFormat(NULL, NULL, pszFilename, &pszFormat, &enmType);
     421        rc = VDGetFormat(NULL, NULL, pszFilename, VDTYPE_INVALID, &pszFormat, &enmType);
    422422        if (RT_FAILURE(rc))
    423423            return errorRuntime("Format autodetect failed: %Rrc\n", rc);
     
    12151215            char *pszFormat = NULL;
    12161216            VDTYPE enmType = VDTYPE_INVALID;
    1217             rc = VDGetFormat(NULL, NULL, pszSrcFilename, &pszFormat, &enmType);
     1217            rc = VDGetFormat(NULL, NULL, pszSrcFilename, VDTYPE_INVALID, &pszFormat, &enmType);
    12181218            if (RT_FAILURE(rc))
    12191219            {
     
    13111311    char *pszFormat = NULL;
    13121312    VDTYPE enmType = VDTYPE_INVALID;
    1313     rc = VDGetFormat(NULL, NULL, pszFilename, &pszFormat, &enmType);
     1313    rc = VDGetFormat(NULL, NULL, pszFilename, VDTYPE_INVALID, &pszFormat, &enmType);
    13141314    if (RT_FAILURE(rc))
    13151315        return errorSyntax("Format autodetect failed: %Rrc\n", rc);
     
    14071407    char *pszFormat = NULL;
    14081408    VDTYPE enmType = VDTYPE_INVALID;
    1409     int rc = VDGetFormat(NULL, NULL, pszFilename, &pszFormat, &enmType);
     1409    int rc = VDGetFormat(NULL, NULL, pszFilename, VDTYPE_INVALID, &pszFormat, &enmType);
    14101410    if (RT_FAILURE(rc))
    14111411        return errorSyntax("Format autodetect failed: %Rrc\n", rc);
     
    18121812    if (!pszFormat)
    18131813    {
    1814         rc = VDGetFormat(NULL, NULL, pszFilename, &pszBackend, &enmType);
     1814        rc = VDGetFormat(NULL, NULL, pszFilename, VDTYPE_INVALID, &pszBackend, &enmType);
    18151815        if (RT_FAILURE(rc))
    18161816            return errorSyntax("Format autodetect failed: %Rrc\n", rc);
     
    18651865    char *pszFormat = NULL;
    18661866    VDTYPE enmType = VDTYPE_INVALID;
    1867     rc = VDGetFormat(NULL, NULL, pszFilename, &pszFormat, &enmType);
     1867    rc = VDGetFormat(NULL, NULL, pszFilename, VDTYPE_INVALID, &pszFormat, &enmType);
    18681868    if (RT_FAILURE(rc))
    18691869        return errorSyntax("Format autodetect failed: %Rrc\n", rc);
     
    20222022    char *pszFormat = NULL;
    20232023    VDTYPE enmType = VDTYPE_INVALID;
    2024     rc = VDGetFormat(NULL, NULL, pszFilename, &pszFormat, &enmType);
     2024    rc = VDGetFormat(NULL, NULL, pszFilename, VDTYPE_INVALID, &pszFormat, &enmType);
    20252025    if (RT_FAILURE(rc))
    20262026        return errorSyntax("Format autodetect failed: %Rrc\n", rc);
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