/** * Internal: Open an image, constructing all necessary data structures. */ static int rawOpenImage(PRAWIMAGE pImage, unsigned uOpenFlags) { pImage->uOpenFlags = uOpenFlags; pImage->fCreate = false; pImage->pIfError = VDIfErrorGet(pImage->pVDIfsDisk); pImage->pIfIo = VDIfIoIntGet(pImage->pVDIfsImage); AssertPtrReturn(pImage->pIfIo, VERR_INVALID_PARAMETER); /* Open the image. */ int rc = vdIfIoIntFileOpen(pImage->pIfIo, pImage->pszFilename, VDOpenFlagsToFileOpenFlags(uOpenFlags, false /* fCreate */), &pImage->pStorage); if (RT_SUCCESS(rc)) { rc = vdIfIoIntFileGetSize(pImage->pIfIo, pImage->pStorage, &pImage->cbSize); if ( RT_SUCCESS(rc) && !(pImage->cbSize % 512)) pImage->uImageFlags |= VD_IMAGE_FLAGS_FIXED; else if (RT_SUCCESS(rc)) rc = VERR_VD_RAW_SIZE_MODULO_512; } /* else: Do NOT signal an appropriate error here, as the VD layer has the * choice of retrying the open if it failed. */ if (RT_FAILURE(rc)) rawFreeImage(pImage, false); return rc; }
/** @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; }
/** @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; }
/** * Internal: Create a raw image. */ static int rawCreateImage(PRAWIMAGE pImage, uint64_t cbSize, unsigned uImageFlags, const char *pszComment, PCVDGEOMETRY pPCHSGeometry, PCVDGEOMETRY pLCHSGeometry, unsigned uOpenFlags, PFNVDPROGRESS pfnProgress, void *pvUser, unsigned uPercentStart, unsigned uPercentSpan) { int rc; RTFOFF cbFree = 0; int32_t fOpen; uImageFlags |= VD_IMAGE_FLAGS_FIXED; pImage->uOpenFlags = uOpenFlags & ~VD_OPEN_FLAGS_READONLY; pImage->uImageFlags = uImageFlags; pImage->fCreate = true; pImage->PCHSGeometry = *pPCHSGeometry; pImage->LCHSGeometry = *pLCHSGeometry; pImage->pIfError = VDIfErrorGet(pImage->pVDIfsDisk); pImage->pIfIo = VDIfIoIntGet(pImage->pVDIfsImage); AssertPtrReturn(pImage->pIfIo, VERR_INVALID_PARAMETER); if (uImageFlags & VD_IMAGE_FLAGS_DIFF) { rc = vdIfError(pImage->pIfError, VERR_VD_RAW_INVALID_TYPE, RT_SRC_POS, N_("Raw: cannot create diff image '%s'"), pImage->pszFilename); goto out; } /* Create image file. */ fOpen = VDOpenFlagsToFileOpenFlags(pImage->uOpenFlags, true /* fCreate */); if (uOpenFlags & VD_OPEN_FLAGS_SEQUENTIAL) fOpen &= ~RTFILE_O_READ; rc = vdIfIoIntFileOpen(pImage->pIfIo, pImage->pszFilename, fOpen, &pImage->pStorage); if (RT_FAILURE(rc)) { rc = vdIfError(pImage->pIfError, rc, RT_SRC_POS, N_("Raw: cannot create image '%s'"), pImage->pszFilename); goto out; } if (!(uOpenFlags & VD_OPEN_FLAGS_SEQUENTIAL)) { /* Check the free space on the disk and leave early if there is not * sufficient space available. */ rc = vdIfIoIntFileGetFreeSpace(pImage->pIfIo, pImage->pszFilename, &cbFree); if (RT_SUCCESS(rc) /* ignore errors */ && ((uint64_t)cbFree < cbSize)) { rc = vdIfError(pImage->pIfError, VERR_DISK_FULL, RT_SRC_POS, N_("Raw: disk would overflow creating image '%s'"), pImage->pszFilename); goto out; } /* Allocate & commit whole file if fixed image, it must be more * effective than expanding file by write operations. */ rc = vdIfIoIntFileSetAllocationSize(pImage->pIfIo, pImage->pStorage, cbSize, 0 /* fFlags */, pfnProgress, pvUser, uPercentStart, uPercentSpan); } if (RT_SUCCESS(rc) && pfnProgress) pfnProgress(pvUser, uPercentStart + uPercentSpan * 98 / 100); pImage->cbSize = cbSize; rc = rawFlushImage(pImage); out: if (RT_SUCCESS(rc) && pfnProgress) pfnProgress(pvUser, uPercentStart + uPercentSpan); if (RT_FAILURE(rc)) rawFreeImage(pImage, rc != VERR_ALREADY_EXISTS); return rc; }
/** * Internal: Create a raw image. */ static int rawCreateImage(PRAWIMAGE pImage, uint64_t cbSize, unsigned uImageFlags, const char *pszComment, PCVDGEOMETRY pPCHSGeometry, PCVDGEOMETRY pLCHSGeometry, unsigned uOpenFlags, PFNVDPROGRESS pfnProgress, void *pvUser, unsigned uPercentStart, unsigned uPercentSpan) { int rc; RTFOFF cbFree = 0; uint64_t uOff; void *pvBuf = NULL; int32_t fOpen; uImageFlags |= VD_IMAGE_FLAGS_FIXED; pImage->uOpenFlags = uOpenFlags & ~VD_OPEN_FLAGS_READONLY; pImage->uImageFlags = uImageFlags; pImage->fCreate = true; pImage->PCHSGeometry = *pPCHSGeometry; pImage->LCHSGeometry = *pLCHSGeometry; pImage->pIfError = VDIfErrorGet(pImage->pVDIfsDisk); pImage->pIfIo = VDIfIoIntGet(pImage->pVDIfsImage); AssertPtrReturn(pImage->pIfIo, VERR_INVALID_PARAMETER); if (uImageFlags & VD_IMAGE_FLAGS_DIFF) { rc = vdIfError(pImage->pIfError, VERR_VD_RAW_INVALID_TYPE, RT_SRC_POS, N_("Raw: cannot create diff image '%s'"), pImage->pszFilename); goto out; } /* Create image file. */ fOpen = VDOpenFlagsToFileOpenFlags(pImage->uOpenFlags, true /* fCreate */); if (uOpenFlags & VD_OPEN_FLAGS_SEQUENTIAL) fOpen &= ~RTFILE_O_READ; rc = vdIfIoIntFileOpen(pImage->pIfIo, pImage->pszFilename, fOpen, &pImage->pStorage); if (RT_FAILURE(rc)) { rc = vdIfError(pImage->pIfError, rc, RT_SRC_POS, N_("Raw: cannot create image '%s'"), pImage->pszFilename); goto out; } if (!(uOpenFlags & VD_OPEN_FLAGS_SEQUENTIAL)) { /* Check the free space on the disk and leave early if there is not * sufficient space available. */ rc = vdIfIoIntFileGetFreeSpace(pImage->pIfIo, pImage->pszFilename, &cbFree); if (RT_SUCCESS(rc) /* ignore errors */ && ((uint64_t)cbFree < cbSize)) { rc = vdIfError(pImage->pIfError, VERR_DISK_FULL, RT_SRC_POS, N_("Raw: disk would overflow creating image '%s'"), pImage->pszFilename); goto out; } /* Allocate & commit whole file if fixed image, it must be more * effective than expanding file by write operations. */ rc = vdIfIoIntFileSetSize(pImage->pIfIo, pImage->pStorage, cbSize); if (RT_FAILURE(rc)) { rc = vdIfError(pImage->pIfError, rc, RT_SRC_POS, N_("Raw: setting image size failed for '%s'"), pImage->pszFilename); goto out; } /* Fill image with zeroes. We do this for every fixed-size image since * on some systems (for example Windows Vista), it takes ages to write * a block near the end of a sparse file and the guest could complain * about an ATA timeout. */ pvBuf = RTMemTmpAllocZ(RAW_FILL_SIZE); if (!pvBuf) { rc = VERR_NO_MEMORY; goto out; } uOff = 0; /* Write data to all image blocks. */ while (uOff < cbSize) { unsigned cbChunk = (unsigned)RT_MIN(cbSize, RAW_FILL_SIZE); rc = vdIfIoIntFileWriteSync(pImage->pIfIo, pImage->pStorage, uOff, pvBuf, cbChunk, NULL); if (RT_FAILURE(rc)) { rc = vdIfError(pImage->pIfError, rc, RT_SRC_POS, N_("Raw: writing block failed for '%s'"), pImage->pszFilename); goto out; } uOff += cbChunk; if (pfnProgress) { rc = pfnProgress(pvUser, uPercentStart + uOff * uPercentSpan * 98 / (cbSize * 100)); if (RT_FAILURE(rc)) goto out; } } } if (RT_SUCCESS(rc) && pfnProgress) pfnProgress(pvUser, uPercentStart + uPercentSpan * 98 / 100); pImage->cbSize = cbSize; rc = rawFlushImage(pImage); out: if (pvBuf) RTMemTmpFree(pvBuf); if (RT_SUCCESS(rc) && pfnProgress) pfnProgress(pvUser, uPercentStart + uPercentSpan); if (RT_FAILURE(rc)) rawFreeImage(pImage, rc != VERR_ALREADY_EXISTS); return rc; }
/** * Internal: Create a raw image. */ static int rawCreateImage(PRAWIMAGE pImage, uint64_t cbSize, unsigned uImageFlags, const char *pszComment, PCVDGEOMETRY pPCHSGeometry, PCVDGEOMETRY pLCHSGeometry, unsigned uOpenFlags, PVDINTERFACEPROGRESS pIfProgress, unsigned uPercentStart, unsigned uPercentSpan) { RT_NOREF1(pszComment); int rc = VINF_SUCCESS; pImage->fCreate = true; pImage->uOpenFlags = uOpenFlags & ~VD_OPEN_FLAGS_READONLY; pImage->uImageFlags = uImageFlags | VD_IMAGE_FLAGS_FIXED; pImage->PCHSGeometry = *pPCHSGeometry; pImage->LCHSGeometry = *pLCHSGeometry; pImage->pIfError = VDIfErrorGet(pImage->pVDIfsDisk); pImage->pIfIo = VDIfIoIntGet(pImage->pVDIfsImage); AssertPtrReturn(pImage->pIfIo, VERR_INVALID_PARAMETER); if (!(pImage->uImageFlags & VD_IMAGE_FLAGS_DIFF)) { /* Create image file. */ uint32_t fOpen = VDOpenFlagsToFileOpenFlags(pImage->uOpenFlags, true /* fCreate */); if (uOpenFlags & VD_OPEN_FLAGS_SEQUENTIAL) fOpen &= ~RTFILE_O_READ; rc = vdIfIoIntFileOpen(pImage->pIfIo, pImage->pszFilename, fOpen, &pImage->pStorage); if (RT_SUCCESS(rc)) { if (!(uOpenFlags & VD_OPEN_FLAGS_SEQUENTIAL)) { RTFOFF cbFree = 0; /* Check the free space on the disk and leave early if there is not * sufficient space available. */ rc = vdIfIoIntFileGetFreeSpace(pImage->pIfIo, pImage->pszFilename, &cbFree); if (RT_FAILURE(rc) /* ignore errors */ || ((uint64_t)cbFree >= cbSize)) { rc = vdIfIoIntFileSetAllocationSize(pImage->pIfIo, pImage->pStorage, cbSize, 0 /* fFlags */, pIfProgress, uPercentStart, uPercentSpan); if (RT_SUCCESS(rc)) { vdIfProgress(pIfProgress, uPercentStart + uPercentSpan * 98 / 100); pImage->cbSize = cbSize; rc = rawFlushImage(pImage); } } else rc = vdIfError(pImage->pIfError, VERR_DISK_FULL, RT_SRC_POS, N_("Raw: disk would overflow creating image '%s'"), pImage->pszFilename); } } else rc = vdIfError(pImage->pIfError, rc, RT_SRC_POS, N_("Raw: cannot create image '%s'"), pImage->pszFilename); } else rc = vdIfError(pImage->pIfError, VERR_VD_RAW_INVALID_TYPE, RT_SRC_POS, N_("Raw: cannot create diff image '%s'"), pImage->pszFilename); if (RT_SUCCESS(rc)) vdIfProgress(pIfProgress, uPercentStart + uPercentSpan); if (RT_FAILURE(rc)) rawFreeImage(pImage, rc != VERR_ALREADY_EXISTS); return rc; }
/** * Internal: Create a parallels image. */ static int parallelsCreateImage(PPARALLELSIMAGE pImage, uint64_t cbSize, unsigned uImageFlags, const char *pszComment, PCVDGEOMETRY pPCHSGeometry, PCVDGEOMETRY pLCHSGeometry, unsigned uOpenFlags, PFNVDPROGRESS pfnProgress, void *pvUser, unsigned uPercentStart, unsigned uPercentSpan) { int rc = VINF_SUCCESS; int32_t fOpen; if (uImageFlags & VD_IMAGE_FLAGS_FIXED) { rc = vdIfError(pImage->pIfError, VERR_VD_INVALID_TYPE, RT_SRC_POS, N_("Parallels: cannot create fixed image '%s'. Create a raw image"), pImage->pszFilename); goto out; } pImage->uOpenFlags = uOpenFlags & ~VD_OPEN_FLAGS_READONLY; pImage->uImageFlags = uImageFlags; pImage->PCHSGeometry = *pPCHSGeometry; pImage->LCHSGeometry = *pLCHSGeometry; if (!pImage->PCHSGeometry.cCylinders) { /* Set defaults. */ pImage->PCHSGeometry.cSectors = 63; pImage->PCHSGeometry.cHeads = 16; pImage->PCHSGeometry.cCylinders = pImage->cbSize / (512 * pImage->PCHSGeometry.cSectors * pImage->PCHSGeometry.cHeads); } pImage->pIfError = VDIfErrorGet(pImage->pVDIfsDisk); pImage->pIfIo = VDIfIoIntGet(pImage->pVDIfsImage); AssertPtrReturn(pImage->pIfIo, VERR_INVALID_PARAMETER); /* Create image file. */ fOpen = VDOpenFlagsToFileOpenFlags(pImage->uOpenFlags, true /* fCreate */); rc = vdIfIoIntFileOpen(pImage->pIfIo, pImage->pszFilename, fOpen, &pImage->pStorage); if (RT_FAILURE(rc)) { rc = vdIfError(pImage->pIfError, rc, RT_SRC_POS, N_("Parallels: cannot create image '%s'"), pImage->pszFilename); goto out; } if (RT_SUCCESS(rc) && pfnProgress) pfnProgress(pvUser, uPercentStart + uPercentSpan * 98 / 100); /* Setup image state. */ pImage->cbSize = cbSize; pImage->cAllocationBitmapEntries = cbSize / 512 / pImage->PCHSGeometry.cSectors; if (pImage->cAllocationBitmapEntries * pImage->PCHSGeometry.cSectors * 512 < cbSize) pImage->cAllocationBitmapEntries++; pImage->fAllocationBitmapChanged = true; pImage->cbFileCurrent = sizeof(ParallelsHeader) + pImage->cAllocationBitmapEntries * sizeof(uint32_t); /* Round to next sector boundary. */ pImage->cbFileCurrent += 512 - pImage->cbFileCurrent % 512; Assert(!(pImage->cbFileCurrent % 512)); pImage->pAllocationBitmap = (uint32_t *)RTMemAllocZ(pImage->cAllocationBitmapEntries * sizeof(uint32_t)); if (!pImage->pAllocationBitmap) rc = VERR_NO_MEMORY; if (RT_SUCCESS(rc)) { ParallelsHeader Header; memcpy(Header.HeaderIdentifier, PARALLELS_HEADER_MAGIC, sizeof(Header.HeaderIdentifier)); Header.uVersion = RT_H2LE_U32(PARALLELS_DISK_VERSION); Header.cHeads = RT_H2LE_U32(pImage->PCHSGeometry.cHeads); Header.cCylinders = RT_H2LE_U32(pImage->PCHSGeometry.cCylinders); Header.cSectorsPerTrack = RT_H2LE_U32(pImage->PCHSGeometry.cSectors); Header.cEntriesInAllocationBitmap = RT_H2LE_U32(pImage->cAllocationBitmapEntries); Header.cSectors = RT_H2LE_U32(pImage->cbSize / 512); memset(Header.Padding, 0, sizeof(Header.Padding)); /* Write header and allocation bitmap. */ rc = vdIfIoIntFileSetSize(pImage->pIfIo, pImage->pStorage, pImage->cbFileCurrent); if (RT_SUCCESS(rc)) rc = vdIfIoIntFileWriteSync(pImage->pIfIo, pImage->pStorage, 0, &Header, sizeof(Header), NULL); if (RT_SUCCESS(rc)) rc = parallelsFlushImage(pImage); /* Writes the allocation bitmap. */ } out: if (RT_SUCCESS(rc) && pfnProgress) pfnProgress(pvUser, uPercentStart + uPercentSpan); if (RT_FAILURE(rc)) parallelsFreeImage(pImage, rc != VERR_ALREADY_EXISTS); return rc; }
static int parallelsOpenImage(PPARALLELSIMAGE pImage, unsigned uOpenFlags) { int rc = VINF_SUCCESS; ParallelsHeader parallelsHeader; pImage->pIfError = VDIfErrorGet(pImage->pVDIfsDisk); pImage->pIfIo = VDIfIoIntGet(pImage->pVDIfsImage); AssertPtrReturn(pImage->pIfIo, VERR_INVALID_PARAMETER); rc = vdIfIoIntFileOpen(pImage->pIfIo, pImage->pszFilename, VDOpenFlagsToFileOpenFlags(uOpenFlags, false /* fCreate */), &pImage->pStorage); if (RT_FAILURE(rc)) goto out; rc = vdIfIoIntFileGetSize(pImage->pIfIo, pImage->pStorage, &pImage->cbFileCurrent); if (RT_FAILURE(rc)) goto out; AssertMsg(pImage->cbFileCurrent % 512 == 0, ("File size is not a multiple of 512\n")); rc = vdIfIoIntFileReadSync(pImage->pIfIo, pImage->pStorage, 0, ¶llelsHeader, sizeof(parallelsHeader), NULL); if (RT_FAILURE(rc)) goto out; if (memcmp(parallelsHeader.HeaderIdentifier, PARALLELS_HEADER_MAGIC, 16)) { /* Check if the file has hdd as extension. It is a fixed size raw image then. */ char *pszExtension = RTPathExt(pImage->pszFilename); if (strcmp(pszExtension, ".hdd")) { rc = VERR_VD_PARALLELS_INVALID_HEADER; goto out; } /* This is a fixed size image. */ pImage->uImageFlags |= VD_IMAGE_FLAGS_FIXED; pImage->cbSize = pImage->cbFileCurrent; pImage->PCHSGeometry.cHeads = 16; pImage->PCHSGeometry.cSectors = 63; uint64_t cCylinders = pImage->cbSize / (512 * pImage->PCHSGeometry.cSectors * pImage->PCHSGeometry.cHeads); pImage->PCHSGeometry.cCylinders = (uint32_t)cCylinders; } else { if (parallelsHeader.uVersion != PARALLELS_DISK_VERSION) { rc = VERR_NOT_SUPPORTED; goto out; } if (parallelsHeader.cEntriesInAllocationBitmap > (1 << 30)) { rc = VERR_NOT_SUPPORTED; goto out; } Log(("cSectors=%u\n", parallelsHeader.cSectors)); pImage->cbSize = ((uint64_t)parallelsHeader.cSectors) * 512; pImage->uImageFlags = VD_IMAGE_FLAGS_NONE; pImage->cAllocationBitmapEntries = parallelsHeader.cEntriesInAllocationBitmap; pImage->pAllocationBitmap = (uint32_t *)RTMemAllocZ((uint32_t)pImage->cAllocationBitmapEntries * sizeof(uint32_t)); if (!pImage->pAllocationBitmap) { rc = VERR_NO_MEMORY; goto out; } rc = vdIfIoIntFileReadSync(pImage->pIfIo, pImage->pStorage, sizeof(ParallelsHeader), pImage->pAllocationBitmap, pImage->cAllocationBitmapEntries * sizeof(uint32_t), NULL); if (RT_FAILURE(rc)) goto out; pImage->PCHSGeometry.cCylinders = parallelsHeader.cCylinders; pImage->PCHSGeometry.cHeads = parallelsHeader.cHeads; pImage->PCHSGeometry.cSectors = parallelsHeader.cSectorsPerTrack; } out: LogFlowFunc(("returns %Rrc\n", rc)); return rc; }