VirtualBox

Changeset 67860 in vbox


Ignore:
Timestamp:
Jul 7, 2017 4:08:30 PM (8 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
116816
Message:

isomaker: Some fixes for bugs found when testing different buffer read sizes and read ordering.

Location:
trunk/src/VBox/Runtime/common/fs
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Runtime/common/fs/isomaker.cpp

    r67850 r67860  
    53435343            pER->cchDescription = sizeof(ISO9660_RRIP_DESC) - 1;
    53445344            pER->cchSource      = sizeof(ISO9660_RRIP_SRC)  - 1;
     5345            pER->bVersion       = ISO9660_RRIP_VER;
    53455346            memcpy(&pER->achPayload[0], RT_STR_TUPLE(ISO9660_RRIP_ID));
    5346             memcpy(&pER->achPayload[sizeof(ISO9660_RRIP_ID)], RT_STR_TUPLE(ISO9660_RRIP_DESC));
    5347             memcpy(&pER->achPayload[sizeof(ISO9660_RRIP_ID) + sizeof(ISO9660_RRIP_DESC)], RT_STR_TUPLE(ISO9660_RRIP_SRC));
     5347            memcpy(&pER->achPayload[sizeof(ISO9660_RRIP_ID) - 1], RT_STR_TUPLE(ISO9660_RRIP_DESC));
     5348            memcpy(&pER->achPayload[sizeof(ISO9660_RRIP_ID) - 1 + sizeof(ISO9660_RRIP_DESC) - 1], RT_STR_TUPLE(ISO9660_RRIP_SRC));
    53485349            pbSys += ISO9660_RRIP_ER_LEN;
    53495350            cbSys -= ISO9660_RRIP_ER_LEN;
     
    63326333    uint8_t abTmpBuf[256];
    63336334    Assert(pName->cbDirRec <= sizeof(abTmpBuf));
    6334     uint32_t const cbOne = rtFsIsoMakerOutFile_GenerateDirRec(pName, fUnicode, pbBuf, pFinalizedDirs);
     6335    uint32_t const cbOne = rtFsIsoMakerOutFile_GenerateDirRec(pName, fUnicode, abTmpBuf, pFinalizedDirs);
    63356336    Assert(cbOne == pName->cbDirRec);
    63366337    if (cbOne == pName->cbDirRecTotal)
     
    64616462        uint8_t cbSysUse  = pDirRec->cbDirRec - offSysUse;
    64626463        if (cbSysUse > 0)
    6463             memmove(&pDirRec->achFileId[1], &pbBuf[offSysUse], cbSysUse);
     6464            memmove(&pDirRec->achFileId[1], &abTmpBuf[offSysUse], cbSysUse);
    64646465        pDirRec->bFileIdLength = 1;
    64656466        cbToCopy = RT_UOFFSETOF(ISO9660DIRREC, achFileId) + 1 + cbSysUse;
     
    65196520        pDir = RTListGetFirst(&pFinalizedDirs->FinalizedDirs, RTFSISOMAKERNAMEDIR, FinalizedEntry);
    65206521        AssertReturnStmt(pDir, *pbBuf = 0xff, 1);
     6522        offInDir64 = offUnsigned - pDir->offDir;
    65216523    }
    65226524    /* Seek backwards: */
  • trunk/src/VBox/Runtime/common/fs/isomakercmd.cpp

    r67605 r67860  
    3333#include <iprt/fsisomaker.h>
    3434
     35#include <iprt/asm.h>
    3536#include <iprt/assert.h>
    3637#include <iprt/buildconfig.h>
     
    9394    RTFSISOMAKERCMD_OPT_OUTPUT_BUFFER_SIZE,
    9495    RTFSISOMAKERCMD_OPT_RANDOM_OUTPUT_BUFFER_SIZE,
     96    RTFSISOMAKERCMD_OPT_RANDOM_ORDER_VERIFICATION,
    9597    RTFSISOMAKERCMD_OPT_NAME_SETUP,
    9698    RTFSISOMAKERCMD_OPT_NO_JOLIET,
     
    312314     * when this is enabled. */
    313315    bool                fRandomOutputReadBufferSize;
     316    /** Do output verification, but do it in random order if non-zero.  The
     317     * values gives the block size to use. */
     318    uint32_t            cbRandomOrderVerifciationBlock;
    314319
    315320    /** @name Processing of inputs
     
    414419    { "--output-buffer-size",           RTFSISOMAKERCMD_OPT_OUTPUT_BUFFER_SIZE,             RTGETOPT_REQ_UINT32  },
    415420    { "--random-output-buffer-size",    RTFSISOMAKERCMD_OPT_RANDOM_OUTPUT_BUFFER_SIZE,      RTGETOPT_REQ_NOTHING },
     421    { "--random-order-verficiation",    RTFSISOMAKERCMD_OPT_RANDOM_ORDER_VERIFICATION,      RTGETOPT_REQ_UINT32 },
    416422    { "--name-setup",                   RTFSISOMAKERCMD_OPT_NAME_SETUP,                     RTGETOPT_REQ_STRING  },
    417423    { "--no-joliet",                    RTFSISOMAKERCMD_OPT_NO_JOLIET,                      RTGETOPT_REQ_NOTHING },
     
    731737}
    732738
     739static int rtFsIsoMakerCmdVerifyImageInRandomOrder(PRTFSISOMAKERCMDOPTS pOpts, RTVFSFILE hVfsSrcFile, RTVFSFILE hVfsDstFile, uint64_t cbImage)
     740{
     741    /*
     742     * Figure the buffer (block) size and allocate a bitmap for noting down blocks we've covered.
     743     */
     744    int      rc;
     745    size_t   cbBuf     = RT_MAX(pOpts->cbRandomOrderVerifciationBlock, 1);
     746    uint64_t cBlocks64 = (cbImage + cbBuf - 1) / cbBuf;
     747    if (cBlocks64 > _512M)
     748        return rtFsIsoMakerCmdErrorRc(pOpts, VERR_OUT_OF_RANGE,
     749                                      "verification block count too high: cBlocks=%#RX64 (cbBuf=%#zx), max 512M", cBlocks64, cbBuf);
     750    uint32_t cBlocks   = (uint32_t)cBlocks64;
     751    uint32_t cbBitmap  = (cBlocks + 63) / 8;
     752    if (cbBitmap > _64M)
     753        return rtFsIsoMakerCmdErrorRc(pOpts, VERR_OUT_OF_RANGE,
     754                                      "verification bitmap too big: cbBitmap=%#RX32 (cbBuf=%#zx), max 64MB", cbBitmap, cbBuf);
     755    void    *pvSrcBuf  = RTMemTmpAlloc(cbBuf);
     756    void    *pvDstBuf  = RTMemTmpAlloc(cbBuf);
     757    void    *pvBitmap  = RTMemTmpAllocZ(cbBitmap);
     758    if (pvSrcBuf && pvDstBuf && pvBitmap)
     759    {
     760        /* Must set the unused bits in the top qword. */
     761        for (uint32_t i = RT_ALIGN_32(cBlocks, 64) - 1; i >= cBlocks; i--)
     762            ASMBitSet(pvBitmap, i);
     763
     764        /*
     765         * Do the verification.
     766         */
     767        rtFsIsoMakerPrintf(pOpts, "Verifying image in random order using %zu (%#zx) byte blocks: %#zx in blocks\n",
     768                           cbBuf, cbBuf, cBlocks);
     769
     770        rc = VINF_SUCCESS;
     771        uint64_t cLeft = cBlocks;
     772        while (cLeft-- > 0)
     773        {
     774            /*
     775             * Figure out which block to check next.
     776             */
     777            uint32_t iBlock = RTRandU32Ex(0, cBlocks - 1);
     778            if (!ASMBitTestAndSet(pvBitmap, iBlock))
     779                Assert(iBlock < (int32_t)cBlocks);
     780            else
     781            {
     782                /* try 32 other random numbers. */
     783                bool     fBitSet;
     784                unsigned cTries = 0;
     785                do
     786                {
     787                    iBlock = RTRandU32Ex(0, cBlocks - 1);
     788                    fBitSet = ASMBitTestAndSet(pvBitmap, iBlock);
     789                } while (fBitSet && ++cTries < 32);
     790                if (fBitSet)
     791                {
     792                    /* Look for the next clear bit after it (with wrap around). */
     793                    int iHit = ASMBitNextClear(pvBitmap, cBlocks, iBlock);
     794                    Assert(iHit < (int32_t)cBlocks);
     795                    if (iHit < 0)
     796                    {
     797                        iHit = ASMBitNextClear(pvBitmap, iBlock, 0);
     798                        Assert(iHit < (int32_t)cBlocks);
     799                    }
     800                    if (iHit >= 0)
     801                    {
     802                        fBitSet  = ASMBitTestAndSet(pvBitmap, iHit);
     803                        if (!fBitSet)
     804                            iBlock = iHit;
     805                        else
     806                        {
     807                            rc = rtFsIsoMakerCmdErrorRc(pOpts, VERR_INTERNAL_ERROR_3,
     808                                                        "Bitmap weirdness: iHit=%#x iBlock=%#x cBlocks=%#x",
     809                                                        iHit, iBlock, cBlocks);
     810                            break;
     811                        }
     812                    }
     813                    else
     814                    {
     815                        rc = rtFsIsoMakerCmdErrorRc(pOpts, VERR_INTERNAL_ERROR_2, "Bitmap weirdness: iBlock=%#x cBlocks=%#x",
     816                                                    iBlock, cBlocks);
     817                        break;
     818                    }
     819                }
     820            }
     821            Assert(ASMBitTest(pvBitmap, iBlock));
     822
     823            /*
     824             * Figure out how much and where to read (last block fun).
     825             */
     826            uint64_t offBlock = iBlock * (uint64_t)cbBuf;
     827            size_t   cbToRead = cbBuf;
     828            if (iBlock + 1 < cBlocks)
     829            { /* likely */ }
     830            else if (cbToRead > cbImage - offBlock)
     831                cbToRead = (size_t)(cbImage - offBlock);
     832            Assert(offBlock + cbToRead <= cbImage);
     833
     834            /*
     835             * Read the blocks.
     836             */
     837            //RTPrintf("Reading block #%#x at %#RX64\n", iBlock, offBlock);
     838            rc = RTVfsFileReadAt(hVfsDstFile, offBlock, pvDstBuf, cbToRead, NULL);
     839            if (RT_SUCCESS(rc))
     840            {
     841                memset(pvSrcBuf, 0xdd, cbBuf);
     842                rc = RTVfsFileReadAt(hVfsSrcFile, offBlock, pvSrcBuf, cbToRead, NULL);
     843                if (RT_SUCCESS(rc))
     844                {
     845                    if (memcmp(pvDstBuf, pvSrcBuf, cbToRead) == 0)
     846                        continue;
     847                    rc = rtFsIsoMakerCmdErrorRc(pOpts, VERR_MISMATCH,
     848                                                "Block #%#x differs! offBlock=%#RX64 cbToRead=%#zu\n"
     849                                                "Virtual ISO (source):\n%.*Rhxd\nWritten ISO (destination):\n%.*Rhxd",
     850                                                iBlock, offBlock, cbToRead, cbToRead, pvSrcBuf, cbToRead, pvDstBuf);
     851                }
     852                else
     853                    rc = rtFsIsoMakerCmdErrorRc(pOpts, rc,
     854                                                "Error reading %#zx bytes source (virtual ISO) block #%#x at %#RX64: %Rrc",
     855                                                cbToRead, iBlock, offBlock, rc);
     856            }
     857            else
     858                rc = rtFsIsoMakerCmdErrorRc(pOpts, rc,
     859                                            "Error reading %#zx bytes destination (written ISO) block #%#x at %#RX64: %Rrc",
     860                                            cbToRead, iBlock, offBlock, rc);
     861            break;
     862        }
     863
     864        if (RT_SUCCESS(rc))
     865            rtFsIsoMakerPrintf(pOpts, "Written image verified fine!\n");
     866    }
     867    else if (!pvSrcBuf || !pvDstBuf)
     868        rc = rtFsIsoMakerCmdErrorRc(pOpts, VERR_NO_TMP_MEMORY, "RTMemTmpAlloc(%#zx) failed", cbBuf);
     869    else
     870        rc = rtFsIsoMakerCmdErrorRc(pOpts, VERR_NO_TMP_MEMORY, "RTMemTmpAlloc(%#zx) failed", cbBuf);
     871    RTMemTmpFree(pvBitmap);
     872    RTMemTmpFree(pvDstBuf);
     873    RTMemTmpFree(pvSrcBuf);
     874    return rc;
     875}
     876
     877
     878/**
     879 * Writes the image to file, no checking, no special buffering.
     880 *
     881 * @returns IPRT status code.
     882 * @param   pOpts               The ISO maker command instance.
     883 * @param   hVfsSrcFile         The source file from the ISO maker.
     884 */
     885static int rtFsIsoMakerCmdWriteImageRandomBufferSize(PRTFSISOMAKERCMDOPTS pOpts, RTVFSFILE hVfsSrcFile, RTVFSFILE hVfsDstFile,
     886                                                     uint64_t cbImage, void **ppvBuf)
     887{
     888    /*
     889     * Copy the virtual image bits to the destination file.
     890     */
     891    void    *pvBuf    = *ppvBuf;
     892    uint32_t cbMaxBuf = pOpts->cbOutputReadBuffer > 0 ? pOpts->cbOutputReadBuffer : _64K;
     893    uint64_t offImage = 0;
     894    while (offImage < cbImage)
     895    {
     896        /* Figure out how much to copy this time. */
     897        size_t cbToCopy = RTRandU32Ex(1, cbMaxBuf - 1);
     898        if (offImage + cbToCopy < cbImage)
     899        { /* likely */ }
     900        else
     901            cbToCopy = (size_t)(cbImage - offImage);
     902        RTMemFree(pvBuf);
     903        *ppvBuf = pvBuf = RTMemTmpAlloc(cbToCopy);
     904        if (pvBuf)
     905        {
     906            /* Do the copying. */
     907            int rc = RTVfsFileReadAt(hVfsSrcFile, offImage, pvBuf, cbToCopy, NULL);
     908            if (RT_SUCCESS(rc))
     909            {
     910                rc = RTVfsFileWriteAt(hVfsDstFile, offImage, pvBuf, cbToCopy, NULL);
     911                if (RT_SUCCESS(rc))
     912                    offImage += cbToCopy;
     913                else
     914                    return rtFsIsoMakerCmdErrorRc(pOpts, rc, "Error %Rrc writing %#zx bytes at offset %#RX64 to '%s'",
     915                                                  rc, cbToCopy, offImage, pOpts->pszOutFile);
     916            }
     917            else
     918                return rtFsIsoMakerCmdErrorRc(pOpts, rc, "Error %Rrc read %#zx bytes at offset %#RX64", rc, cbToCopy, offImage);
     919        }
     920        else
     921            return rtFsIsoMakerCmdErrorRc(pOpts, VERR_NO_TMP_MEMORY, "RTMemTmpAlloc(%#zx) failed", cbToCopy);
     922    }
     923    return VINF_SUCCESS;
     924}
     925
     926
     927/**
     928 * Writes the image to file, no checking, no special buffering.
     929 *
     930 * @returns IPRT status code.
     931 * @param   pOpts               The ISO maker command instance.
     932 * @param   hVfsSrcFile         The source file from the ISO maker.
     933 */
     934static int rtFsIsoMakerCmdWriteImageSimple(PRTFSISOMAKERCMDOPTS pOpts, RTVFSFILE hVfsSrcFile, RTVFSFILE hVfsDstFile,
     935                                           uint64_t cbImage, void *pvBuf, size_t cbBuf)
     936{
     937    /*
     938     * Copy the virtual image bits to the destination file.
     939     */
     940    uint64_t offImage = 0;
     941    while (offImage < cbImage)
     942    {
     943        /* Figure out how much to copy this time. */
     944        size_t cbToCopy = cbBuf;
     945        if (offImage + cbToCopy < cbImage)
     946        { /* likely */ }
     947        else
     948            cbToCopy = (size_t)(cbImage - offImage);
     949
     950        /* Do the copying. */
     951        int rc = RTVfsFileReadAt(hVfsSrcFile, offImage, pvBuf, cbToCopy, NULL);
     952        if (RT_SUCCESS(rc))
     953        {
     954            rc = RTVfsFileWriteAt(hVfsDstFile, offImage, pvBuf, cbToCopy, NULL);
     955            if (RT_SUCCESS(rc))
     956                offImage += cbToCopy;
     957            else
     958                return rtFsIsoMakerCmdErrorRc(pOpts, rc, "Error %Rrc writing %#zx bytes at offset %#RX64 to '%s'",
     959                                              rc, cbToCopy, offImage, pOpts->pszOutFile);
     960        }
     961        else
     962            return rtFsIsoMakerCmdErrorRc(pOpts, rc, "Error %Rrc read %#zx bytes at offset %#RX64", rc, cbToCopy, offImage);
     963    }
     964    return VINF_SUCCESS;
     965}
     966
    733967
    734968/**
     
    760994            uint32_t        offError;
    761995            RTERRINFOSTATIC ErrInfo;
    762             rc = RTVfsChainOpenFile(pOpts->pszOutFile, RTFILE_O_WRITE | RTFILE_O_CREATE_REPLACE | RTFILE_O_DENY_WRITE,
     996            rc = RTVfsChainOpenFile(pOpts->pszOutFile, RTFILE_O_READWRITE | RTFILE_O_CREATE_REPLACE | RTFILE_O_DENY_WRITE,
    763997                                    &hVfsDstFile, &offError, RTErrInfoInitStatic(&ErrInfo));
    764998            if (RT_SUCCESS(rc))
    765999            {
    7661000                /*
    767                  * Copy the virtual image bits to the destination file.
     1001                 * Apply the desired writing method.
    7681002                 */
    769                 uint64_t offImage = 0;
    770                 while (offImage < cbImage)
    771                 {
    772                     /* Figure out how much to copy this time. */
    773                     size_t cbToCopy = cbBuf;
    774                     if (pOpts->fRandomOutputReadBufferSize)
    775                         cbToCopy = RTRandU32Ex(1, (uint32_t)cbBuf - 1);
    776                     if (offImage + cbToCopy < cbImage)
    777                     { /* likely */ }
    778                     else
    779                         cbToCopy = (size_t)(cbImage - offImage);
    780 
    781                     /* Do the copying. */
    782                     rc = RTVfsFileReadAt(hVfsSrcFile, offImage, pvBuf, cbToCopy, NULL);
    783                     if (RT_SUCCESS(rc))
    784                     {
    785                         rc = RTVfsFileWriteAt(hVfsDstFile, offImage, pvBuf, cbToCopy, NULL);
    786                         if (RT_SUCCESS(rc))
    787                             offImage += cbToCopy;
    788                         else
    789                         {
    790                             rc = rtFsIsoMakerCmdErrorRc(pOpts, rc, "Error %Rrc writing %#zx bytes at offset %#RX64 to '%s'",
    791                                                         rc, cbToCopy, offImage, pOpts->pszOutFile);
    792                             break;
    793                         }
    794                     }
    795                     else
    796                     {
    797                         rc = rtFsIsoMakerCmdErrorRc(pOpts, rc, "Error %Rrc read %#zx bytes at offset %#RX64", rc, cbToCopy, offImage);
    798                         break;
    799                     }
    800                 }
     1003                if (!pOpts->fRandomOutputReadBufferSize)
     1004                    rc = rtFsIsoMakerCmdWriteImageRandomBufferSize(pOpts, hVfsSrcFile, hVfsDstFile, cbImage, &pvBuf);
     1005                else
     1006                    rc = rtFsIsoMakerCmdWriteImageSimple(pOpts, hVfsSrcFile, hVfsDstFile, cbImage, pvBuf, cbBuf);
     1007                RTMemTmpFree(pvBuf);
     1008
     1009                if (RT_SUCCESS(rc) && pOpts->cbRandomOrderVerifciationBlock > 0)
     1010                    rc = rtFsIsoMakerCmdVerifyImageInRandomOrder(pOpts, hVfsSrcFile, hVfsDstFile, cbImage);
    8011011
    8021012                /*
     
    8131023            }
    8141024            else
     1025            {
     1026                RTMemTmpFree(pvBuf);
    8151027                rc = rtFsIsoMakerCmdChainError(pOpts, "RTVfsChainOpenFile", pOpts->pszOutFile, rc, offError, &ErrInfo.Core);
    816 
    817             RTMemTmpFree(pvBuf);
     1028            }
    8181029        }
    8191030        else
    820             rc = rtFsIsoMakerCmdErrorRc(pOpts, rc, "RTMemTmpAlloc(%zu) failed: %Rrc", pOpts->cbOutputReadBuffer, rc);
     1031            rc = rtFsIsoMakerCmdErrorRc(pOpts, VERR_NO_TMP_MEMORY, "RTMemTmpAlloc(%zu) failed", cbBuf);
    8211032    }
    8221033    else
     
    14091620
    14101621    pOpts->cItemsAdded += Results.cAddedFiles;
     1622    pOpts->cItemsAdded += Results.cAddedSymlinks;
    14111623    pOpts->cItemsAdded += Results.cAddedDirs;
    14121624    pOpts->cItemsAdded += Results.cBootCatEntries != UINT32_MAX ? Results.cBootCatEntries : 0;
     
    14181630    rtFsIsoMakerPrintf(pOpts, "    cbAddedDataBlocks:   %'14RU64 bytes\n", Results.cbAddedDataBlocks);
    14191631    rtFsIsoMakerPrintf(pOpts, "    cAddedFiles:         %'14RU32\n", Results.cAddedFiles);
     1632    rtFsIsoMakerPrintf(pOpts, "    cAddedSymlinks:      %'14RU32\n", Results.cAddedSymlinks);
    14201633    if (Results.cBootCatEntries == UINT32_MAX)
    14211634        rtFsIsoMakerPrintf(pOpts, "    cBootCatEntries:               none\n");
     
    20782291                break;
    20792292
     2293            case RTFSISOMAKERCMD_OPT_OUTPUT_BUFFER_SIZE:                /* --output-buffer-size {cb} */
     2294                pOpts->cbOutputReadBuffer = ValueUnion.u32;
     2295                break;
     2296
     2297            case RTFSISOMAKERCMD_OPT_RANDOM_OUTPUT_BUFFER_SIZE:         /* --random-output-buffer-size */
     2298                pOpts->fRandomOutputReadBufferSize = true;
     2299                break;
     2300
     2301            case RTFSISOMAKERCMD_OPT_RANDOM_ORDER_VERIFICATION:         /* --random-order-verficiation {cb} */
     2302                pOpts->cbRandomOrderVerifciationBlock = ValueUnion.u32;
     2303                break;
     2304
    20802305            case RTFSISOMAKERCMD_OPT_IMPORT_ISO:
    20812306                rc = rtFsIsoMakerCmdOptImportIso(pOpts, ValueUnion.psz);
  • trunk/src/VBox/Runtime/common/fs/isomakerimport.cpp

    r67850 r67860  
    24962496    pResults->cbAddedDataBlocks = 0;
    24972497    pResults->cAddedFiles       = 0;
     2498    pResults->cAddedSymlinks    = 0;
    24982499    pResults->cBootCatEntries   = UINT32_MAX;
    24992500    pResults->cbSysArea         = 0;
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