VirtualBox

Ignore:
Timestamp:
Feb 10, 2016 12:47:33 AM (9 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
105459
Message:

IPRT: Added 'off' parameter to RTVfsIoStrmSgWrite and RTVfsIoStrmSgRead so it's easier to write passthru layers. Added RTVfsIoStrmReadAll, RTVfsIoStrmReadAllFree, RTVfsIoStrmFromBuffer, RTManifestPtIosIsInstanceOf, RTCrX509Certificate_ReadFromBuffer and RTCrDigestUpdateFromVfsFile. Updated the manifest passthru read code to handle ReadAt requests which skips parts and jumps back to re-read stuff on streams/files which are seekable.

Location:
trunk/src/VBox/Runtime/common/checksum
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Runtime/common/checksum/manifest2.cpp

    r59575 r59620  
    527527
    528528    /*
    529      * Ignore this entry.
     529     * Ignore this entry?
    530530     */
    531531    char const * const *ppsz = pEquals->papszIgnoreEntries;
  • trunk/src/VBox/Runtime/common/checksum/manifest3.cpp

    r57358 r59620  
    3232#include <iprt/manifest.h>
    3333
     34#include <iprt/alloca.h>
    3435#include <iprt/asm.h>
    3536#include <iprt/assert.h>
     
    9192    /** The hashes.  */
    9293    PRTMANIFESTHASHES   pHashes;
     94    /** The current hash position. */
     95    RTFOFF              offCurPos;
    9396    /** Whether we're reading or writing. */
    9497    bool                fReadOrWrite;
     
    315318{
    316319    PRTMANIFESTPTIOS pThis = (PRTMANIFESTPTIOS)pvThis;
    317     int rc = RTVfsIoStrmSgRead(pThis->hVfsIos, pSgBuf, fBlocking, pcbRead);
     320    int rc;
     321
     322    /*
     323     * To make sure we're continuing where we left off, we must have the exact
     324     * stream position since a previous read using 'off' may change it.
     325     */
     326    RTFOFF offActual = off == -1 ? RTVfsIoStrmTell(pThis->hVfsIos) : off;
     327    if (offActual == pThis->offCurPos)
     328    {
     329        rc = RTVfsIoStrmSgRead(pThis->hVfsIos, off, pSgBuf, fBlocking, pcbRead);
     330        if (RT_SUCCESS(rc))
     331        {
     332            rtManifestPtIos_UpdateHashes(pThis, pSgBuf, pcbRead ? *pcbRead : ~(size_t)0);
     333            if (!pcbRead)
     334                for (uint32_t iSeg = 0; iSeg < pSgBuf->cSegs; iSeg++)
     335                    pThis->offCurPos += pSgBuf->paSegs[iSeg].cbSeg;
     336            else
     337                pThis->offCurPos += *pcbRead;
     338        }
     339        Assert(RTVfsIoStrmTell(pThis->hVfsIos) == pThis->offCurPos);
     340    }
     341    else
     342    {
     343        /*
     344         * If we're skipping over stuff, we need to read the gap and hash it.
     345         */
     346        if (pThis->offCurPos < offActual)
     347        {
     348            size_t cbBuf = _8K;
     349            void  *pvBuf = alloca(cbBuf);
     350            do
     351            {
     352                RTFOFF cbGap = off - pThis->offCurPos;
     353                size_t cbThisRead = cbGap >= (RTFOFF)cbBuf ? cbBuf : (size_t)cbGap;
     354                size_t cbActual;
     355                rc = RTVfsIoStrmReadAt(pThis->hVfsIos, pThis->offCurPos, pvBuf, cbThisRead, fBlocking, &cbActual);
     356                if (RT_FAILURE(rc) || rc == VINF_TRY_AGAIN)
     357                    return rc;
     358
     359                rtManifestHashesUpdate(pThis->pHashes, pvBuf, cbActual);
     360                pThis->offCurPos += cbActual;
     361
     362                if (rc == VINF_EOF)
     363                {
     364                    if (pcbRead)
     365                        *pcbRead = 0;
     366                    else
     367                        rc = VERR_EOF;
     368                    return rc;
     369                }
     370            } while (pThis->offCurPos < offActual);
     371            Assert(RTVfsIoStrmTell(pThis->hVfsIos) == offActual);
     372        }
     373
     374        /*
     375         * At this point we've eliminated any gap and can execute the requested read.
     376         */
     377        rc = RTVfsIoStrmSgRead(pThis->hVfsIos, off, pSgBuf, fBlocking, pcbRead);
     378        if (RT_SUCCESS(rc))
     379        {
     380            /* See if there is anything to update the hash with. */
     381            size_t cbLeft = pcbRead ? *pcbRead : ~(size_t)0;
     382            for (uint32_t iSeg = 0; iSeg < pSgBuf->cSegs; iSeg++)
     383            {
     384                size_t cbThis = pSgBuf->paSegs[iSeg].cbSeg;
     385                if (cbThis > cbLeft)
     386                    cbThis = cbLeft;
     387
     388                if (   offActual >= pThis->offCurPos
     389                    && pThis->offCurPos < offActual + (ssize_t)cbThis)
     390                {
     391                    size_t offSeg = (size_t)(offActual - pThis->offCurPos);
     392                    rtManifestHashesUpdate(pThis->pHashes, (uint8_t *)pSgBuf->paSegs[iSeg].pvSeg + offSeg, cbThis - offSeg);
     393                    pThis->offCurPos += cbThis - offSeg;
     394                }
     395
     396                cbLeft -= cbThis;
     397                if (!cbLeft)
     398                    break;
     399                offActual += cbThis;
     400            }
     401        }
     402    }
     403    return rc;
     404}
     405
     406
     407/**
     408 * @interface_method_impl{RTVFSIOSTREAMOPS,pfnWrite}
     409 */
     410static DECLCALLBACK(int) rtManifestPtIos_Write(void *pvThis, RTFOFF off, PCRTSGBUF pSgBuf, bool fBlocking, size_t *pcbWritten)
     411{
     412    PRTMANIFESTPTIOS pThis = (PRTMANIFESTPTIOS)pvThis;
     413    AssertReturn(off == -1 || off == pThis->offCurPos, VERR_WRONG_ORDER);
     414    Assert(RTVfsIoStrmTell(pThis->hVfsIos) == pThis->offCurPos);
     415
     416    int rc = RTVfsIoStrmSgWrite(pThis->hVfsIos, -1 /*off*/, pSgBuf, fBlocking, pcbWritten);
    318417    if (RT_SUCCESS(rc))
    319         rtManifestPtIos_UpdateHashes(pThis, pSgBuf, pcbRead ? *pcbRead : ~(size_t)0);
    320     Assert(off == -1); NOREF(off);
    321     return rc;
    322 }
    323 
    324 
    325 /**
    326  * @interface_method_impl{RTVFSIOSTREAMOPS,pfnWrite}
    327  */
    328 static DECLCALLBACK(int) rtManifestPtIos_Write(void *pvThis, RTFOFF off, PCRTSGBUF pSgBuf, bool fBlocking, size_t *pcbWritten)
    329 {
    330     PRTMANIFESTPTIOS pThis = (PRTMANIFESTPTIOS)pvThis;
    331     int rc = RTVfsIoStrmSgWrite(pThis->hVfsIos, pSgBuf, fBlocking, pcbWritten);
    332     if (RT_SUCCESS(rc))
     418    {
    333419        rtManifestPtIos_UpdateHashes(pThis, pSgBuf, pcbWritten ? *pcbWritten : ~(size_t)0);
    334     Assert(off == -1); NOREF(off);
     420        if (!pcbWritten)
     421            for (uint32_t iSeg = 0; iSeg < pSgBuf->cSegs; iSeg++)
     422                pThis->offCurPos += pSgBuf->paSegs[iSeg].cbSeg;
     423        else
     424            pThis->offCurPos += *pcbWritten;
     425    }
    335426    return rc;
    336427}
     
    425516    AssertPtr(pszEntry);
    426517    AssertPtr(phVfsIosPassthru);
     518
     519    RTFOFF const offCurPos = RTVfsIoStrmTell(hVfsIos);
     520    AssertReturn(offCurPos >= 0, (int)offCurPos);
     521
    427522    uint32_t cRefs = RTManifestRetain(hManifest);
    428523    AssertReturn(cRefs != UINT32_MAX, VERR_INVALID_HANDLE);
     524
    429525    cRefs = RTVfsIoStrmRetain(hVfsIos);
    430526    AssertReturnStmt(cRefs != UINT32_MAX, RTManifestRelease(hManifest), VERR_INVALID_HANDLE);
     
    441537        pThis->hVfsIos          = hVfsIos;
    442538        pThis->pHashes          = rtManifestHashesCreate(fAttrs);
     539        pThis->offCurPos        = offCurPos;
    443540        pThis->hManifest        = hManifest;
    444541        pThis->fReadOrWrite     = fReadOrWrite;
     
    478575    rtManifestHashesFinal(pThis->pHashes);
    479576    return rtManifestHashesSetAttrs(pThis->pHashes, pThis->hManifest, pThis->pszEntry);
     577}
     578
     579
     580/**
     581 * Checks if the give I/O stream is a manifest passthru instance or not.
     582 *
     583 * @returns true if it's a manifest passthru I/O stream, false if not.
     584 * @param   hVfsPtIos   Possible the manifest passthru I/O stream handle.
     585 */
     586RTDECL(bool) RTManifestPtIosIsInstanceOf(RTVFSIOSTREAM hVfsPtIos)
     587{
     588    if (hVfsPtIos != NIL_RTVFSIOSTREAM)
     589    {
     590        PRTMANIFESTPTIOS pThis = (PRTMANIFESTPTIOS)RTVfsIoStreamToPrivate(hVfsPtIos, &g_rtManifestPassthruIosOps);
     591        if (pThis)
     592            return true;
     593    }
     594    return false;
    480595}
    481596
Note: See TracChangeset for help on using the changeset viewer.

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette