VirtualBox

Changeset 67503 in vbox for trunk/src


Ignore:
Timestamp:
Jun 20, 2017 1:10:56 PM (8 years ago)
Author:
vboxsync
Message:

IPRT: More ISO maker code (import related).

File:
1 edited

Legend:

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

    r67502 r67503  
    127127    uint32_t                idPrimaryVol;
    128128
     129    /** Set if we've already seen a joliet volume descriptor. */
     130    bool                    fSeenJoliet;
     131
    129132    /** Sector buffer for volume descriptors and such. */
    130133    union
     
    157160/** Import ISO contains more than one el torito descriptor. */
    158161#define VERR_ISOMK_IMPORT_MULTIPLE_EL_TORITO_DESCS      (-24909)
     162/** Import ISO contains more than one joliet volume descriptor. */
     163#define VERR_ISOMK_IMPORT_MULTIPLE_JOLIET_VOL_DESCS     (-24908)
    159164/** Import ISO starts with supplementary volume descriptor before any
    160165 * primary ones. */
    161166#define VERR_ISOMK_IMPORT_SUPPLEMENTARY_BEFORE_PRIMARY  (-24909)
     167/** Import ISO contains an unsupported primary volume descriptor version. */
     168#define VERR_IOSMK_IMPORT_PRIMARY_VOL_DESC_VER          (-24909)
    162169/** Import ISO contains a bad primary volume descriptor. */
    163170#define VERR_ISOMK_IMPORT_BAD_PRIMARY_VOL_DESC          (-24910)
     171/** Import ISO contains an unsupported supplementary volume descriptor
     172 *  version. */
     173#define VERR_IOSMK_IMPORT_SUP_VOL_DESC_VER              (-24909)
     174/** Import ISO contains a bad supplementary volume descriptor. */
     175#define VERR_ISOMK_IMPORT_BAD_SUP_VOL_DESC              (-24910)
    164176/** Import ISO uses a logical block size other than 2KB. */
    165177#define VERR_ISOMK_IMPORT_LOGICAL_BLOCK_SIZE_NOT_2KB    (-24911)
     
    168180/** Import ISO uses invalid volume sequence number. */
    169181#define VERR_ISOMK_IMPORT_INVALID_VOLUMNE_SEQ_NO        (-24913)
     182/** Import ISO has different volume space sizes of primary and supplementary
     183 * volume descriptors. */
     184#define VERR_ISOMK_IMPORT_VOLUME_SPACE_SIZE_MISMATCH    (-24913)
     185/** Import ISO has different volume set sizes of primary and supplementary
     186 * volume descriptors. */
     187#define VERR_ISOMK_IMPORT_VOLUME_IN_SET_MISMATCH        (-24913)
    170188/** Import ISO contains a bad root directory record. */
    171189#define VERR_ISOMK_IMPORT_BAD_ROOT_DIR_REC              (-24914)
     
    368386     * Work our way thru all the directory records.
    369387     */
     388    Log3(("rtFsIsoImportProcessIso9660TreeWorker: Starting at @%#RX64 LB %#zx\n", off - cbChunk, cbChunk));
    370389    while (cbChunk > 0)
    371390    {
     
    380399            pDirRec = (PCISO9660DIRREC)memmove(&pThis->abBuf[ISO9660_SECTOR_SIZE - cbChunk], pDirRec, cbChunk);
    381400
     401            Assert(!(off & (ISO9660_SECTOR_SIZE - 1)));
    382402            uint32_t cbToRead = RT_MIN(cbDir, sizeof(pThis->abBuf) - ISO9660_SECTOR_SIZE);
    383403            rc = RTVfsFileReadAt(pThis->hSrcFile, off, &pThis->abBuf[ISO9660_SECTOR_SIZE], cbToRead, NULL);
     
    385405                return rtFsIsoImpError(pThis, rc, "Error reading %#RX32 bytes at %#RX64 (dir): %Rrc", off, cbToRead);
    386406
     407            Log3(("rtFsIsoImportProcessIso9660TreeWorker: Read %#zx more bytes @%#RX64, now got @%#RX64 LB %#zx\n",
     408                  cbToRead, off, off - cbChunk, cbChunk + cbToRead));
    387409            off     += cbToRead;
    388410            cbDir   -= cbToRead;
     
    401423                if (   cbChunk <= UINT8_MAX
    402424                    && cbDir == 0)
     425                {
     426                    Log3(("rtFsIsoImportProcessIso9660TreeWorker: cbDirRec=0 --> Restart loop\n"));
    403427                    continue;
     428                }
     429                Log3(("rtFsIsoImportProcessIso9660TreeWorker: cbDirRec=0 --> jumped to @%#RX64 LB %#zx\n", off - cbChunk, cbChunk));
    404430            }
     431            /* ASSUMES we're working in multiples of sectors! */
     432            else if (cbDir == 0)
     433                break;
    405434            else
    406435            {
     436                Assert(!(off & (ISO9660_SECTOR_SIZE - 1)));
    407437                uint32_t cbToRead = RT_MIN(cbDir, sizeof(pThis->abBuf));
    408438                rc = RTVfsFileReadAt(pThis->hSrcFile, off, pThis->abBuf, cbToRead, NULL);
     
    410440                    return rtFsIsoImpError(pThis, rc, "Error reading %#RX32 bytes at %#RX64 (dir): %Rrc", off, cbToRead);
    411441
     442                Log3(("rtFsIsoImportProcessIso9660TreeWorker: cbDirRec=0 --> Read %#zx more bytes @%#RX64, now got @%#RX64 LB %#zx\n",
     443                      cbToRead, off, off - cbChunk, cbChunk + cbToRead));
    412444                off     += cbToRead;
    413445                cbDir   -= cbToRead;
     
    421453         * likely to get error with subsequent record too.
    422454         */
    423         Log3(("pDirRec=%p @%#010RX64 cb=%#04x ff=%#04x off=%#010RX32 cb=%#010RX32 id=%.*Rhxs\n", pDirRec, off - cbChunk, pDirRec->cbDirRec, pDirRec->fFileFlags,
    424               ISO9660_GET_ENDIAN(&pDirRec->offExtent), ISO9660_GET_ENDIAN(&pDirRec->cbData), pDirRec->bFileIdLength, pDirRec->achFileId));
     455        uint8_t const         cbSys = pDirRec->cbDirRec - RT_UOFFSETOF(ISO9660DIRREC, achFileId)
     456                                    - pDirRec->bFileIdLength - !(pDirRec->bFileIdLength & 1);
     457        uint8_t const * const pbSys = (uint8_t const *)&pDirRec->achFileId[pDirRec->bFileIdLength + !(pDirRec->bFileIdLength & 1)];
     458        Log3(("pDirRec=%p @%#010RX64 cb=%#04x ff=%#04x off=%#010RX32 cb=%#010RX32 cbSys=%#x id=%.*Rhxs\n",
     459              pDirRec, off - cbChunk, pDirRec->cbDirRec, pDirRec->fFileFlags, ISO9660_GET_ENDIAN(&pDirRec->offExtent),
     460              ISO9660_GET_ENDIAN(&pDirRec->cbData), cbSys, pDirRec->bFileIdLength, pDirRec->achFileId));
    425461        rc = rtFsIsoImportValidateDirRec(pThis, pDirRec, cbChunk);
    426462        if (RT_FAILURE(rc))
     
    460496                    pThis->szNameBuf[cchName - offName] = '\0';
    461497            }
     498            Log3(("  name='%s'\n", pThis->szNameBuf));
    462499
    463500            /** @todo rock ridge. */
    464 
     501            if (cbSys > 0)
     502            {
     503                RT_NOREF(pbSys);
     504            }
    465505            /*
    466506             * Add the object and enter it into the namespace.
     
    553593     * Make sure we've got a root in the namespace.
    554594     */
    555     uint32_t idxDir = RTFsIsoMakerGetObjIdxForPath(pThis->hIsoMaker, RTFSISOMAKER_NAMESPACE_ISO_9660, "/");
     595    uint32_t idxDir = RTFsIsoMakerGetObjIdxForPath(pThis->hIsoMaker,
     596                                                   !fUnicode ? RTFSISOMAKER_NAMESPACE_ISO_9660 : RTFSISOMAKER_NAMESPACE_JOLIET,
     597                                                    "/");
    556598    if (idxDir == UINT32_MAX)
    557599    {
    558600        idxDir = RTFSISOMAKER_CFG_IDX_ROOT;
    559         int rc = RTFsIsoMakerObjSetPath(pThis->hIsoMaker, RTFSISOMAKER_CFG_IDX_ROOT, RTFSISOMAKER_NAMESPACE_ISO_9660, "/");
     601        int rc = RTFsIsoMakerObjSetPath(pThis->hIsoMaker, RTFSISOMAKER_CFG_IDX_ROOT,
     602                                        !fUnicode ? RTFSISOMAKER_NAMESPACE_ISO_9660 : RTFSISOMAKER_NAMESPACE_JOLIET, "/");
    560603        if (RT_FAILURE(rc))
    561604            return rtFsIsoImpError(pThis, rc, "RTFsIsoMakerObjSetPath failed on root dir: %Rrc", rc);
     
    665708     */
    666709    if (pVolDesc->bFileStructureVersion != ISO9660_FILE_STRUCTURE_VERSION)
    667         return rtFsIsoImpError(pThis, VERR_VFS_UNSUPPORTED_FORMAT,
     710        return rtFsIsoImpError(pThis, VERR_IOSMK_IMPORT_PRIMARY_VOL_DESC_VER,
    668711                               "Unsupported file structure version: %#x", pVolDesc->bFileStructureVersion);
    669712
     
    730773
    731774
    732 static int rtFsIsoImportProcessSupplementaryDesc(PRTFSISOMKIMPORTER pThis, PISO9660SUPVOLDESC pSup)
    733 {
    734     RT_NOREF(pThis, pSup);
     775static int rtFsIsoImportProcessSupplementaryDesc(PRTFSISOMKIMPORTER pThis, PISO9660SUPVOLDESC pVolDesc)
     776{
     777    /*
     778     * Validate dual fields first.
     779     */
     780    if (pVolDesc->bFileStructureVersion != ISO9660_FILE_STRUCTURE_VERSION)
     781        return rtFsIsoImpError(pThis, VERR_IOSMK_IMPORT_SUP_VOL_DESC_VER,
     782                               "Unsupported file structure version: %#x", pVolDesc->bFileStructureVersion);
     783
     784    if (RT_LE2H_U16(pVolDesc->cbLogicalBlock.le) != RT_BE2H_U16(pVolDesc->cbLogicalBlock.be))
     785        return rtFsIsoImpError(pThis, VERR_ISOMK_IMPORT_BAD_SUP_VOL_DESC,
     786                               "Mismatching logical block size: {%#RX16,%#RX16}",
     787                               RT_BE2H_U16(pVolDesc->cbLogicalBlock.be), RT_LE2H_U16(pVolDesc->cbLogicalBlock.le));
     788    if (RT_LE2H_U32(pVolDesc->VolumeSpaceSize.le) != RT_BE2H_U32(pVolDesc->VolumeSpaceSize.be))
     789        return rtFsIsoImpError(pThis, VERR_ISOMK_IMPORT_BAD_SUP_VOL_DESC,
     790                               "Mismatching volume space size: {%#RX32,%#RX32}",
     791                               RT_BE2H_U32(pVolDesc->VolumeSpaceSize.be), RT_LE2H_U32(pVolDesc->VolumeSpaceSize.le));
     792    if (RT_LE2H_U16(pVolDesc->cVolumesInSet.le) != RT_BE2H_U16(pVolDesc->cVolumesInSet.be))
     793        return rtFsIsoImpError(pThis, VERR_ISOMK_IMPORT_BAD_SUP_VOL_DESC,
     794                               "Mismatching volumes in set: {%#RX16,%#RX16}",
     795                               RT_BE2H_U16(pVolDesc->cVolumesInSet.be), RT_LE2H_U16(pVolDesc->cVolumesInSet.le));
     796    if (RT_LE2H_U16(pVolDesc->VolumeSeqNo.le) != RT_BE2H_U16(pVolDesc->VolumeSeqNo.be))
     797        return rtFsIsoImpError(pThis, VERR_ISOMK_IMPORT_BAD_SUP_VOL_DESC,
     798                               "Mismatching volume sequence no.: {%#RX16,%#RX16}",
     799                               RT_BE2H_U16(pVolDesc->VolumeSeqNo.be), RT_LE2H_U16(pVolDesc->VolumeSeqNo.le));
     800    if (RT_LE2H_U32(pVolDesc->cbPathTable.le) != RT_BE2H_U32(pVolDesc->cbPathTable.be))
     801        return rtFsIsoImpError(pThis, VERR_ISOMK_IMPORT_BAD_SUP_VOL_DESC,
     802                               "Mismatching path table size: {%#RX32,%#RX32}",
     803                               RT_BE2H_U32(pVolDesc->cbPathTable.be), RT_LE2H_U32(pVolDesc->cbPathTable.le));
     804
     805    /*
     806     * Validate field values against our expectations.
     807     */
     808    if (ISO9660_GET_ENDIAN(&pVolDesc->cbLogicalBlock) != ISO9660_SECTOR_SIZE)
     809        return rtFsIsoImpError(pThis, VERR_ISOMK_IMPORT_LOGICAL_BLOCK_SIZE_NOT_2KB,
     810                               "Unsupported block size: %#x", ISO9660_GET_ENDIAN(&pVolDesc->cbLogicalBlock));
     811
     812    if (ISO9660_GET_ENDIAN(&pVolDesc->cVolumesInSet) != pThis->cVolumesInSet)
     813        return rtFsIsoImpError(pThis, VERR_ISOMK_IMPORT_VOLUME_IN_SET_MISMATCH, "Volumes in set: %#x, expected %#x",
     814                               ISO9660_GET_ENDIAN(&pVolDesc->cVolumesInSet), pThis->cVolumesInSet);
     815
     816    if (ISO9660_GET_ENDIAN(&pVolDesc->VolumeSeqNo) != pThis->idPrimaryVol)
     817        return rtFsIsoImpError(pThis, VERR_ISOMK_IMPORT_INVALID_VOLUMNE_SEQ_NO,
     818                               "Unexpected volume sequence number: %#x (expected %#x)",
     819                               ISO9660_GET_ENDIAN(&pVolDesc->VolumeSeqNo), pThis->idPrimaryVol);
     820
     821    if (ISO9660_GET_ENDIAN(&pVolDesc->VolumeSpaceSize) != pThis->cBlocksInPrimaryVolumeSpace)
     822        return rtFsIsoImpError(pThis, VERR_ISOMK_IMPORT_INVALID_VOLUMNE_SEQ_NO,
     823                               "Volume space size differs between primary and supplementary descriptors: %#x, primary %#x",
     824                               ISO9660_GET_ENDIAN(&pVolDesc->VolumeSpaceSize), pThis->cBlocksInPrimaryVolumeSpace);
     825
     826    /*
     827     * Validate the root directory record.
     828     */
     829    int rc = rtFsIsoImportValidateRootDirRec(pThis, &pVolDesc->RootDir.DirRec);
     830    if (RT_FAILURE(rc))
     831        return rc;
     832
     833    /*
     834     * Is this a joliet descriptor? Ignore if not.
     835     */
     836    uint8_t uJolietLevel = 0;
     837    if (   pVolDesc->abEscapeSequences[0] == ISO9660_JOLIET_ESC_SEQ_0
     838        && pVolDesc->abEscapeSequences[1] == ISO9660_JOLIET_ESC_SEQ_1)
     839        switch (pVolDesc->abEscapeSequences[2])
     840        {
     841            case ISO9660_JOLIET_ESC_SEQ_2_LEVEL_1: uJolietLevel = 1; break;
     842            case ISO9660_JOLIET_ESC_SEQ_2_LEVEL_2: uJolietLevel = 2; break;
     843            case ISO9660_JOLIET_ESC_SEQ_2_LEVEL_3: uJolietLevel = 3; break;
     844            default: Log(("rtFsIsoImportProcessSupplementaryDesc: last joliet escape sequence byte doesn't match: %#x\n",
     845                          pVolDesc->abEscapeSequences[2]));
     846        }
     847    if (uJolietLevel == 0)
     848        return VINF_SUCCESS;
     849
     850    /*
     851     * Only one joliet descriptor.
     852     */
     853    if (pThis->fSeenJoliet)
     854        return rtFsIsoImpError(pThis, VERR_ISOMK_IMPORT_MULTIPLE_JOLIET_VOL_DESCS,
     855                               "More than one Joliet volume descriptor is not supported");
     856    pThis->fSeenJoliet = true;
     857
     858    /*
     859     * Process the directory tree.
     860     */
     861    if (!(pThis->fFlags & RTFSISOMK_IMPORT_F_NO_JOLIET))
     862        return rtFsIsoImportProcessIso9660Tree(pThis, ISO9660_GET_ENDIAN(&pVolDesc->RootDir.DirRec.offExtent),
     863                                               ISO9660_GET_ENDIAN(&pVolDesc->RootDir.DirRec.cbData), true /*fUnicode*/);
    735864    return VINF_SUCCESS;
    736865}
     
    790919        pThis->idxSrcFile       = UINT32_MAX;
    791920        //pThis->Block2FileRoot = NULL;
     921        //pThis->cBlocksInPrimaryVolumeSpace = 0;
     922        //pThis->cbPrimaryVolumeSpace = 0
     923        //pThis->cVolumesInSet  = 0;
     924        //pThis->idPrimaryVol   = 0;
     925        //pThis->fSeenJoliet    = false;
    792926
    793927        /*
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