示例#1
0
文件: VDVfs.cpp 项目: bringhurst/vbox
/**
 * @interface_method_impl{RTVFSIOSTREAMOPS,pfnWrite}
 */
static DECLCALLBACK(int) vdVfsFile_Write(void *pvThis, RTFOFF off, PCRTSGBUF pSgBuf, bool fBlocking, size_t *pcbWritten)
{
    PVDVFSFILE pThis = (PVDVFSFILE)pvThis;
    int rc = VINF_SUCCESS;

    Assert(pSgBuf->cSegs == 1);
    NOREF(fBlocking);

    /*
     * Find the current position and check if it's within the volume.
     * Writing beyond the end of a volume is not supported.
     */
    uint64_t offUnsigned = off < 0 ? pThis->offCurPos : (uint64_t)off;
    if (offUnsigned >= VDGetSize(pThis->pDisk, VD_LAST_IMAGE))
    {
        if (pcbWritten)
        {
            *pcbWritten = 0;
            pThis->offCurPos = offUnsigned;
        }
        return VERR_NOT_SUPPORTED;
    }

    size_t cbLeftToWrite;
    if (offUnsigned + pSgBuf->paSegs[0].cbSeg > VDGetSize(pThis->pDisk, VD_LAST_IMAGE))
    {
        if (!pcbWritten)
            return VERR_EOF;
        *pcbWritten = cbLeftToWrite = (size_t)(VDGetSize(pThis->pDisk, VD_LAST_IMAGE) - offUnsigned);
    }
    else
    {
        cbLeftToWrite = pSgBuf->paSegs[0].cbSeg;
        if (pcbWritten)
            *pcbWritten = cbLeftToWrite;
    }

    /*
     * Ok, we've got a valid stretch within the file.  Do the reading.
     */
    if (cbLeftToWrite > 0)
    {
        rc = vdWriteHelper(pThis->pDisk, (uint64_t)off, pSgBuf->paSegs[0].pvSeg, cbLeftToWrite);
        if (RT_SUCCESS(rc))
            offUnsigned += cbLeftToWrite;
    }

    pThis->offCurPos = offUnsigned;
    return rc;
}
示例#2
0
文件: VDVfs.cpp 项目: bringhurst/vbox
/**
 * @interface_method_impl{RTVFSFILEOPS,pfnSeek}
 */
static DECLCALLBACK(int) vdVfsFile_Seek(void *pvThis, RTFOFF offSeek, unsigned uMethod, PRTFOFF poffActual)
{
    PVDVFSFILE pThis = (PVDVFSFILE)pvThis;

    /*
     * Seek relative to which position.
     */
    uint64_t offWrt;
    switch (uMethod)
    {
        case RTFILE_SEEK_BEGIN:
            offWrt = 0;
            break;

        case RTFILE_SEEK_CURRENT:
            offWrt = pThis->offCurPos;
            break;

        case RTFILE_SEEK_END:
            offWrt = VDGetSize(pThis->pDisk, VD_LAST_IMAGE);
            break;

        default:
            return VERR_INTERNAL_ERROR_5;
    }

    /*
     * Calc new position, take care to stay within bounds.
     *
     * @todo: Setting position beyond the end of the disk does not make sense.
     */
    uint64_t offNew;
    if (offSeek == 0)
        offNew = offWrt;
    else if (offSeek > 0)
    {
        offNew = offWrt + offSeek;
        if (   offNew < offWrt
            || offNew > RTFOFF_MAX)
            offNew = RTFOFF_MAX;
    }
    else if ((uint64_t)-offSeek < offWrt)
        offNew = offWrt + offSeek;
    else
        offNew = 0;

    /*
     * Update the state and set return value.
     */
    pThis->offCurPos = offNew;

    *poffActual = offNew;
    return VINF_SUCCESS;
}
示例#3
0
/**
 * Creates a flattened image
 *
 * @returns VBox status code.
 * @param   pszPath         Where to create the flattened file in the FUSE file
 *                          system.
 * @param   pszImage        The image to flatten.
 * @param   ppFile          Where to return the pointer to the instance.
 *                          Optional.
 */
static int vboxfuseFlatImageCreate(const char *pszPath, const char *pszImage, PVBOXFUSEFLATIMAGE *ppFile)
{
    /*
     * Check that we can create this file.
     */
    const char *pszName;
    PVBOXFUSEDIR pParent;
    int rc = vboxfuseTreeLookupParentForInsert(pszPath, &pszName, &pParent);
    if (RT_FAILURE(rc))
        return rc;
    if (pParent)
        vboxfuseNodeReleaseAndUnlock(&pParent->Node);

    /*
     * Try open the image file (without holding any locks).
     */
    char *pszFormat;
    VDTYPE enmType;
    rc = VDGetFormat(NULL /* pVDIIfsDisk */, NULL /* pVDIIfsImage*/, pszImage, &pszFormat, &enmType);
    if (RT_FAILURE(rc))
    {
        LogRel(("VDGetFormat(%s,) failed, rc=%Rrc\n", pszImage, rc));
        return rc;
    }

    PVBOXHDD pDisk = NULL;
    rc = VDCreate(NULL /* pVDIIfsDisk */, enmType, &pDisk);
    if (RT_SUCCESS(rc))
    {
        rc = VDOpen(pDisk, pszFormat, pszImage, 0, NULL /* pVDIfsImage */);
        if (RT_FAILURE(rc))
        {
            LogRel(("VDCreate(,%s,%s,,,) failed, rc=%Rrc\n", pszFormat, pszImage, rc));
            VDClose(pDisk, false /* fDeletes */);
        }
    }
    else
        Log(("VDCreate failed, rc=%Rrc\n", rc));
    if (RT_FAILURE(rc))
    {
        RTStrFree(pszFormat);
        return rc;
    }

    /*
     * Allocate and initialize the new directory node.
     */
    rc = vboxfuseTreeLookupParentForInsert(pszPath, &pszName, &pParent);
    if (RT_SUCCESS(rc))
    {
        PVBOXFUSEFLATIMAGE pNewFlatImage;
        rc = vboxfuseNodeAlloc(sizeof(*pNewFlatImage), pszName, VBOXFUSETYPE_FLAT_IMAGE, pParent, (PVBOXFUSENODE *)&pNewFlatImage);
        if (RT_SUCCESS(rc))
        {
            pNewFlatImage->pDisk          = pDisk;
            pNewFlatImage->pszFormat      = pszFormat;
            pNewFlatImage->cReaders       = VDIsReadOnly(pNewFlatImage->pDisk) ? INT32_MAX / 2 : 0;
            pNewFlatImage->cWriters       = 0;
            pNewFlatImage->Node.cbPrimary = VDGetSize(pNewFlatImage->pDisk, 0 /* base */);

            /*
             * Insert it.
             */
            rc = vboxfuseDirInsertChild(pParent, &pNewFlatImage->Node);
            if (    RT_SUCCESS(rc)
                &&  ppFile)
            {
                vboxfuseNodeLockAndRetain(&pNewFlatImage->Node);
                *ppFile = pNewFlatImage;
            }
            vboxfuseNodeRelease(&pNewFlatImage->Node);
            pDisk = NULL;
        }
        if (pParent)
            vboxfuseNodeReleaseAndUnlock(&pParent->Node);
    }
    if (RT_FAILURE(rc) && pDisk != NULL)
        VDClose(pDisk, false /* fDelete */);
    return rc;
}
示例#4
0
文件: VDVfs.cpp 项目: bringhurst/vbox
/**
 * @interface_method_impl{RTVFSFILEOPS,pfnQuerySize}
 */
static DECLCALLBACK(int) vdVfsFile_QuerySize(void *pvThis, uint64_t *pcbFile)
{
    PVDVFSFILE pThis = (PVDVFSFILE)pvThis;
    *pcbFile = VDGetSize(pThis->pDisk, VD_LAST_IMAGE);
    return VINF_SUCCESS;
}
int main(int argc, char *argv[])
{
    int rc;

    RTR3InitExe(argc, &argv, 0);

    if (argc != 3)
    {
        RTPrintf("Usage: ./tstVDCopy <hdd1> <hdd2>\n");
        return 1;
    }

    RTPrintf("tstVDCopy: TESTING...\n");

    PVBOXHDD         pVD1 = NULL;
    PVBOXHDD         pVD2 = NULL;
    PVDINTERFACE     pVDIfs = NULL;
    VDINTERFACEERROR VDIfError;
    char *pszVD1 = NULL;
    char *pszVD2 = NULL;
    char *pbBuf1 = NULL;
    char *pbBuf2 = NULL;
    VDTYPE enmTypeVD1 = VDTYPE_INVALID;
    VDTYPE enmTypeVD2 = VDTYPE_INVALID;

#define CHECK(str) \
    do \
    { \
        if (RT_FAILURE(rc)) \
        { \
            RTPrintf("%s rc=%Rrc\n", str, rc); \
            if (pVD1) \
                VDCloseAll(pVD1); \
            if (pVD2) \
                VDCloseAll(pVD2); \
            return rc; \
        } \
    } while (0)

    pbBuf1 = (char *)RTMemAllocZ(VD_MERGE_BUFFER_SIZE);
    pbBuf2 = (char *)RTMemAllocZ(VD_MERGE_BUFFER_SIZE);

    /* Create error interface. */
    VDIfError.pfnError = tstVDError;

    rc = VDInterfaceAdd(&VDIfError.Core, "tstVD_Error", VDINTERFACETYPE_ERROR,
                        NULL, sizeof(VDINTERFACEERROR), &pVDIfs);
    AssertRC(rc);

    rc = VDGetFormat(NULL /* pVDIfsDisk */, NULL /* pVDIfsImage */,
                     argv[1], &pszVD1, &enmTypeVD1);
    CHECK("VDGetFormat() hdd1");

    rc = VDGetFormat(NULL /* pVDIfsDisk */, NULL /* pVDIfsImage */,
                     argv[2], &pszVD2, &enmTypeVD2);
    CHECK("VDGetFormat() hdd2");

    rc = VDCreate(pVDIfs, VDTYPE_HDD, &pVD1);
    CHECK("VDCreate() hdd1");

    rc = VDCreate(pVDIfs, VDTYPE_HDD, &pVD2);
    CHECK("VDCreate() hdd1");

    rc = VDOpen(pVD1, pszVD1, argv[1], VD_OPEN_FLAGS_NORMAL, NULL);
    CHECK("VDOpen() hdd1");

    rc = VDOpen(pVD2, pszVD2, argv[2], VD_OPEN_FLAGS_NORMAL, NULL);
    CHECK("VDOpen() hdd2");

    uint64_t cbSize1 = 0;
    uint64_t cbSize2 = 0;

    cbSize1 = VDGetSize(pVD1, 0);
    Assert(cbSize1 != 0);
    cbSize2 = VDGetSize(pVD1, 0);
    Assert(cbSize1 != 0);

    if (cbSize1 == cbSize2)
    {
        uint64_t uOffCurr = 0;

        /* Compare block by block. */
        while (uOffCurr < cbSize1)
        {
            size_t cbRead = RT_MIN((cbSize1 - uOffCurr), VD_MERGE_BUFFER_SIZE);

            rc = VDRead(pVD1, uOffCurr, pbBuf1, cbRead);
            CHECK("VDRead() hdd1");

            rc = VDRead(pVD2, uOffCurr, pbBuf2, cbRead);
            CHECK("VDRead() hdd2");

            if (memcmp(pbBuf1, pbBuf2, cbRead))
            {
                RTPrintf("tstVDCopy: Images differ uOffCurr=%llu\n", uOffCurr);
                /* Do byte by byte comparison. */
                for (size_t i = 0; i < cbRead; i++)
                {
                    if (pbBuf1[i] != pbBuf2[i])
                    {
                        RTPrintf("tstVDCopy: First different byte is at offset %llu\n", uOffCurr + i);
                        break;
                    }
                }
                break;
            }

            uOffCurr += cbRead;
        }
    }
    else
        RTPrintf("tstVDCopy: Images have different size hdd1=%llu hdd2=%llu\n", cbSize1, cbSize2);

    VDClose(pVD1, false);
    CHECK("VDClose() hdd1");

    VDClose(pVD2, false);
    CHECK("VDClose() hdd2");

    VDDestroy(pVD1);
    VDDestroy(pVD2);
    RTMemFree(pbBuf1);
    RTMemFree(pbBuf2);
#undef CHECK

    rc = VDShutdown();
    if (RT_FAILURE(rc))
    {
        RTPrintf("tstVDCopy: unloading backends failed! rc=%Rrc\n", rc);
        g_cErrors++;
    }
    /*
     * Summary
     */
    if (!g_cErrors)
        RTPrintf("tstVDCopy: SUCCESS\n");
    else
        RTPrintf("tstVDCopy: FAILURE - %d errors\n", g_cErrors);

    return !!g_cErrors;
}