VirtualBox

Ignore:
Timestamp:
Nov 6, 2017 12:48:25 PM (7 years ago)
Author:
vboxsync
Message:

fatvfs.cpp: Split dir and file structures into shared and handle specific parts, like the ifsvfs does.

File:
1 edited

Legend:

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

    r69046 r69595  
    8686*********************************************************************************************************************************/
    8787/** Pointer to a FAT directory instance. */
    88 typedef struct RTFSFATDIR *PRTFSFATDIR;
     88typedef struct RTFSFATDIRSHRD *PRTFSFATDIRSHRD;
    8989
    9090
     
    134134    /** The parent directory keeps a list of open objects (RTFSFATOBJ). */
    135135    RTLISTNODE          Entry;
     136    /** Reference counter.   */
     137    uint32_t volatile   cRefs;
    136138    /** The parent directory (not released till all children are close). */
    137     PRTFSFATDIR         pParentDir;
     139    PRTFSFATDIRSHRD     pParentDir;
    138140    /** The byte offset of the directory entry in the parent dir.
    139141     * This is set to UINT32_MAX for the root directory. */
     
    160162typedef RTFSFATOBJ *PRTFSFATOBJ;
    161163
    162 typedef struct RTFSFATFILE
     164typedef struct RTFSFATFILESHRD
    163165{
    164166    /** Core FAT object info.  */
    165167    RTFSFATOBJ          Core;
     168} RTFSFATFILESHRD;
     169typedef RTFSFATFILESHRD *PRTFSFATFILESHRD;
     170
     171
     172typedef struct RTFSFATFILE
     173{
     174    /** Pointer to the shared data. */
     175    PRTFSFATFILESHRD    pShared;
    166176    /** The current file offset. */
    167177    uint32_t            offFile;
     
    181191 * keeps a list of open children.
    182192 */
    183 typedef struct RTFSFATDIR
     193typedef struct RTFSFATDIRSHRD
    184194{
    185195    /** Core FAT object info.  */
    186196    RTFSFATOBJ          Core;
    187     /** The VFS handle for this directory (for reference counting). */
    188     RTVFSDIR            hVfsSelf;
    189197    /** Open child objects (RTFSFATOBJ). */
    190198    RTLISTNODE          OpenChildren;
     
    220228            /** Number of dirty sectors. */
    221229            uint32_t            cDirtySectors;
    222             /** Dirty sector map. */
     230            /** Dirty sector bitmap (one bit per sector). */
    223231            uint8_t            *pbDirtySectors;
    224232        } Full;
     
    233241        } Simple;
    234242    } u;
     243} RTFSFATDIRSHRD;
     244/** Pointer to a FAT directory instance. */
     245typedef RTFSFATDIRSHRD *PRTFSFATDIRSHRD;
     246
     247
     248/**
     249 * FAT directory.
     250 */
     251typedef struct RTFSFATDIR
     252{
     253    /** Core FAT object info.  */
     254    PRTFSFATDIRSHRD     pShared;
     255    /** The current directory offset. */
     256    uint32_t            offDir;
    235257} RTFSFATDIR;
    236258/** Pointer to a FAT directory instance. */
     
    365387    /** The size of the root directory, rounded up to the nearest sector size. */
    366388    uint32_t        cbRootDir;
    367     /** The root directory handle. */
    368     RTVFSDIR        hVfsRootDir;
    369389    /** The root directory instance data. */
    370     PRTFSFATDIR    pRootDir;
     390    PRTFSFATDIRSHRD pRootDir;
    371391
    372392    /** Serial number. */
     
    431451*   Internal Functions                                                                                                           *
    432452*********************************************************************************************************************************/
    433 static void rtFsFatDir_AddOpenChild(PRTFSFATDIR pDir, PRTFSFATOBJ pChild);
    434 static void rtFsFatDir_RemoveOpenChild(PRTFSFATDIR pDir, PRTFSFATOBJ pChild);
    435 static int  rtFsFatDir_GetEntryForUpdate(PRTFSFATDIR pThis, uint32_t offEntryInDir, PFATDIRENTRY *ppDirEntry, uint32_t *puWriteLock);
    436 static int  rtFsFatDir_PutEntryAfterUpdate(PRTFSFATDIR pThis, PFATDIRENTRY pDirEntry, uint32_t uWriteLock);
    437 static int  rtFsFatDir_Flush(PRTFSFATDIR pThis);
    438 static int  rtFsFatDir_New(PRTFSFATVOL pThis, PRTFSFATDIR pParentDir, PCFATDIRENTRY pDirEntry, uint32_t offEntryInDir,
    439                            uint32_t idxCluster, uint64_t offDisk, uint32_t cbDir, PRTVFSDIR phVfsDir, PRTFSFATDIR *ppDir);
     453static PRTFSFATOBJ rtFsFatDirShrd_LookupShared(PRTFSFATDIRSHRD pThis, uint32_t offEntryInDir);
     454static void rtFsFatDirShrd_AddOpenChild(PRTFSFATDIRSHRD pDir, PRTFSFATOBJ pChild);
     455static void rtFsFatDirShrd_RemoveOpenChild(PRTFSFATDIRSHRD pDir, PRTFSFATOBJ pChild);
     456static int  rtFsFatDirShrd_GetEntryForUpdate(PRTFSFATDIRSHRD pThis, uint32_t offEntryInDir,
     457                                             PFATDIRENTRY *ppDirEntry, uint32_t *puWriteLock);
     458static int  rtFsFatDirShrd_PutEntryAfterUpdate(PRTFSFATDIRSHRD pThis, PFATDIRENTRY pDirEntry, uint32_t uWriteLock);
     459static int  rtFsFatDirShrd_Flush(PRTFSFATDIRSHRD pThis);
     460static int  rtFsFatDir_New(PRTFSFATVOL pThis, PRTFSFATDIRSHRD pParentDir, PCFATDIRENTRY pDirEntry, uint32_t offEntryInDir,
     461                           uint32_t idxCluster, uint64_t offDisk, uint32_t cbDir, PRTVFSDIR phVfsDir);
    440462
    441463
     
    14571479{
    14581480    RTListInit(&pObj->Entry);
     1481    pObj->cRefs             = 1;
    14591482    pObj->pParentDir        = NULL;
    14601483    pObj->pVol              = pVol;
     
    14851508{
    14861509    RTListInit(&pObj->Entry);
     1510    pObj->cRefs             = 1;
    14871511    pObj->pParentDir        = NULL;
    14881512    pObj->pVol              = pVol;
     
    15151539    if (pObj->fMaybeDirtyDirEnt)
    15161540    {
    1517         int rc2 = rtFsFatDir_Flush(pObj->pParentDir);
     1541        int rc2 = rtFsFatDirShrd_Flush(pObj->pParentDir);
    15181542        if (RT_SUCCESS(rc2))
    15191543            pObj->fMaybeDirtyDirEnt = false;
     
    15351559    int rc = rtFsFatObj_FlushMetaData(pObj);
    15361560    if (pObj->pParentDir)
    1537         rtFsFatDir_RemoveOpenChild(pObj->pParentDir, pObj);
     1561        rtFsFatDirShrd_RemoveOpenChild(pObj->pParentDir, pObj);
    15381562    rtFsFatChain_Delete(&pObj->Clusters);
    15391563    return rc;
     
    15471571{
    15481572    PRTFSFATFILE pThis = (PRTFSFATFILE)pvThis;
    1549     return rtFsFatObj_Close(&pThis->Core);
    1550 }
    1551 
    1552 
    1553 /**
    1554  * @interface_method_impl{RTVFSOBJOPS,pfnQueryInfo}
    1555  */
    1556 static DECLCALLBACK(int) rtFsFatObj_QueryInfo(void *pvThis, PRTFSOBJINFO pObjInfo, RTFSOBJATTRADD enmAddAttr)
    1557 {
    1558     PRTFSFATOBJ pThis = (PRTFSFATOBJ)pvThis;
     1573    LogFlow(("rtFsFatFile_Close(%p/%p)\n", pThis, pThis->pShared));
     1574
     1575    PRTFSFATFILESHRD pShared = pThis->pShared;
     1576    pThis->pShared = NULL;
     1577
     1578    int rc = VINF_SUCCESS;
     1579    if (pShared)
     1580    {
     1581        if (ASMAtomicDecU32(&pShared->Core.cRefs) == 0)
     1582        {
     1583            LogFlow(("rtFsFatFile_Close: Destroying shared structure %p\n", pShared));
     1584            rc = rtFsFatObj_Close(&pShared->Core);
     1585            RTMemFree(pShared);
     1586        }
     1587        else
     1588            rc = rtFsFatObj_FlushMetaData(&pShared->Core);
     1589    }
     1590    return rc;
     1591}
     1592
     1593
     1594/**
     1595 * Worker for rtFsFatFile_QueryInfo and rtFsFatDir_QueryInfo
     1596 */
     1597static int rtFsFatObj_QueryInfo(PRTFSFATOBJ pThis, PRTFSOBJINFO pObjInfo, RTFSOBJATTRADD enmAddAttr)
     1598{
     1599    LogFlow(("rtFsFatObj_QueryInfo: %p fMode=%#x\n", pThis, pThis->fAttrib));
    15591600
    15601601    pObjInfo->cbObject              = pThis->cbObject;
     
    15991640
    16001641/**
     1642 * @interface_method_impl{RTVFSOBJOPS,pfnQueryInfo}
     1643 */
     1644static DECLCALLBACK(int) rtFsFatFile_QueryInfo(void *pvThis, PRTFSOBJINFO pObjInfo, RTFSOBJATTRADD enmAddAttr)
     1645{
     1646    PRTFSFATFILE pThis = (PRTFSFATFILE)pvThis;
     1647    return rtFsFatObj_QueryInfo(&pThis->pShared->Core, pObjInfo, enmAddAttr);
     1648}
     1649
     1650
     1651
     1652/**
    16011653 * @interface_method_impl{RTVFSIOSTREAMOPS,pfnRead}
    16021654 */
    16031655static DECLCALLBACK(int) rtFsFatFile_Read(void *pvThis, RTFOFF off, PCRTSGBUF pSgBuf, bool fBlocking, size_t *pcbRead)
    16041656{
    1605     PRTFSFATFILE pThis = (PRTFSFATFILE)pvThis;
     1657    PRTFSFATFILE     pThis   = (PRTFSFATFILE)pvThis;
     1658    PRTFSFATFILESHRD pShared = pThis->pShared;
    16061659    AssertReturn(pSgBuf->cSegs != 0, VERR_INTERNAL_ERROR_3);
    16071660    RT_NOREF(fBlocking);
     
    16121665    if (off == -1)
    16131666        off = pThis->offFile;
    1614     if ((uint64_t)off >= pThis->Core.cbObject)
     1667    if ((uint64_t)off >= pShared->Core.cbObject)
    16151668    {
    16161669        if (pcbRead)
     
    16261679     */
    16271680    int      rc         = VINF_SUCCESS;
    1628     uint32_t cbFileLeft = pThis->Core.cbObject - (uint32_t)off;
     1681    uint32_t cbFileLeft = pShared->Core.cbObject - (uint32_t)off;
    16291682    uint32_t cbRead     = 0;
    16301683    size_t   cbLeft     = pSgBuf->paSegs[0].cbSeg;
     
    16341687        if (cbFileLeft > 0)
    16351688        {
    1636             uint64_t offDisk = rtFsFatChain_FileOffsetToDiskOff(&pThis->Core.Clusters, (uint32_t)off, pThis->Core.pVol);
     1689            uint64_t offDisk = rtFsFatChain_FileOffsetToDiskOff(&pShared->Core.Clusters, (uint32_t)off, pShared->Core.pVol);
    16371690            if (offDisk != UINT64_MAX)
    16381691            {
    1639                 uint32_t cbToRead = pThis->Core.Clusters.cbCluster - ((uint32_t)off & (pThis->Core.Clusters.cbCluster - 1));
     1692                uint32_t cbToRead = pShared->Core.Clusters.cbCluster - ((uint32_t)off & (pShared->Core.Clusters.cbCluster - 1));
    16401693                if (cbToRead > cbLeft)
    16411694                    cbToRead = (uint32_t)cbLeft;
    16421695                if (cbToRead > cbFileLeft)
    16431696                    cbToRead = cbFileLeft;
    1644                 rc = RTVfsFileReadAt(pThis->Core.pVol->hVfsBacking, offDisk, pbDst, cbToRead, NULL);
     1697                rc = RTVfsFileReadAt(pShared->Core.pVol->hVfsBacking, offDisk, pbDst, cbToRead, NULL);
    16451698                if (RT_SUCCESS(rc))
    16461699                {
     
    17371790        uint32_t     uWriteLock;
    17381791        PFATDIRENTRY pDirEntry;
    1739         rc = rtFsFatDir_GetEntryForUpdate(pObj->pParentDir, pObj->offEntryInDir, &pDirEntry, &uWriteLock);
     1792        rc = rtFsFatDirShrd_GetEntryForUpdate(pObj->pParentDir, pObj->offEntryInDir, &pDirEntry, &uWriteLock);
    17401793        if (RT_SUCCESS(rc))
    17411794        {
     
    17501803                pDirEntry->u.idxClusterHigh = (uint16_t)(idxFirstCluster >> 16);
    17511804
    1752             rc = rtFsFatDir_PutEntryAfterUpdate(pObj->pParentDir, pDirEntry, uWriteLock);
     1805            rc = rtFsFatDirShrd_PutEntryAfterUpdate(pObj->pParentDir, pDirEntry, uWriteLock);
    17531806            pObj->fMaybeDirtyDirEnt = true;
    17541807        }
     
    17631816static DECLCALLBACK(int) rtFsFatFile_Write(void *pvThis, RTFOFF off, PCRTSGBUF pSgBuf, bool fBlocking, size_t *pcbWritten)
    17641817{
    1765     PRTFSFATFILE pThis = (PRTFSFATFILE)pvThis;
    1766     PRTFSFATVOL  pVol  = pThis->Core.pVol;
     1818    PRTFSFATFILE     pThis   = (PRTFSFATFILE)pvThis;
     1819    PRTFSFATFILESHRD pShared = pThis->pShared;
     1820    PRTFSFATVOL      pVol    = pShared->Core.pVol;
    17671821    AssertReturn(pSgBuf->cSegs != 0, VERR_INTERNAL_ERROR_3);
    17681822    RT_NOREF(fBlocking);
     
    17841838    {
    17851839        /* Figure out how much we can write.  Checking for max file size and such. */
    1786         uint32_t cbToWrite = pThis->Core.Clusters.cbCluster - ((uint32_t)off & (pThis->Core.Clusters.cbCluster - 1));
     1840        uint32_t cbToWrite = pShared->Core.Clusters.cbCluster - ((uint32_t)off & (pShared->Core.Clusters.cbCluster - 1));
    17871841        if (cbToWrite > cbLeft)
    17881842            cbToWrite = (uint32_t)cbLeft;
     
    17991853
    18001854        /* Grow the file? */
    1801         if ((uint32_t)offNew > pThis->Core.cbObject)
    1802         {
    1803             rc = rtFsFatObj_SetSize(&pThis->Core, (uint32_t)offNew);
     1855        if ((uint32_t)offNew > pShared->Core.cbObject)
     1856        {
     1857            rc = rtFsFatObj_SetSize(&pShared->Core, (uint32_t)offNew);
    18041858            if (RT_SUCCESS(rc))
    18051859            { /* likely */}
     
    18091863
    18101864        /* Figure the disk offset. */
    1811         uint64_t offDisk = rtFsFatChain_FileOffsetToDiskOff(&pThis->Core.Clusters, (uint32_t)off, pVol);
     1865        uint64_t offDisk = rtFsFatChain_FileOffsetToDiskOff(&pShared->Core.Clusters, (uint32_t)off, pVol);
    18121866        if (offDisk != UINT64_MAX)
    18131867        {
     
    18431897static DECLCALLBACK(int) rtFsFatFile_Flush(void *pvThis)
    18441898{
    1845     PRTFSFATFILE pThis = (PRTFSFATFILE)pvThis;
    1846     int rc1 = rtFsFatObj_FlushMetaData(&pThis->Core);
    1847     int rc2 = RTVfsFileFlush(pThis->Core.pVol->hVfsBacking);
     1899    PRTFSFATFILE     pThis   = (PRTFSFATFILE)pvThis;
     1900    PRTFSFATFILESHRD pShared = pThis->pShared;
     1901    int rc1 = rtFsFatObj_FlushMetaData(&pShared->Core);
     1902    int rc2 = RTVfsFileFlush(pShared->Core.pVol->hVfsBacking);
    18481903    return RT_FAILURE(rc1) ? rc1 : rc2;
    18491904}
     
    19391994static DECLCALLBACK(int) rtFsFatFile_Seek(void *pvThis, RTFOFF offSeek, unsigned uMethod, PRTFOFF poffActual)
    19401995{
    1941     PRTFSFATFILE pThis = (PRTFSFATFILE)pvThis;
     1996    PRTFSFATFILE     pThis   = (PRTFSFATFILE)pvThis;
     1997    PRTFSFATFILESHRD pShared = pThis->pShared;
     1998
    19421999    RTFOFF offNew;
    19432000    switch (uMethod)
     
    19472004            break;
    19482005        case RTFILE_SEEK_END:
    1949             offNew = (RTFOFF)pThis->Core.cbObject + offSeek;
     2006            offNew = (RTFOFF)pShared->Core.cbObject + offSeek;
    19502007            break;
    19512008        case RTFILE_SEEK_CURRENT:
     
    19742031static DECLCALLBACK(int) rtFsFatFile_QuerySize(void *pvThis, uint64_t *pcbFile)
    19752032{
    1976     PRTFSFATFILE pThis = (PRTFSFATFILE)pvThis;
    1977     *pcbFile = pThis->Core.cbObject;
     2033    PRTFSFATFILE     pThis   = (PRTFSFATFILE)pvThis;
     2034    PRTFSFATFILESHRD pShared = pThis->pShared;
     2035    *pcbFile = pShared->Core.cbObject;
    19782036    return VINF_SUCCESS;
    19792037}
     
    19912049            "FatFile",
    19922050            rtFsFatFile_Close,
    1993             rtFsFatObj_QueryInfo,
     2051            rtFsFatFile_QueryInfo,
    19942052            RTVFSOBJOPS_VERSION
    19952053        },
     
    20332091 * @param   phVfsFile       Where to return the file handle.
    20342092 */
    2035 static int rtFsFatFile_New(PRTFSFATVOL pThis, PRTFSFATDIR pParentDir, PCFATDIRENTRY pDirEntry, uint32_t offEntryInDir,
     2093static int rtFsFatFile_New(PRTFSFATVOL pThis, PRTFSFATDIRSHRD pParentDir, PCFATDIRENTRY pDirEntry, uint32_t offEntryInDir,
    20362094                           uint64_t fOpen, PRTVFSFILE phVfsFile)
    20372095{
     
    20442102    if (RT_SUCCESS(rc))
    20452103    {
     2104        pNewFile->offFile = 0;
     2105        pNewFile->pShared = NULL;
     2106
    20462107        /*
    2047          * Initialize it all so rtFsFatFile_Close doesn't trip up in anyway.
     2108         * Look for existing shared object, create a new one if necessary.
    20482109         */
    2049         rtFsFatObj_InitFromDirEntry(&pNewFile->Core, pDirEntry, offEntryInDir, pThis);
    2050         pNewFile->offFile = 0;
    2051         rc = rtFsFatClusterMap_ReadClusterChain(pThis, RTFSFAT_GET_CLUSTER(pDirEntry, pThis), &pNewFile->Core.Clusters);
    2052         if (RT_SUCCESS(rc))
    2053         {
    2054             /*
    2055              * Link into parent directory so we can use it to update
    2056              * our directory entry.
    2057              */
    2058             rtFsFatDir_AddOpenChild(pParentDir, &pNewFile->Core);
    2059 
    2060             /*
    2061              * Should we truncate the file or anything of that sort?
    2062              */
    2063             if (   (fOpen & RTFILE_O_TRUNCATE)
    2064                 || (fOpen & RTFILE_O_ACTION_MASK) == RTFILE_O_CREATE_REPLACE)
    2065                 rc = rtFsFatObj_SetSize(&pNewFile->Core, 0);
     2110        PRTFSFATFILESHRD pShared = (PRTFSFATFILESHRD)rtFsFatDirShrd_LookupShared(pParentDir, offEntryInDir);
     2111        if (pShared)
     2112        {
     2113            LogFlow(("rtFsFatFile_New: cbObject=%#RX32 \n", pShared->Core.cbObject));
     2114            pNewFile->pShared = pShared;
     2115            return VINF_SUCCESS;
     2116        }
     2117
     2118        pShared = (PRTFSFATFILESHRD)RTMemAllocZ(sizeof(*pShared));
     2119        if (pShared)
     2120        {
     2121            rtFsFatObj_InitFromDirEntry(&pShared->Core, pDirEntry, offEntryInDir, pThis);
     2122            pNewFile->pShared = pShared;
     2123
     2124            rc = rtFsFatClusterMap_ReadClusterChain(pThis, RTFSFAT_GET_CLUSTER(pDirEntry, pThis), &pShared->Core.Clusters);
    20662125            if (RT_SUCCESS(rc))
    2067                 return VINF_SUCCESS;
    2068         }
    2069 
     2126            {
     2127                /*
     2128                 * Link into parent directory so we can use it to update
     2129                 * our directory entry.
     2130                 */
     2131                rtFsFatDirShrd_AddOpenChild(pParentDir, &pShared->Core);
     2132
     2133                /*
     2134                 * Should we truncate the file or anything of that sort?
     2135                 */
     2136                if (   (fOpen & RTFILE_O_TRUNCATE)
     2137                    || (fOpen & RTFILE_O_ACTION_MASK) == RTFILE_O_CREATE_REPLACE)
     2138                    rc = rtFsFatObj_SetSize(&pShared->Core, 0);
     2139                if (RT_SUCCESS(rc))
     2140                {
     2141                    LogFlow(("rtFsFatFile_New: cbObject=%#RX32 pShared=%p\n", pShared->Core.cbObject, pShared));
     2142                    return VINF_SUCCESS;
     2143                }
     2144            }
     2145        }
     2146        else
     2147            rc = VERR_NO_MEMORY;
     2148
     2149        /* Destroy the file object. */
    20702150        RTVfsFileRelease(*phVfsFile);
    20712151    }
     
    20752155
    20762156
     2157/**
     2158 * Looks up the shared structure for a child.
     2159 *
     2160 * @returns Referenced pointer to the shared structure, NULL if not found.
     2161 * @param   pThis           The directory.
     2162 * @param   offEntryInDir   The directory record offset of the child.
     2163 */
     2164static PRTFSFATOBJ rtFsFatDirShrd_LookupShared(PRTFSFATDIRSHRD pThis, uint32_t offEntryInDir)
     2165{
     2166    PRTFSFATOBJ pCur;
     2167    RTListForEach(&pThis->OpenChildren, pCur, RTFSFATOBJ, Entry)
     2168    {
     2169        if (pCur->offEntryInDir == offEntryInDir)
     2170        {
     2171            uint32_t cRefs = ASMAtomicIncU32(&pCur->cRefs);
     2172            Assert(cRefs > 1); RT_NOREF(cRefs);
     2173            return pCur;
     2174        }
     2175    }
     2176    return NULL;
     2177}
    20772178
    20782179
     
    20832184 * @param   pThis           The directory.
    20842185 */
    2085 static int rtFsFatDir_FlushFullyBuffered(PRTFSFATDIR pThis)
     2186static int rtFsFatDirShrd_FlushFullyBuffered(PRTFSFATDIRSHRD pThis)
    20862187{
    20872188    Assert(pThis->fFullyBuffered);
     
    20902191    int             rc          = VINF_SUCCESS;
    20912192    for (uint32_t i = 0; i < pThis->u.Full.cSectors; i++)
    2092         if (pThis->u.Full.pbDirtySectors[i])
     2193        if (ASMBitTest(pThis->u.Full.pbDirtySectors, i))
    20932194        {
    20942195            int rc2 = RTVfsFileWriteAt(hVfsBacking, pThis->offEntriesOnDisk + i * cbSector,
    20952196                                       (uint8_t *)pThis->paEntries + i * cbSector, cbSector, NULL);
    20962197            if (RT_SUCCESS(rc2))
    2097                 pThis->u.Full.pbDirtySectors[i] = false;
     2198                ASMBitClear(pThis->u.Full.pbDirtySectors, i);
    20982199            else if (RT_SUCCESS(rc))
    20992200                rc = rc2;
     
    21092210 * @param   pThis           The directory.
    21102211 */
    2111 static int rtFsFatDir_FlushSimple(PRTFSFATDIR pThis)
     2212static int rtFsFatDirShrd_FlushSimple(PRTFSFATDIRSHRD pThis)
    21122213{
    21132214    Assert(!pThis->fFullyBuffered);
     
    21342235 * @param   pThis           The directory.
    21352236 */
    2136 static int rtFsFatDir_Flush(PRTFSFATDIR pThis)
     2237static int rtFsFatDirShrd_Flush(PRTFSFATDIRSHRD pThis)
    21372238{
    21382239    if (pThis->fFullyBuffered)
    2139         return rtFsFatDir_FlushFullyBuffered(pThis);
    2140     return rtFsFatDir_FlushSimple(pThis);
     2240        return rtFsFatDirShrd_FlushFullyBuffered(pThis);
     2241    return rtFsFatDirShrd_FlushSimple(pThis);
    21412242}
    21422243
     
    21452246 * Gets one or more entires at @a offEntryInDir.
    21462247 *
    2147  * Common worker for rtFsFatDir_GetEntriesAt and rtFsFatDir_GetEntryForUpdate
     2248 * Common worker for rtFsFatDirShrd_GetEntriesAt and rtFsFatDirShrd_GetEntryForUpdate
    21482249 *
    21492250 * @returns IPRT status code.
     
    21562257 *                              @a *ppaEntries points to.
    21572258 * @param   puBufferReadLock    Where to return the buffer read lock handle.
    2158  *                              Call rtFsFatDir_ReleaseBufferAfterReading when
     2259 *                              Call rtFsFatDirShrd_ReleaseBufferAfterReading when
    21592260 *                              done.
    21602261 */
    2161 static int rtFsFatDir_GetEntriesAtCommon(PRTFSFATDIR pThis, uint32_t offEntryInDir, bool fForUpdate,
    2162                                          PFATDIRENTRYUNION *ppaEntries, uint32_t *pcEntries, uint32_t *puLock)
     2262static int rtFsFatDirShrd_GetEntriesAtCommon(PRTFSFATDIRSHRD pThis, uint32_t offEntryInDir, bool fForUpdate,
     2263                                             PFATDIRENTRYUNION *ppaEntries, uint32_t *pcEntries, uint32_t *puLock)
    21632264{
    21642265    *puLock = UINT32_MAX;
     
    22042305                    rc = VINF_SUCCESS;
    22052306                else
    2206                     rc = rtFsFatDir_FlushSimple(pThis);
     2307                    rc = rtFsFatDirShrd_FlushSimple(pThis);
    22072308                if (RT_SUCCESS(rc))
    22082309                {
     
    22442345 * @param   uWriteLock      The write lock.
    22452346 */
    2246 static int rtFsFatDir_PutEntryAfterUpdate(PRTFSFATDIR pThis, PFATDIRENTRY pDirEntry, uint32_t uWriteLock)
     2347static int rtFsFatDirShrd_PutEntryAfterUpdate(PRTFSFATDIRSHRD pThis, PFATDIRENTRY pDirEntry, uint32_t uWriteLock)
    22472348{
    22482349    Assert(uWriteLock == UINT32_C(0x80000001));
     
    22512352    {
    22522353        uint32_t idxSector = ((uintptr_t)pDirEntry - (uintptr_t)pThis->paEntries) / pThis->Core.pVol->cbSector;
    2253         pThis->u.Full.pbDirtySectors[idxSector] = true;
     2354        ASMBitSet(pThis->u.Full.pbDirtySectors, idxSector);
    22542355    }
    22552356    else
     
    22622363 * Gets the pointer to the given directory entry for the purpose of updating it.
    22632364 *
    2264  * Call rtFsFatDir_PutEntryAfterUpdate afterwards.
     2365 * Call rtFsFatDirShrd_PutEntryAfterUpdate afterwards.
    22652366 *
    22662367 * @returns IPRT status code.
     
    22712372 * @param   puWriteLock     Where to return the write lock.
    22722373 */
    2273 static int rtFsFatDir_GetEntryForUpdate(PRTFSFATDIR pThis, uint32_t offEntryInDir, PFATDIRENTRY *ppDirEntry,
    2274                                         uint32_t *puWriteLock)
     2374static int rtFsFatDirShrd_GetEntryForUpdate(PRTFSFATDIRSHRD pThis, uint32_t offEntryInDir, PFATDIRENTRY *ppDirEntry,
     2375                                            uint32_t *puWriteLock)
    22752376{
    22762377    uint32_t cEntriesIgn;
    2277     return rtFsFatDir_GetEntriesAtCommon(pThis, offEntryInDir, true /*fForUpdate*/, (PFATDIRENTRYUNION *)ppDirEntry,
    2278                                          &cEntriesIgn, puWriteLock);
     2378    return rtFsFatDirShrd_GetEntriesAtCommon(pThis, offEntryInDir, true /*fForUpdate*/, (PFATDIRENTRYUNION *)ppDirEntry,
     2379                                             &cEntriesIgn, puWriteLock);
    22792380}
    22802381
     
    22882389 * @param   uBufferReadLock The buffer lock.
    22892390 */
    2290 static void rtFsFatDir_ReleaseBufferAfterReading(PRTFSFATDIR pThis, uint32_t uBufferReadLock)
     2391static void rtFsFatDirShrd_ReleaseBufferAfterReading(PRTFSFATDIRSHRD pThis, uint32_t uBufferReadLock)
    22912392{
    22922393    RT_NOREF(pThis, uBufferReadLock);
     
    23062407 *                              @a *ppaEntries points to.
    23072408 * @param   puBufferReadLock    Where to return the buffer read lock handle.
    2308  *                              Call rtFsFatDir_ReleaseBufferAfterReading when
     2409 *                              Call rtFsFatDirShrd_ReleaseBufferAfterReading when
    23092410 *                              done.
    23102411 */
    2311 static int rtFsFatDir_GetEntriesAt(PRTFSFATDIR pThis, uint32_t offEntryInDir,
    2312                                    PCFATDIRENTRYUNION *ppaEntries, uint32_t *pcEntries, uint32_t *puBufferReadLock)
    2313 {
    2314     return rtFsFatDir_GetEntriesAtCommon(pThis, offEntryInDir, false /*fForUpdate*/, (PFATDIRENTRYUNION *)ppaEntries,
    2315                                          pcEntries, puBufferReadLock);
     2412static int rtFsFatDirShrd_GetEntriesAt(PRTFSFATDIRSHRD pThis, uint32_t offEntryInDir,
     2413                                       PCFATDIRENTRYUNION *ppaEntries, uint32_t *pcEntries, uint32_t *puBufferReadLock)
     2414{
     2415    return rtFsFatDirShrd_GetEntriesAtCommon(pThis, offEntryInDir, false /*fForUpdate*/, (PFATDIRENTRYUNION *)ppaEntries,
     2416                                             pcEntries, puBufferReadLock);
    23162417}
    23172418
     
    24572558 * @param   pDirEntry       Where to return a copy of the directory entry.
    24582559 */
    2459 static int rtFsFatDir_FindEntry(PRTFSFATDIR pThis, const char *pszEntry, uint32_t *poffEntryInDir, bool *pfLong,
    2460                                 PFATDIRENTRY pDirEntry)
     2560static int rtFsFatDirShrd_FindEntry(PRTFSFATDIRSHRD pThis, const char *pszEntry, uint32_t *poffEntryInDir, bool *pfLong,
     2561                                    PFATDIRENTRY pDirEntry)
    24612562{
    24622563    /* Set return values. */
     
    24892590        uint32_t            cEntries    = 0;
    24902591        PCFATDIRENTRYUNION  paEntries   = NULL;
    2491         int rc = rtFsFatDir_GetEntriesAt(pThis, offEntryInDir, &paEntries, &cEntries, &uBufferLock);
     2592        int rc = rtFsFatDirShrd_GetEntriesAt(pThis, offEntryInDir, &paEntries, &cEntries, &uBufferLock);
    24922593        if (RT_FAILURE(rc))
    24932594            return rc;
     
    25082609                    if (pThis->Core.pVol->enmBpbVersion >= RTFSFATBPBVER_DOS_2_0)
    25092610                    {
    2510                         rtFsFatDir_ReleaseBufferAfterReading(pThis, uBufferLock);
     2611                        rtFsFatDirShrd_ReleaseBufferAfterReading(pThis, uBufferLock);
    25112612                        return VERR_FILE_NOT_FOUND;
    25122613                    }
     
    25562657                *pDirEntry      = paEntries[iEntry].Entry;
    25572658                *pfLong         = false;
    2558                 rtFsFatDir_ReleaseBufferAfterReading(pThis, uBufferLock);
     2659                rtFsFatDirShrd_ReleaseBufferAfterReading(pThis, uBufferLock);
    25592660                return VINF_SUCCESS;
    25602661            }
     
    25672668                *pDirEntry      = paEntries[iEntry].Entry;
    25682669                *pfLong         = true;
    2569                 rtFsFatDir_ReleaseBufferAfterReading(pThis, uBufferLock);
     2670                rtFsFatDirShrd_ReleaseBufferAfterReading(pThis, uBufferLock);
    25702671                return VINF_SUCCESS;
    25712672            }
     
    25742675        }
    25752676
    2576         rtFsFatDir_ReleaseBufferAfterReading(pThis, uBufferLock);
     2677        rtFsFatDirShrd_ReleaseBufferAfterReading(pThis, uBufferLock);
    25772678    }
    25782679
     
    25822683
    25832684/**
    2584  * Watered down version of rtFsFatDir_FindEntry that is used by the short name
     2685 * Watered down version of rtFsFatDirShrd_FindEntry that is used by the short name
    25852686 * generator to check for duplicates.
    25862687 *
     
    25912692 * @param   pszEntry        The entry to look for.
    25922693 */
    2593 static int rtFsFatDir_FindEntryShort(PRTFSFATDIR pThis, const char *pszName8Dot3)
     2694static int rtFsFatDirShrd_FindEntryShort(PRTFSFATDIRSHRD pThis, const char *pszName8Dot3)
    25942695{
    25952696    Assert(strlen(pszName8Dot3) == 8+3);
     
    26082709        uint32_t            cEntries    = 0;
    26092710        PCFATDIRENTRYUNION  paEntries   = NULL;
    2610         int rc = rtFsFatDir_GetEntriesAt(pThis, offEntryInDir, &paEntries, &cEntries, &uBufferLock);
     2711        int rc = rtFsFatDirShrd_GetEntriesAt(pThis, offEntryInDir, &paEntries, &cEntries, &uBufferLock);
    26112712        if (RT_FAILURE(rc))
    26122713            return rc;
     
    26262727                    if (pThis->Core.pVol->enmBpbVersion >= RTFSFATBPBVER_DOS_2_0)
    26272728                    {
    2628                         rtFsFatDir_ReleaseBufferAfterReading(pThis, uBufferLock);
     2729                        rtFsFatDirShrd_ReleaseBufferAfterReading(pThis, uBufferLock);
    26292730                        return VERR_FILE_NOT_FOUND;
    26302731                    }
     
    26462747            else if (memcmp(paEntries[iEntry].Entry.achName, pszName8Dot3, sizeof(paEntries[iEntry].Entry.achName)) == 0)
    26472748            {
    2648                 rtFsFatDir_ReleaseBufferAfterReading(pThis, uBufferLock);
     2749                rtFsFatDirShrd_ReleaseBufferAfterReading(pThis, uBufferLock);
    26492750                return VINF_SUCCESS;
    26502751            }
    26512752        }
    26522753
    2653         rtFsFatDir_ReleaseBufferAfterReading(pThis, uBufferLock);
     2754        rtFsFatDirShrd_ReleaseBufferAfterReading(pThis, uBufferLock);
    26542755    }
    26552756
     
    28042905
    28052906/**
    2806  * Worker for rtFsFatDir_GenerateShortName.
     2907 * Worker for rtFsFatDirShrd_GenerateShortName.
    28072908 */
    28082909static void rtFsFatDir_CopyShortName(char *pszDst, uint32_t cchDst, const char *pszSrc, size_t cchSrc, char chPad)
     
    28572958 * @param   pDirEntry       Where to put the short name.
    28582959 */
    2859 static int rtFsFatDir_GenerateShortName(PRTFSFATDIR pThis, const char *pszEntry, PFATDIRENTRY pDirEntry)
     2960static int rtFsFatDirShrd_GenerateShortName(PRTFSFATDIRSHRD pThis, const char *pszEntry, PFATDIRENTRY pDirEntry)
    28602961{
    28612962    /* Do some input parsing. */
     
    28772978    {
    28782979        szShortName[7] = iLastDigit + '0';
    2879         int rc = rtFsFatDir_FindEntryShort(pThis, szShortName);
     2980        int rc = rtFsFatDirShrd_FindEntryShort(pThis, szShortName);
    28802981        if (rc == VERR_FILE_NOT_FOUND)
    28812982        {
     
    28962997            szShortName[6] = iFirstDigit + '0';
    28972998            szShortName[7] = iLastDigit  + '0';
    2898             int rc = rtFsFatDir_FindEntryShort(pThis, szShortName);
     2999            int rc = rtFsFatDirShrd_FindEntryShort(pThis, szShortName);
    28993000            if (rc == VERR_FILE_NOT_FOUND)
    29003001            {
     
    29203021        szShortName[4] = szHex[cchHex - 4];
    29213022        szShortName[3] = szHex[cchHex - 5];
    2922         int rc = rtFsFatDir_FindEntryShort(pThis, szShortName);
     3023        int rc = rtFsFatDirShrd_FindEntryShort(pThis, szShortName);
    29233024        if (rc == VERR_FILE_NOT_FOUND)
    29243025        {
     
    29493050 * @param   pcSlots         Where to return the actual number of slots used.
    29503051 */
    2951 static int rtFsFatDir_MaybeCreateLongNameAndShortAlias(PRTFSFATDIR pThis, const char *pszEntry, bool fIs8Dot3Name,
    2952                                                        PFATDIRENTRY pDirEntry, PFATDIRNAMESLOT paSlots, uint32_t *pcSlots)
     3052static int rtFsFatDirShrd_MaybeCreateLongNameAndShortAlias(PRTFSFATDIRSHRD pThis, const char *pszEntry, bool fIs8Dot3Name,
     3053                                                           PFATDIRENTRY pDirEntry, PFATDIRNAMESLOT paSlots, uint32_t *pcSlots)
    29533054{
    29543055    RT_NOREF(pThis, pDirEntry, paSlots, pszEntry);
     
    29793080         */
    29803081        if (!fIs8Dot3Name)
    2981             rc = rtFsFatDir_GenerateShortName(pThis, pszEntry, pDirEntry);
     3082            rc = rtFsFatDirShrd_GenerateShortName(pThis, pszEntry, pDirEntry);
    29823083        if (RT_SUCCESS(rc))
    29833084        {
     
    30353136 *                          returned.
    30363137 */
    3037 static int rtFsFatChain_FindFreeEntries(PRTFSFATDIR pThis, uint32_t cEntriesNeeded,
     3138static int rtFsFatChain_FindFreeEntries(PRTFSFATDIRSHRD pThis, uint32_t cEntriesNeeded,
    30383139                                        uint32_t *poffEntryInDir, uint32_t *pcFreeTail)
    30393140{
     
    30563157        uint32_t            cEntries    = 0;
    30573158        PCFATDIRENTRYUNION  paEntries   = NULL;
    3058         int rc = rtFsFatDir_GetEntriesAt(pThis, offEntryInDir, &paEntries, &cEntries, &uBufferLock);
     3159        int rc = rtFsFatDirShrd_GetEntriesAt(pThis, offEntryInDir, &paEntries, &cEntries, &uBufferLock);
    30593160        if (RT_FAILURE(rc))
    30603161            return rc;
     
    30803181                    *pcFreeTail     = cEntriesNeeded;
    30813182                    *poffEntryInDir = offStartFreeEntries;
    3082                     rtFsFatDir_ReleaseBufferAfterReading(pThis, uBufferLock);
     3183                    rtFsFatDirShrd_ReleaseBufferAfterReading(pThis, uBufferLock);
    30833184                    return VINF_SUCCESS;
    30843185                }
     
    30883189                    if (pThis->Core.pVol->enmBpbVersion >= RTFSFATBPBVER_DOS_2_0)
    30893190                    {
    3090                         rtFsFatDir_ReleaseBufferAfterReading(pThis, uBufferLock);
     3191                        rtFsFatDirShrd_ReleaseBufferAfterReading(pThis, uBufferLock);
    30913192                        *pcFreeTail = cFreeEntries = (cbDir - offStartFreeEntries) / sizeof(FATDIRENTRY);
    30923193                        if (cFreeEntries >= cEntriesNeeded)
    30933194                        {
    30943195                            *poffEntryInDir = offStartFreeEntries;
    3095                             rtFsFatDir_ReleaseBufferAfterReading(pThis, uBufferLock);
     3196                            rtFsFatDirShrd_ReleaseBufferAfterReading(pThis, uBufferLock);
    30963197                            return VINF_SUCCESS;
    30973198                        }
     
    31063207            }
    31073208        }
    3108         rtFsFatDir_ReleaseBufferAfterReading(pThis, uBufferLock);
     3209        rtFsFatDirShrd_ReleaseBufferAfterReading(pThis, uBufferLock);
    31093210    }
    31103211    *pcFreeTail = cFreeEntries;
     
    31233224 * @param   cMinNewEntries  The minimum number of new entries to allocated.
    31243225 */
    3125 static int rtFsFatChain_GrowDirectory(PRTFSFATDIR pThis, uint32_t cMinNewEntries)
     3226static int rtFsFatChain_GrowDirectory(PRTFSFATDIRSHRD pThis, uint32_t cMinNewEntries)
    31263227{
    31273228    RT_NOREF(pThis, cMinNewEntries);
     
    31403241 * @param   poffEntryInDir  Where to return the directory offset.
    31413242 */
    3142 static int rtFsFatChain_InsertEntries(PRTFSFATDIR pThis, PCFATDIRENTRY pDirEntry, PFATDIRNAMESLOT paSlots, uint32_t cSlots,
     3243static int rtFsFatChain_InsertEntries(PRTFSFATDIRSHRD pThis, PCFATDIRENTRY pDirEntry, PFATDIRNAMESLOT paSlots, uint32_t cSlots,
    31433244                                      uint32_t *poffEntryInDir)
    31443245{
     
    31793280            uint32_t        uBufferLock;
    31803281            PFATDIRENTRY    pDstEntry;
    3181             rc = rtFsFatDir_GetEntryForUpdate(pThis, offCurrent, &pDstEntry, &uBufferLock);
     3282            rc = rtFsFatDirShrd_GetEntryForUpdate(pThis, offCurrent, &pDstEntry, &uBufferLock);
    31823283            if (RT_SUCCESS(rc))
    31833284            {
     
    31863287                else
    31873288                    memcpy(pDstEntry, pDirEntry,          sizeof(*pDstEntry));
    3188                 rc = rtFsFatDir_PutEntryAfterUpdate(pThis, pDstEntry, uBufferLock);
     3289                rc = rtFsFatDirShrd_PutEntryAfterUpdate(pThis, pDstEntry, uBufferLock);
    31893290                if (RT_SUCCESS(rc))
    31903291                    continue;
     
    31973298            while (iSrcSlot-- > 0)
    31983299            {
    3199                 int rc2 = rtFsFatDir_GetEntryForUpdate(pThis, offFirstInDir + iSrcSlot * sizeof(FATDIRENTRY),
     3300                int rc2 = rtFsFatDirShrd_GetEntryForUpdate(pThis, offFirstInDir + iSrcSlot * sizeof(FATDIRENTRY),
    32003301                                                       &pDstEntry, &uBufferLock);
    32013302                if (RT_SUCCESS(rc2))
    32023303                {
    32033304                    pDstEntry->achName[0] = FATDIRENTRY_CH0_DELETED;
    3204                     rtFsFatDir_PutEntryAfterUpdate(pThis, pDstEntry, uBufferLock);
     3305                    rtFsFatDirShrd_PutEntryAfterUpdate(pThis, pDstEntry, uBufferLock);
    32053306                }
    32063307            }
     
    32343335 * @param   pDirEntry       Where to return a copy of the directory entry.
    32353336 *
    3236  * @remarks ASSUMES caller has already called rtFsFatDir_FindEntry to make sure
     3337 * @remarks ASSUMES caller has already called rtFsFatDirShrd_FindEntry to make sure
    32373338 *          the entry doesn't exist.
    32383339 */
    3239 static int rtFsFatDir_CreateEntry(PRTFSFATDIR pThis, const char *pszEntry, uint8_t fAttrib, uint32_t cbInitial,
    3240                                   uint32_t *poffEntryInDir, PFATDIRENTRY pDirEntry)
     3340static int rtFsFatDirShrd_CreateEntry(PRTFSFATDIRSHRD pThis, const char *pszEntry, uint8_t fAttrib, uint32_t cbInitial,
     3341                                      uint32_t *poffEntryInDir, PFATDIRENTRY pDirEntry)
    32413342{
    32423343    PRTFSFATVOL pVol = pThis->Core.pVol;
     
    32653366    FATDIRNAMESLOT  aSlots[FATDIRNAMESLOT_MAX_SLOTS];
    32663367    AssertCompile(RTFSFAT_MAX_LFN_CHARS < RT_ELEMENTS(aSlots) * FATDIRNAMESLOT_CHARS_PER_SLOT);
    3267     int rc = rtFsFatDir_MaybeCreateLongNameAndShortAlias(pThis, pszEntry, fIs8Dot3Name, pDirEntry, aSlots, &cSlots);
     3368    int rc = rtFsFatDirShrd_MaybeCreateLongNameAndShortAlias(pThis, pszEntry, fIs8Dot3Name, pDirEntry, aSlots, &cSlots);
    32683369    if (RT_SUCCESS(rc))
    32693370    {
     
    33083409
    33093410
     3411/**
     3412 * Releases a reference to a shared directory structure.
     3413 *
     3414 * @param   pShared             The shared directory structure.
     3415 */
     3416static int rtFsFatDirShrd_Release(PRTFSFATDIRSHRD pShared)
     3417{
     3418    uint32_t cRefs = ASMAtomicDecU32(&pShared->Core.cRefs);
     3419    Assert(cRefs < UINT32_MAX / 2);
     3420    if (cRefs == 0)
     3421    {
     3422        LogFlow(("rtFsFatDirShrd_Release: Destroying shared structure %p\n", pShared));
     3423        Assert(pShared->Core.cRefs == 0);
     3424
     3425        int rc;
     3426        if (pShared->paEntries)
     3427        {
     3428            rc = rtFsFatDirShrd_Flush(pShared);
     3429            RTMemFree(pShared->paEntries);
     3430            pShared->paEntries = NULL;
     3431        }
     3432        else
     3433            rc = VINF_SUCCESS;
     3434
     3435        if (   pShared->fFullyBuffered
     3436            && pShared->u.Full.pbDirtySectors)
     3437        {
     3438            RTMemFree(pShared->u.Full.pbDirtySectors);
     3439            pShared->u.Full.pbDirtySectors = NULL;
     3440        }
     3441
     3442        int rc2 = rtFsFatObj_Close(&pShared->Core);
     3443        if (RT_SUCCESS(rc))
     3444            rc = rc2;
     3445
     3446        RTMemFree(pShared);
     3447        return rc;
     3448    }
     3449    return VINF_SUCCESS;
     3450}
     3451
     3452
     3453/**
     3454 * Retains a reference to a shared directory structure.
     3455 *
     3456 * @param   pShared             The shared directory structure.
     3457 */
     3458static void rtFsFatDirShrd_Retain(PRTFSFATDIRSHRD pShared)
     3459{
     3460    uint32_t cRefs = ASMAtomicIncU32(&pShared->Core.cRefs);
     3461    Assert(cRefs > 1); NOREF(cRefs);
     3462}
     3463
    33103464
    33113465/**
     
    33143468static DECLCALLBACK(int) rtFsFatDir_Close(void *pvThis)
    33153469{
     3470    PRTFSFATDIR     pThis   = (PRTFSFATDIR)pvThis;
     3471    PRTFSFATDIRSHRD pShared = pThis->pShared;
     3472    pThis->pShared = NULL;
     3473    if (pShared)
     3474        return rtFsFatDirShrd_Release(pShared);
     3475    return VINF_SUCCESS;
     3476}
     3477
     3478
     3479/**
     3480 * @interface_method_impl{RTVFSOBJOPS,pfnQueryInfo}
     3481 */
     3482static DECLCALLBACK(int) rtFsFatDir_QueryInfo(void *pvThis, PRTFSOBJINFO pObjInfo, RTFSOBJATTRADD enmAddAttr)
     3483{
    33163484    PRTFSFATDIR pThis = (PRTFSFATDIR)pvThis;
    3317     int rc;
    3318     if (pThis->paEntries)
    3319     {
    3320         rc = rtFsFatDir_Flush(pThis);
    3321         RTMemFree(pThis->paEntries);
    3322         pThis->paEntries = NULL;
    3323     }
    3324     else
    3325         rc = VINF_SUCCESS;
    3326 
    3327     rtFsFatObj_Close(&pThis->Core);
    3328     return rc;
     3485    return rtFsFatObj_QueryInfo(&pThis->pShared->Core, pObjInfo, enmAddAttr);
    33293486}
    33303487
     
    33503507        *phVfsDir = NIL_RTVFSDIR;
    33513508
    3352         PRTFSFATDIR pThis = (PRTFSFATDIR)pvThis;
    3353         uint32_t    offEntryInDir;
    3354         bool        fLong;
    3355         FATDIRENTRY DirEntry;
    3356         rc = rtFsFatDir_FindEntry(pThis, pszEntry, &offEntryInDir, &fLong, &DirEntry);
     3509        PRTFSFATDIR     pThis   = (PRTFSFATDIR)pvThis;
     3510        PRTFSFATDIRSHRD pShared = pThis->pShared;
     3511        uint32_t        offEntryInDir;
     3512        bool            fLong;
     3513        FATDIRENTRY     DirEntry;
     3514        rc = rtFsFatDirShrd_FindEntry(pShared, pszEntry, &offEntryInDir, &fLong, &DirEntry);
    33573515        if (RT_SUCCESS(rc))
    33583516        {
     
    33613519                case FAT_ATTR_DIRECTORY:
    33623520                {
    3363                     rc = rtFsFatDir_New(pThis->Core.pVol, pThis, &DirEntry, offEntryInDir,
    3364                                         RTFSFAT_GET_CLUSTER(&DirEntry, pThis->Core.pVol), UINT64_MAX /*offDisk*/,
    3365                                         DirEntry.cbFile, phVfsDir, NULL /*ppDir*/);
     3521                    rc = rtFsFatDir_New(pShared->Core.pVol, pShared, &DirEntry, offEntryInDir,
     3522                                        RTFSFAT_GET_CLUSTER(&DirEntry, pShared->Core.pVol), UINT64_MAX /*offDisk*/,
     3523                                        DirEntry.cbFile, phVfsDir);
    33663524                    break;
    33673525                }
     
    33883546static DECLCALLBACK(int) rtFsFatDir_OpenFile(void *pvThis, const char *pszFilename, uint32_t fOpen, PRTVFSFILE phVfsFile)
    33893547{
    3390     PRTFSFATDIR pThis = (PRTFSFATDIR)pvThis;
     3548    PRTFSFATDIR     pThis   = (PRTFSFATDIR)pvThis;
     3549    PRTFSFATDIRSHRD pShared = pThis->pShared;
    33913550
    33923551    /*
     
    33963555    bool        fLong;
    33973556    FATDIRENTRY DirEntry;
    3398     int rc = rtFsFatDir_FindEntry(pThis, pszFilename, &offEntryInDir, &fLong, &DirEntry);
     3557    int rc = rtFsFatDirShrd_FindEntry(pShared, pszFilename, &offEntryInDir, &fLong, &DirEntry);
    33993558    if (RT_SUCCESS(rc))
    34003559    {
     
    34083567                        || (fOpen & RTFILE_O_ACTION_MASK) == RTFILE_O_OPEN_CREATE
    34093568                        || (fOpen & RTFILE_O_ACTION_MASK) == RTFILE_O_CREATE_REPLACE)
    3410                         rc = rtFsFatFile_New(pThis->Core.pVol, pThis, &DirEntry, offEntryInDir, fOpen, phVfsFile);
     3569                        rc = rtFsFatFile_New(pShared->Core.pVol, pShared, &DirEntry, offEntryInDir, fOpen, phVfsFile);
    34113570                    else
    34123571                        rc = VERR_ALREADY_EXISTS;
     
    34323591                 || (fOpen & RTFILE_O_ACTION_MASK) == RTFILE_O_CREATE_REPLACE) )
    34333592    {
    3434         rc = rtFsFatDir_CreateEntry(pThis, pszFilename, FAT_ATTR_ARCHIVE, 0 /*cbInitial*/, &offEntryInDir, &DirEntry);
     3593        rc = rtFsFatDirShrd_CreateEntry(pShared, pszFilename, FAT_ATTR_ARCHIVE, 0 /*cbInitial*/, &offEntryInDir, &DirEntry);
    34353594        if (RT_SUCCESS(rc))
    3436             rc = rtFsFatFile_New(pThis->Core.pVol, pThis, &DirEntry, offEntryInDir, fOpen, phVfsFile);
     3595            rc = rtFsFatFile_New(pShared->Core.pVol, pShared, &DirEntry, offEntryInDir, fOpen, phVfsFile);
    34373596    }
    34383597    return rc;
     
    34943653     * Try locate the entry.
    34953654     */
    3496     PRTFSFATDIR pThis = (PRTFSFATDIR)pvThis;
    3497     uint32_t    offEntryInDir;
    3498     bool        fLong;
    3499     FATDIRENTRY DirEntry;
    3500     int rc = rtFsFatDir_FindEntry(pThis, pszEntry, &offEntryInDir, &fLong, &DirEntry);
     3655    PRTFSFATDIR     pThis   = (PRTFSFATDIR)pvThis;
     3656    PRTFSFATDIRSHRD pShared = pThis->pShared;
     3657    uint32_t        offEntryInDir;
     3658    bool            fLong;
     3659    FATDIRENTRY     DirEntry;
     3660    int rc = rtFsFatDirShrd_FindEntry(pShared, pszEntry, &offEntryInDir, &fLong, &DirEntry);
    35013661    Log2(("rtFsFatDir_QueryEntryInfo: FindEntry(,%s,) -> %Rrc\n", pszEntry, rc));
    35023662    if (RT_SUCCESS(rc))
     
    35083668        RTFSFATOBJ TmpObj;
    35093669        RT_ZERO(TmpObj);
    3510         rtFsFatObj_InitFromDirEntry(&TmpObj, &DirEntry, offEntryInDir, pThis->Core.pVol);
     3670        rtFsFatObj_InitFromDirEntry(&TmpObj, &DirEntry, offEntryInDir, pShared->Core.pVol);
    35113671        rc = rtFsFatObj_QueryInfo(&TmpObj, pObjInfo, enmAddAttr);
    35123672    }
     
    35703730        "FatDir",
    35713731        rtFsFatDir_Close,
    3572         rtFsFatObj_QueryInfo,
     3732        rtFsFatDir_QueryInfo,
    35733733        RTVFSOBJOPS_VERSION
    35743734    },
     
    35983758
    35993759
     3760
     3761
    36003762/**
    36013763 * Adds an open child to the parent directory.
     
    36073769 * @param   pDir        The directory.
    36083770 * @param   pChild      The child being opened.
    3609  * @sa      rtFsFatDir_RemoveOpenChild
    3610  */
    3611 static void rtFsFatDir_AddOpenChild(PRTFSFATDIR pDir, PRTFSFATOBJ pChild)
    3612 {
    3613     /* First child that gets opened retains the parent directory.  This is
    3614        released by the final open child. */
    3615     if (RTListIsEmpty(&pDir->OpenChildren))
    3616     {
    3617         uint32_t cRefs = RTVfsDirRetain(pDir->hVfsSelf);
    3618         Assert(cRefs != UINT32_MAX); NOREF(cRefs);
    3619 
    3620         /* Root also retains the whole file system. */
    3621         if (pDir->Core.pVol->pRootDir == pDir)
    3622         {
    3623             Assert(pDir->Core.pVol);
    3624             Assert(pDir->Core.pVol == pChild->pVol);
    3625             cRefs = RTVfsRetain(pDir->Core.pVol->hVfsSelf);
    3626             Assert(cRefs != UINT32_MAX); NOREF(cRefs);
    3627         }
    3628     }
     3771 * @sa      rtFsFatDirShrd_RemoveOpenChild
     3772 */
     3773static void rtFsFatDirShrd_AddOpenChild(PRTFSFATDIRSHRD pDir, PRTFSFATOBJ pChild)
     3774{
     3775    rtFsFatDirShrd_Retain(pDir);
     3776
    36293777    RTListAppend(&pDir->OpenChildren, &pChild->Entry);
    36303778    pChild->pParentDir = pDir;
     
    36413789 *          objects to be released recursively (parent dir and the volume).
    36423790 *
    3643  * @sa      rtFsFatDir_AddOpenChild
    3644  */
    3645 static void rtFsFatDir_RemoveOpenChild(PRTFSFATDIR pDir, PRTFSFATOBJ pChild)
     3791 * @sa      rtFsFatDirShrd_AddOpenChild
     3792 */
     3793static void rtFsFatDirShrd_RemoveOpenChild(PRTFSFATDIRSHRD pDir, PRTFSFATOBJ pChild)
    36463794{
    36473795    AssertReturnVoid(pChild->pParentDir == pDir);
     
    36493797    pChild->pParentDir = NULL;
    36503798
    3651     /* Final child? If so, release directory. */
    3652     if (RTListIsEmpty(&pDir->OpenChildren))
    3653     {
    3654         bool const fIsRootDir = pDir->Core.pVol->pRootDir == pDir;
    3655 
    3656         uint32_t cRefs = RTVfsDirRelease(pDir->hVfsSelf);
    3657         Assert(cRefs != UINT32_MAX); NOREF(cRefs);
    3658 
    3659         /* Root directory releases the file system as well.  Since the volume
    3660            holds a reference to the root directory, it will remain valid after
    3661            the above release. */
    3662         if (fIsRootDir)
    3663         {
    3664             Assert(cRefs > 0);
    3665             Assert(pDir->Core.pVol);
    3666             Assert(pDir->Core.pVol == pChild->pVol);
    3667             cRefs = RTVfsRelease(pDir->Core.pVol->hVfsSelf);
    3668             Assert(cRefs != UINT32_MAX); NOREF(cRefs);
    3669         }
    3670     }
    3671 }
    3672 
    3673 
    3674 /**
    3675  * Instantiates a new directory.
     3799    rtFsFatDirShrd_Release(pDir);
     3800}
     3801
     3802
     3803/**
     3804 * Instantiates a new shared directory instance.
     3805 *
     3806 * @returns IPRT status code.
     3807 * @param   pThis           The FAT volume instance.
     3808 * @param   pParentDir      The parent directory.  This is NULL for the root
     3809 *                          directory.
     3810 * @param   pDirEntry       The parent directory entry. This is NULL for the
     3811 *                          root directory.
     3812 * @param   offEntryInDir   The byte offset of the directory entry in the parent
     3813 *                          directory.  UINT32_MAX if root directory.
     3814 * @param   idxCluster      The cluster where the directory content is to be
     3815 *                          found. This can be UINT32_MAX if a root FAT12/16
     3816 *                          directory.
     3817 * @param   offDisk         The disk byte offset of the FAT12/16 root directory.
     3818 *                          This is UINT64_MAX if idxCluster is given.
     3819 * @param   cbDir           The size of the directory.
     3820 * @param   ppSharedDir     Where to return shared FAT directory instance.
     3821 */
     3822static int rtFsFatDirShrd_New(PRTFSFATVOL pThis, PRTFSFATDIRSHRD pParentDir, PCFATDIRENTRY pDirEntry, uint32_t offEntryInDir,
     3823                              uint32_t idxCluster, uint64_t offDisk, uint32_t cbDir, PRTFSFATDIRSHRD *ppSharedDir)
     3824{
     3825    Assert((idxCluster == UINT32_MAX) != (offDisk == UINT64_MAX));
     3826    Assert((pDirEntry == NULL) == (offEntryInDir == UINT32_MAX));
     3827    *ppSharedDir = NULL;
     3828
     3829    int rc = VERR_NO_MEMORY;
     3830    PRTFSFATDIRSHRD pShared = (PRTFSFATDIRSHRD)RTMemAllocZ(sizeof(*pShared));
     3831    if (pShared)
     3832    {
     3833        /*
     3834         * Initialize it all so rtFsFatDir_Close doesn't trip up in anyway.
     3835         */
     3836        RTListInit(&pShared->OpenChildren);
     3837        if (pDirEntry)
     3838            rtFsFatObj_InitFromDirEntry(&pShared->Core, pDirEntry, offEntryInDir, pThis);
     3839        else
     3840            rtFsFatObj_InitDummy(&pShared->Core, cbDir, RTFS_TYPE_DIRECTORY | RTFS_DOS_DIRECTORY | RTFS_UNIX_ALL_PERMS, pThis);
     3841
     3842        pShared->cEntries           = cbDir / sizeof(FATDIRENTRY);
     3843        pShared->fIsLinearRootDir   = idxCluster == UINT32_MAX;
     3844        pShared->fFullyBuffered     = pShared->fIsLinearRootDir;
     3845        pShared->paEntries          = NULL;
     3846        pShared->offEntriesOnDisk   = UINT64_MAX;
     3847        if (pShared->fFullyBuffered)
     3848            pShared->cbAllocatedForEntries = RT_ALIGN_32(cbDir, pThis->cbSector);
     3849        else
     3850            pShared->cbAllocatedForEntries = pThis->cbSector;
     3851
     3852        /*
     3853         * If clustered backing, read the chain and see if we cannot still do the full buffering.
     3854         */
     3855        if (idxCluster != UINT32_MAX)
     3856        {
     3857            rc = rtFsFatClusterMap_ReadClusterChain(pThis, idxCluster, &pShared->Core.Clusters);
     3858            if (RT_SUCCESS(rc))
     3859            {
     3860                if (   pShared->Core.Clusters.cClusters >= 1
     3861                    && pShared->Core.Clusters.cbChain   <= _64K
     3862                    && rtFsFatChain_IsContiguous(&pShared->Core.Clusters))
     3863                {
     3864                    Assert(pShared->Core.Clusters.cbChain >= cbDir);
     3865                    pShared->cbAllocatedForEntries = pShared->Core.Clusters.cbChain;
     3866                    pShared->fFullyBuffered = true;
     3867                }
     3868            }
     3869        }
     3870        else
     3871        {
     3872            rtFsFatChain_InitEmpty(&pShared->Core.Clusters, pThis);
     3873            rc = VINF_SUCCESS;
     3874        }
     3875        if (RT_SUCCESS(rc))
     3876        {
     3877            /*
     3878             * Allocate and initialize the buffering.  Fill the buffer.
     3879             */
     3880            pShared->paEntries = (PFATDIRENTRYUNION)RTMemAlloc(pShared->cbAllocatedForEntries);
     3881            if (!pShared->paEntries)
     3882            {
     3883                if (pShared->fFullyBuffered && !pShared->fIsLinearRootDir)
     3884                {
     3885                    pShared->fFullyBuffered = false;
     3886                    pShared->cbAllocatedForEntries = pThis->cbSector;
     3887                    pShared->paEntries = (PFATDIRENTRYUNION)RTMemAlloc(pShared->cbAllocatedForEntries);
     3888                }
     3889                if (!pShared->paEntries)
     3890                    rc = VERR_NO_MEMORY;
     3891            }
     3892
     3893            if (RT_SUCCESS(rc))
     3894            {
     3895                if (pShared->fFullyBuffered)
     3896                {
     3897                    pShared->u.Full.cDirtySectors   = 0;
     3898                    pShared->u.Full.cSectors        = pShared->cbAllocatedForEntries / pThis->cbSector;
     3899                    pShared->u.Full.pbDirtySectors  = (uint8_t *)RTMemAllocZ((pShared->u.Full.cSectors + 63) / 8);
     3900                    if (pShared->u.Full.pbDirtySectors)
     3901                        pShared->offEntriesOnDisk   = offDisk != UINT64_MAX ? offDisk
     3902                                                    : rtFsFatClusterToDiskOffset(pThis, idxCluster);
     3903                    else
     3904                        rc = VERR_NO_MEMORY;
     3905                }
     3906                else
     3907                {
     3908                    pShared->offEntriesOnDisk       = rtFsFatClusterToDiskOffset(pThis, idxCluster);
     3909                    pShared->u.Simple.offInDir      = 0;
     3910                    pShared->u.Simple.fDirty        = false;
     3911                }
     3912                if (RT_SUCCESS(rc))
     3913                    rc = RTVfsFileReadAt(pThis->hVfsBacking, pShared->offEntriesOnDisk,
     3914                                         pShared->paEntries, pShared->cbAllocatedForEntries, NULL);
     3915                if (RT_SUCCESS(rc))
     3916                {
     3917                    /*
     3918                     * Link into parent directory so we can use it to update
     3919                     * our directory entry.
     3920                     */
     3921                    if (pParentDir)
     3922                        rtFsFatDirShrd_AddOpenChild(pParentDir, &pShared->Core);
     3923                    *ppSharedDir = pShared;
     3924                    return VINF_SUCCESS;
     3925                }
     3926            }
     3927
     3928            /* Free the buffer on failure so rtFsFatDir_Close doesn't try do anything with it. */
     3929            RTMemFree(pShared->paEntries);
     3930            pShared->paEntries = NULL;
     3931        }
     3932
     3933        Assert(pShared->Core.cRefs == 1);
     3934        rtFsFatDirShrd_Release(pShared);
     3935    }
     3936    return rc;
     3937}
     3938
     3939
     3940/**
     3941 * Instantiates a new directory with a shared structure presupplied.
     3942 *
     3943 * @returns IPRT status code.
     3944 * @param   pThis           The FAT volume instance.
     3945 * @param   pShared         Referenced pointer to the shared structure.  The
     3946 *                          reference is always CONSUMED.
     3947 * @param   phVfsDir        Where to return the directory handle.
     3948 */
     3949static int rtFsFatDir_NewWithShared(PRTFSFATVOL pThis, PRTFSFATDIRSHRD pShared, PRTVFSDIR phVfsDir)
     3950{
     3951    /*
     3952     * Create VFS object around the shared structure.
     3953     */
     3954    PRTFSFATDIR pNewDir;
     3955    int rc = RTVfsNewDir(&g_rtFsFatDirOps, sizeof(*pNewDir), 0 /*fFlags*/, pThis->hVfsSelf,
     3956                         NIL_RTVFSLOCK /*use volume lock*/, phVfsDir, (void **)&pNewDir);
     3957    if (RT_SUCCESS(rc))
     3958    {
     3959        /*
     3960         * Look for existing shared object, create a new one if necessary.
     3961         * We CONSUME a reference to pShared here.
     3962         */
     3963        pNewDir->offDir  = 0;
     3964        pNewDir->pShared = pShared;
     3965        return VINF_SUCCESS;
     3966    }
     3967
     3968    rtFsFatDirShrd_Release(pShared);
     3969    *phVfsDir = NIL_RTVFSDIR;
     3970    return rc;
     3971}
     3972
     3973
     3974
     3975/**
     3976 * Instantiates a new directory VFS, creating the shared structure as necessary.
    36763977 *
    36773978 * @returns IPRT status code.
     
    36903991 * @param   cbDir           The size of the directory.
    36913992 * @param   phVfsDir        Where to return the directory handle.
    3692  * @param   ppDir           Where to return the FAT directory instance data.
    3693  */
    3694 static int rtFsFatDir_New(PRTFSFATVOL pThis, PRTFSFATDIR pParentDir, PCFATDIRENTRY pDirEntry, uint32_t offEntryInDir,
    3695                           uint32_t idxCluster, uint64_t offDisk, uint32_t cbDir, PRTVFSDIR phVfsDir, PRTFSFATDIR *ppDir)
    3696 {
    3697     Assert((idxCluster == UINT32_MAX) != (offDisk == UINT64_MAX));
    3698     Assert((pDirEntry == NULL) == (offEntryInDir == UINT32_MAX));
    3699     if (ppDir)
    3700         *ppDir = NULL;
    3701 
    3702     PRTFSFATDIR pNewDir;
    3703     int rc = RTVfsNewDir(&g_rtFsFatDirOps, sizeof(*pNewDir), pParentDir ? 0 : RTVFSDIR_F_NO_VFS_REF,
    3704                          pThis->hVfsSelf, NIL_RTVFSLOCK /*use volume lock*/, phVfsDir, (void **)&pNewDir);
    3705     if (RT_SUCCESS(rc))
    3706     {
    3707         /*
    3708          * Initialize it all so rtFsFatDir_Close doesn't trip up in anyway.
    3709          */
    3710         RTListInit(&pNewDir->OpenChildren);
    3711         if (pDirEntry)
    3712             rtFsFatObj_InitFromDirEntry(&pNewDir->Core, pDirEntry, offEntryInDir, pThis);
    3713         else
    3714             rtFsFatObj_InitDummy(&pNewDir->Core, cbDir, RTFS_TYPE_DIRECTORY | RTFS_DOS_DIRECTORY | RTFS_UNIX_ALL_PERMS, pThis);
    3715 
    3716         pNewDir->hVfsSelf           = *phVfsDir;
    3717         pNewDir->cEntries           = cbDir / sizeof(FATDIRENTRY);
    3718         pNewDir->fIsLinearRootDir   = idxCluster == UINT32_MAX;
    3719         pNewDir->fFullyBuffered     = pNewDir->fIsLinearRootDir;
    3720         pNewDir->paEntries          = NULL;
    3721         pNewDir->offEntriesOnDisk   = UINT64_MAX;
    3722         if (pNewDir->fFullyBuffered)
    3723             pNewDir->cbAllocatedForEntries = RT_ALIGN_32(cbDir, pThis->cbSector);
    3724         else
    3725             pNewDir->cbAllocatedForEntries = pThis->cbSector;
    3726 
    3727         /*
    3728          * If clustered backing, read the chain and see if we cannot still do the full buffering.
    3729          */
    3730         if (idxCluster != UINT32_MAX)
    3731         {
    3732             rc = rtFsFatClusterMap_ReadClusterChain(pThis, idxCluster, &pNewDir->Core.Clusters);
    3733             if (RT_SUCCESS(rc))
    3734             {
    3735                 if (   pNewDir->Core.Clusters.cClusters >= 1
    3736                     && pNewDir->Core.Clusters.cbChain   <= _64K
    3737                     && rtFsFatChain_IsContiguous(&pNewDir->Core.Clusters))
    3738                 {
    3739                     Assert(pNewDir->Core.Clusters.cbChain >= cbDir);
    3740                     pNewDir->cbAllocatedForEntries = pNewDir->Core.Clusters.cbChain;
    3741                     pNewDir->fFullyBuffered = true;
    3742                 }
    3743             }
    3744         }
    3745         else
    3746             rtFsFatChain_InitEmpty(&pNewDir->Core.Clusters, pThis);
    3747         if (RT_SUCCESS(rc))
    3748         {
    3749             /*
    3750              * Allocate and initialize the buffering.  Fill the buffer.
    3751              */
    3752             pNewDir->paEntries = (PFATDIRENTRYUNION)RTMemAlloc(pNewDir->cbAllocatedForEntries);
    3753             if (!pNewDir->paEntries)
    3754             {
    3755                 if (pNewDir->fFullyBuffered && !pNewDir->fIsLinearRootDir)
    3756                 {
    3757                     pNewDir->fFullyBuffered = false;
    3758                     pNewDir->cbAllocatedForEntries = pThis->cbSector;
    3759                     pNewDir->paEntries = (PFATDIRENTRYUNION)RTMemAlloc(pNewDir->cbAllocatedForEntries);
    3760                 }
    3761                 if (!pNewDir->paEntries)
    3762                     rc = VERR_NO_MEMORY;
    3763             }
    3764 
    3765             if (RT_SUCCESS(rc))
    3766             {
    3767                 if (pNewDir->fFullyBuffered)
    3768                 {
    3769                     pNewDir->u.Full.cDirtySectors   = 0;
    3770                     pNewDir->u.Full.cSectors        = pNewDir->cbAllocatedForEntries / pThis->cbSector;
    3771                     pNewDir->u.Full.pbDirtySectors  = (uint8_t *)RTMemAllocZ((pNewDir->u.Full.cSectors + 63) / 8);
    3772                     if (pNewDir->u.Full.pbDirtySectors)
    3773                         pNewDir->offEntriesOnDisk   = offDisk != UINT64_MAX ? offDisk
    3774                                                     : rtFsFatClusterToDiskOffset(pThis, idxCluster);
    3775                     else
    3776                         rc = VERR_NO_MEMORY;
    3777                 }
    3778                 else
    3779                 {
    3780                     pNewDir->offEntriesOnDisk       = rtFsFatClusterToDiskOffset(pThis, idxCluster);
    3781                     pNewDir->u.Simple.offInDir      = 0;
    3782                     pNewDir->u.Simple.fDirty        = false;
    3783                 }
    3784                 if (RT_SUCCESS(rc))
    3785                     rc = RTVfsFileReadAt(pThis->hVfsBacking, pNewDir->offEntriesOnDisk,
    3786                                          pNewDir->paEntries, pNewDir->cbAllocatedForEntries, NULL);
    3787                 if (RT_SUCCESS(rc))
    3788                 {
    3789                     /*
    3790                      * Link into parent directory so we can use it to update
    3791                      * our directory entry.
    3792                      */
    3793                     if (pParentDir)
    3794                         rtFsFatDir_AddOpenChild(pParentDir, &pNewDir->Core);
    3795                     if (ppDir)
    3796                         *ppDir = pNewDir;
    3797                     return VINF_SUCCESS;
    3798                 }
    3799             }
    3800 
    3801             /* Free the buffer on failure so rtFsFatDir_Close doesn't try do anything with it. */
    3802             RTMemFree(pNewDir->paEntries);
    3803             pNewDir->paEntries = NULL;
    3804         }
    3805 
    3806         RTVfsDirRelease(*phVfsDir);
    3807     }
    3808     *phVfsDir = NIL_RTVFSDIR;
    3809     if (ppDir)
    3810         *ppDir = NULL;
    3811     return rc;
     3993 */
     3994static int  rtFsFatDir_New(PRTFSFATVOL pThis, PRTFSFATDIRSHRD pParentDir, PCFATDIRENTRY pDirEntry, uint32_t offEntryInDir,
     3995                           uint32_t idxCluster, uint64_t offDisk, uint32_t cbDir, PRTVFSDIR phVfsDir)
     3996{
     3997    /*
     3998     * Look for existing shared object, create a new one if necessary.
     3999     */
     4000    PRTFSFATDIRSHRD pShared = (PRTFSFATDIRSHRD)rtFsFatDirShrd_LookupShared(pParentDir, offEntryInDir);
     4001    if (!pShared)
     4002    {
     4003        int rc = rtFsFatDirShrd_New(pThis, pParentDir, pDirEntry, offEntryInDir, idxCluster, offDisk, cbDir, &pShared);
     4004        if (RT_FAILURE(rc))
     4005        {
     4006            *phVfsDir = NIL_RTVFSDIR;
     4007            return rc;
     4008        }
     4009    }
     4010    return rtFsFatDir_NewWithShared(pThis, pShared, phVfsDir);
    38124011}
    38134012
     
    38234022    PRTFSFATVOL pThis = (PRTFSFATVOL)pvThis;
    38244023    LogFlow(("rtFsFatVol_Close(%p)\n", pThis));
    3825     int rc = rtFsFatClusterMap_Destroy(pThis);
    3826 
    3827     if (pThis->hVfsRootDir != NIL_RTVFSDIR)
     4024
     4025    int rc = VINF_SUCCESS;
     4026    if (pThis->pRootDir != NULL)
    38284027    {
    38294028        Assert(RTListIsEmpty(&pThis->pRootDir->OpenChildren));
    3830         uint32_t cRefs = RTVfsDirRelease(pThis->hVfsRootDir);
    3831         Assert(cRefs == 0); NOREF(cRefs);
    3832         pThis->hVfsRootDir = NIL_RTVFSDIR;
    3833         pThis->pRootDir    = NULL;
    3834     }
     4029        Assert(pThis->pRootDir->Core.cRefs == 1);
     4030        rc = rtFsFatDirShrd_Release(pThis->pRootDir);
     4031        pThis->pRootDir = NULL;
     4032    }
     4033
     4034    int rc2 = rtFsFatClusterMap_Destroy(pThis);
     4035    if (RT_SUCCESS(rc))
     4036        rc = rc2;
    38354037
    38364038    RTVfsFileRelease(pThis->hVfsBacking);
     
    38524054
    38534055/**
    3854  * @interface_method_impl{RTVFSOPS,pfnOpenRoo}
     4056 * @interface_method_impl{RTVFSOPS,pfnOpenRoot}
    38554057 */
    38564058static DECLCALLBACK(int) rtFsFatVol_OpenRoot(void *pvThis, PRTVFSDIR phVfsDir)
    38574059{
    38584060    PRTFSFATVOL pThis = (PRTFSFATVOL)pvThis;
    3859     uint32_t cRefs = RTVfsDirRetain(pThis->hVfsRootDir);
    3860     if (cRefs != UINT32_MAX)
    3861     {
    3862         *phVfsDir = pThis->hVfsRootDir;
    3863         return VINF_SUCCESS;
    3864     }
    3865     return VERR_INTERNAL_ERROR_5;
     4061
     4062    rtFsFatDirShrd_Retain(pThis->pRootDir); /* consumed by the next call */
     4063    return rtFsFatDir_NewWithShared(pThis, pThis->pRootDir, phVfsDir);
    38664064}
    38674065
     
    44854683    pThis->cRootDirEntries      = UINT32_MAX;
    44864684    pThis->cbRootDir            = 0;
    4487     pThis->hVfsRootDir          = NIL_RTVFSDIR;
    44884685    pThis->pRootDir             = NULL;
    44894686
     
    45584755     */
    45594756    if (pThis->idxRootDirCluster == UINT32_MAX)
    4560         rc = rtFsFatDir_New(pThis, NULL /*pParentDir*/, NULL /*pDirEntry*/, UINT32_MAX /*offEntryInDir*/,
    4561                             UINT32_MAX, pThis->offRootDir, pThis->cbRootDir,
    4562                             &pThis->hVfsRootDir, &pThis->pRootDir);
     4757        rc = rtFsFatDirShrd_New(pThis, NULL /*pParentDir*/, NULL /*pDirEntry*/, UINT32_MAX /*offEntryInDir*/,
     4758                                UINT32_MAX, pThis->offRootDir, pThis->cbRootDir, &pThis->pRootDir);
    45634759    else
    4564         rc = rtFsFatDir_New(pThis, NULL /*pParentDir*/, NULL /*pDirEntry*/, UINT32_MAX /*offEntryInDir*/,
    4565                             pThis->idxRootDirCluster, UINT64_MAX, pThis->cbRootDir,
    4566                             &pThis->hVfsRootDir, &pThis->pRootDir);
     4760        rc = rtFsFatDirShrd_New(pThis, NULL /*pParentDir*/, NULL /*pDirEntry*/, UINT32_MAX /*offEntryInDir*/,
     4761                                pThis->idxRootDirCluster, UINT64_MAX, pThis->cbRootDir, &pThis->pRootDir);
    45674762    return rc;
    45684763}
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