Пример #1
0
/** @copydoc VBOXHDDBACKEND::pfnRead */
static int parallelsRead(void *pBackendData, uint64_t uOffset, void *pvBuf,
                         size_t cbToRead, size_t *pcbActuallyRead)
{
    LogFlowFunc(("pBackendData=%#p uOffset=%llu pvBuf=%#p cbToRead=%zu pcbActuallyRead=%#p\n",
                 pBackendData, uOffset, pvBuf, cbToRead, pcbActuallyRead));
    PPARALLELSIMAGE pImage = (PPARALLELSIMAGE)pBackendData;
    int rc = VINF_SUCCESS;

    AssertPtr(pImage);
    Assert(uOffset % 512 == 0);
    Assert(cbToRead % 512 == 0);

    if (pImage->uImageFlags & VD_IMAGE_FLAGS_FIXED)
        rc = vdIfIoIntFileReadSync(pImage->pIfIo, pImage->pStorage, uOffset, pvBuf, cbToRead, NULL);
    else
    {
        uint64_t uSector;
        uint32_t iIndexInAllocationTable;

        /* Calculate offset in the real file. */
        uSector = uOffset / 512;

        /* One chunk in the file is always one track big. */
        iIndexInAllocationTable = (uint32_t)(uSector / pImage->PCHSGeometry.cSectors);
        uSector = uSector % pImage->PCHSGeometry.cSectors;

        Assert(iIndexInAllocationTable < pImage->cAllocationBitmapEntries);

        cbToRead = RT_MIN(cbToRead, (pImage->PCHSGeometry.cSectors - uSector)*512);

        LogFlowFunc(("AllocationBitmap[%u]=%u uSector=%u cbToRead=%zu cAllocationBitmapEntries=%u\n",
                     iIndexInAllocationTable, pImage->pAllocationBitmap[iIndexInAllocationTable],
                     uSector, cbToRead, pImage->cAllocationBitmapEntries));

        if (pImage->pAllocationBitmap[iIndexInAllocationTable] == 0)
            rc = VERR_VD_BLOCK_FREE;
        else
        {
            uint64_t uOffsetInFile = ((uint64_t)pImage->pAllocationBitmap[iIndexInAllocationTable] + uSector) * 512;

            LogFlowFunc(("uOffsetInFile=%llu\n", uOffsetInFile));
            rc = vdIfIoIntFileReadSync(pImage->pIfIo, pImage->pStorage, uOffsetInFile,
                                       pvBuf, cbToRead, NULL);
        }
    }

    if (   (   RT_SUCCESS(rc)
            || rc == VERR_VD_BLOCK_FREE)
        && pcbActuallyRead)
        *pcbActuallyRead = cbToRead;

    LogFlowFunc(("returns %Rrc\n", rc));
    return rc;
}
Пример #2
0
/** @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, &parallelsHeader,
                               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;
}
Пример #3
0
/** @copydoc VBOXHDDBACKEND::pfnRead */
static int rawRead(void *pBackendData, uint64_t uOffset, void *pvBuf,
                   size_t cbToRead, size_t *pcbActuallyRead)
{
    LogFlowFunc(("pBackendData=%#p uOffset=%llu pvBuf=%#p cbToRead=%zu pcbActuallyRead=%#p\n", pBackendData, uOffset, pvBuf, cbToRead, pcbActuallyRead));
    PRAWIMAGE pImage = (PRAWIMAGE)pBackendData;
    int rc;

    AssertPtr(pImage);
    Assert(uOffset % 512 == 0);
    Assert(cbToRead % 512 == 0);

    if (   uOffset + cbToRead > pImage->cbSize
        || cbToRead == 0)
    {
        rc = VERR_INVALID_PARAMETER;
        goto out;
    }

    /* For sequential access do not allow to go back. */
    if (   pImage->uOpenFlags & VD_OPEN_FLAGS_SEQUENTIAL
        && uOffset < pImage->offAccess)
    {
        rc = VERR_INVALID_PARAMETER;
        goto out;
    }

    rc = vdIfIoIntFileReadSync(pImage->pIfIo, pImage->pStorage, uOffset, pvBuf,
                               cbToRead, NULL);
    pImage->offAccess = uOffset + cbToRead;
    if (pcbActuallyRead)
        *pcbActuallyRead = cbToRead;

out:
    LogFlowFunc(("returns %Rrc\n", rc));
    return rc;
}
Пример #4
0
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,
                               &parallelsHeader, 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;
}