Changeset 79965 in vbox
- Timestamp:
- Jul 24, 2019 8:32:32 PM (5 years ago)
- Location:
- trunk
- Files:
-
- 23 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/include/VBox/vd-image-backend.h
r76585 r79965 96 96 * @param pVDIfsDisk Pointer to the per-disk VD interface list. 97 97 * @param pVDIfsImage Pointer to the per-image VD interface list. 98 * @param enmDesiredType The desired image type, VDTYPE_INVALID if anything goes. 98 99 * @param penmType Returns the supported device type on success. 99 100 */ 100 101 DECLR3CALLBACKMEMBER(int, pfnProbe, (const char *pszFilename, PVDINTERFACE pVDIfsDisk, 101 PVDINTERFACE pVDIfsImage, VDTYPE *penmType));102 PVDINTERFACE pVDIfsImage, VDTYPE enmDesiredType, VDTYPE *penmType)); 102 103 103 104 /** -
trunk/include/VBox/vd.h
r79742 r79965 592 592 * @param pVDIfsImage Pointer to the per-image VD interface list. 593 593 * @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. 594 595 * @param ppszFormat Receives pointer of the UTF-8 string which contains the format name. 595 596 * The returned pointer must be freed using RTStrFree(). … … 597 598 */ 598 599 VBOXDDU_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); 600 602 601 603 /** -
trunk/src/VBox/Frontends/VBoxManage/VBoxInternalManage.cpp
r77595 r79965 656 656 VDTYPE enmType = VDTYPE_INVALID; 657 657 int rc = VDGetFormat(NULL /* pVDIfsDisk */, NULL /* pVDIfsImage */, 658 argv[1], &pszFormat, &enmType);658 argv[1], VDTYPE_INVALID, &pszFormat, &enmType); 659 659 if (RT_FAILURE(rc)) 660 660 return RTMsgErrorExit(RTEXITCODE_FAILURE, "Format autodetect failed: %Rrc", rc); … … 709 709 VDTYPE enmType = VDTYPE_INVALID; 710 710 int rc = VDGetFormat(NULL /* pVDIfsDisk */, NULL /* pVDIfsImage */, 711 argv[0], &pszFormat, &enmType);711 argv[0], VDTYPE_INVALID, &pszFormat, &enmType); 712 712 if (RT_FAILURE(rc)) 713 713 return RTMsgErrorExit(RTEXITCODE_FAILURE, "Format autodetect failed: %Rrc", rc); … … 2016 2016 VDTYPE enmType = VDTYPE_INVALID; 2017 2017 vrc = VDGetFormat(NULL /* pVDIfsDisk */, NULL /* pVDIfsImage */, 2018 src.c_str(), &pszFormat, &enmType);2018 src.c_str(), VDTYPE_INVALID, &pszFormat, &enmType); 2019 2019 if (RT_FAILURE(vrc) || enmType != VDTYPE_HDD) 2020 2020 { … … 2164 2164 char *pszFormat = NULL; 2165 2165 vrc = VDGetFormat(NULL /* pVDIfsDisk */, NULL /* pVDIfsImage */, 2166 src.c_str(), &pszFormat, &enmSrcType);2166 src.c_str(), VDTYPE_HDD, &pszFormat, &enmSrcType); 2167 2167 if (RT_FAILURE(vrc)) 2168 2168 { … … 2282 2282 2283 2283 vrc = VDGetFormat(NULL /* pVDIfsDisk */, NULL /* pVDIfsImage */, 2284 image.c_str(), &pszFormat, &enmSrcType);2284 image.c_str(), VDTYPE_HDD, &pszFormat, &enmSrcType); 2285 2285 if (RT_FAILURE(vrc) && (vrc != VERR_VD_IMAGE_CORRUPTED)) 2286 2286 { -
trunk/src/VBox/ImageMounter/VBoxFUSE/VBoxFUSE.cpp
r76553 r79965 521 521 char *pszFormat; 522 522 VDTYPE enmType; 523 rc = VDGetFormat(NULL /* pVDIIfsDisk */, NULL /* pVDIIfsImage*/, pszImage, &pszFormat, &enmType);523 rc = VDGetFormat(NULL /* pVDIIfsDisk */, NULL /* pVDIIfsImage*/, pszImage, VDTYPE_INVALID,&pszFormat, &enmType); 524 524 if (RT_FAILURE(rc)) 525 525 { -
trunk/src/VBox/ImageMounter/vboximg-mount/vboximg-mount.cpp
r77143 r79965 1372 1372 * Create HDD container to open base image and differencing images into 1373 1373 */ 1374 rc = VDGetFormat(NULL /* pVDIIfsDisk */, NULL /* pVDIIfsImage*/, 1374 rc = VDGetFormat(NULL /* pVDIIfsDisk */, NULL /* pVDIIfsImage*/, VDTYPE_INVALID, 1375 1375 CSTR(pVDiskBaseImagePath), &pszFormat, &enmType); 1376 1376 -
trunk/src/VBox/Main/src-server/MediumImpl.cpp
r79961 r79965 7619 7619 if (isImport) 7620 7620 { 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; 7621 7624 VDTYPE enmType = VDTYPE_INVALID; 7622 7625 char *backendName = NULL; … … 7634 7637 { 7635 7638 vrc = VDGetFormat(NULL /* pVDIfsDisk */, NULL /* pVDIfsImage */, 7636 locationFull.c_str(), &backendName, &enmType);7639 locationFull.c_str(), enmDesiredType, &backendName, &enmType); 7637 7640 } 7638 7641 else if ( vrc != VERR_FILE_NOT_FOUND … … 7644 7647 locationFull = aLocation; 7645 7648 vrc = VDGetFormat(NULL /* pVDIfsDisk */, NULL /* pVDIfsImage */, 7646 locationFull.c_str(), &backendName, &enmType);7649 locationFull.c_str(), enmDesiredType, &backendName, &enmType); 7647 7650 } 7648 7651 -
trunk/src/VBox/Storage/CUE.cpp
r78169 r79965 1432 1432 /** @copydoc VDIMAGEBACKEND::pfnProbe */ 1433 1433 static DECLCALLBACK(int) cueProbe(const char *pszFilename, PVDINTERFACE pVDIfsDisk, 1434 PVDINTERFACE pVDIfsImage, VDTYPE *penmType)1435 { 1436 RT_NOREF 1(pVDIfsDisk);1434 PVDINTERFACE pVDIfsImage, VDTYPE enmDesiredType, VDTYPE *penmType) 1435 { 1436 RT_NOREF(pVDIfsDisk, enmDesiredType); 1437 1437 LogFlowFunc(("pszFilename=\"%s\" pVDIfsDisk=%#p pVDIfsImage=%#p\n", pszFilename, pVDIfsDisk, pVDIfsImage)); 1438 1438 int rc = VINF_SUCCESS; -
trunk/src/VBox/Storage/DMG.cpp
r76553 r79965 1742 1742 /** @interface_method_impl{VDIMAGEBACKEND,pfnProbe} */ 1743 1743 static DECLCALLBACK(int) dmgProbe(const char *pszFilename, PVDINTERFACE pVDIfsDisk, 1744 PVDINTERFACE pVDIfsImage, VDTYPE *penmType)1745 { 1746 RT_NOREF 1(pVDIfsDisk);1744 PVDINTERFACE pVDIfsImage, VDTYPE enmDesiredType, VDTYPE *penmType) 1745 { 1746 RT_NOREF(pVDIfsDisk, enmDesiredType); 1747 1747 LogFlowFunc(("pszFilename=\"%s\" pVDIfsDisk=%#p pVDIfsImage=%#p penmType=%#p\n", 1748 1748 pszFilename, pVDIfsDisk, pVDIfsImage, penmType)); -
trunk/src/VBox/Storage/ISCSI.cpp
r76553 r79965 4767 4767 /** @copydoc VDIMAGEBACKEND::pfnProbe */ 4768 4768 static DECLCALLBACK(int) iscsiProbe(const char *pszFilename, PVDINTERFACE pVDIfsDisk, 4769 PVDINTERFACE pVDIfsImage, VDTYPE *penmType)4770 { 4771 RT_NOREF 4(pszFilename, pVDIfsDisk, pVDIfsImage, penmType);4769 PVDINTERFACE pVDIfsImage, VDTYPE enmDesiredType, VDTYPE *penmType) 4770 { 4771 RT_NOREF(pszFilename, pVDIfsDisk, pVDIfsImage, enmDesiredType, penmType); 4772 4772 LogFlowFunc(("pszFilename=\"%s\"\n", pszFilename)); 4773 4773 -
trunk/src/VBox/Storage/Parallels.cpp
r77699 r79965 376 376 /** @copydoc VDIMAGEBACKEND::pfnProbe */ 377 377 static DECLCALLBACK(int) parallelsProbe(const char *pszFilename, PVDINTERFACE pVDIfsDisk, 378 PVDINTERFACE pVDIfsImage, VDTYPE *penmType)379 { 380 RT_NOREF 1(pVDIfsDisk);378 PVDINTERFACE pVDIfsImage, VDTYPE enmDesiredType, VDTYPE *penmType) 379 { 380 RT_NOREF(pVDIfsDisk, enmDesiredType); 381 381 int rc; 382 382 PVDIOSTORAGE pStorage; -
trunk/src/VBox/Storage/QCOW.cpp
r77924 r79965 1577 1577 /** @copydoc VDIMAGEBACKEND::pfnProbe */ 1578 1578 static DECLCALLBACK(int) qcowProbe(const char *pszFilename, PVDINTERFACE pVDIfsDisk, 1579 PVDINTERFACE pVDIfsImage, VDTYPE *penmType)1580 { 1581 RT_NOREF 1(pVDIfsDisk);1579 PVDINTERFACE pVDIfsImage, VDTYPE enmDesiredType, VDTYPE *penmType) 1580 { 1581 RT_NOREF(pVDIfsDisk, enmDesiredType); 1582 1582 LogFlowFunc(("pszFilename=\"%s\" pVDIfsDisk=%#p pVDIfsImage=%#p\n", pszFilename, pVDIfsDisk, pVDIfsImage)); 1583 1583 PVDIOSTORAGE pStorage = NULL; -
trunk/src/VBox/Storage/QED.cpp
r77232 r79965 1503 1503 /** @copydoc VDIMAGEBACKEND::pfnProbe */ 1504 1504 static DECLCALLBACK(int) qedProbe(const char *pszFilename, PVDINTERFACE pVDIfsDisk, 1505 PVDINTERFACE pVDIfsImage, VDTYPE *penmType)1506 { 1507 RT_NOREF 1(pVDIfsDisk);1505 PVDINTERFACE pVDIfsImage, VDTYPE enmDesiredType, VDTYPE *penmType) 1506 { 1507 RT_NOREF(pVDIfsDisk, enmDesiredType); 1508 1508 LogFlowFunc(("pszFilename=\"%s\" pVDIfsDisk=%#p pVDIfsImage=%#p\n", pszFilename, pVDIfsDisk, pVDIfsImage)); 1509 1509 PVDIOSTORAGE pStorage = NULL; -
trunk/src/VBox/Storage/RAW.cpp
r76553 r79965 28 28 #include <iprt/alloc.h> 29 29 #include <iprt/path.h> 30 #include <iprt/formats/iso9660.h> 31 #include <iprt/formats/udf.h> 30 32 31 33 #include "VDBackends.h" … … 320 322 } 321 323 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 */ 335 static 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 */ 496 static 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 322 517 323 518 /** @copydoc VDIMAGEBACKEND::pfnProbe */ 324 519 static DECLCALLBACK(int) rawProbe(const char *pszFilename, PVDINTERFACE pVDIfsDisk, 325 PVDINTERFACE pVDIfsImage, VDTYPE *penmType)326 { 327 RT_NOREF 1(pVDIfsDisk);520 PVDINTERFACE pVDIfsImage, VDTYPE enmDesiredType, VDTYPE *penmType) 521 { 522 RT_NOREF(pVDIfsDisk, enmDesiredType); 328 523 LogFlowFunc(("pszFilename=\"%s\" pVDIfsDisk=%#p pVDIfsImage=%#p\n", pszFilename, pVDIfsDisk, pVDIfsImage)); 329 524 PVDIOSTORAGE pStorage = NULL; … … 343 538 { 344 539 uint64_t cbFile; 345 const char *pszSuffix = RTPathSuffix(pszFilename);346 540 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)) 351 542 { 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) 354 575 { 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)) 365 578 { 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; */ 366 587 *penmType = VDTYPE_OPTICAL_DISC; 367 588 rc = VINF_SUCCESS; 368 589 } 369 590 } 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) 375 602 { 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) 381 605 { 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; */ 382 613 *penmType = VDTYPE_FLOPPY; 383 614 rc = VINF_SUCCESS; 384 615 } 385 616 } 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 } 388 654 } 389 655 else -
trunk/src/VBox/Storage/VD.cpp
r76553 r79965 5408 5408 * @param pVDIfsImage Pointer to the per-image VD interface list. 5409 5409 * @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. 5410 5411 * @param ppszFormat Receives pointer of the UTF-8 string which contains the format name. 5411 5412 * The returned pointer must be freed using RTStrFree(). 5413 * @param penmType Where to store the type of the image. 5412 5414 */ 5413 5415 VBOXDDU_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) 5415 5418 { 5416 5419 int rc = VERR_NOT_SUPPORTED; … … 5430 5433 ("penmType=%#p\n", penmType), 5431 5434 VERR_INVALID_PARAMETER); 5435 AssertReturn(enmDesiredType >= VDTYPE_INVALID && enmDesiredType <= VDTYPE_FLOPPY, VERR_INVALID_PARAMETER); 5432 5436 5433 5437 if (!vdPluginIsInitialized()) … … 5464 5468 AssertRC(rc); 5465 5469 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 5466 5477 /* Find the backend supporting this file format. */ 5467 5478 for (unsigned i = 0; i < vdGetImageBackendCount(); i++) … … 5473 5484 if (pBackend->pfnProbe) 5474 5485 { 5475 rc = pBackend->pfnProbe(pszFilename, pVDIfsDisk, pVDIfsImage, penmType);5486 rc = pBackend->pfnProbe(pszFilename, pVDIfsDisk, pVDIfsImage, enmDesiredType, penmType); 5476 5487 if ( RT_SUCCESS(rc) 5477 5488 /* The correct backend has been found, but there is a small -
trunk/src/VBox/Storage/VDI.cpp
r79742 r79965 1410 1410 /** @copydoc VDIMAGEBACKEND::pfnProbe */ 1411 1411 static 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); 1414 1415 LogFlowFunc(("pszFilename=\"%s\"\n", pszFilename)); 1415 1416 int rc = VINF_SUCCESS; -
trunk/src/VBox/Storage/VDPlugin.cpp
r76553 r79965 77 77 static RTLDRMOD *g_ahBackendPlugins = NULL; 78 78 #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 */ 80 86 static PCVDIMAGEBACKEND aStaticBackends[] = 81 87 { … … 88 94 &g_QCowBackend, 89 95 &g_VhdxBackend, 90 &g_RawBackend,91 96 &g_CueBackend, 92 97 &g_VBoxIsoMakerBackend, 98 &g_RawBackend, 93 99 &g_ISCSIBackend 94 100 }; -
trunk/src/VBox/Storage/VDVfs.cpp
r76553 r79965 714 714 char *pszFormat = NULL; 715 715 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); 717 717 if (RT_SUCCESS(rc)) 718 718 { -
trunk/src/VBox/Storage/VHD.cpp
r77780 r79965 1296 1296 /** @interface_method_impl{VDIMAGEBACKEND,pfnProbe} */ 1297 1297 static DECLCALLBACK(int) vhdProbe(const char *pszFilename, PVDINTERFACE pVDIfsDisk, 1298 PVDINTERFACE pVDIfsImage, VDTYPE *penmType)1299 { 1300 RT_NOREF 1(pVDIfsDisk);1298 PVDINTERFACE pVDIfsImage, VDTYPE enmDesiredType, VDTYPE *penmType) 1299 { 1300 RT_NOREF(pVDIfsDisk, enmDesiredType); 1301 1301 LogFlowFunc(("pszFilename=\"%s\" pVDIfsDisk=%#p pVDIfsImage=%#p\n", pszFilename, pVDIfsDisk, pVDIfsImage)); 1302 1302 PVDIOSTORAGE pStorage; -
trunk/src/VBox/Storage/VHDX.cpp
r76553 r79965 1770 1770 /** @copydoc VDIMAGEBACKEND::pfnProbe */ 1771 1771 static DECLCALLBACK(int) vhdxProbe(const char *pszFilename, PVDINTERFACE pVDIfsDisk, 1772 PVDINTERFACE pVDIfsImage, VDTYPE *penmType)1773 { 1774 RT_NOREF 1(pVDIfsDisk);1772 PVDINTERFACE pVDIfsImage, VDTYPE enmDesiredType, VDTYPE *penmType) 1773 { 1774 RT_NOREF(pVDIfsDisk, enmDesiredType); 1775 1775 LogFlowFunc(("pszFilename=\"%s\" pVDIfsDisk=%#p pVDIfsImage=%#p\n", pszFilename, pVDIfsDisk, pVDIfsImage)); 1776 1776 PVDIOSTORAGE pStorage = NULL; -
trunk/src/VBox/Storage/VISO.cpp
r76553 r79965 209 209 * @interface_method_impl{VDIMAGEBACKEND,pfnProbe} 210 210 */ 211 static DECLCALLBACK(int) visoProbe(const char *pszFilename, PVDINTERFACE pVDIfsDisk, PVDINTERFACE pVDIfsImage, VDTYPE *penmType) 211 static DECLCALLBACK(int) visoProbe(const char *pszFilename, PVDINTERFACE pVDIfsDisk, PVDINTERFACE pVDIfsImage, 212 VDTYPE enmDesiredType, VDTYPE *penmType) 212 213 { 213 214 /* … … 224 225 225 226 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. */ 226 233 227 234 /* -
trunk/src/VBox/Storage/VMDK.cpp
r78399 r79965 5233 5233 /** @copydoc VDIMAGEBACKEND::pfnProbe */ 5234 5234 static 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); 5237 5238 LogFlowFunc(("pszFilename=\"%s\" pVDIfsDisk=%#p pVDIfsImage=%#p penmType=%#p\n", 5238 5239 pszFilename, pVDIfsDisk, pVDIfsImage, penmType)); -
trunk/src/VBox/Storage/testcase/tstVD.cpp
r76553 r79965 544 544 RTFileClose(File); 545 545 rc = VDGetFormat(NULL /* pVDIfsDisk */, NULL /* pVDIfsImage */, 546 pszBaseFilename, &pszFormat, &enmType);546 pszBaseFilename, VDTYPE_INVALID, &pszFormat, &enmType); 547 547 RTPrintf("VDGetFormat() pszFormat=%s rc=%Rrc\n", pszFormat, rc); 548 548 if (RT_SUCCESS(rc) && strcmp(pszFormat, pszBackend)) -
trunk/src/VBox/Storage/testcase/vbox-img.cpp
r76553 r79965 283 283 /* Don't pass error interface, as that would triggers error messages 284 284 * 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); 286 286 if (RT_FAILURE(rc)) 287 287 return errorRuntime("Format autodetect failed: %Rrc\n", rc); … … 419 419 /* Don't pass error interface, as that would triggers error messages 420 420 * 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); 422 422 if (RT_FAILURE(rc)) 423 423 return errorRuntime("Format autodetect failed: %Rrc\n", rc); … … 1215 1215 char *pszFormat = NULL; 1216 1216 VDTYPE enmType = VDTYPE_INVALID; 1217 rc = VDGetFormat(NULL, NULL, pszSrcFilename, &pszFormat, &enmType);1217 rc = VDGetFormat(NULL, NULL, pszSrcFilename, VDTYPE_INVALID, &pszFormat, &enmType); 1218 1218 if (RT_FAILURE(rc)) 1219 1219 { … … 1311 1311 char *pszFormat = NULL; 1312 1312 VDTYPE enmType = VDTYPE_INVALID; 1313 rc = VDGetFormat(NULL, NULL, pszFilename, &pszFormat, &enmType);1313 rc = VDGetFormat(NULL, NULL, pszFilename, VDTYPE_INVALID, &pszFormat, &enmType); 1314 1314 if (RT_FAILURE(rc)) 1315 1315 return errorSyntax("Format autodetect failed: %Rrc\n", rc); … … 1407 1407 char *pszFormat = NULL; 1408 1408 VDTYPE enmType = VDTYPE_INVALID; 1409 int rc = VDGetFormat(NULL, NULL, pszFilename, &pszFormat, &enmType);1409 int rc = VDGetFormat(NULL, NULL, pszFilename, VDTYPE_INVALID, &pszFormat, &enmType); 1410 1410 if (RT_FAILURE(rc)) 1411 1411 return errorSyntax("Format autodetect failed: %Rrc\n", rc); … … 1812 1812 if (!pszFormat) 1813 1813 { 1814 rc = VDGetFormat(NULL, NULL, pszFilename, &pszBackend, &enmType);1814 rc = VDGetFormat(NULL, NULL, pszFilename, VDTYPE_INVALID, &pszBackend, &enmType); 1815 1815 if (RT_FAILURE(rc)) 1816 1816 return errorSyntax("Format autodetect failed: %Rrc\n", rc); … … 1865 1865 char *pszFormat = NULL; 1866 1866 VDTYPE enmType = VDTYPE_INVALID; 1867 rc = VDGetFormat(NULL, NULL, pszFilename, &pszFormat, &enmType);1867 rc = VDGetFormat(NULL, NULL, pszFilename, VDTYPE_INVALID, &pszFormat, &enmType); 1868 1868 if (RT_FAILURE(rc)) 1869 1869 return errorSyntax("Format autodetect failed: %Rrc\n", rc); … … 2022 2022 char *pszFormat = NULL; 2023 2023 VDTYPE enmType = VDTYPE_INVALID; 2024 rc = VDGetFormat(NULL, NULL, pszFilename, &pszFormat, &enmType);2024 rc = VDGetFormat(NULL, NULL, pszFilename, VDTYPE_INVALID, &pszFormat, &enmType); 2025 2025 if (RT_FAILURE(rc)) 2026 2026 return errorSyntax("Format autodetect failed: %Rrc\n", rc);
Note:
See TracChangeset
for help on using the changeset viewer.