VirtualBox

Changeset 67595 in vbox for trunk/src/VBox/Runtime/common


Ignore:
Timestamp:
Jun 24, 2017 11:28:35 AM (7 years ago)
Author:
vboxsync
Message:

IPRT: More ISO maker code (import + multi-extent related).

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

Legend:

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

    r67570 r67595  
    650650    else
    651651    {
    652 
    653652        return VERR_NOT_IMPLEMENTED; /** @todo multi-extent stuff . */
    654653    }
  • trunk/src/VBox/Runtime/common/fs/isomaker.cpp

    r67549 r67595  
    6464
    6565/** The sector size. */
    66 #define RTFSISOMAKER_SECTOR_SIZE            _2K
     66#define RTFSISOMAKER_SECTOR_SIZE                _2K
    6767/** The sector offset mask. */
    68 #define RTFSISOMAKER_SECTOR_OFFSET_MASK     (_2K - 1)
     68#define RTFSISOMAKER_SECTOR_OFFSET_MASK         (_2K - 1)
    6969/** Maximum number of objects. */
    70 #define RTFSISOMAKER_MAX_OBJECTS            _16M
     70#define RTFSISOMAKER_MAX_OBJECTS                _16M
    7171/** Maximum number of objects per directory. */
    72 #define RTFSISOMAKER_MAX_OBJECTS_PER_DIR    _256K /**< @todo check limit */
     72#define RTFSISOMAKER_MAX_OBJECTS_PER_DIR        _256K /**< @todo check limit */
     73
     74/** Number of bytes to store per dir record when using multiple extents. */
     75#define RTFSISOMAKER_MAX_ISO9660_EXTENT_SIZE    UINT32_C(0xfffff800)
    7376
    7477/** UTF-8 name buffer.  */
    75 #define RTFSISOMAKER_MAX_NAME_BUF           768
     78#define RTFSISOMAKER_MAX_NAME_BUF               768
    7679
    7780/** TRANS.TBL left padding length.
    7881 * We keep the amount of padding low to avoid wasing memory when generating
    7982 * these long obsolete files. */
    80 #define RTFSISOMAKER_TRANS_TBL_LEFT_PAD     12
     83#define RTFSISOMAKER_TRANS_TBL_LEFT_PAD         12
    8184
    8285/** Tests if @a a_ch is in the set of d-characters. */
     
    227230     * This is set when the image is being finalized. */
    228231    uint16_t                cbDirRec;
    229     /** Same as cbDirRec but with end of sector zero padding added. */
    230     uint16_t                cbDirRecWithZeroPad;
     232    /** Number of directory records needed to cover the entire file size.  */
     233    uint16_t                cDirRecs;
     234    /** The total directory record size (cbDirRec * cDirRecs), including end of
     235     *  sector zero padding. */
     236    uint16_t                cbDirRecTotal;
    231237
    232238    /** The number of bytes the name requires in the directory record. */
     
    19111917
    19121918    /*
     1919     * If this is a file, check the size against the ISO level.
     1920     * This ASSUMES that only files which size we already know will be 4GB+ sized.
     1921     */
     1922    if (   (pNamespace->fNamespace & RTFSISOMAKER_NAMESPACE_ISO_9660)
     1923        && pNamespace->uLevel < 3
     1924        && pObj->enmType == RTFSISOMAKEROBJTYPE_FILE)
     1925    {
     1926        PRTFSISOMAKERFILE pFile = (PRTFSISOMAKERFILE)pObj;
     1927        if (pFile->cbData >= _4G)
     1928            return VERR_ISOMK_FILE_TOO_BIG_REQ_ISO_LEVEL_3;
     1929    }
     1930
     1931    /*
    19131932     * If the object is already named, unset that name before continuing.
    19141933     */
     
    19882007            pName->offDirRec            = UINT32_MAX;
    19892008            pName->cbDirRec             = 0;
    1990             pName->cbDirRecWithZeroPad  = 0;
     2009            pName->cDirRecs             = 1;
     2010            pName->cbDirRecTotal        = 0;
    19912011
    19922012            memcpy(pName->szName, szName, cchName);
     
    38613881    size_t cbDirRec  = RT_UOFFSETOF(ISO9660DIRREC, achFileId) + pName->cbNameInDirRec + !(pName->cbNameInDirRec & 1);
    38623882    AssertReturn(cbDirRec <= UINT8_MAX, VERR_FILENAME_TOO_LONG);
    3863     pName->cbDirRecWithZeroPad = pName->cbDirRec = (uint8_t)cbDirRec;
     3883
     3884    pName->cbDirRec = (uint8_t)cbDirRec;
     3885    pName->cDirRecs = 1;
     3886    if (pName->pObj->enmType == RTFSISOMAKEROBJTYPE_FILE)
     3887    {
     3888        PRTFSISOMAKERFILE pFile = (PRTFSISOMAKERFILE)pName->pObj;
     3889        if (pFile->cbData > UINT32_MAX)
     3890            pName->cDirRecs = (pFile->cbData + RTFSISOMAKER_MAX_ISO9660_EXTENT_SIZE - 1) / RTFSISOMAKER_MAX_ISO9660_EXTENT_SIZE;
     3891    }
    38643892
    38653893    /*
     
    38733901    }
    38743902
     3903    pName->cbDirRecTotal = pName->cbDirRec * pName->cDirRecs;
    38753904    return VINF_SUCCESS;
    38763905}
     
    39493978                AssertRCReturn(rc, rc);
    39503979
    3951                 if ((RTFSISOMAKER_SECTOR_SIZE - (offInDir & RTFSISOMAKER_SECTOR_OFFSET_MASK)) < pChild->cbDirRec)
     3980                if ((RTFSISOMAKER_SECTOR_SIZE - (offInDir & RTFSISOMAKER_SECTOR_OFFSET_MASK)) < pChild->cbDirRecTotal)
    39523981                {
    39533982                    Assert(ppChild[-1] == pChild && &ppChild[-1] != pCurDir->papChildren);
    3954                     ppChild[-2]->cbDirRecWithZeroPad += RTFSISOMAKER_SECTOR_SIZE - (offInDir & RTFSISOMAKER_SECTOR_OFFSET_MASK);
    3955                     offInDir = (offInDir | RTFSISOMAKER_SECTOR_OFFSET_MASK) + 1; /* doesn't fit, skip to next sector. */
    3956                     Log4(("rtFsIsoMakerFinalizeDirectoriesInIsoNamespace: zero padding dir rec @%#x: %#x -> %#x; offset %#x -> %#x\n",
    3957                           ppChild[-2]->offDirRec, ppChild[-2]->cbDirRec, ppChild[-2]->cbDirRecWithZeroPad, pChild->offDirRec, offInDir));
    3958                     pChild->offDirRec = offInDir;
     3983                    if (   pChild->cDirRecs == 1
     3984                        || pChild->cDirRecs <= RTFSISOMAKER_SECTOR_SIZE / pChild->cbDirRec)
     3985                    {
     3986                        ppChild[-2]->cbDirRecTotal += RTFSISOMAKER_SECTOR_SIZE - (offInDir & RTFSISOMAKER_SECTOR_OFFSET_MASK);
     3987                        offInDir = (offInDir | RTFSISOMAKER_SECTOR_OFFSET_MASK) + 1; /* doesn't fit, skip to next sector. */
     3988                        Log4(("rtFsIsoMakerFinalizeDirectoriesInIsoNamespace: zero padding dir rec @%#x: %#x -> %#x; offset %#x -> %#x\n",
     3989                              ppChild[-2]->offDirRec, ppChild[-2]->cbDirRec, ppChild[-2]->cbDirRecTotal, pChild->offDirRec, offInDir));
     3990                        pChild->offDirRec = offInDir;
     3991                    }
     3992                    /* else: too complicated and ulikely, so whatever. */
    39593993                }
    39603994
    3961                 offInDir += pChild->cbDirRec;
     3995                offInDir += pChild->cbDirRecTotal;
    39623996                if (pChild->cchTransNm)
    39633997                    cbTransTbl += 2 /* type & space*/
     
    50475081 * Generates ISO-9660 directory record into the specified buffer.
    50485082 *
    5049  * @returns Number of bytes copied into the buffer.
     5083 * The caller must deal with multi-extent copying and end of sector zero
     5084 * padding.
     5085 *
     5086 * @returns Number of bytes copied into the buffer (pName->cbDirRec).
    50505087 * @param   pName       The namespace node.
    50515088 * @param   fUnicode    Set if the name should be translated to big endian
    50525089 *                      UTF-16BE / UCS-2BE, i.e. we're in the joliet namespace.
    5053  * @param   pbBuf       The buffer.  This is at least pName->cbDirRec bytes big.
     5090 * @param   pbBuf       The buffer.  This is at least pName->cbDirRec bytes big
     5091 *                      (i.e. at most 256 bytes).
    50545092 */
    50555093static uint32_t rtFsIsoMakerOutFile_GenerateDirRec(PRTFSISOMAKERNAME pName, bool fUnicode, uint8_t *pbBuf)
     
    51225160    /** @todo rock ridge. */
    51235161
    5124     /*
    5125      * Do end-of-sector zero padding.
    5126      */
    5127     if (pName->cbDirRecWithZeroPad == pName->cbDirRec)
    5128     { /* likely */ }
    5129     else
    5130     {
    5131         Assert(pName->cbDirRecWithZeroPad >= pName->cbDirRec);
    5132         memset((uint8_t *)pDirRec + pName->cbDirRec, 0, pName->cbDirRecWithZeroPad - pName->cbDirRec);
    5133     }
    5134 
    5135     return pName->cbDirRecWithZeroPad;
     5162    return pName->cbDirRec;
     5163}
     5164
     5165
     5166/**
     5167 * Generates ISO-9660 directory records into the specified buffer.
     5168 *
     5169 * @returns Number of bytes copied into the buffer.
     5170 * @param   pName       The namespace node.
     5171 * @param   fUnicode    Set if the name should be translated to big endian
     5172 *                      UTF-16BE / UCS-2BE, i.e. we're in the joliet namespace.
     5173 * @param   pbBuf       The buffer.  This is at least pName->cbDirRecTotal bytes
     5174 *                      big.
     5175 */
     5176static uint32_t rtFsIsoMakerOutFile_GenerateDirRecDirect(PRTFSISOMAKERNAME pName, bool fUnicode, uint8_t *pbBuf)
     5177{
     5178    /*
     5179     * Normally there is just a single record without any zero padding.
     5180     */
     5181    uint32_t cbReturn = rtFsIsoMakerOutFile_GenerateDirRec(pName, fUnicode, pbBuf);
     5182    if (RT_LIKELY(pName->cbDirRecTotal == cbReturn))
     5183        return cbReturn;
     5184    Assert(cbReturn < pName->cbDirRecTotal);
     5185
     5186    /*
     5187     * Deal with multiple records.
     5188     */
     5189    if (pName->cDirRecs > 1)
     5190    {
     5191        Assert(pName->pObj->enmType == RTFSISOMAKEROBJTYPE_FILE);
     5192        PRTFSISOMAKERFILE pFile = (PRTFSISOMAKERFILE)pName->pObj;
     5193
     5194        /* Set max size and duplicate the first directory record cDirRecs - 1 times. */
     5195        uint32_t const cbOne   = cbReturn;
     5196        PISO9660DIRREC pDirRec = (PISO9660DIRREC)pbBuf;
     5197        pDirRec->cbData.be   = RT_H2BE_U32_C(RTFSISOMAKER_MAX_ISO9660_EXTENT_SIZE);
     5198        pDirRec->cbData.le   = RT_H2LE_U32_C(RTFSISOMAKER_MAX_ISO9660_EXTENT_SIZE);
     5199        pDirRec->fFileFlags |= ISO9660_FILE_FLAGS_MULTI_EXTENT;
     5200
     5201        PISO9660DIRREC pCurDirRec = pDirRec;
     5202        uint32_t       offExtent  = (uint32_t)(pFile->offData / RTFSISOMAKER_SECTOR_SIZE);
     5203        Assert(offExtent == ISO9660_GET_ENDIAN(&pDirRec->offExtent));
     5204        for (uint32_t iDirRec = 1; iDirRec < pName->cDirRecs; iDirRec++)
     5205        {
     5206            pCurDirRec = (PISO9660DIRREC)memcpy(&pbBuf[cbReturn], pDirRec, cbOne);
     5207
     5208            offExtent += RTFSISOMAKER_MAX_ISO9660_EXTENT_SIZE / RTFSISOMAKER_SECTOR_SIZE;
     5209            pCurDirRec->offExtent.le = RT_H2LE_U32(offExtent);
     5210
     5211            cbReturn += cbOne;
     5212            iDirRec++;
     5213        }
     5214        Assert(cbReturn <= pName->cbDirRecTotal);
     5215
     5216        /* Adjust the size in the final record. */
     5217        uint32_t cbDataLast = (uint32_t)(pFile->cbData % RTFSISOMAKER_MAX_ISO9660_EXTENT_SIZE);
     5218        pCurDirRec->cbData.be   = RT_H2BE_U32(cbDataLast);
     5219        pCurDirRec->cbData.le   = RT_H2LE_U32(cbDataLast);
     5220        pCurDirRec->fFileFlags &= ~ISO9660_FILE_FLAGS_MULTI_EXTENT;
     5221    }
     5222
     5223    /*
     5224     * Do end of sector zero padding.
     5225     */
     5226    if (cbReturn < pName->cbDirRecTotal)
     5227        memset(&pbBuf[cbReturn], 0, (uint32_t)pName->cbDirRecTotal - cbReturn);
     5228
     5229    return pName->cbDirRecTotal;
    51365230}
    51375231
     
    51525246                                                          uint32_t off, uint8_t *pbBuf, size_t cbBuf)
    51535247{
    5154     uint8_t abTmpBuf[256 * 2];
    5155     Assert(off < pName->cbDirRecWithZeroPad);
    5156     Assert(pName->cbDirRecWithZeroPad <= sizeof(abTmpBuf));
    5157 
    5158     size_t cbToCopy = rtFsIsoMakerOutFile_GenerateDirRec(pName, fUnicode, pbBuf);
    5159     cbToCopy = RT_MIN(cbBuf, cbToCopy - off);
    5160     memcpy(pbBuf, &abTmpBuf[off], cbToCopy);
    5161     return (uint32_t)cbToCopy;
     5248    Assert(off < pName->cbDirRecTotal);
     5249
     5250    /*
     5251     * This is reasonably simple when there is only one directory record and
     5252     * without any padding.
     5253     */
     5254    uint8_t abTmpBuf[256];
     5255    Assert(pName->cbDirRec <= sizeof(abTmpBuf));
     5256    uint32_t const cbOne = rtFsIsoMakerOutFile_GenerateDirRec(pName, fUnicode, pbBuf);
     5257    Assert(cbOne == pName->cbDirRec);
     5258    if (cbOne == pName->cbDirRecTotal)
     5259    {
     5260        uint32_t cbToCopy = RT_MIN((uint32_t)cbBuf, cbOne - off);
     5261        memcpy(pbBuf, &abTmpBuf[off], cbToCopy);
     5262        return cbToCopy;
     5263    }
     5264    Assert(cbOne < pName->cbDirRecTotal);
     5265
     5266    /*
     5267     * Single record and zero padding?
     5268     */
     5269    uint32_t cbCopied = 0;
     5270    if (pName->cDirRecs == 1)
     5271    {
     5272        /* Anything from the record to copy? */
     5273        if (off < cbOne)
     5274        {
     5275            cbCopied = RT_MIN((uint32_t)cbBuf, cbOne - off);
     5276            memcpy(pbBuf, &abTmpBuf[off], cbCopied);
     5277            pbBuf += cbCopied;
     5278            cbBuf -= cbCopied;
     5279            off   += cbCopied;
     5280        }
     5281
     5282        /* Anything from the zero padding? */
     5283        if (off >= cbOne && cbBuf > 0)
     5284        {
     5285            uint32_t cbToZero = RT_MIN((uint32_t)cbBuf, (uint32_t)pName->cbDirRecTotal - off);
     5286            memset(pbBuf, 0, cbToZero);
     5287            cbCopied += cbToZero;
     5288        }
     5289    }
     5290    /*
     5291     * Multi-extent stuff.  Need to modify the cbData member as we copy.
     5292     */
     5293    else
     5294    {
     5295        Assert(pName->pObj->enmType == RTFSISOMAKEROBJTYPE_FILE);
     5296        PRTFSISOMAKERFILE pFile = (PRTFSISOMAKERFILE)pName->pObj;
     5297
     5298        /* Max out the size. */
     5299        PISO9660DIRREC pDirRec = (PISO9660DIRREC)abTmpBuf;
     5300        pDirRec->cbData.be   = RT_H2BE_U32_C(RTFSISOMAKER_MAX_ISO9660_EXTENT_SIZE);
     5301        pDirRec->cbData.le   = RT_H2LE_U32_C(RTFSISOMAKER_MAX_ISO9660_EXTENT_SIZE);
     5302        pDirRec->fFileFlags |= ISO9660_FILE_FLAGS_MULTI_EXTENT;
     5303
     5304        /* Copy directory records. */
     5305        uint32_t offDirRec = pName->offDirRec;
     5306        uint32_t offExtent = pFile->offData / RTFSISOMAKER_SECTOR_SIZE;
     5307        for (uint32_t i = 0; i < pName->cDirRecs && cbBuf > 0; i++)
     5308        {
     5309            uint32_t const offInRec = off - offDirRec;
     5310            if (offInRec < cbOne)
     5311            {
     5312                /* Update the record. */
     5313                pDirRec->offExtent.be = RT_H2BE_U32(offExtent);
     5314                pDirRec->offExtent.le = RT_H2LE_U32(offExtent);
     5315                if (i + 1 == pName->cDirRecs)
     5316                {
     5317                    uint32_t cbDataLast = pFile->cbData % RTFSISOMAKER_MAX_ISO9660_EXTENT_SIZE;
     5318                    pDirRec->cbData.be   = RT_H2BE_U32(cbDataLast);
     5319                    pDirRec->cbData.le   = RT_H2LE_U32(cbDataLast);
     5320                    pDirRec->fFileFlags &= ~ISO9660_FILE_FLAGS_MULTI_EXTENT;
     5321                }
     5322
     5323                /* Copy chunk. */
     5324                uint32_t cbToCopy = RT_MIN((uint32_t)cbBuf, cbOne - offInRec);
     5325                memcpy(pbBuf, &abTmpBuf[offInRec], cbToCopy);
     5326                cbCopied += cbToCopy;
     5327                pbBuf    += cbToCopy;
     5328                cbBuf    -= cbToCopy;
     5329                off      += cbToCopy;
     5330            }
     5331
     5332            offDirRec += cbOne;
     5333            offExtent += RTFSISOMAKER_MAX_ISO9660_EXTENT_SIZE / RTFSISOMAKER_SECTOR_SIZE;
     5334        }
     5335
     5336        /* Anything from the zero padding? */
     5337        if (off >= offDirRec && cbBuf > 0)
     5338        {
     5339            uint32_t cbToZero = RT_MIN((uint32_t)cbBuf, (uint32_t)pName->cbDirRecTotal - offDirRec);
     5340            memset(pbBuf, 0, cbToZero);
     5341            cbCopied += cbToZero;
     5342        }
     5343    }
     5344
     5345    return cbCopied;
    51625346}
    51635347
     
    51855369
    51865370    /* Generate a regular directory record. */
    5187     uint8_t abTmpBuf[256 * 2];
    5188     Assert(off < pName->cbDirRecWithZeroPad);
     5371    uint8_t abTmpBuf[256];
     5372    Assert(off < pName->cbDirRec);
    51895373    size_t cbToCopy = rtFsIsoMakerOutFile_GenerateDirRec(pName, fUnicode, abTmpBuf);
    5190     Assert(cbToCopy == pName->cbDirRecWithZeroPad);
    5191     cbToCopy = pName->cbDirRec;
     5374    Assert(cbToCopy == pName->cbDirRec);
    51925375
    51935376    /* Replace the filename part. */
     
    53215504            {
    53225505                PRTFSISOMAKERNAME pChild = pDir->papChildren[iChild];
    5323                 if ((offInDir - pChild->offDirRec) < pChild->cbDirRecWithZeroPad)
     5506                if ((offInDir - pChild->offDirRec) < pChild->cbDirRecTotal)
    53245507                    break;
    53255508                iChild++;
     
    53375520            uint32_t cbCopied;
    53385521            if (   offInDir == pChild->offDirRec
    5339                 && cbBuf    >= pChild->cbDirRecWithZeroPad)
    5340                 cbCopied = rtFsIsoMakerOutFile_GenerateDirRec(pChild, fUnicode, pbBuf);
     5522                && cbBuf    >= pChild->cbDirRecTotal)
     5523                cbCopied = rtFsIsoMakerOutFile_GenerateDirRecDirect(pChild, fUnicode, pbBuf);
    53415524            else
    53425525                cbCopied = rtFsIsoMakerOutFile_GenerateDirRecPartial(pChild, fUnicode, offInDir - pChild->offDirRec, pbBuf, cbBuf);
  • trunk/src/VBox/Runtime/common/fs/isomakercmd.cpp

    r67549 r67595  
    446446    { "--application-id",               'A',                                                RTGETOPT_REQ_STRING  },
    447447    DD("-biblio",                       RTFSISOMAKERCMD_OPT_BIBLIOGRAPHIC_FILE_ID,          RTGETOPT_REQ_STRING  ),
    448     DD("-copyright",                     RTFSISOMAKERCMD_OPT_COPYRIGHT_FILE_ID,             RTGETOPT_REQ_STRING  ),
     448    DD("-copyright",                    RTFSISOMAKERCMD_OPT_COPYRIGHT_FILE_ID,              RTGETOPT_REQ_STRING  ),
    449449    DD("-publisher",                    'P',                                                RTGETOPT_REQ_STRING  ),
    450450    { "--preparer",                     'p',                                                RTGETOPT_REQ_STRING  },
     
    14041404    pOpts->cItemsAdded += Results.cAddedFiles;
    14051405    pOpts->cItemsAdded += Results.cAddedDirs;
    1406     pOpts->cItemsAdded += Results.cBootCatEntries;
     1406    pOpts->cItemsAdded += Results.cBootCatEntries != UINT32_MAX ? Results.cBootCatEntries : 0;
    14071407    pOpts->cItemsAdded += Results.cbSysArea != 0 ? 1 : 0;
    14081408
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