VirtualBox

Ignore:
Timestamp:
May 3, 2017 11:59:50 PM (8 years ago)
Author:
vboxsync
Message:

iso9660: Refactored the code to deal with root directory reference problem where you could release the final volume reference while the root directory was still in use. Bad design inherited from the FAT code (that's next, sigh). Also dealt with sharing on disk data and keeping VFS handle specific data (i.e. the file/dir offset) separate.

File:
1 edited

Legend:

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

    r66762 r66765  
    5757
    5858/** Pointer to a ISO 9660 directory instance. */
    59 typedef struct RTFSISO9660DIR *PRTFSISO9660DIR;
     59typedef struct RTFSISO9660DIRSHRD *PRTFSISO9660DIRSHRD;
    6060
    6161
     
    7878
    7979/**
    80  * ISO 9660 file system object (common part to files and dirs).
    81  */
    82 typedef struct RTFSISO9660OBJ
    83 {
    84     /** The parent directory keeps a list of open objects (RTFSISO9660OBJ). */
     80 * ISO 9660 file system object, shared part.
     81 */
     82typedef struct RTFSISO9660CORE
     83{
     84    /** The parent directory keeps a list of open objects (RTFSISO9660CORE). */
    8585    RTLISTNODE          Entry;
     86    /** Reference counter.   */
     87    uint32_t volatile   cRefs;
    8688    /** The parent directory (not released till all children are close). */
    87     PRTFSISO9660DIR     pParentDir;
     89    PRTFSISO9660DIRSHRD     pParentDir;
    8890    /** The byte offset of the first directory record. */
    8991    uint64_t            offDirRec;
     
    108110    /** Array of additional extents. */
    109111    PRTFSISO9660EXTENT  paExtents;
    110 } RTFSISO9660OBJ;
    111 typedef RTFSISO9660OBJ *PRTFSISO9660OBJ;
    112 
    113 /**
    114  * ISO 9660 file.
    115  */
    116 typedef struct RTFSISO9660FILE
     112} RTFSISO9660CORE;
     113typedef RTFSISO9660CORE *PRTFSISO9660CORE;
     114
     115/**
     116 * ISO 9660 file, shared data.
     117 */
     118typedef struct RTFSISO9660FILESHRD
    117119{
    118120    /** Core ISO9660 object info.  */
    119     RTFSISO9660OBJ      Core;
    120     /** The current file offset. */
    121     uint64_t            offFile;
    122 } RTFSISO9660FILE;
     121    RTFSISO9660CORE     Core;
     122} RTFSISO9660FILESHRD;
    123123/** Pointer to a ISO 9660 file object. */
    124 typedef RTFSISO9660FILE *PRTFSISO9660FILE;
    125 
    126 
    127 /**
    128  * ISO 9660 directory.
     124typedef RTFSISO9660FILESHRD *PRTFSISO9660FILESHRD;
     125
     126
     127/**
     128 * ISO 9660 directory, shared data.
    129129 *
    130130 * We will always read in the whole directory just to keep things really simple.
    131131 */
    132 typedef struct RTFSISO9660DIR
     132typedef struct RTFSISO9660DIRSHRD
    133133{
    134134    /** Core ISO 9660 object info.  */
    135     RTFSISO9660OBJ      Core;
    136     /** The VFS handle for this directory (for reference counting). */
    137     RTVFSDIR            hVfsSelf;
    138     /** Open child objects (RTFSISO9660OBJ). */
     135    RTFSISO9660CORE     Core;
     136    /** Open child objects (RTFSISO9660CORE). */
    139137    RTLISTNODE          OpenChildren;
    140138
     
    143141    /** The size of the directory content (duplicate of Core.cbObject). */
    144142    uint32_t            cbDir;
    145 } RTFSISO9660DIR;
     143} RTFSISO9660DIRSHRD;
    146144/** Pointer to a ISO 9660 directory instance. */
    147 typedef RTFSISO9660DIR *PRTFSISO9660DIR;
    148 
     145typedef RTFSISO9660DIRSHRD *PRTFSISO9660DIRSHRD;
     146
     147
     148/**
     149 * Private data for a VFS file object.
     150 */
     151typedef struct RTFSISO9660FILEOBJ
     152{
     153    /** Pointer to the shared data. */
     154    PRTFSISO9660FILESHRD    pShared;
     155    /** The current file offset. */
     156    uint64_t                offFile;
     157} RTFSISO9660FILEOBJ;
     158typedef RTFSISO9660FILEOBJ *PRTFSISO9660FILEOBJ;
     159
     160/**
     161 * Private data for a VFS directory object.
     162 */
     163typedef struct RTFSISO9660DIROBJ
     164{
     165    /** Pointer to the shared data. */
     166    PRTFSISO9660DIRSHRD     pShared;
     167    /** The current directory offset. */
     168    uint32_t                offDir;
     169} RTFSISO9660DIROBJ;
     170typedef RTFSISO9660DIROBJ *PRTFSISO9660DIROBJ;
    149171
    150172
     
    155177{
    156178    /** Handle to itself. */
    157     RTVFS           hVfsSelf;
     179    RTVFS                   hVfsSelf;
    158180    /** The file, partition, or whatever backing the ISO 9660 volume. */
    159     RTVFSFILE       hVfsBacking;
     181    RTVFSFILE               hVfsBacking;
    160182    /** The size of the backing thingy. */
    161     uint64_t        cbBacking;
     183    uint64_t                cbBacking;
    162184    /** Flags. */
    163     uint32_t        fFlags;
     185    uint32_t                fFlags;
    164186    /** The sector size (in bytes). */
    165     uint32_t        cbSector;
     187    uint32_t                cbSector;
    166188    /** The size of a logical block in bytes. */
    167     uint32_t        cbBlock;
     189    uint32_t                cbBlock;
    168190    /** The primary volume space size in blocks. */
    169     uint32_t        cBlocksInPrimaryVolumeSpace;
     191    uint32_t                cBlocksInPrimaryVolumeSpace;
    170192    /** The primary volume space size in bytes. */
    171     uint64_t        cbPrimaryVolumeSpace;
     193    uint64_t                cbPrimaryVolumeSpace;
    172194    /** The number of volumes in the set. */
    173     uint32_t        cVolumesInSet;
     195    uint32_t                cVolumesInSet;
    174196    /** The primary volume sequence ID. */
    175     uint32_t        idPrimaryVol;
     197    uint32_t                idPrimaryVol;
    176198    /** Set if using UTF16-2 (joliet). */
    177     bool            fIsUtf16;
    178 
    179     /** The root directory handle. */
    180     RTVFSDIR        hVfsRootDir;
    181     /** The root directory instance data. */
    182     PRTFSISO9660DIR pRootDir;
     199    bool                    fIsUtf16;
     200
     201    /** The root directory shared data. */
     202    PRTFSISO9660DIRSHRD     pRootDir;
    183203} RTFSISO9660VOL;
    184204
     
    193213*   Internal Functions                                                                                                           *
    194214*********************************************************************************************************************************/
    195 static void rtFsIso9660Dir_AddOpenChild(PRTFSISO9660DIR pDir, PRTFSISO9660OBJ pChild);
    196 static void rtFsIso9660Dir_RemoveOpenChild(PRTFSISO9660DIR pDir, PRTFSISO9660OBJ pChild);
    197 static int  rtFsIso9660Dir_New(PRTFSISO9660VOL pThis, PRTFSISO9660DIR pParentDir, PCISO9660DIRREC pDirRec, uint32_t cDirRecs,
    198                                uint64_t offDirRec, PRTVFSDIR phVfsDir, PRTFSISO9660DIR *ppDir);
     215static void rtFsIso9660DirShrd_AddOpenChild(PRTFSISO9660DIRSHRD pDir, PRTFSISO9660CORE pChild);
     216static void rtFsIso9660DirShrd_RemoveOpenChild(PRTFSISO9660DIRSHRD pDir, PRTFSISO9660CORE pChild);
     217static int  rtFsIso9660Dir_New(PRTFSISO9660VOL pThis, PRTFSISO9660DIRSHRD pParentDir, PCISO9660DIRREC pDirRec,
     218                               uint32_t cDirRecs, uint64_t offDirRec, PRTVFSDIR phVfsDir);
     219static PRTFSISO9660CORE rtFsIso9660Dir_LookupShared(PRTFSISO9660DIRSHRD pThis, uint64_t offDirRec);
    199220
    200221
     
    229250
    230251/**
    231  * Initialization of a RTFSISO9660OBJ structure from a directory record.
    232  *
    233  * @note    The RTFSISO9660OBJ::pParentDir and RTFSISO9660OBJ::Clusters members are
     252 * Initialization of a RTFSISO9660CORE structure from a directory record.
     253 *
     254 * @note    The RTFSISO9660CORE::pParentDir and RTFSISO9660CORE::Clusters members are
    234255 *          properly initialized elsewhere.
    235256 *
    236  * @param   pObj            The structure to initialize.
     257 * @param   pCore           The structure to initialize.
    237258 * @param   pDirRec         The primary directory record.
    238259 * @param   cDirRecs        Number of directory records.
     
    240261 * @param   pVol            The volume.
    241262 */
    242 static void rtFsIso9660Obj_InitFromDirRec(PRTFSISO9660OBJ pObj, PCISO9660DIRREC pDirRec, uint32_t cDirRecs,
    243                                           uint64_t offDirRec, PRTFSISO9660VOL pVol)
     263static void rtFsIso9660Core_InitFromDirRec(PRTFSISO9660CORE pCore, PCISO9660DIRREC pDirRec, uint32_t cDirRecs,
     264                                           uint64_t offDirRec, PRTFSISO9660VOL pVol)
    244265{
    245266    Assert(cDirRecs == 1); RT_NOREF(cDirRecs);
    246267
    247     RTListInit(&pObj->Entry);
    248     pObj->pParentDir           = NULL;
    249     pObj->pVol                 = pVol;
    250     pObj->offDirRec            = offDirRec;
    251     pObj->fAttrib              = pDirRec->fFileFlags & ISO9660_FILE_FLAGS_DIRECTORY
    252                                ? RTFS_DOS_DIRECTORY | RTFS_TYPE_DIRECTORY : RTFS_TYPE_FILE;
     268    RTListInit(&pCore->Entry);
     269    pCore->cRefs                = 1;
     270    pCore->pParentDir           = NULL;
     271    pCore->pVol                 = pVol;
     272    pCore->offDirRec            = offDirRec;
     273    pCore->fAttrib              = pDirRec->fFileFlags & ISO9660_FILE_FLAGS_DIRECTORY
     274                                ? RTFS_DOS_DIRECTORY | RTFS_TYPE_DIRECTORY : RTFS_TYPE_FILE;
    253275    if (pDirRec->fFileFlags & ISO9660_FILE_FLAGS_HIDDEN)
    254         pObj->fAttrib |= RTFS_DOS_HIDDEN;
    255     pObj->cbObject             = ISO9660_GET_ENDIAN(&pDirRec->cbData);
    256     pObj->cExtents             = 1;
    257     pObj->FirstExtent.cbExtent = pObj->cbObject;
    258     pObj->FirstExtent.offDisk  = ISO9660_GET_ENDIAN(&pDirRec->offExtent) * (uint64_t)pVol->cbBlock;
    259 
    260     rtFsIso9660DateTime2TimeSpec(&pObj->ModificationTime, &pDirRec->RecTime);
    261     pObj->BirthTime  = pObj->ModificationTime;
    262     pObj->AccessTime = pObj->ModificationTime;
    263     pObj->ChangeTime = pObj->ModificationTime;
    264 }
    265 
    266 
    267 
    268 /**
    269  * Worker for rtFsIso9660File_Close and rtFsIso9660Dir_Close that does common work.
    270  *
    271  * @returns IPRT status code.
    272  * @param   pObj            The common object structure.
    273  */
    274 static int rtFsIso9660Obj_Close(PRTFSISO9660OBJ pObj)
    275 {
    276     if (pObj->pParentDir)
    277         rtFsIso9660Dir_RemoveOpenChild(pObj->pParentDir, pObj);
    278     if (pObj->paExtents)
    279     {
    280         RTMemFree(pObj->paExtents);
    281         pObj->paExtents = NULL;
    282     }
    283     return VINF_SUCCESS;
    284 }
    285 
    286 
    287 /**
    288  * @interface_method_impl{RTVFSOBJOPS,pfnClose}
    289  */
    290 static DECLCALLBACK(int) rtFsIso9660File_Close(void *pvThis)
    291 {
    292     PRTFSISO9660FILE pThis = (PRTFSISO9660FILE)pvThis;
    293     LogFlow(("rtFsIso9660File_Close(%p)\n", pThis));
    294     return rtFsIso9660Obj_Close(&pThis->Core);
    295 }
    296 
    297 
    298 /**
    299  * @interface_method_impl{RTVFSOBJOPS,pfnQueryInfo}
    300  */
    301 static DECLCALLBACK(int) rtFsIso9660Obj_QueryInfo(void *pvThis, PRTFSOBJINFO pObjInfo, RTFSOBJATTRADD enmAddAttr)
    302 {
    303     PRTFSISO9660OBJ pThis = (PRTFSISO9660OBJ)pvThis;
    304 
    305     pObjInfo->cbObject              = pThis->cbObject;
    306     pObjInfo->cbAllocated           = RT_ALIGN_64(pThis->cbObject, pThis->pVol->cbBlock);
    307     pObjInfo->AccessTime            = pThis->AccessTime;
    308     pObjInfo->ModificationTime      = pThis->ModificationTime;
    309     pObjInfo->ChangeTime            = pThis->ChangeTime;
    310     pObjInfo->BirthTime             = pThis->BirthTime;
    311     pObjInfo->Attr.fMode            = pThis->fAttrib;
     276        pCore->fAttrib |= RTFS_DOS_HIDDEN;
     277    pCore->cbObject             = ISO9660_GET_ENDIAN(&pDirRec->cbData);
     278    pCore->cExtents             = 1;
     279    pCore->FirstExtent.cbExtent = pCore->cbObject;
     280    pCore->FirstExtent.offDisk  = ISO9660_GET_ENDIAN(&pDirRec->offExtent) * (uint64_t)pVol->cbBlock;
     281
     282    rtFsIso9660DateTime2TimeSpec(&pCore->ModificationTime, &pDirRec->RecTime);
     283    pCore->BirthTime  = pCore->ModificationTime;
     284    pCore->AccessTime = pCore->ModificationTime;
     285    pCore->ChangeTime = pCore->ModificationTime;
     286}
     287
     288
     289/**
     290 * Worker for rtFsIso9660File_QueryInfo and rtFsIso9660Dir_QueryInfo.
     291 */
     292static int rtFsIso9660Core_QueryInfo(PRTFSISO9660CORE pCore, PRTFSOBJINFO pObjInfo, RTFSOBJATTRADD enmAddAttr)
     293{
     294    pObjInfo->cbObject              = pCore->cbObject;
     295    pObjInfo->cbAllocated           = RT_ALIGN_64(pCore->cbObject, pCore->pVol->cbBlock);
     296    pObjInfo->AccessTime            = pCore->AccessTime;
     297    pObjInfo->ModificationTime      = pCore->ModificationTime;
     298    pObjInfo->ChangeTime            = pCore->ChangeTime;
     299    pObjInfo->BirthTime             = pCore->BirthTime;
     300    pObjInfo->Attr.fMode            = pCore->fAttrib;
    312301    pObjInfo->Attr.enmAdditional    = enmAddAttr;
    313302
     
    344333
    345334/**
     335 * Worker for rtFsIso9660File_Close and rtFsIso9660Dir_Close that does common work.
     336 *
     337 * @param   pCore           The common shared structure.
     338 */
     339static void rtFsIso9660Core_Destroy(PRTFSISO9660CORE pCore)
     340{
     341    if (pCore->pParentDir)
     342        rtFsIso9660DirShrd_RemoveOpenChild(pCore->pParentDir, pCore);
     343    if (pCore->paExtents)
     344    {
     345        RTMemFree(pCore->paExtents);
     346        pCore->paExtents = NULL;
     347    }
     348}
     349
     350
     351/**
     352 * @interface_method_impl{RTVFSOBJOPS,pfnClose}
     353 */
     354static DECLCALLBACK(int) rtFsIso9660File_Close(void *pvThis)
     355{
     356    PRTFSISO9660FILEOBJ  pThis   = (PRTFSISO9660FILEOBJ)pvThis;
     357    LogFlow(("rtFsIso9660File_Close(%p/%p)\n", pThis, pThis->pShared));
     358
     359    PRTFSISO9660FILESHRD pShared = pThis->pShared;
     360    pThis->pShared = NULL;
     361    if (pShared)
     362    {
     363        if (ASMAtomicDecU32(&pShared->Core.cRefs) == 0)
     364        {
     365            LogFlow(("rtFsIso9660File_Close: Destroying shared structure %p\n", pShared));
     366            rtFsIso9660Core_Destroy(&pShared->Core);
     367            RTMemFree(pShared);
     368        }
     369    }
     370    return VINF_SUCCESS;
     371}
     372
     373
     374/**
     375 * @interface_method_impl{RTVFSOBJOPS,pfnQueryInfo}
     376 */
     377static DECLCALLBACK(int) rtFsIso9660File_QueryInfo(void *pvThis, PRTFSOBJINFO pObjInfo, RTFSOBJATTRADD enmAddAttr)
     378{
     379    PRTFSISO9660FILEOBJ pThis = (PRTFSISO9660FILEOBJ)pvThis;
     380    return rtFsIso9660Core_QueryInfo(&pThis->pShared->Core, pObjInfo, enmAddAttr);
     381}
     382
     383
     384/**
    346385 * @interface_method_impl{RTVFSIOSTREAMOPS,pfnRead}
    347386 */
    348387static DECLCALLBACK(int) rtFsIso9660File_Read(void *pvThis, RTFOFF off, PCRTSGBUF pSgBuf, bool fBlocking, size_t *pcbRead)
    349388{
    350     PRTFSISO9660FILE pThis = (PRTFSISO9660FILE)pvThis;
     389    PRTFSISO9660FILEOBJ  pThis   = (PRTFSISO9660FILEOBJ)pvThis;
     390    PRTFSISO9660FILESHRD pShared = pThis->pShared;
    351391    AssertReturn(pSgBuf->cSegs != 0, VERR_INTERNAL_ERROR_3);
    352392    RT_NOREF(fBlocking);
     
    357397    if (off == -1)
    358398        off = pThis->offFile;
    359     if ((uint64_t)off >= pThis->Core.cbObject)
     399    if ((uint64_t)off >= pShared->Core.cbObject)
    360400    {
    361401        if (pcbRead)
     
    373413    int      rc         = VINF_SUCCESS;
    374414    size_t   cbRead     = 0;
    375     uint64_t cbFileLeft = pThis->Core.cbObject - (uint64_t)off;
     415    uint64_t cbFileLeft = pShared->Core.cbObject - (uint64_t)off;
    376416    size_t   cbLeft     = pSgBuf->paSegs[0].cbSeg;
    377417    uint8_t *pbDst      = (uint8_t *)pSgBuf->paSegs[0].pvSeg;
    378     if (pThis->Core.cExtents == 1)
     418    if (pShared->Core.cExtents == 1)
    379419    {
    380420        if (cbLeft > 0)
     
    383423            if (cbToRead > cbFileLeft)
    384424                cbToRead = (size_t)cbFileLeft;
    385             rc = RTVfsFileReadAt(pThis->Core.pVol->hVfsBacking, pThis->Core.FirstExtent.offDisk + off, pbDst, cbToRead, NULL);
     425            rc = RTVfsFileReadAt(pShared->Core.pVol->hVfsBacking, pShared->Core.FirstExtent.offDisk + off, pbDst, cbToRead, NULL);
    386426            if (RT_SUCCESS(rc))
    387427            {
     
    466506static DECLCALLBACK(int) rtFsIso9660File_Tell(void *pvThis, PRTFOFF poffActual)
    467507{
    468     PRTFSISO9660FILE pThis = (PRTFSISO9660FILE)pvThis;
     508    PRTFSISO9660FILEOBJ pThis = (PRTFSISO9660FILEOBJ)pvThis;
    469509    *poffActual = pThis->offFile;
    470510    return VINF_SUCCESS;
     
    475515 * @interface_method_impl{RTVFSOBJSETOPS,pfnMode}
    476516 */
    477 static DECLCALLBACK(int) rtFsIso9660Obj_SetMode(void *pvThis, RTFMODE fMode, RTFMODE fMask)
     517static DECLCALLBACK(int) rtFsIso9660File_SetMode(void *pvThis, RTFMODE fMode, RTFMODE fMask)
    478518{
    479519    RT_NOREF(pvThis, fMode, fMask);
     
    485525 * @interface_method_impl{RTVFSOBJSETOPS,pfnSetTimes}
    486526 */
    487 static DECLCALLBACK(int) rtFsIso9660Obj_SetTimes(void *pvThis, PCRTTIMESPEC pAccessTime, PCRTTIMESPEC pModificationTime,
     527static DECLCALLBACK(int) rtFsIso9660File_SetTimes(void *pvThis, PCRTTIMESPEC pAccessTime, PCRTTIMESPEC pModificationTime,
    488528                                                 PCRTTIMESPEC pChangeTime, PCRTTIMESPEC pBirthTime)
    489529{
     
    496536 * @interface_method_impl{RTVFSOBJSETOPS,pfnSetOwner}
    497537 */
    498 static DECLCALLBACK(int) rtFsIso9660Obj_SetOwner(void *pvThis, RTUID uid, RTGID gid)
     538static DECLCALLBACK(int) rtFsIso9660File_SetOwner(void *pvThis, RTUID uid, RTGID gid)
    499539{
    500540    RT_NOREF(pvThis, uid, gid);
     
    508548static DECLCALLBACK(int) rtFsIso9660File_Seek(void *pvThis, RTFOFF offSeek, unsigned uMethod, PRTFOFF poffActual)
    509549{
    510     PRTFSISO9660FILE pThis = (PRTFSISO9660FILE)pvThis;
     550    PRTFSISO9660FILEOBJ pThis = (PRTFSISO9660FILEOBJ)pvThis;
    511551    RTFOFF offNew;
    512552    switch (uMethod)
     
    516556            break;
    517557        case RTFILE_SEEK_END:
    518             offNew = (RTFOFF)pThis->Core.cbObject + offSeek;
     558            offNew = (RTFOFF)pThis->pShared->Core.cbObject + offSeek;
    519559            break;
    520560        case RTFILE_SEEK_CURRENT:
     
    543583static DECLCALLBACK(int) rtFsIso9660File_QuerySize(void *pvThis, uint64_t *pcbFile)
    544584{
    545     PRTFSISO9660FILE pThis = (PRTFSISO9660FILE)pvThis;
    546     *pcbFile = pThis->Core.cbObject;
     585    PRTFSISO9660FILEOBJ pThis = (PRTFSISO9660FILEOBJ)pvThis;
     586    *pcbFile = pThis->pShared->Core.cbObject;
    547587    return VINF_SUCCESS;
    548588}
     
    552592 * FAT file operations.
    553593 */
    554 DECL_HIDDEN_CONST(const RTVFSFILEOPS) g_rtFsIso9660FileOps =
     594DECL_HIDDEN_CONST(const RTVFSFILEOPS) g_rtFsIos9660FileOps =
    555595{
    556596    { /* Stream */
     
    560600            "FatFile",
    561601            rtFsIso9660File_Close,
    562             rtFsIso9660Obj_QueryInfo,
     602            rtFsIso9660File_QueryInfo,
    563603            RTVFSOBJOPS_VERSION
    564604        },
     
    579619        RTVFSOBJSETOPS_VERSION,
    580620        RT_OFFSETOF(RTVFSFILEOPS, Stream.Obj) - RT_OFFSETOF(RTVFSFILEOPS, ObjSet),
    581         rtFsIso9660Obj_SetMode,
    582         rtFsIso9660Obj_SetTimes,
    583         rtFsIso9660Obj_SetOwner,
     621        rtFsIso9660File_SetMode,
     622        rtFsIso9660File_SetTimes,
     623        rtFsIso9660File_SetOwner,
    584624        RTVFSOBJSETOPS_VERSION
    585625    },
     
    595635 * @returns IPRT status code.
    596636 * @param   pThis           The FAT volume instance.
    597  * @param   pParentDir      The parent directory.
     637 * @param   pParentDir      The parent directory (shared part).
    598638 * @param   pDirRec         The directory record.
    599639 * @param   cDirRecs        Number of directory records if more than one.
     
    604644 * @param   phVfsFile       Where to return the file handle.
    605645 */
    606 static int rtFsIso9660File_New(PRTFSISO9660VOL pThis, PRTFSISO9660DIR pParentDir, PCISO9660DIRREC pDirRec, uint32_t cDirRecs,
    607                                 uint64_t offDirRec, uint64_t fOpen, PRTVFSFILE phVfsFile)
     646static int rtFsIso9660File_New(PRTFSISO9660VOL pThis, PRTFSISO9660DIRSHRD pParentDir, PCISO9660DIRREC pDirRec, uint32_t cDirRecs,
     647                               uint64_t offDirRec, uint64_t fOpen, PRTVFSFILE phVfsFile)
    608648{
    609649    AssertPtr(pParentDir);
    610650
    611     PRTFSISO9660FILE pNewFile;
    612     int rc = RTVfsNewFile(&g_rtFsIso9660FileOps, sizeof(*pNewFile), fOpen, pThis->hVfsSelf, NIL_RTVFSLOCK /*use volume lock*/,
     651    /*
     652     * Create a VFS object.
     653     */
     654    PRTFSISO9660FILEOBJ pNewFile;
     655    int rc = RTVfsNewFile(&g_rtFsIos9660FileOps, sizeof(*pNewFile), fOpen, pThis->hVfsSelf, NIL_RTVFSLOCK /*use volume lock*/,
    613656                          phVfsFile, (void **)&pNewFile);
    614657    if (RT_SUCCESS(rc))
    615658    {
    616659        /*
    617          * Initialize it all so rtFsIso9660File_Close doesn't trip up in anyway.
     660         * Look for existing shared object, create a new one if necessary.
    618661         */
    619         rtFsIso9660Obj_InitFromDirRec(&pNewFile->Core, pDirRec, cDirRecs, offDirRec, pThis);
    620         pNewFile->offFile = 0;
    621 
    622         /*
    623          * Link into parent directory so we can use it to update
    624          * our directory entry.
    625          */
    626         rtFsIso9660Dir_AddOpenChild(pParentDir, &pNewFile->Core);
    627 
    628         return VINF_SUCCESS;
    629 
     662        PRTFSISO9660FILESHRD pShared = (PRTFSISO9660FILESHRD)rtFsIso9660Dir_LookupShared(pParentDir, offDirRec);
     663        if (!pShared)
     664        {
     665            pShared = (PRTFSISO9660FILESHRD)RTMemAllocZ(sizeof(*pShared));
     666            if (pShared)
     667            {
     668                /*
     669                 * Initialize it all so rtFsIso9660File_Close doesn't trip up in anyway.
     670                 */
     671                rtFsIso9660Core_InitFromDirRec(&pShared->Core, pDirRec, cDirRecs, offDirRec, pThis);
     672                rtFsIso9660DirShrd_AddOpenChild(pParentDir, &pShared->Core);
     673            }
     674        }
     675        if (pShared)
     676        {
     677            pNewFile->offFile = 0;
     678            pNewFile->pShared = pShared;
     679            return VINF_SUCCESS;
     680        }
     681
     682        rc = VERR_NO_MEMORY;
    630683    }
    631684    *phVfsFile = NIL_RTVFSFILE;
     
    652705}
    653706
     707
     708/**
     709 * Looks up the shared structure for a child.
     710 *
     711 * @returns Referenced pointer to the shared structure, NULL if not found.
     712 * @param   pThis           The directory.
     713 * @param   offDirRec       The directory record offset of the child.
     714 */
     715static PRTFSISO9660CORE rtFsIso9660Dir_LookupShared(PRTFSISO9660DIRSHRD pThis, uint64_t offDirRec)
     716{
     717    PRTFSISO9660CORE pCur;
     718    RTListForEach(&pThis->OpenChildren, pCur, RTFSISO9660CORE, Entry)
     719    {
     720        if (pCur->offDirRec == offDirRec)
     721        {
     722            uint32_t cRefs = ASMAtomicIncU32(&pCur->cRefs);
     723            Assert(cRefs > 1);
     724            return pCur;
     725        }
     726    }
     727    return NULL;
     728}
    654729
    655730
     
    669744 * @param   pfMode          Where to return the file type, rock ridge adjusted.
    670745 */
    671 static int rtFsIso9660Dir_FindEntry(PRTFSISO9660DIR pThis, const char *pszEntry, uint64_t *poffDirRec, PCISO9660DIRREC *ppDirRec,
    672                                     uint32_t *pcDirRecs, PRTFMODE pfMode)
     746static int rtFsIso9660Dir_FindEntry(PRTFSISO9660DIRSHRD pThis, const char *pszEntry,
     747                                    uint64_t *poffDirRec, PCISO9660DIRREC *ppDirRec, uint32_t *pcDirRecs, PRTFMODE pfMode)
    673748{
    674749    /* Set return values. */
     
    773848
    774849/**
     850 * Releases a reference to a shared directory structure.
     851 *
     852 * @param   pShared             The shared directory structure.
     853 */
     854static void rtFsIso9660DirShrd_Release(PRTFSISO9660DIRSHRD pShared)
     855{
     856    uint32_t cRefs = ASMAtomicDecU32(&pShared->Core.cRefs);
     857    Assert(cRefs < UINT32_MAX / 2);
     858    if (cRefs == 0)
     859    {
     860        LogFlow(("rtFsIso9660DirShrd_Release: Destroying shared structure %p\n", pShared));
     861        Assert(pShared->Core.cRefs == 0);
     862        if (pShared->pbDir)
     863        {
     864            RTMemFree(pShared->pbDir);
     865            pShared->pbDir = NULL;
     866        }
     867        rtFsIso9660Core_Destroy(&pShared->Core);
     868        RTMemFree(pShared);
     869    }
     870}
     871
     872
     873/**
     874 * Retains a reference to a shared directory structure.
     875 *
     876 * @param   pShared             The shared directory structure.
     877 */
     878static void rtFsIso9660DirShrd_Retain(PRTFSISO9660DIRSHRD pShared)
     879{
     880    uint32_t cRefs = ASMAtomicIncU32(&pShared->Core.cRefs);
     881    Assert(cRefs > 1); NOREF(cRefs);
     882}
     883
     884
     885
     886/**
    775887 * @interface_method_impl{RTVFSOBJOPS,pfnClose}
    776888 */
    777889static DECLCALLBACK(int) rtFsIso9660Dir_Close(void *pvThis)
    778890{
    779     PRTFSISO9660DIR pThis = (PRTFSISO9660DIR)pvThis;
    780     LogFlow(("rtFsIso9660Dir_Close(%p)\n", pThis));
    781     if (pThis->pbDir)
    782     {
    783         RTMemFree(pThis->pbDir);
    784         pThis->pbDir = NULL;
    785     }
    786     return rtFsIso9660Obj_Close(&pThis->Core);
     891    PRTFSISO9660DIROBJ pThis = (PRTFSISO9660DIROBJ)pvThis;
     892    LogFlow(("rtFsIso9660Dir_Close(%p/%p)\n", pThis, pThis->pShared));
     893
     894    PRTFSISO9660DIRSHRD pShared = pThis->pShared;
     895    pThis->pShared = NULL;
     896    if (pShared)
     897        rtFsIso9660DirShrd_Release(pShared);
     898    return VINF_SUCCESS;
     899}
     900
     901
     902/**
     903 * @interface_method_impl{RTVFSOBJOPS,pfnQueryInfo}
     904 */
     905static DECLCALLBACK(int) rtFsIso9660Dir_QueryInfo(void *pvThis, PRTFSOBJINFO pObjInfo, RTFSOBJATTRADD enmAddAttr)
     906{
     907    PRTFSISO9660DIROBJ pThis = (PRTFSISO9660DIROBJ)pvThis;
     908    return rtFsIso9660Core_QueryInfo(&pThis->pShared->Core, pObjInfo, enmAddAttr);
     909}
     910
     911
     912/**
     913 * @interface_method_impl{RTVFSOBJSETOPS,pfnMode}
     914 */
     915static DECLCALLBACK(int) rtFsIso9660Dir_SetMode(void *pvThis, RTFMODE fMode, RTFMODE fMask)
     916{
     917    RT_NOREF(pvThis, fMode, fMask);
     918    return VERR_WRITE_PROTECT;
     919}
     920
     921
     922/**
     923 * @interface_method_impl{RTVFSOBJSETOPS,pfnSetTimes}
     924 */
     925static DECLCALLBACK(int) rtFsIso9660Dir_SetTimes(void *pvThis, PCRTTIMESPEC pAccessTime, PCRTTIMESPEC pModificationTime,
     926                                                 PCRTTIMESPEC pChangeTime, PCRTTIMESPEC pBirthTime)
     927{
     928    RT_NOREF(pvThis, pAccessTime, pModificationTime, pChangeTime, pBirthTime);
     929    return VERR_WRITE_PROTECT;
     930}
     931
     932
     933/**
     934 * @interface_method_impl{RTVFSOBJSETOPS,pfnSetOwner}
     935 */
     936static DECLCALLBACK(int) rtFsIso9660Dir_SetOwner(void *pvThis, RTUID uid, RTGID gid)
     937{
     938    RT_NOREF(pvThis, uid, gid);
     939    return VERR_WRITE_PROTECT;
    787940}
    788941
     
    808961            *phVfsDir = NIL_RTVFSDIR;
    809962
    810         PRTFSISO9660DIR pThis = (PRTFSISO9660DIR)pvThis;
    811         PCISO9660DIRREC pDirRec;
    812         uint64_t        offDirRec;
    813         uint32_t        cDirRecs;
    814         RTFMODE         fMode;
    815         rc = rtFsIso9660Dir_FindEntry(pThis, pszEntry, &offDirRec, &pDirRec, &cDirRecs, &fMode);
     963        PRTFSISO9660DIROBJ  pThis = (PRTFSISO9660DIROBJ)pvThis;
     964        PRTFSISO9660DIRSHRD pShared = pThis->pShared;
     965        PCISO9660DIRREC     pDirRec;
     966        uint64_t            offDirRec;
     967        uint32_t            cDirRecs;
     968        RTFMODE             fMode;
     969        rc = rtFsIso9660Dir_FindEntry(pShared, pszEntry, &offDirRec, &pDirRec, &cDirRecs, &fMode);
    816970        Log2(("rtFsIso9660Dir_TraversalOpen: FindEntry(,%s,) -> %Rrc\n", pszEntry, rc));
    817971        if (RT_SUCCESS(rc))
     
    820974            {
    821975                case RTFS_TYPE_DIRECTORY:
    822                     rc = rtFsIso9660Dir_New(pThis->Core.pVol, pThis, pDirRec, cDirRecs, offDirRec, phVfsDir, NULL /*ppDir*/);
     976                    rc = rtFsIso9660Dir_New(pShared->Core.pVol, pShared, pDirRec, cDirRecs, offDirRec, phVfsDir);
    823977                    break;
    824978
     
    8531007static DECLCALLBACK(int) rtFsIso9660Dir_OpenFile(void *pvThis, const char *pszFilename, uint32_t fOpen, PRTVFSFILE phVfsFile)
    8541008{
    855     PRTFSISO9660DIR pThis = (PRTFSISO9660DIR)pvThis;
     1009    PRTFSISO9660DIROBJ  pThis   = (PRTFSISO9660DIROBJ)pvThis;
     1010    PRTFSISO9660DIRSHRD pShared = pThis->pShared;
    8561011
    8571012    /*
     
    8691024    uint32_t        cDirRecs;
    8701025    RTFMODE         fMode;
    871     int rc = rtFsIso9660Dir_FindEntry(pThis, pszFilename, &offDirRec, &pDirRec, &cDirRecs, &fMode);
     1026    int rc = rtFsIso9660Dir_FindEntry(pShared, pszFilename, &offDirRec, &pDirRec, &cDirRecs, &fMode);
    8721027    Log2(("rtFsIso9660Dir_OpenFile: FindEntry(,%s,) -> %Rrc\n", pszFilename, rc));
    8731028    if (RT_SUCCESS(rc))
     
    8761031        {
    8771032            case RTFS_TYPE_FILE:
    878                 rc = rtFsIso9660File_New(pThis->Core.pVol, pThis, pDirRec, cDirRecs, offDirRec, fOpen, phVfsFile);
     1033                rc = rtFsIso9660File_New(pShared->Core.pVol, pShared, pDirRec, cDirRecs, offDirRec, fOpen, phVfsFile);
    8791034                break;
    8801035
     
    9531108     * Try locate the entry.
    9541109     */
    955     PRTFSISO9660DIR pThis = (PRTFSISO9660DIR)pvThis;
    956     PCISO9660DIRREC pDirRec;
    957     uint64_t        offDirRec;
    958     uint32_t        cDirRecs;
    959     RTFMODE         fMode;
    960     int rc = rtFsIso9660Dir_FindEntry(pThis, pszEntry, &offDirRec, &pDirRec, &cDirRecs, &fMode);
     1110    PRTFSISO9660DIROBJ  pThis   = (PRTFSISO9660DIROBJ)pvThis;
     1111    PRTFSISO9660DIRSHRD pShared = pThis->pShared;
     1112    PCISO9660DIRREC     pDirRec;
     1113    uint64_t            offDirRec;
     1114    uint32_t            cDirRecs;
     1115    RTFMODE             fMode;
     1116    int rc = rtFsIso9660Dir_FindEntry(pShared, pszEntry, &offDirRec, &pDirRec, &cDirRecs, &fMode);
    9611117    Log2(("rtFsIso9660Dir_QueryEntryInfo: FindEntry(,%s,) -> %Rrc\n", pszEntry, rc));
    9621118    if (RT_SUCCESS(rc))
    9631119    {
    9641120        /*
    965          * To avoid duplicating code in rtFsIso9660Obj_InitFromDirRec and
    966          * rtFsIso9660Obj_QueryInfo, we create a dummy RTFSISO9660OBJ on the stack.
     1121         * To avoid duplicating code in rtFsIso9660Core_InitFromDirRec and
     1122         * rtFsIso9660Core_QueryInfo, we create a dummy RTFSISO9660CORE on the stack.
    9671123         */
    968         RTFSISO9660OBJ TmpObj;
     1124        RTFSISO9660CORE TmpObj;
    9691125        RT_ZERO(TmpObj);
    970         rtFsIso9660Obj_InitFromDirRec(&TmpObj, pDirRec, cDirRecs, offDirRec, pThis->Core.pVol);
    971         rc = rtFsIso9660Obj_QueryInfo(&TmpObj, pObjInfo, enmAddAttr);
     1126        rtFsIso9660Core_InitFromDirRec(&TmpObj, pDirRec, cDirRecs, offDirRec, pShared->Core.pVol);
     1127        rc = rtFsIso9660Core_QueryInfo(&TmpObj, pObjInfo, enmAddAttr);
    9721128    }
    9731129    return rc;
     
    10281184        "ISO 9660 Dir",
    10291185        rtFsIso9660Dir_Close,
    1030         rtFsIso9660Obj_QueryInfo,
     1186        rtFsIso9660Dir_QueryInfo,
    10311187        RTVFSOBJOPS_VERSION
    10321188    },
     
    10361192        RTVFSOBJSETOPS_VERSION,
    10371193        RT_OFFSETOF(RTVFSDIROPS, Obj) - RT_OFFSETOF(RTVFSDIROPS, ObjSet),
    1038         rtFsIso9660Obj_SetMode,
    1039         rtFsIso9660Obj_SetTimes,
    1040         rtFsIso9660Obj_SetOwner,
     1194        rtFsIso9660File_SetMode,
     1195        rtFsIso9660File_SetTimes,
     1196        rtFsIso9660File_SetOwner,
    10411197        RTVFSOBJSETOPS_VERSION
    10421198    },
     
    10571213
    10581214/**
    1059  * Adds an open child to the parent directory.
     1215 * Adds an open child to the parent directory's shared structure.
    10601216 *
    10611217 * Maintains an additional reference to the parent dir to prevent it from going
     
    10651221 * @param   pDir        The directory.
    10661222 * @param   pChild      The child being opened.
    1067  * @sa      rtFsIso9660Dir_RemoveOpenChild
    1068  */
    1069 static void rtFsIso9660Dir_AddOpenChild(PRTFSISO9660DIR pDir, PRTFSISO9660OBJ pChild)
    1070 {
    1071     /* First child that gets opened retains the parent directory.  This is
    1072        released by the final open child. */
    1073     if (RTListIsEmpty(&pDir->OpenChildren))
    1074     {
    1075         uint32_t cRefs = RTVfsDirRetain(pDir->hVfsSelf);
    1076         Assert(cRefs != UINT32_MAX); NOREF(cRefs);
    1077 
    1078         /* Root also retains the whole file system. */
    1079         if (pDir->Core.pVol->pRootDir == pDir)
    1080         {
    1081             Assert(pDir->Core.pVol);
    1082             Assert(pDir->Core.pVol == pChild->pVol);
    1083             cRefs = RTVfsRetain(pDir->Core.pVol->hVfsSelf);
    1084             Assert(cRefs != UINT32_MAX); NOREF(cRefs);
    1085             LogFlow(("rtFsIso9660Dir_AddOpenChild(%p,%p) retains volume (%d)\n", pDir, pChild, cRefs));
    1086         }
    1087         else
    1088             LogFlow(("rtFsIso9660Dir_AddOpenChild(%p,%p) retains parent only (%d)\n", pDir, pChild, cRefs));
    1089     }
    1090     else
    1091         LogFlow(("rtFsIso9660Dir_AddOpenChild(%p,%p) retains nothing\n", pDir, pChild));
     1223 * @sa      rtFsIso9660DirShrd_RemoveOpenChild
     1224 */
     1225static void rtFsIso9660DirShrd_AddOpenChild(PRTFSISO9660DIRSHRD pDir, PRTFSISO9660CORE pChild)
     1226{
     1227    rtFsIso9660DirShrd_Retain(pDir);
     1228
    10921229    RTListAppend(&pDir->OpenChildren, &pChild->Entry);
    10931230    pChild->pParentDir = pDir;
     
    11041241 *          objects to be released recursively (parent dir and the volume).
    11051242 *
    1106  * @sa      rtFsIso9660Dir_AddOpenChild
    1107  */
    1108 static void rtFsIso9660Dir_RemoveOpenChild(PRTFSISO9660DIR pDir, PRTFSISO9660OBJ pChild)
     1243 * @sa      rtFsIso9660DirShrd_AddOpenChild
     1244 */
     1245static void rtFsIso9660DirShrd_RemoveOpenChild(PRTFSISO9660DIRSHRD pDir, PRTFSISO9660CORE pChild)
    11091246{
    11101247    AssertReturnVoid(pChild->pParentDir == pDir);
     
    11121249    pChild->pParentDir = NULL;
    11131250
    1114     /* Final child? If so, release directory. */
    1115     if (RTListIsEmpty(&pDir->OpenChildren))
    1116     {
    1117         bool const fIsRootDir = pDir->Core.pVol->pRootDir == pDir;
    1118 
    1119         uint32_t cRefs = RTVfsDirRelease(pDir->hVfsSelf);
    1120         Assert(cRefs != UINT32_MAX); NOREF(cRefs);
    1121 
    1122         /* Root directory releases the file system as well.  Since the volume
    1123            holds a reference to the root directory, it will remain valid after
    1124            the above release. */
    1125         if (fIsRootDir)
    1126         {
    1127             Assert(cRefs > 0);
    1128             Assert(pDir->Core.pVol);
    1129             Assert(pDir->Core.pVol == pChild->pVol);
    1130             cRefs = RTVfsRelease(pDir->Core.pVol->hVfsSelf);
    1131             Assert(cRefs != UINT32_MAX); NOREF(cRefs);
    1132             LogFlow(("rtFsIso9660Dir_RemoveOpenChild(%p,%p) releases volume (%d)\n", pDir, pChild, cRefs));
    1133         }
    1134         else
    1135             LogFlow(("rtFsIso9660Dir_RemoveOpenChild(%p,%p) releases parent only (%d)\n", pDir, pChild, cRefs));
    1136     }
    1137     else
    1138         LogFlow(("rtFsIso9660Dir_RemoveOpenChild(%p,%p) releases nothing\n", pDir, pChild));
     1251    rtFsIso9660DirShrd_Release(pDir);
    11391252}
    11401253
     
    11441257 * Logs the content of a directory.
    11451258 */
    1146 static void rtFsIso9660Dir_LogContent(PRTFSISO9660DIR pThis)
     1259static void rtFsIso9660DirShrd_LogContent(PRTFSISO9660DIRSHRD pThis)
    11471260{
    11481261    if (LogIs2Enabled())
     
    12111324
    12121325/**
    1213  * Instantiates a new directory.
     1326 * Instantiates a new shared directory structure.
     1327 *
     1328 * @returns IPRT status code.
     1329 * @param   pThis           The FAT volume instance.
     1330 * @param   pParentDir      The parent directory.  This is NULL for the root
     1331 *                          directory.
     1332 * @param   pDirRec         The directory record.
     1333 * @param   cDirRecs        Number of directory records if more than one.
     1334 * @param   offDirRec       The byte offset of the directory record.
     1335 * @param   ppShared        Where to return the shared directory structure.
     1336 */
     1337static int  rtFsIso9660DirShrd_New(PRTFSISO9660VOL pThis, PRTFSISO9660DIRSHRD pParentDir, PCISO9660DIRREC pDirRec,
     1338                                   uint32_t cDirRecs, uint64_t offDirRec, PRTFSISO9660DIRSHRD *ppShared)
     1339{
     1340    /*
     1341     * Allocate a new structure and initialize it.
     1342     */
     1343    int rc = VERR_NO_MEMORY;
     1344    PRTFSISO9660DIRSHRD pShared = (PRTFSISO9660DIRSHRD)RTMemAllocZ(sizeof(*pShared));
     1345    if (pShared)
     1346    {
     1347        rtFsIso9660Core_InitFromDirRec(&pShared->Core, pDirRec, cDirRecs, offDirRec, pThis);
     1348        RTListInit(&pShared->OpenChildren);
     1349        pShared->cbDir              = ISO9660_GET_ENDIAN(&pDirRec->cbData);
     1350        pShared->pbDir              = (uint8_t *)RTMemAllocZ(pShared->cbDir + 256);
     1351        if (pShared->pbDir)
     1352        {
     1353            rc = RTVfsFileReadAt(pThis->hVfsBacking, pShared->Core.FirstExtent.offDisk, pShared->pbDir, pShared->cbDir, NULL);
     1354            if (RT_SUCCESS(rc))
     1355            {
     1356#ifdef LOG_ENABLED
     1357                rtFsIso9660DirShrd_LogContent(pShared);
     1358#endif
     1359
     1360                /*
     1361                 * Link into parent directory so we can use it to update
     1362                 * our directory entry.
     1363                 */
     1364                if (pParentDir)
     1365                    rtFsIso9660DirShrd_AddOpenChild(pParentDir, &pShared->Core);
     1366                *ppShared = pShared;
     1367                return VINF_SUCCESS;
     1368            }
     1369        }
     1370    }
     1371    *ppShared = NULL;
     1372    return rc;
     1373}
     1374
     1375
     1376/**
     1377 * Instantiates a new directory with a shared structure presupplied.
     1378 *
     1379 * @returns IPRT status code.
     1380 * @param   pThis           The FAT volume instance.
     1381 * @param   pShared         Referenced pointer to the shared structure.  The
     1382 *                          reference is always CONSUMED.
     1383 * @param   phVfsDir        Where to return the directory handle.
     1384 */
     1385static int rtFsIso9660Dir_NewWithShared(PRTFSISO9660VOL pThis, PRTFSISO9660DIRSHRD pShared, PRTVFSDIR phVfsDir)
     1386{
     1387    /*
     1388     * Create VFS object around the shared structure.
     1389     */
     1390    PRTFSISO9660DIROBJ pNewDir;
     1391    int rc = RTVfsNewDir(&g_rtFsIso9660DirOps, sizeof(*pNewDir), 0 /*fFlags*/, pThis->hVfsSelf,
     1392                         NIL_RTVFSLOCK /*use volume lock*/, phVfsDir, (void **)&pNewDir);
     1393    if (RT_SUCCESS(rc))
     1394    {
     1395        /*
     1396         * Look for existing shared object, create a new one if necessary.
     1397         * We CONSUME a reference to pShared here.
     1398         */
     1399        pNewDir->offDir  = 0;
     1400        pNewDir->pShared = pShared;
     1401        return VINF_SUCCESS;
     1402    }
     1403
     1404    rtFsIso9660DirShrd_Release(pShared);
     1405    *phVfsDir = NIL_RTVFSDIR;
     1406    return rc;
     1407}
     1408
     1409
     1410
     1411/**
     1412 * Instantiates a new directory VFS instance, creating the shared structure as
     1413 * necessary.
    12141414 *
    12151415 * @returns IPRT status code.
     
    12211421 * @param   offDirRec       The byte offset of the directory record.
    12221422 * @param   phVfsDir        Where to return the directory handle.
    1223  * @param   ppDir           Where to return the FAT directory instance data.
    1224  */
    1225 static int  rtFsIso9660Dir_New(PRTFSISO9660VOL pThis, PRTFSISO9660DIR pParentDir, PCISO9660DIRREC pDirRec, uint32_t cDirRecs,
    1226                                uint64_t offDirRec, PRTVFSDIR phVfsDir, PRTFSISO9660DIR *ppDir)
    1227 {
    1228     if (ppDir)
    1229         *ppDir = NULL;
    1230 
    1231     PRTFSISO9660DIR pNewDir;
    1232     int rc = RTVfsNewDir(&g_rtFsIso9660DirOps, sizeof(*pNewDir), pParentDir ? 0 : RTVFSDIR_F_NO_VFS_REF,
    1233                          pThis->hVfsSelf, NIL_RTVFSLOCK /*use volume lock*/, phVfsDir, (void **)&pNewDir);
    1234     if (RT_SUCCESS(rc))
    1235     {
    1236         /*
    1237          * Initialize it all so rtFsIso9660Dir_Close doesn't trip up in anyway.
    1238          */
    1239         rtFsIso9660Obj_InitFromDirRec(&pNewDir->Core, pDirRec, cDirRecs, offDirRec, pThis);
    1240         RTListInit(&pNewDir->OpenChildren);
    1241         pNewDir->hVfsSelf           = *phVfsDir;
    1242         pNewDir->cbDir              = ISO9660_GET_ENDIAN(&pDirRec->cbData);
    1243         pNewDir->pbDir              = (uint8_t *)RTMemAllocZ(pNewDir->cbDir + 256);
    1244         if (pNewDir->pbDir)
    1245         {
    1246             rc = RTVfsFileReadAt(pThis->hVfsBacking, pNewDir->Core.FirstExtent.offDisk, pNewDir->pbDir, pNewDir->cbDir, NULL);
    1247             if (RT_SUCCESS(rc))
    1248             {
    1249 #ifdef LOG_ENABLED
    1250                 rtFsIso9660Dir_LogContent(pNewDir);
    1251 #endif
    1252 
    1253                 /*
    1254                  * Link into parent directory so we can use it to update
    1255                  * our directory entry.
    1256                  */
    1257                 if (pParentDir)
    1258                     rtFsIso9660Dir_AddOpenChild(pParentDir, &pNewDir->Core);
    1259                 if (ppDir)
    1260                     *ppDir = pNewDir;
    1261                 return VINF_SUCCESS;
    1262             }
    1263         }
    1264         else
    1265             rc = VERR_NO_MEMORY;
    1266         RTVfsDirRelease(*phVfsDir);
    1267     }
    1268     *phVfsDir = NIL_RTVFSDIR;
    1269     if (ppDir)
    1270         *ppDir = NULL;
    1271     return rc;
    1272 }
    1273 
     1423 */
     1424static int  rtFsIso9660Dir_New(PRTFSISO9660VOL pThis, PRTFSISO9660DIRSHRD pParentDir, PCISO9660DIRREC pDirRec,
     1425                               uint32_t cDirRecs, uint64_t offDirRec, PRTVFSDIR phVfsDir)
     1426{
     1427    /*
     1428     * Look for existing shared object, create a new one if necessary.
     1429     */
     1430    int                 rc      = VINF_SUCCESS;
     1431    PRTFSISO9660DIRSHRD pShared = (PRTFSISO9660DIRSHRD)rtFsIso9660Dir_LookupShared(pParentDir, offDirRec);
     1432    if (!pShared)
     1433    {
     1434        rc = rtFsIso9660DirShrd_New(pThis, pParentDir, pDirRec, cDirRecs, offDirRec, &pShared);
     1435        if (RT_FAILURE(rc))
     1436        {
     1437            *phVfsDir = NIL_RTVFSDIR;
     1438            return rc;
     1439        }
     1440    }
     1441    return rtFsIso9660Dir_NewWithShared(pThis, pShared, phVfsDir);
     1442}
    12741443
    12751444
     
    12831452    Log(("rtFsIso9660Vol_Close(%p)\n", pThis));
    12841453
    1285     if (pThis->hVfsRootDir != NIL_RTVFSDIR)
     1454    if (pThis->pRootDir)
    12861455    {
    12871456        Assert(RTListIsEmpty(&pThis->pRootDir->OpenChildren));
    1288         uint32_t cRefs = RTVfsDirRelease(pThis->hVfsRootDir);
    1289         Assert(cRefs == 0); NOREF(cRefs);
    1290         pThis->hVfsRootDir = NIL_RTVFSDIR;
    1291         pThis->pRootDir    = NULL;
     1457        Assert(pThis->pRootDir->Core.cRefs == 1);
     1458        rtFsIso9660DirShrd_Release(pThis->pRootDir);
     1459        pThis->pRootDir = NULL;
    12921460    }
    12931461
     
    13151483{
    13161484    PRTFSISO9660VOL pThis = (PRTFSISO9660VOL)pvThis;
    1317     uint32_t cRefs = RTVfsDirRetain(pThis->hVfsRootDir);
    1318     if (cRefs != UINT32_MAX)
    1319     {
    1320         *phVfsDir = pThis->hVfsRootDir;
    1321         LogFlow(("rtFsIso9660Vol_OpenRoot -> %p\n", *phVfsDir));
    1322         return VINF_SUCCESS;
    1323     }
    1324     return VERR_INTERNAL_ERROR_5;
     1485
     1486    rtFsIso9660DirShrd_Retain(pThis->pRootDir); /* consumed by the next call */
     1487    return rtFsIso9660Dir_NewWithShared(pThis, pThis->pRootDir, phVfsDir);
    13251488}
    13261489
     
    16951858    pThis->idPrimaryVol                 = UINT32_MAX;
    16961859    pThis->fIsUtf16                     = false;
    1697     pThis->hVfsRootDir                  = NIL_RTVFSDIR;
    16981860    pThis->pRootDir                     = NULL;
    16991861
     
    18131975    {
    18141976        pThis->fIsUtf16 = true;
    1815         return rtFsIso9660Dir_New(pThis, NULL, &JolietRootDir, 1, offJolietRootDirRec, &pThis->hVfsRootDir, &pThis->pRootDir);
    1816     }
    1817     return rtFsIso9660Dir_New(pThis, NULL, &RootDir, 1, offRootDirRec, &pThis->hVfsRootDir, &pThis->pRootDir);
     1977        return rtFsIso9660DirShrd_New(pThis, NULL, &JolietRootDir, 1, offJolietRootDirRec, &pThis->pRootDir);
     1978    }
     1979    return rtFsIso9660DirShrd_New(pThis, NULL, &RootDir, 1, offRootDirRec, &pThis->pRootDir);
    18181980}
    18191981
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