VirtualBox

Changeset 67568 in vbox for trunk/src/VBox/Runtime


Ignore:
Timestamp:
Jun 22, 2017 4:24:56 PM (7 years ago)
Author:
vboxsync
Message:

iso9660vfs.cpp: Implemented support for multi-extent files (really large files).

File:
1 edited

Legend:

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

    r67559 r67568  
    417417 *          properly initialized elsewhere.
    418418 *
     419 * @returns IRPT status code.  Either VINF_SUCCESS or VERR_NO_MEMORY, the latter
     420 *          only if @a cDirRecs is above 1.
    419421 * @param   pCore           The structure to initialize.
    420422 * @param   pDirRec         The primary directory record.
     
    424426 * @param   pVol            The volume.
    425427 */
    426 static void rtFsIso9660Core_InitFromDirRec(PRTFSISO9660CORE pCore, PCISO9660DIRREC pDirRec, uint32_t cDirRecs,
    427                                            uint64_t offDirRec, uint32_t uVersion, PRTFSISO9660VOL pVol)
     428static int rtFsIso9660Core_InitFromDirRec(PRTFSISO9660CORE pCore, PCISO9660DIRREC pDirRec, uint32_t cDirRecs,
     429                                          uint64_t offDirRec, uint32_t uVersion, PRTFSISO9660VOL pVol)
    428430{
    429431    Assert(cDirRecs == 1); RT_NOREF(cDirRecs);
     
    448450    pCore->AccessTime = pCore->ModificationTime;
    449451    pCore->ChangeTime = pCore->ModificationTime;
     452
     453    /*
     454     * Deal with multiple extents.
     455     */
     456    if (RT_LIKELY(cDirRecs == 1))
     457    { /* done */ }
     458    else
     459    {
     460        PRTFSISO9660EXTENT pCurExtent = &pCore->FirstExtent;
     461        while (cDirRecs > 1)
     462        {
     463            offDirRec += pDirRec->cbDirRec;
     464            pDirRec = (PCISO9660DIRREC)((uintptr_t)pDirRec + pDirRec->cbDirRec);
     465            if (pDirRec->cbDirRec != 0)
     466            {
     467                uint64_t offDisk = ISO9660_GET_ENDIAN(&pDirRec->offExtent) * (uint64_t)pVol->cbBlock;
     468                uint32_t cbExtent  = ISO9660_GET_ENDIAN(&pDirRec->cbData);
     469                pCore->cbObject += cbExtent;
     470
     471                if (pCurExtent->offDisk + pCurExtent->cbExtent == offDisk)
     472                    pCurExtent->cbExtent += cbExtent;
     473                else
     474                {
     475                    void *pvNew = RTMemRealloc(pCore->paExtents, pCore->cExtents * sizeof(pCore->paExtents[0]));
     476                    if (pvNew)
     477                        pCore->paExtents = (PRTFSISO9660EXTENT)pvNew;
     478                    else
     479                    {
     480                        RTMemFree(pCore->paExtents);
     481                        return VERR_NO_MEMORY;
     482                    }
     483                    pCurExtent = &pCore->paExtents[pCore->cExtents - 1];
     484                    pCurExtent->cbExtent = cbExtent;
     485                    pCurExtent->offDisk  = offDisk;
     486                    pCore->cExtents++;
     487                }
     488                cDirRecs--;
     489            }
     490            else
     491            {
     492                size_t cbSkip = (offDirRec + pVol->cbSector) & ~(pVol->cbSector - 1U);
     493                offDirRec += cbSkip;
     494                pDirRec = (PCISO9660DIRREC)((uintptr_t)pDirRec + cbSkip);
     495            }
     496        }
     497    }
     498    return VINF_SUCCESS;
    450499}
    451500
     
    836885                 * Initialize it all so rtFsIso9660File_Close doesn't trip up in anyway.
    837886                 */
    838                 rtFsIso9660Core_InitFromDirRec(&pShared->Core, pDirRec, cDirRecs, offDirRec, uVersion, pThis);
    839                 rtFsIso9660DirShrd_AddOpenChild(pParentDir, &pShared->Core);
     887                rc = rtFsIso9660Core_InitFromDirRec(&pShared->Core, pDirRec, cDirRecs, offDirRec, uVersion, pThis);
     888                if (RT_SUCCESS(rc))
     889                    rtFsIso9660DirShrd_AddOpenChild(pParentDir, &pShared->Core);
     890                else
     891                {
     892                    RTMemFree(pShared);
     893                    pShared = NULL;
     894                }
    840895            }
    841896        }
     
    876931    }
    877932    return NULL;
     933}
     934
     935
     936/**
     937 * Checks if @a pNext is an extent of @a pFirst.
     938 *
     939 * @returns true if @a pNext is the next extent, false if not
     940 * @param   pFirst      The directory record describing the first or the
     941 *                      previous extent.
     942 * @param   pNext       The directory record alleged to be the next extent.
     943 */
     944DECLINLINE(bool) rtFsIso9660Dir_IsDirRecNextExtent(PCISO9660DIRREC pFirst, PCISO9660DIRREC pNext)
     945{
     946    if (RT_LIKELY(pNext->bFileIdLength == pFirst->bFileIdLength))
     947    {
     948        if (RT_LIKELY((pNext->fFileFlags | ISO9660_FILE_FLAGS_MULTI_EXTENT) == pFirst->fFileFlags))
     949        {
     950            if (RT_LIKELY(memcmp(pNext->achFileId, pFirst->achFileId, pNext->bFileIdLength) == 0))
     951                return true;
     952        }
     953    }
     954    return false;
    878955}
    879956
     
    10591136        {
    10601137            /* Try match the filename. */
    1061             /** @todo deal with multi-extent filenames, or however that
    1062              *        works... */
    10631138            if (fIsUtf16)
    10641139            {
     
    10861161            *poffDirRec = pThis->Core.FirstExtent.offDisk + offEntryInDir;
    10871162            *ppDirRec   = pDirRec;
    1088             *pcDirRecs  = 1;
    10891163            *pfMode     = pDirRec->fFileFlags & ISO9660_FILE_FLAGS_DIRECTORY ? RTFS_TYPE_DIRECTORY : RTFS_TYPE_FILE;
     1164
     1165            /*
     1166             * Deal with the unlikely scenario of multi extent records.
     1167             */
     1168            if (!(pDirRec->fFileFlags & ISO9660_FILE_FLAGS_MULTI_EXTENT))
     1169                *pcDirRecs = 1;
     1170            else
     1171            {
     1172                offEntryInDir += pDirRec->cbDirRec;
     1173
     1174                uint32_t cDirRecs = 1;
     1175                while (offEntryInDir + RT_UOFFSETOF(ISO9660DIRREC, achFileId) <= cbDir)
     1176                {
     1177                    PCISO9660DIRREC pDirRec2 = (PCISO9660DIRREC)&pThis->pbDir[offEntryInDir];
     1178                    if (pDirRec2->cbDirRec != 0)
     1179                    {
     1180                        Assert(rtFsIso9660Dir_IsDirRecNextExtent(pDirRec, pDirRec2));
     1181                        cDirRecs++;
     1182                        if (!(pDirRec2->fFileFlags & ISO9660_FILE_FLAGS_MULTI_EXTENT))
     1183                            break;
     1184                        offEntryInDir += pDirRec2->cbDirRec;
     1185                    }
     1186                    else
     1187                        offEntryInDir = (offEntryInDir + pThis->Core.pVol->cbSector) & ~(pThis->Core.pVol->cbSector - 1U);
     1188                }
     1189
     1190                *pcDirRecs = cDirRecs;
     1191            }
    10901192            return VINF_SUCCESS;
    10911193        }
     
    14141516        RTFSISO9660CORE TmpObj;
    14151517        RT_ZERO(TmpObj);
    1416         rtFsIso9660Core_InitFromDirRec(&TmpObj, pDirRec, cDirRecs, offDirRec, uVersion, pShared->Core.pVol);
    1417         rc = rtFsIso9660Core_QueryInfo(&TmpObj, pObjInfo, enmAddAttr);
     1518        rc = rtFsIso9660Core_InitFromDirRec(&TmpObj, pDirRec, cDirRecs, offDirRec, uVersion, pShared->Core.pVol);
     1519        if (RT_SUCCESS(rc))
     1520        {
     1521            rc = rtFsIso9660Core_QueryInfo(&TmpObj, pObjInfo, enmAddAttr);
     1522            RTMemFree(TmpObj.paExtents);
     1523        }
    14181524    }
    14191525    return rc;
     
    15611667            RTFSISO9660CORE TmpObj;
    15621668            RT_ZERO(TmpObj);
    1563             rtFsIso9660Core_InitFromDirRec(&TmpObj, pDirRec, 1/*cDirRecs*/, /** @todo multi-extent stuff */
     1669            rtFsIso9660Core_InitFromDirRec(&TmpObj, pDirRec, 1 /* cDirRecs - see below why 1 */,
    15641670                                           pThis->offDir + pShared->Core.FirstExtent.offDisk, uVersion, pShared->Core.pVol);
    15651671            int rc = rtFsIso9660Core_QueryInfo(&TmpObj, &pDirEntry->Info, enmAddAttr);
    15661672
    15671673            /*
    1568              * Update the location and return.
     1674             * Update the directory location and handle multi extent records.
     1675             *
     1676             * Multi extent records only affect the file size and the directory location,
     1677             * so we deal with it here instead of involving * rtFsIso9660Core_InitFromDirRec
     1678             * which would potentially require freeing memory and such.
    15691679             */
    1570             Log3(("rtFsIso9660Dir_ReadDir: offDir=%#07x: %s (rc=%Rrc)\n", pThis->offDir, pDirEntry->szName, rc));
    1571             pThis->offDir += pDirRec->cbDirRec;
     1680            if (!(pDirRec->fFileFlags & ISO9660_FILE_FLAGS_MULTI_EXTENT))
     1681            {
     1682                Log3(("rtFsIso9660Dir_ReadDir: offDir=%#07x: %s (rc=%Rrc)\n", pThis->offDir, pDirEntry->szName, rc));
     1683                pThis->offDir += pDirRec->cbDirRec;
     1684            }
     1685            else
     1686            {
     1687                uint32_t cExtents = 1;
     1688                uint32_t offDir   = pThis->offDir + pDirRec->cbDirRec;
     1689                while (offDir + RT_UOFFSETOF(ISO9660DIRREC, achFileId) <= pShared->cbDir)
     1690                {
     1691                    PCISO9660DIRREC pDirRec2 = (PCISO9660DIRREC)&pShared->pbDir[offDir];
     1692                    if (pDirRec2->cbDirRec != 0)
     1693                    {
     1694                        pDirEntry->Info.cbObject += ISO9660_GET_ENDIAN(&pDirRec2->cbData);
     1695                        offDir += pDirRec2->cbDirRec;
     1696                        cExtents++;
     1697                        if (!(pDirRec2->fFileFlags & ISO9660_FILE_FLAGS_MULTI_EXTENT))
     1698                            break;
     1699                    }
     1700                    else
     1701                        offDir = (offDir + pShared->Core.pVol->cbSector) & ~(pShared->Core.pVol->cbSector - 1U);
     1702                }
     1703                Log3(("rtFsIso9660Dir_ReadDir: offDir=%#07x, %u extents ending at %#07x: %s (rc=%Rrc)\n",
     1704                      pThis->offDir, cExtents, offDir, pDirEntry->szName, rc));
     1705                pThis->offDir = offDir;
     1706            }
     1707
    15721708            return rc;
    15731709        }
     
    17351871 * @param   pParentDir      The parent directory.  This is NULL for the root
    17361872 *                          directory.
    1737  * @param   pDirRec         The directory record.
     1873 * @param   pDirRec         The directory record.  Will access @a cDirRecs
     1874 *                          records.
    17381875 * @param   cDirRecs        Number of directory records if more than one.
    17391876 * @param   offDirRec       The byte offset of the directory record.
    17401877 * @param   ppShared        Where to return the shared directory structure.
    17411878 */
    1742 static int  rtFsIso9660DirShrd_New(PRTFSISO9660VOL pThis, PRTFSISO9660DIRSHRD pParentDir, PCISO9660DIRREC pDirRec,
    1743                                    uint32_t cDirRecs, uint64_t offDirRec, PRTFSISO9660DIRSHRD *ppShared)
     1879static int rtFsIso9660DirShrd_New(PRTFSISO9660VOL pThis, PRTFSISO9660DIRSHRD pParentDir, PCISO9660DIRREC pDirRec,
     1880                                  uint32_t cDirRecs, uint64_t offDirRec, PRTFSISO9660DIRSHRD *ppShared)
    17441881{
    17451882    /*
     
    17501887    if (pShared)
    17511888    {
    1752         rtFsIso9660Core_InitFromDirRec(&pShared->Core, pDirRec, cDirRecs, offDirRec, 0 /*uVersion*/, pThis);
    1753         RTListInit(&pShared->OpenChildren);
    1754         pShared->cbDir              = ISO9660_GET_ENDIAN(&pDirRec->cbData);
    1755         pShared->pbDir              = (uint8_t *)RTMemAllocZ(pShared->cbDir + 256);
    1756         if (pShared->pbDir)
    1757         {
    1758             rc = RTVfsFileReadAt(pThis->hVfsBacking, pShared->Core.FirstExtent.offDisk, pShared->pbDir, pShared->cbDir, NULL);
    1759             if (RT_SUCCESS(rc))
     1889        rc = rtFsIso9660Core_InitFromDirRec(&pShared->Core, pDirRec, cDirRecs, offDirRec, 0 /*uVersion*/, pThis);
     1890        if (RT_SUCCESS(rc))
     1891        {
     1892            RTListInit(&pShared->OpenChildren);
     1893            pShared->cbDir = ISO9660_GET_ENDIAN(&pDirRec->cbData);
     1894            pShared->pbDir = (uint8_t *)RTMemAllocZ(pShared->cbDir + 256);
     1895            if (pShared->pbDir)
    17601896            {
     1897                rc = RTVfsFileReadAt(pThis->hVfsBacking, pShared->Core.FirstExtent.offDisk, pShared->pbDir, pShared->cbDir, NULL);
     1898                if (RT_SUCCESS(rc))
     1899                {
    17611900#ifdef LOG_ENABLED
    1762                 rtFsIso9660DirShrd_LogContent(pShared);
     1901                    rtFsIso9660DirShrd_LogContent(pShared);
    17631902#endif
    17641903
    1765                 /*
    1766                  * Link into parent directory so we can use it to update
    1767                  * our directory entry.
    1768                  */
    1769                 if (pParentDir)
    1770                     rtFsIso9660DirShrd_AddOpenChild(pParentDir, &pShared->Core);
    1771                 *ppShared = pShared;
    1772                 return VINF_SUCCESS;
     1904                    /*
     1905                     * Link into parent directory so we can use it to update
     1906                     * our directory entry.
     1907                     */
     1908                    if (pParentDir)
     1909                        rtFsIso9660DirShrd_AddOpenChild(pParentDir, &pShared->Core);
     1910                    *ppShared = pShared;
     1911                    return VINF_SUCCESS;
     1912                }
    17731913            }
    17741914        }
     1915        RTMemFree(pShared);
    17751916    }
    17761917    *ppShared = NULL;
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