VirtualBox

Ignore:
Timestamp:
May 31, 2017 11:14:37 AM (8 years ago)
Author:
vboxsync
Message:

IPRT/vfstarwriter.cpp: Initial push-file implementation (untested).

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Runtime/common/zip/tarvfswriter.cpp

    r67150 r67166  
    131131    /** The current I/O stream position (relative to offData). */
    132132    uint64_t                offCurrent;
    133     /** The expected size amount of file content.  This is set to UINT64_MAX if
    134      * open-ended file size. */
     133    /** The expected size amount of file content, or max file size if open-ended. */
    135134    uint64_t                cbExpected;
    136135    /** The current amount of file content written. */
     
    138137    /** Object info copy for rtZipTarWriterPush_QueryInfo. */
    139138    RTFSOBJINFO             ObjInfo;
     139    /** Set if open-ended file size requiring a tar header update when done. */
     140    bool                    fOpenEnded;
    140141} RTZIPTARFSSTREAMWRITERPUSH;
    141142/** Pointer to a push I/O instance. */
     
    176177*   Internal Functions                                                                                                           *
    177178*********************************************************************************************************************************/
     179static DECLCALLBACK(int) rtZipTarWriterPush_Seek(void *pvThis, RTFOFF offSeek, unsigned uMethod, PRTFOFF poffActual);
    178180static int rtZipTarFssWriter_CompleteCurrentPushFile(PRTZIPTARFSSTREAMWRITER pThis);
    179181static int rtZipTarFssWriter_AddFile(PRTZIPTARFSSTREAMWRITER pThis, const char *pszPath, RTVFSIOSTREAM hVfsIos,
     
    506508    PRTZIPTARFSSTREAMWRITER     pParent = pPush->pParent;
    507509    AssertPtrReturn(pParent, VERR_WRONG_ORDER);
    508     Assert(!pcbWritten || !*pcbWritten /* assume caller sets this to zero so we can be lazy here */);
    509510
    510511    int rc = pParent->rcFatal;
     
    519520
    520521    /*
    521      * Deal with simple non-seeking write first.
    522      */
    523     size_t cbWritten = 0;
    524     Assert(pPush->offCurrent <= pPush->cbExpected);
    525     Assert(pPush->offCurrent <= pPush->cbCurrent);
     522     * Hopefully we don't need to seek.  But if we do, let the seek method do
     523     * it as it's not entirely trivial.
     524     */
    526525    if (   off < 0
    527526        || (uint64_t)off == pPush->offCurrent)
    528     {
     527        rc = VINF_SUCCESS;
     528    else
     529        rc = rtZipTarWriterPush_Seek(pvThis, off, RTFILE_SEEK_BEGIN, NULL);
     530    if (RT_SUCCESS(rc))
     531    {
     532        Assert(pPush->offCurrent <= pPush->cbExpected);
     533        Assert(pPush->offCurrent <= pPush->cbCurrent);
    529534        AssertMsgReturn(cbToWrite <= pPush->cbExpected - pPush->offCurrent,
    530535                        ("offCurrent=%#RX64 + cbToWrite=%#zx = %#RX64; cbExpected=%RX64\n",
    531536                         pPush->offCurrent, cbToWrite, pPush->offCurrent + cbToWrite, pPush->cbExpected),
    532537                        VERR_DISK_FULL);
     538        size_t cbWritten = 0;
    533539        rc = RTVfsIoStrmWrite(pParent->hVfsIos, pvToWrite, cbToWrite, fBlocking, &cbWritten);
    534540        if (RT_SUCCESS(rc))
     
    540546                pPush->cbCurrent   = pPush->offCurrent;
    541547            }
    542         }
    543     }
    544     /*
    545      * Needs to seek, more validation, possible zero filling of the space in between.
    546      */
    547     else
    548     {
    549         AssertMsgReturn((uint64_t)off <= pPush->cbExpected,
    550                         ("off=%#RX64 cbExpected=%#RX64", (uint64_t)off, pPush->cbExpected),
    551                         VERR_SEEK);
    552         AssertMsgReturn(cbToWrite <= pPush->cbExpected - (uint64_t)off,
    553                         ("off=%#RX64 + cbToWrite=%#zx = %#RX64; cbExpected=%RX64\n",
    554                          (uint64_t)off, cbToWrite, (uint64_t)off + cbToWrite, pPush->cbExpected),
    555                         VERR_DISK_FULL);
    556 
    557         /* Zero fill seek gap if necessary. */
    558         if ((uint64_t)off > pPush->cbCurrent)
    559         {
    560             if (pPush->offCurrent == pPush->cbCurrent)
    561                 rc = VINF_SUCCESS;
    562             else
    563             {
    564                 AssertReturn(pParent->hVfsFile != NIL_RTVFSFILE, VERR_NOT_A_FILE);
    565                 rc = RTVfsFileSeek(pParent->hVfsFile, pPush->offData + pPush->cbCurrent, RTFILE_SEEK_BEGIN, NULL);
    566                 if (RT_SUCCESS(rc))
    567                     pPush->offCurrent = pPush->cbCurrent;
    568             }
    569 
    570             if (RT_SUCCESS(rc))
    571             {
    572                 uint64_t cbToZero = (uint64_t)off - pPush->cbCurrent;
    573                 rc = RTVfsIoStrmZeroFill(pParent->hVfsIos, cbToZero);
    574                 if (RT_SUCCESS(rc))
    575                 {
    576                     pPush->offCurrent  += cbToZero;
    577                     pParent->cbWritten += cbToZero;
    578                 }
    579             }
    580         }
    581         /* Seek backwards to the desired position. */
    582         else
    583         {
    584             AssertReturn(pParent->hVfsFile != NIL_RTVFSFILE, VERR_NOT_A_FILE);
    585             rc = RTVfsFileSeek(pParent->hVfsFile, pPush->offData + (uint64_t)off, RTFILE_SEEK_BEGIN, NULL);
    586             if (RT_SUCCESS(rc))
    587                 pPush->offCurrent = (uint64_t)off;
    588         }
    589 
    590         /* Do the write. */
    591         if (RT_SUCCESS(rc))
    592         {
    593             rc = RTVfsIoStrmWrite(pParent->hVfsIos, pvToWrite, cbToWrite, fBlocking, &cbWritten);
    594             if (RT_SUCCESS(rc))
    595             {
    596                 pPush->offCurrent += cbWritten;
    597                 if (pPush->offCurrent > pPush->cbCurrent)
    598                 {
    599                     pParent->cbWritten = pPush->offCurrent - pPush->cbCurrent;
    600                     pPush->cbCurrent   = pPush->offCurrent;
    601                 }
    602             }
     548            if (pcbWritten)
     549                *pcbWritten = cbWritten;
    603550        }
    604551    }
     
    607554     * Fatal errors get down here, non-fatal ones returns earlier.
    608555     */
    609     if (pcbWritten)
    610         *pcbWritten = cbWritten;
    611556    if (RT_SUCCESS(rc))
    612557        return VINF_SUCCESS;
     
    711656    int rc = pParent->rcFatal;
    712657    AssertRCReturn(rc, rc);
     658    Assert(pPush->offCurrent <= pPush->cbCurrent);
    713659
    714660    /*
    715661     * Calculate the new file offset.
    716662     */
    717     uint64_t offNew;
     663    RTFOFF offNewSigned;
    718664    switch (uMethod)
    719665    {
    720666        case RTFILE_SEEK_BEGIN:
    721             AssertReturn(offSeek >= 0, VERR_NEGATIVE_SEEK);
    722             offNew = (uint64_t)offSeek;
     667            offNewSigned = offSeek;
    723668            break;
    724 
    725669        case RTFILE_SEEK_CURRENT:
    726             if (offSeek >= 0)
    727             {
    728                 offNew = (uint64_t)offSeek + pPush->offCurrent;
    729                 AssertReturn(offNew >= pPush->offCurrent, VERR_SEEK);
    730             }
    731             else if ((uint64_t)-offSeek <= pPush->offCurrent)
    732                 offNew = 0;
    733             else
    734                 offNew = pPush->offCurrent + offSeek;
     670            offNewSigned = pPush->offCurrent + offSeek;
    735671            break;
    736 
    737672        case RTFILE_SEEK_END:
    738             if (offSeek >= 0)
    739             {
    740                 offNew = (uint64_t)offSeek + pPush->cbCurrent;
    741                 AssertReturn(offNew >= pPush->cbCurrent, VERR_SEEK);
    742             }
    743             else if ((uint64_t)-offSeek <= pPush->cbCurrent)
    744                 offNew = 0;
    745             else
    746                 offNew = pPush->cbCurrent + offSeek;
     673            offNewSigned = pPush->cbCurrent + offSeek;
    747674            break;
    748 
    749675        default:
    750             AssertFailedReturn(VERR_INTERNAL_ERROR_5);
     676            AssertFailedReturn(VERR_INVALID_PARAMETER);
    751677    }
    752678
     
    754680     * Check the new file offset against expectations.
    755681     */
     682    AssertMsgReturn(offNewSigned >= 0, ("offNewSigned=%RTfoff\n", offNewSigned), VERR_NEGATIVE_SEEK);
     683
     684    uint64_t offNew = (uint64_t)offNewSigned;
    756685    AssertMsgReturn(offNew <= pPush->cbExpected, ("offNew=%#RX64 cbExpected=%#Rx64\n", offNew, pPush->cbExpected), VERR_SEEK);
    757686
     
    783712    }
    784713    /*
    785      * Just change the file positions.
     714     * Just change the file position to somewhere we've already written.
    786715     */
    787716    else
     
    793722        pPush->offCurrent = offNew;
    794723    }
     724    Assert(pPush->offCurrent <= pPush->cbCurrent);
    795725
    796726    *poffActual = pPush->offCurrent;
     
    911841     * content at pPush->offHdr and we only need to update the size.
    912842     */
    913     if (pPush->cbExpected == UINT64_MAX)
     843    if (pPush->fOpenEnded)
    914844    {
    915845        rc = rtZipTarFssWriter_FormatOffset(pThis->aHdrs[0].Common.size, pPush->cbCurrent);
     
    18501780     * Create an I/O stream object for the caller to use.
    18511781     */
     1782    RTFOFF const offHdr = RTVfsIoStrmTell(pThis->hVfsIos);
     1783    AssertReturn(offHdr >= 0, (int)offHdr);
     1784
    18521785    PRTZIPTARFSSTREAMWRITERPUSH pPush;
    18531786    RTVFSIOSTREAM hVfsIos;
     
    18711804    pPush->pParent      = NULL;
    18721805    pPush->cbExpected   = cbFile;
    1873     pPush->offHdr       = RTVfsIoStrmTell(pThis->hVfsIos);
     1806    pPush->offHdr       = (uint64_t)offHdr;
    18741807    pPush->offData      = 0;
    18751808    pPush->offCurrent   = 0;
    18761809    pPush->cbCurrent    = 0;
    18771810    pPush->ObjInfo      = ObjInfo;
     1811    pPush->fOpenEnded   = cbFile == UINT64_MAX;
    18781812
    18791813    /*
     
    18831817    if (RT_SUCCESS(rc))
    18841818    {
    1885         rc = RTVfsIoStrmWrite(pThis->hVfsIos, pThis->aHdrs, pThis->cHdrs * sizeof(pThis->aHdrs[0]), true /*fBlocking*/, NULL);
     1819        size_t cbHdrs = pThis->cHdrs * sizeof(pThis->aHdrs[0]);
     1820        rc = RTVfsIoStrmWrite(pThis->hVfsIos, pThis->aHdrs, cbHdrs, true /*fBlocking*/, NULL);
    18861821        if (RT_SUCCESS(rc))
    18871822        {
    1888             pThis->cbWritten += pThis->cHdrs * sizeof(pThis->aHdrs[0]);
     1823            pThis->cbWritten += cbHdrs;
    18891824
    18901825            /*
    18911826             * Complete the object and return.
    18921827             */
    1893             pPush->offData = RTVfsIoStrmTell(pThis->hVfsIos);
     1828            pPush->offData = pPush->offHdr + cbHdrs;
     1829            if (cbFile == UINT64_MAX)
     1830                pPush->cbExpected = (uint64_t)(RTFOFF_MAX - _4K) - pPush->offData;
    18941831            pPush->pParent = pThis;
    18951832            pThis->pPush   = pPush;
Note: See TracChangeset for help on using the changeset viewer.

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