/** @copydoc VBOXHDDBACKEND::pfnCheckIfValid */ static int parallelsCheckIfValid(const char *pszFilename, PVDINTERFACE pVDIfsDisk, PVDINTERFACE pVDIfsImage, VDTYPE *penmType) { int rc; PVDIOSTORAGE pStorage; ParallelsHeader parallelsHeader; PVDINTERFACEIOINT pIfIo = VDIfIoIntGet(pVDIfsImage); AssertPtrReturn(pIfIo, VERR_INVALID_PARAMETER); rc = vdIfIoIntFileOpen(pIfIo, pszFilename, VDOpenFlagsToFileOpenFlags(VD_OPEN_FLAGS_READONLY, false /* fCreate */), &pStorage); if (RT_FAILURE(rc)) return rc; rc = vdIfIoIntFileReadSync(pIfIo, pStorage, 0, ¶llelsHeader, sizeof(ParallelsHeader), NULL); if (RT_SUCCESS(rc)) { if ( !memcmp(parallelsHeader.HeaderIdentifier, PARALLELS_HEADER_MAGIC, 16) && (parallelsHeader.uVersion == PARALLELS_DISK_VERSION)) rc = VINF_SUCCESS; else { /* * The image may be an fixed size image. * Unfortunately fixed sized parallels images * are just raw files hence no magic header to * check for. * The code succeeds if the file is a multiple * of 512 and if the file extensions is *.hdd */ uint64_t cbFile; char *pszExtension; rc = vdIfIoIntFileGetSize(pIfIo, pStorage, &cbFile); if (RT_FAILURE(rc) || ((cbFile % 512) != 0)) { vdIfIoIntFileClose(pIfIo, pStorage); return VERR_VD_PARALLELS_INVALID_HEADER; } pszExtension = RTPathExt(pszFilename); if (!pszExtension || strcmp(pszExtension, ".hdd")) rc = VERR_VD_PARALLELS_INVALID_HEADER; else rc = VINF_SUCCESS; } } if (RT_SUCCESS(rc)) *penmType = VDTYPE_HDD; vdIfIoIntFileClose(pIfIo, pStorage); return rc; }
/** * Internal. Free all allocated space for representing an image except pImage, * and optionally delete the image from disk. */ static int parallelsFreeImage(PPARALLELSIMAGE pImage, bool fDelete) { int rc = VINF_SUCCESS; /* Freeing a never allocated image (e.g. because the open failed) is * not signalled as an error. After all nothing bad happens. */ if (pImage) { if (pImage->pStorage) { /* No point updating the file that is deleted anyway. */ if (!fDelete) parallelsFlushImage(pImage); vdIfIoIntFileClose(pImage->pIfIo, pImage->pStorage); pImage->pStorage = NULL; } if (pImage->pAllocationBitmap) { RTMemFree(pImage->pAllocationBitmap); pImage->pAllocationBitmap = NULL; } if (fDelete && pImage->pszFilename) vdIfIoIntFileDelete(pImage->pIfIo, pImage->pszFilename); } return rc; }
/** * Internal. Free all allocated space for representing an image except pImage, * and optionally delete the image from disk. */ static int rawFreeImage(PRAWIMAGE pImage, bool fDelete) { int rc = VINF_SUCCESS; /* Freeing a never allocated image (e.g. because the open failed) is * not signalled as an error. After all nothing bad happens. */ if (pImage) { if (pImage->pStorage) { /* No point updating the file that is deleted anyway. */ if (!fDelete) { /* For newly created images in sequential mode fill it to * the nominal size. */ if ( pImage->uOpenFlags & VD_OPEN_FLAGS_SEQUENTIAL && !(pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY) && pImage->fCreate) { /* Fill rest of image with zeroes, a must for sequential * images to reach the nominal size. */ uint64_t uOff; void *pvBuf = RTMemTmpAllocZ(RAW_FILL_SIZE); if (RT_LIKELY(pvBuf)) { uOff = pImage->offAccess; /* Write data to all image blocks. */ while (uOff < pImage->cbSize) { unsigned cbChunk = (unsigned)RT_MIN(pImage->cbSize - uOff, RAW_FILL_SIZE); rc = vdIfIoIntFileWriteSync(pImage->pIfIo, pImage->pStorage, uOff, pvBuf, cbChunk); if (RT_FAILURE(rc)) break; uOff += cbChunk; } RTMemTmpFree(pvBuf); } else rc = VERR_NO_MEMORY; } rawFlushImage(pImage); } rc = vdIfIoIntFileClose(pImage->pIfIo, pImage->pStorage); pImage->pStorage = NULL; } if (fDelete && pImage->pszFilename) vdIfIoIntFileDelete(pImage->pIfIo, pImage->pszFilename); } LogFlowFunc(("returns %Rrc\n", rc)); return rc; }
/** @copydoc VBOXHDDBACKEND::pfnCheckIfValid */ static DECLCALLBACK(int) rawCheckIfValid(const char *pszFilename, PVDINTERFACE pVDIfsDisk, PVDINTERFACE pVDIfsImage, VDTYPE *penmType) { LogFlowFunc(("pszFilename=\"%s\" pVDIfsDisk=%#p pVDIfsImage=%#p\n", pszFilename, pVDIfsDisk, pVDIfsImage)); PVDIOSTORAGE pStorage = NULL; uint64_t cbFile; int rc = VINF_SUCCESS; char *pszSuffix = NULL; PVDINTERFACEIOINT pIfIo = VDIfIoIntGet(pVDIfsImage); AssertPtrReturn(pIfIo, VERR_INVALID_PARAMETER); if ( !VALID_PTR(pszFilename) || !*pszFilename) { rc = VERR_INVALID_PARAMETER; goto out; } pszSuffix = RTPathSuffix(pszFilename); /* * Open the file and read the footer. */ rc = vdIfIoIntFileOpen(pIfIo, pszFilename, VDOpenFlagsToFileOpenFlags(VD_OPEN_FLAGS_READONLY, false /* fCreate */), &pStorage); if (RT_SUCCESS(rc)) rc = vdIfIoIntFileGetSize(pIfIo, pStorage, &cbFile); /* Try to guess the image type based on the extension. */ if ( RT_SUCCESS(rc) && pszSuffix) { if ( !RTStrICmp(pszSuffix, ".iso") || !RTStrICmp(pszSuffix, ".cdr")) /* DVD images. */ { /* Note that there are ISO images smaller than 1 MB; it is impossible to distinguish * between raw floppy and CD images based on their size (and cannot be reliably done * based on contents, either). */ if (cbFile % 2048) rc = VERR_VD_RAW_SIZE_MODULO_2048; else if (cbFile <= 32768) rc = VERR_VD_RAW_SIZE_OPTICAL_TOO_SMALL; else { *penmType = VDTYPE_DVD; rc = VINF_SUCCESS; } } else if ( !RTStrICmp(pszSuffix, ".img") || !RTStrICmp(pszSuffix, ".ima") || !RTStrICmp(pszSuffix, ".dsk") || !RTStrICmp(pszSuffix, ".flp") || !RTStrICmp(pszSuffix, ".vfd")) /* Floppy images */ { if (cbFile % 512) rc = VERR_VD_RAW_SIZE_MODULO_512; else if (cbFile > RAW_MAX_FLOPPY_IMG_SIZE) rc = VERR_VD_RAW_SIZE_FLOPPY_TOO_BIG; else { *penmType = VDTYPE_FLOPPY; rc = VINF_SUCCESS; } } else rc = VERR_VD_RAW_INVALID_HEADER; } else rc = VERR_VD_RAW_INVALID_HEADER; if (pStorage) vdIfIoIntFileClose(pIfIo, pStorage); out: LogFlowFunc(("returns %Rrc\n", rc)); return rc; }