Changeset 69595 in vbox
- Timestamp:
- Nov 6, 2017 12:48:25 PM (7 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Runtime/common/fs/fatvfs.cpp
r69046 r69595 86 86 *********************************************************************************************************************************/ 87 87 /** Pointer to a FAT directory instance. */ 88 typedef struct RTFSFATDIR *PRTFSFATDIR;88 typedef struct RTFSFATDIRSHRD *PRTFSFATDIRSHRD; 89 89 90 90 … … 134 134 /** The parent directory keeps a list of open objects (RTFSFATOBJ). */ 135 135 RTLISTNODE Entry; 136 /** Reference counter. */ 137 uint32_t volatile cRefs; 136 138 /** The parent directory (not released till all children are close). */ 137 PRTFSFATDIR 139 PRTFSFATDIRSHRD pParentDir; 138 140 /** The byte offset of the directory entry in the parent dir. 139 141 * This is set to UINT32_MAX for the root directory. */ … … 160 162 typedef RTFSFATOBJ *PRTFSFATOBJ; 161 163 162 typedef struct RTFSFATFILE 164 typedef struct RTFSFATFILESHRD 163 165 { 164 166 /** Core FAT object info. */ 165 167 RTFSFATOBJ Core; 168 } RTFSFATFILESHRD; 169 typedef RTFSFATFILESHRD *PRTFSFATFILESHRD; 170 171 172 typedef struct RTFSFATFILE 173 { 174 /** Pointer to the shared data. */ 175 PRTFSFATFILESHRD pShared; 166 176 /** The current file offset. */ 167 177 uint32_t offFile; … … 181 191 * keeps a list of open children. 182 192 */ 183 typedef struct RTFSFATDIR 193 typedef struct RTFSFATDIRSHRD 184 194 { 185 195 /** Core FAT object info. */ 186 196 RTFSFATOBJ Core; 187 /** The VFS handle for this directory (for reference counting). */188 RTVFSDIR hVfsSelf;189 197 /** Open child objects (RTFSFATOBJ). */ 190 198 RTLISTNODE OpenChildren; … … 220 228 /** Number of dirty sectors. */ 221 229 uint32_t cDirtySectors; 222 /** Dirty sector map. */230 /** Dirty sector bitmap (one bit per sector). */ 223 231 uint8_t *pbDirtySectors; 224 232 } Full; … … 233 241 } Simple; 234 242 } u; 243 } RTFSFATDIRSHRD; 244 /** Pointer to a FAT directory instance. */ 245 typedef RTFSFATDIRSHRD *PRTFSFATDIRSHRD; 246 247 248 /** 249 * FAT directory. 250 */ 251 typedef struct RTFSFATDIR 252 { 253 /** Core FAT object info. */ 254 PRTFSFATDIRSHRD pShared; 255 /** The current directory offset. */ 256 uint32_t offDir; 235 257 } RTFSFATDIR; 236 258 /** Pointer to a FAT directory instance. */ … … 365 387 /** The size of the root directory, rounded up to the nearest sector size. */ 366 388 uint32_t cbRootDir; 367 /** The root directory handle. */368 RTVFSDIR hVfsRootDir;369 389 /** The root directory instance data. */ 370 PRTFSFATDIR 390 PRTFSFATDIRSHRD pRootDir; 371 391 372 392 /** Serial number. */ … … 431 451 * Internal Functions * 432 452 *********************************************************************************************************************************/ 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); 453 static PRTFSFATOBJ rtFsFatDirShrd_LookupShared(PRTFSFATDIRSHRD pThis, uint32_t offEntryInDir); 454 static void rtFsFatDirShrd_AddOpenChild(PRTFSFATDIRSHRD pDir, PRTFSFATOBJ pChild); 455 static void rtFsFatDirShrd_RemoveOpenChild(PRTFSFATDIRSHRD pDir, PRTFSFATOBJ pChild); 456 static int rtFsFatDirShrd_GetEntryForUpdate(PRTFSFATDIRSHRD pThis, uint32_t offEntryInDir, 457 PFATDIRENTRY *ppDirEntry, uint32_t *puWriteLock); 458 static int rtFsFatDirShrd_PutEntryAfterUpdate(PRTFSFATDIRSHRD pThis, PFATDIRENTRY pDirEntry, uint32_t uWriteLock); 459 static int rtFsFatDirShrd_Flush(PRTFSFATDIRSHRD pThis); 460 static int rtFsFatDir_New(PRTFSFATVOL pThis, PRTFSFATDIRSHRD pParentDir, PCFATDIRENTRY pDirEntry, uint32_t offEntryInDir, 461 uint32_t idxCluster, uint64_t offDisk, uint32_t cbDir, PRTVFSDIR phVfsDir); 440 462 441 463 … … 1457 1479 { 1458 1480 RTListInit(&pObj->Entry); 1481 pObj->cRefs = 1; 1459 1482 pObj->pParentDir = NULL; 1460 1483 pObj->pVol = pVol; … … 1485 1508 { 1486 1509 RTListInit(&pObj->Entry); 1510 pObj->cRefs = 1; 1487 1511 pObj->pParentDir = NULL; 1488 1512 pObj->pVol = pVol; … … 1515 1539 if (pObj->fMaybeDirtyDirEnt) 1516 1540 { 1517 int rc2 = rtFsFatDir _Flush(pObj->pParentDir);1541 int rc2 = rtFsFatDirShrd_Flush(pObj->pParentDir); 1518 1542 if (RT_SUCCESS(rc2)) 1519 1543 pObj->fMaybeDirtyDirEnt = false; … … 1535 1559 int rc = rtFsFatObj_FlushMetaData(pObj); 1536 1560 if (pObj->pParentDir) 1537 rtFsFatDir _RemoveOpenChild(pObj->pParentDir, pObj);1561 rtFsFatDirShrd_RemoveOpenChild(pObj->pParentDir, pObj); 1538 1562 rtFsFatChain_Delete(&pObj->Clusters); 1539 1563 return rc; … … 1547 1571 { 1548 1572 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 */ 1597 static int rtFsFatObj_QueryInfo(PRTFSFATOBJ pThis, PRTFSOBJINFO pObjInfo, RTFSOBJATTRADD enmAddAttr) 1598 { 1599 LogFlow(("rtFsFatObj_QueryInfo: %p fMode=%#x\n", pThis, pThis->fAttrib)); 1559 1600 1560 1601 pObjInfo->cbObject = pThis->cbObject; … … 1599 1640 1600 1641 /** 1642 * @interface_method_impl{RTVFSOBJOPS,pfnQueryInfo} 1643 */ 1644 static 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 /** 1601 1653 * @interface_method_impl{RTVFSIOSTREAMOPS,pfnRead} 1602 1654 */ 1603 1655 static DECLCALLBACK(int) rtFsFatFile_Read(void *pvThis, RTFOFF off, PCRTSGBUF pSgBuf, bool fBlocking, size_t *pcbRead) 1604 1656 { 1605 PRTFSFATFILE pThis = (PRTFSFATFILE)pvThis; 1657 PRTFSFATFILE pThis = (PRTFSFATFILE)pvThis; 1658 PRTFSFATFILESHRD pShared = pThis->pShared; 1606 1659 AssertReturn(pSgBuf->cSegs != 0, VERR_INTERNAL_ERROR_3); 1607 1660 RT_NOREF(fBlocking); … … 1612 1665 if (off == -1) 1613 1666 off = pThis->offFile; 1614 if ((uint64_t)off >= p This->Core.cbObject)1667 if ((uint64_t)off >= pShared->Core.cbObject) 1615 1668 { 1616 1669 if (pcbRead) … … 1626 1679 */ 1627 1680 int rc = VINF_SUCCESS; 1628 uint32_t cbFileLeft = p This->Core.cbObject - (uint32_t)off;1681 uint32_t cbFileLeft = pShared->Core.cbObject - (uint32_t)off; 1629 1682 uint32_t cbRead = 0; 1630 1683 size_t cbLeft = pSgBuf->paSegs[0].cbSeg; … … 1634 1687 if (cbFileLeft > 0) 1635 1688 { 1636 uint64_t offDisk = rtFsFatChain_FileOffsetToDiskOff(&p This->Core.Clusters, (uint32_t)off, pThis->Core.pVol);1689 uint64_t offDisk = rtFsFatChain_FileOffsetToDiskOff(&pShared->Core.Clusters, (uint32_t)off, pShared->Core.pVol); 1637 1690 if (offDisk != UINT64_MAX) 1638 1691 { 1639 uint32_t cbToRead = p This->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)); 1640 1693 if (cbToRead > cbLeft) 1641 1694 cbToRead = (uint32_t)cbLeft; 1642 1695 if (cbToRead > cbFileLeft) 1643 1696 cbToRead = cbFileLeft; 1644 rc = RTVfsFileReadAt(p This->Core.pVol->hVfsBacking, offDisk, pbDst, cbToRead, NULL);1697 rc = RTVfsFileReadAt(pShared->Core.pVol->hVfsBacking, offDisk, pbDst, cbToRead, NULL); 1645 1698 if (RT_SUCCESS(rc)) 1646 1699 { … … 1737 1790 uint32_t uWriteLock; 1738 1791 PFATDIRENTRY pDirEntry; 1739 rc = rtFsFatDir _GetEntryForUpdate(pObj->pParentDir, pObj->offEntryInDir, &pDirEntry, &uWriteLock);1792 rc = rtFsFatDirShrd_GetEntryForUpdate(pObj->pParentDir, pObj->offEntryInDir, &pDirEntry, &uWriteLock); 1740 1793 if (RT_SUCCESS(rc)) 1741 1794 { … … 1750 1803 pDirEntry->u.idxClusterHigh = (uint16_t)(idxFirstCluster >> 16); 1751 1804 1752 rc = rtFsFatDir _PutEntryAfterUpdate(pObj->pParentDir, pDirEntry, uWriteLock);1805 rc = rtFsFatDirShrd_PutEntryAfterUpdate(pObj->pParentDir, pDirEntry, uWriteLock); 1753 1806 pObj->fMaybeDirtyDirEnt = true; 1754 1807 } … … 1763 1816 static DECLCALLBACK(int) rtFsFatFile_Write(void *pvThis, RTFOFF off, PCRTSGBUF pSgBuf, bool fBlocking, size_t *pcbWritten) 1764 1817 { 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; 1767 1821 AssertReturn(pSgBuf->cSegs != 0, VERR_INTERNAL_ERROR_3); 1768 1822 RT_NOREF(fBlocking); … … 1784 1838 { 1785 1839 /* Figure out how much we can write. Checking for max file size and such. */ 1786 uint32_t cbToWrite = p This->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)); 1787 1841 if (cbToWrite > cbLeft) 1788 1842 cbToWrite = (uint32_t)cbLeft; … … 1799 1853 1800 1854 /* Grow the file? */ 1801 if ((uint32_t)offNew > p This->Core.cbObject)1802 { 1803 rc = rtFsFatObj_SetSize(&p This->Core, (uint32_t)offNew);1855 if ((uint32_t)offNew > pShared->Core.cbObject) 1856 { 1857 rc = rtFsFatObj_SetSize(&pShared->Core, (uint32_t)offNew); 1804 1858 if (RT_SUCCESS(rc)) 1805 1859 { /* likely */} … … 1809 1863 1810 1864 /* Figure the disk offset. */ 1811 uint64_t offDisk = rtFsFatChain_FileOffsetToDiskOff(&p This->Core.Clusters, (uint32_t)off, pVol);1865 uint64_t offDisk = rtFsFatChain_FileOffsetToDiskOff(&pShared->Core.Clusters, (uint32_t)off, pVol); 1812 1866 if (offDisk != UINT64_MAX) 1813 1867 { … … 1843 1897 static DECLCALLBACK(int) rtFsFatFile_Flush(void *pvThis) 1844 1898 { 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); 1848 1903 return RT_FAILURE(rc1) ? rc1 : rc2; 1849 1904 } … … 1939 1994 static DECLCALLBACK(int) rtFsFatFile_Seek(void *pvThis, RTFOFF offSeek, unsigned uMethod, PRTFOFF poffActual) 1940 1995 { 1941 PRTFSFATFILE pThis = (PRTFSFATFILE)pvThis; 1996 PRTFSFATFILE pThis = (PRTFSFATFILE)pvThis; 1997 PRTFSFATFILESHRD pShared = pThis->pShared; 1998 1942 1999 RTFOFF offNew; 1943 2000 switch (uMethod) … … 1947 2004 break; 1948 2005 case RTFILE_SEEK_END: 1949 offNew = (RTFOFF)p This->Core.cbObject + offSeek;2006 offNew = (RTFOFF)pShared->Core.cbObject + offSeek; 1950 2007 break; 1951 2008 case RTFILE_SEEK_CURRENT: … … 1974 2031 static DECLCALLBACK(int) rtFsFatFile_QuerySize(void *pvThis, uint64_t *pcbFile) 1975 2032 { 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; 1978 2036 return VINF_SUCCESS; 1979 2037 } … … 1991 2049 "FatFile", 1992 2050 rtFsFatFile_Close, 1993 rtFsFat Obj_QueryInfo,2051 rtFsFatFile_QueryInfo, 1994 2052 RTVFSOBJOPS_VERSION 1995 2053 }, … … 2033 2091 * @param phVfsFile Where to return the file handle. 2034 2092 */ 2035 static int rtFsFatFile_New(PRTFSFATVOL pThis, PRTFSFATDIR pParentDir, PCFATDIRENTRY pDirEntry, uint32_t offEntryInDir,2093 static int rtFsFatFile_New(PRTFSFATVOL pThis, PRTFSFATDIRSHRD pParentDir, PCFATDIRENTRY pDirEntry, uint32_t offEntryInDir, 2036 2094 uint64_t fOpen, PRTVFSFILE phVfsFile) 2037 2095 { … … 2044 2102 if (RT_SUCCESS(rc)) 2045 2103 { 2104 pNewFile->offFile = 0; 2105 pNewFile->pShared = NULL; 2106 2046 2107 /* 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. 2048 2109 */ 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); 2066 2125 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. */ 2070 2150 RTVfsFileRelease(*phVfsFile); 2071 2151 } … … 2075 2155 2076 2156 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 */ 2164 static 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 } 2077 2178 2078 2179 … … 2083 2184 * @param pThis The directory. 2084 2185 */ 2085 static int rtFsFatDir _FlushFullyBuffered(PRTFSFATDIRpThis)2186 static int rtFsFatDirShrd_FlushFullyBuffered(PRTFSFATDIRSHRD pThis) 2086 2187 { 2087 2188 Assert(pThis->fFullyBuffered); … … 2090 2191 int rc = VINF_SUCCESS; 2091 2192 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)) 2093 2194 { 2094 2195 int rc2 = RTVfsFileWriteAt(hVfsBacking, pThis->offEntriesOnDisk + i * cbSector, 2095 2196 (uint8_t *)pThis->paEntries + i * cbSector, cbSector, NULL); 2096 2197 if (RT_SUCCESS(rc2)) 2097 pThis->u.Full.pbDirtySectors[i] = false;2198 ASMBitClear(pThis->u.Full.pbDirtySectors, i); 2098 2199 else if (RT_SUCCESS(rc)) 2099 2200 rc = rc2; … … 2109 2210 * @param pThis The directory. 2110 2211 */ 2111 static int rtFsFatDir _FlushSimple(PRTFSFATDIRpThis)2212 static int rtFsFatDirShrd_FlushSimple(PRTFSFATDIRSHRD pThis) 2112 2213 { 2113 2214 Assert(!pThis->fFullyBuffered); … … 2134 2235 * @param pThis The directory. 2135 2236 */ 2136 static int rtFsFatDir _Flush(PRTFSFATDIRpThis)2237 static int rtFsFatDirShrd_Flush(PRTFSFATDIRSHRD pThis) 2137 2238 { 2138 2239 if (pThis->fFullyBuffered) 2139 return rtFsFatDir _FlushFullyBuffered(pThis);2140 return rtFsFatDir _FlushSimple(pThis);2240 return rtFsFatDirShrd_FlushFullyBuffered(pThis); 2241 return rtFsFatDirShrd_FlushSimple(pThis); 2141 2242 } 2142 2243 … … 2145 2246 * Gets one or more entires at @a offEntryInDir. 2146 2247 * 2147 * Common worker for rtFsFatDir _GetEntriesAt and rtFsFatDir_GetEntryForUpdate2248 * Common worker for rtFsFatDirShrd_GetEntriesAt and rtFsFatDirShrd_GetEntryForUpdate 2148 2249 * 2149 2250 * @returns IPRT status code. … … 2156 2257 * @a *ppaEntries points to. 2157 2258 * @param puBufferReadLock Where to return the buffer read lock handle. 2158 * Call rtFsFatDir _ReleaseBufferAfterReading when2259 * Call rtFsFatDirShrd_ReleaseBufferAfterReading when 2159 2260 * done. 2160 2261 */ 2161 static int rtFsFatDir _GetEntriesAtCommon(PRTFSFATDIRpThis, uint32_t offEntryInDir, bool fForUpdate,2162 PFATDIRENTRYUNION *ppaEntries, uint32_t *pcEntries, uint32_t *puLock)2262 static int rtFsFatDirShrd_GetEntriesAtCommon(PRTFSFATDIRSHRD pThis, uint32_t offEntryInDir, bool fForUpdate, 2263 PFATDIRENTRYUNION *ppaEntries, uint32_t *pcEntries, uint32_t *puLock) 2163 2264 { 2164 2265 *puLock = UINT32_MAX; … … 2204 2305 rc = VINF_SUCCESS; 2205 2306 else 2206 rc = rtFsFatDir _FlushSimple(pThis);2307 rc = rtFsFatDirShrd_FlushSimple(pThis); 2207 2308 if (RT_SUCCESS(rc)) 2208 2309 { … … 2244 2345 * @param uWriteLock The write lock. 2245 2346 */ 2246 static int rtFsFatDir _PutEntryAfterUpdate(PRTFSFATDIRpThis, PFATDIRENTRY pDirEntry, uint32_t uWriteLock)2347 static int rtFsFatDirShrd_PutEntryAfterUpdate(PRTFSFATDIRSHRD pThis, PFATDIRENTRY pDirEntry, uint32_t uWriteLock) 2247 2348 { 2248 2349 Assert(uWriteLock == UINT32_C(0x80000001)); … … 2251 2352 { 2252 2353 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); 2254 2355 } 2255 2356 else … … 2262 2363 * Gets the pointer to the given directory entry for the purpose of updating it. 2263 2364 * 2264 * Call rtFsFatDir _PutEntryAfterUpdate afterwards.2365 * Call rtFsFatDirShrd_PutEntryAfterUpdate afterwards. 2265 2366 * 2266 2367 * @returns IPRT status code. … … 2271 2372 * @param puWriteLock Where to return the write lock. 2272 2373 */ 2273 static int rtFsFatDir _GetEntryForUpdate(PRTFSFATDIRpThis, uint32_t offEntryInDir, PFATDIRENTRY *ppDirEntry,2274 uint32_t *puWriteLock)2374 static int rtFsFatDirShrd_GetEntryForUpdate(PRTFSFATDIRSHRD pThis, uint32_t offEntryInDir, PFATDIRENTRY *ppDirEntry, 2375 uint32_t *puWriteLock) 2275 2376 { 2276 2377 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); 2279 2380 } 2280 2381 … … 2288 2389 * @param uBufferReadLock The buffer lock. 2289 2390 */ 2290 static void rtFsFatDir _ReleaseBufferAfterReading(PRTFSFATDIRpThis, uint32_t uBufferReadLock)2391 static void rtFsFatDirShrd_ReleaseBufferAfterReading(PRTFSFATDIRSHRD pThis, uint32_t uBufferReadLock) 2291 2392 { 2292 2393 RT_NOREF(pThis, uBufferReadLock); … … 2306 2407 * @a *ppaEntries points to. 2307 2408 * @param puBufferReadLock Where to return the buffer read lock handle. 2308 * Call rtFsFatDir _ReleaseBufferAfterReading when2409 * Call rtFsFatDirShrd_ReleaseBufferAfterReading when 2309 2410 * done. 2310 2411 */ 2311 static int rtFsFatDir _GetEntriesAt(PRTFSFATDIRpThis, 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);2412 static 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); 2316 2417 } 2317 2418 … … 2457 2558 * @param pDirEntry Where to return a copy of the directory entry. 2458 2559 */ 2459 static int rtFsFatDir _FindEntry(PRTFSFATDIRpThis, const char *pszEntry, uint32_t *poffEntryInDir, bool *pfLong,2460 PFATDIRENTRY pDirEntry)2560 static int rtFsFatDirShrd_FindEntry(PRTFSFATDIRSHRD pThis, const char *pszEntry, uint32_t *poffEntryInDir, bool *pfLong, 2561 PFATDIRENTRY pDirEntry) 2461 2562 { 2462 2563 /* Set return values. */ … … 2489 2590 uint32_t cEntries = 0; 2490 2591 PCFATDIRENTRYUNION paEntries = NULL; 2491 int rc = rtFsFatDir _GetEntriesAt(pThis, offEntryInDir, &paEntries, &cEntries, &uBufferLock);2592 int rc = rtFsFatDirShrd_GetEntriesAt(pThis, offEntryInDir, &paEntries, &cEntries, &uBufferLock); 2492 2593 if (RT_FAILURE(rc)) 2493 2594 return rc; … … 2508 2609 if (pThis->Core.pVol->enmBpbVersion >= RTFSFATBPBVER_DOS_2_0) 2509 2610 { 2510 rtFsFatDir _ReleaseBufferAfterReading(pThis, uBufferLock);2611 rtFsFatDirShrd_ReleaseBufferAfterReading(pThis, uBufferLock); 2511 2612 return VERR_FILE_NOT_FOUND; 2512 2613 } … … 2556 2657 *pDirEntry = paEntries[iEntry].Entry; 2557 2658 *pfLong = false; 2558 rtFsFatDir _ReleaseBufferAfterReading(pThis, uBufferLock);2659 rtFsFatDirShrd_ReleaseBufferAfterReading(pThis, uBufferLock); 2559 2660 return VINF_SUCCESS; 2560 2661 } … … 2567 2668 *pDirEntry = paEntries[iEntry].Entry; 2568 2669 *pfLong = true; 2569 rtFsFatDir _ReleaseBufferAfterReading(pThis, uBufferLock);2670 rtFsFatDirShrd_ReleaseBufferAfterReading(pThis, uBufferLock); 2570 2671 return VINF_SUCCESS; 2571 2672 } … … 2574 2675 } 2575 2676 2576 rtFsFatDir _ReleaseBufferAfterReading(pThis, uBufferLock);2677 rtFsFatDirShrd_ReleaseBufferAfterReading(pThis, uBufferLock); 2577 2678 } 2578 2679 … … 2582 2683 2583 2684 /** 2584 * Watered down version of rtFsFatDir _FindEntry that is used by the short name2685 * Watered down version of rtFsFatDirShrd_FindEntry that is used by the short name 2585 2686 * generator to check for duplicates. 2586 2687 * … … 2591 2692 * @param pszEntry The entry to look for. 2592 2693 */ 2593 static int rtFsFatDir _FindEntryShort(PRTFSFATDIRpThis, const char *pszName8Dot3)2694 static int rtFsFatDirShrd_FindEntryShort(PRTFSFATDIRSHRD pThis, const char *pszName8Dot3) 2594 2695 { 2595 2696 Assert(strlen(pszName8Dot3) == 8+3); … … 2608 2709 uint32_t cEntries = 0; 2609 2710 PCFATDIRENTRYUNION paEntries = NULL; 2610 int rc = rtFsFatDir _GetEntriesAt(pThis, offEntryInDir, &paEntries, &cEntries, &uBufferLock);2711 int rc = rtFsFatDirShrd_GetEntriesAt(pThis, offEntryInDir, &paEntries, &cEntries, &uBufferLock); 2611 2712 if (RT_FAILURE(rc)) 2612 2713 return rc; … … 2626 2727 if (pThis->Core.pVol->enmBpbVersion >= RTFSFATBPBVER_DOS_2_0) 2627 2728 { 2628 rtFsFatDir _ReleaseBufferAfterReading(pThis, uBufferLock);2729 rtFsFatDirShrd_ReleaseBufferAfterReading(pThis, uBufferLock); 2629 2730 return VERR_FILE_NOT_FOUND; 2630 2731 } … … 2646 2747 else if (memcmp(paEntries[iEntry].Entry.achName, pszName8Dot3, sizeof(paEntries[iEntry].Entry.achName)) == 0) 2647 2748 { 2648 rtFsFatDir _ReleaseBufferAfterReading(pThis, uBufferLock);2749 rtFsFatDirShrd_ReleaseBufferAfterReading(pThis, uBufferLock); 2649 2750 return VINF_SUCCESS; 2650 2751 } 2651 2752 } 2652 2753 2653 rtFsFatDir _ReleaseBufferAfterReading(pThis, uBufferLock);2754 rtFsFatDirShrd_ReleaseBufferAfterReading(pThis, uBufferLock); 2654 2755 } 2655 2756 … … 2804 2905 2805 2906 /** 2806 * Worker for rtFsFatDir _GenerateShortName.2907 * Worker for rtFsFatDirShrd_GenerateShortName. 2807 2908 */ 2808 2909 static void rtFsFatDir_CopyShortName(char *pszDst, uint32_t cchDst, const char *pszSrc, size_t cchSrc, char chPad) … … 2857 2958 * @param pDirEntry Where to put the short name. 2858 2959 */ 2859 static int rtFsFatDir _GenerateShortName(PRTFSFATDIRpThis, const char *pszEntry, PFATDIRENTRY pDirEntry)2960 static int rtFsFatDirShrd_GenerateShortName(PRTFSFATDIRSHRD pThis, const char *pszEntry, PFATDIRENTRY pDirEntry) 2860 2961 { 2861 2962 /* Do some input parsing. */ … … 2877 2978 { 2878 2979 szShortName[7] = iLastDigit + '0'; 2879 int rc = rtFsFatDir _FindEntryShort(pThis, szShortName);2980 int rc = rtFsFatDirShrd_FindEntryShort(pThis, szShortName); 2880 2981 if (rc == VERR_FILE_NOT_FOUND) 2881 2982 { … … 2896 2997 szShortName[6] = iFirstDigit + '0'; 2897 2998 szShortName[7] = iLastDigit + '0'; 2898 int rc = rtFsFatDir _FindEntryShort(pThis, szShortName);2999 int rc = rtFsFatDirShrd_FindEntryShort(pThis, szShortName); 2899 3000 if (rc == VERR_FILE_NOT_FOUND) 2900 3001 { … … 2920 3021 szShortName[4] = szHex[cchHex - 4]; 2921 3022 szShortName[3] = szHex[cchHex - 5]; 2922 int rc = rtFsFatDir _FindEntryShort(pThis, szShortName);3023 int rc = rtFsFatDirShrd_FindEntryShort(pThis, szShortName); 2923 3024 if (rc == VERR_FILE_NOT_FOUND) 2924 3025 { … … 2949 3050 * @param pcSlots Where to return the actual number of slots used. 2950 3051 */ 2951 static int rtFsFatDir _MaybeCreateLongNameAndShortAlias(PRTFSFATDIRpThis, const char *pszEntry, bool fIs8Dot3Name,2952 PFATDIRENTRY pDirEntry, PFATDIRNAMESLOT paSlots, uint32_t *pcSlots)3052 static int rtFsFatDirShrd_MaybeCreateLongNameAndShortAlias(PRTFSFATDIRSHRD pThis, const char *pszEntry, bool fIs8Dot3Name, 3053 PFATDIRENTRY pDirEntry, PFATDIRNAMESLOT paSlots, uint32_t *pcSlots) 2953 3054 { 2954 3055 RT_NOREF(pThis, pDirEntry, paSlots, pszEntry); … … 2979 3080 */ 2980 3081 if (!fIs8Dot3Name) 2981 rc = rtFsFatDir _GenerateShortName(pThis, pszEntry, pDirEntry);3082 rc = rtFsFatDirShrd_GenerateShortName(pThis, pszEntry, pDirEntry); 2982 3083 if (RT_SUCCESS(rc)) 2983 3084 { … … 3035 3136 * returned. 3036 3137 */ 3037 static int rtFsFatChain_FindFreeEntries(PRTFSFATDIR pThis, uint32_t cEntriesNeeded,3138 static int rtFsFatChain_FindFreeEntries(PRTFSFATDIRSHRD pThis, uint32_t cEntriesNeeded, 3038 3139 uint32_t *poffEntryInDir, uint32_t *pcFreeTail) 3039 3140 { … … 3056 3157 uint32_t cEntries = 0; 3057 3158 PCFATDIRENTRYUNION paEntries = NULL; 3058 int rc = rtFsFatDir _GetEntriesAt(pThis, offEntryInDir, &paEntries, &cEntries, &uBufferLock);3159 int rc = rtFsFatDirShrd_GetEntriesAt(pThis, offEntryInDir, &paEntries, &cEntries, &uBufferLock); 3059 3160 if (RT_FAILURE(rc)) 3060 3161 return rc; … … 3080 3181 *pcFreeTail = cEntriesNeeded; 3081 3182 *poffEntryInDir = offStartFreeEntries; 3082 rtFsFatDir _ReleaseBufferAfterReading(pThis, uBufferLock);3183 rtFsFatDirShrd_ReleaseBufferAfterReading(pThis, uBufferLock); 3083 3184 return VINF_SUCCESS; 3084 3185 } … … 3088 3189 if (pThis->Core.pVol->enmBpbVersion >= RTFSFATBPBVER_DOS_2_0) 3089 3190 { 3090 rtFsFatDir _ReleaseBufferAfterReading(pThis, uBufferLock);3191 rtFsFatDirShrd_ReleaseBufferAfterReading(pThis, uBufferLock); 3091 3192 *pcFreeTail = cFreeEntries = (cbDir - offStartFreeEntries) / sizeof(FATDIRENTRY); 3092 3193 if (cFreeEntries >= cEntriesNeeded) 3093 3194 { 3094 3195 *poffEntryInDir = offStartFreeEntries; 3095 rtFsFatDir _ReleaseBufferAfterReading(pThis, uBufferLock);3196 rtFsFatDirShrd_ReleaseBufferAfterReading(pThis, uBufferLock); 3096 3197 return VINF_SUCCESS; 3097 3198 } … … 3106 3207 } 3107 3208 } 3108 rtFsFatDir _ReleaseBufferAfterReading(pThis, uBufferLock);3209 rtFsFatDirShrd_ReleaseBufferAfterReading(pThis, uBufferLock); 3109 3210 } 3110 3211 *pcFreeTail = cFreeEntries; … … 3123 3224 * @param cMinNewEntries The minimum number of new entries to allocated. 3124 3225 */ 3125 static int rtFsFatChain_GrowDirectory(PRTFSFATDIR pThis, uint32_t cMinNewEntries)3226 static int rtFsFatChain_GrowDirectory(PRTFSFATDIRSHRD pThis, uint32_t cMinNewEntries) 3126 3227 { 3127 3228 RT_NOREF(pThis, cMinNewEntries); … … 3140 3241 * @param poffEntryInDir Where to return the directory offset. 3141 3242 */ 3142 static int rtFsFatChain_InsertEntries(PRTFSFATDIR pThis, PCFATDIRENTRY pDirEntry, PFATDIRNAMESLOT paSlots, uint32_t cSlots,3243 static int rtFsFatChain_InsertEntries(PRTFSFATDIRSHRD pThis, PCFATDIRENTRY pDirEntry, PFATDIRNAMESLOT paSlots, uint32_t cSlots, 3143 3244 uint32_t *poffEntryInDir) 3144 3245 { … … 3179 3280 uint32_t uBufferLock; 3180 3281 PFATDIRENTRY pDstEntry; 3181 rc = rtFsFatDir _GetEntryForUpdate(pThis, offCurrent, &pDstEntry, &uBufferLock);3282 rc = rtFsFatDirShrd_GetEntryForUpdate(pThis, offCurrent, &pDstEntry, &uBufferLock); 3182 3283 if (RT_SUCCESS(rc)) 3183 3284 { … … 3186 3287 else 3187 3288 memcpy(pDstEntry, pDirEntry, sizeof(*pDstEntry)); 3188 rc = rtFsFatDir _PutEntryAfterUpdate(pThis, pDstEntry, uBufferLock);3289 rc = rtFsFatDirShrd_PutEntryAfterUpdate(pThis, pDstEntry, uBufferLock); 3189 3290 if (RT_SUCCESS(rc)) 3190 3291 continue; … … 3197 3298 while (iSrcSlot-- > 0) 3198 3299 { 3199 int rc2 = rtFsFatDir _GetEntryForUpdate(pThis, offFirstInDir + iSrcSlot * sizeof(FATDIRENTRY),3300 int rc2 = rtFsFatDirShrd_GetEntryForUpdate(pThis, offFirstInDir + iSrcSlot * sizeof(FATDIRENTRY), 3200 3301 &pDstEntry, &uBufferLock); 3201 3302 if (RT_SUCCESS(rc2)) 3202 3303 { 3203 3304 pDstEntry->achName[0] = FATDIRENTRY_CH0_DELETED; 3204 rtFsFatDir _PutEntryAfterUpdate(pThis, pDstEntry, uBufferLock);3305 rtFsFatDirShrd_PutEntryAfterUpdate(pThis, pDstEntry, uBufferLock); 3205 3306 } 3206 3307 } … … 3234 3335 * @param pDirEntry Where to return a copy of the directory entry. 3235 3336 * 3236 * @remarks ASSUMES caller has already called rtFsFatDir _FindEntry to make sure3337 * @remarks ASSUMES caller has already called rtFsFatDirShrd_FindEntry to make sure 3237 3338 * the entry doesn't exist. 3238 3339 */ 3239 static int rtFsFatDir _CreateEntry(PRTFSFATDIRpThis, const char *pszEntry, uint8_t fAttrib, uint32_t cbInitial,3240 uint32_t *poffEntryInDir, PFATDIRENTRY pDirEntry)3340 static int rtFsFatDirShrd_CreateEntry(PRTFSFATDIRSHRD pThis, const char *pszEntry, uint8_t fAttrib, uint32_t cbInitial, 3341 uint32_t *poffEntryInDir, PFATDIRENTRY pDirEntry) 3241 3342 { 3242 3343 PRTFSFATVOL pVol = pThis->Core.pVol; … … 3265 3366 FATDIRNAMESLOT aSlots[FATDIRNAMESLOT_MAX_SLOTS]; 3266 3367 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); 3268 3369 if (RT_SUCCESS(rc)) 3269 3370 { … … 3308 3409 3309 3410 3411 /** 3412 * Releases a reference to a shared directory structure. 3413 * 3414 * @param pShared The shared directory structure. 3415 */ 3416 static 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 */ 3458 static void rtFsFatDirShrd_Retain(PRTFSFATDIRSHRD pShared) 3459 { 3460 uint32_t cRefs = ASMAtomicIncU32(&pShared->Core.cRefs); 3461 Assert(cRefs > 1); NOREF(cRefs); 3462 } 3463 3310 3464 3311 3465 /** … … 3314 3468 static DECLCALLBACK(int) rtFsFatDir_Close(void *pvThis) 3315 3469 { 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 */ 3482 static DECLCALLBACK(int) rtFsFatDir_QueryInfo(void *pvThis, PRTFSOBJINFO pObjInfo, RTFSOBJATTRADD enmAddAttr) 3483 { 3316 3484 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); 3329 3486 } 3330 3487 … … 3350 3507 *phVfsDir = NIL_RTVFSDIR; 3351 3508 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); 3357 3515 if (RT_SUCCESS(rc)) 3358 3516 { … … 3361 3519 case FAT_ATTR_DIRECTORY: 3362 3520 { 3363 rc = rtFsFatDir_New(p This->Core.pVol, pThis, &DirEntry, offEntryInDir,3364 RTFSFAT_GET_CLUSTER(&DirEntry, p This->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); 3366 3524 break; 3367 3525 } … … 3388 3546 static DECLCALLBACK(int) rtFsFatDir_OpenFile(void *pvThis, const char *pszFilename, uint32_t fOpen, PRTVFSFILE phVfsFile) 3389 3547 { 3390 PRTFSFATDIR pThis = (PRTFSFATDIR)pvThis; 3548 PRTFSFATDIR pThis = (PRTFSFATDIR)pvThis; 3549 PRTFSFATDIRSHRD pShared = pThis->pShared; 3391 3550 3392 3551 /* … … 3396 3555 bool fLong; 3397 3556 FATDIRENTRY DirEntry; 3398 int rc = rtFsFatDir _FindEntry(pThis, pszFilename, &offEntryInDir, &fLong, &DirEntry);3557 int rc = rtFsFatDirShrd_FindEntry(pShared, pszFilename, &offEntryInDir, &fLong, &DirEntry); 3399 3558 if (RT_SUCCESS(rc)) 3400 3559 { … … 3408 3567 || (fOpen & RTFILE_O_ACTION_MASK) == RTFILE_O_OPEN_CREATE 3409 3568 || (fOpen & RTFILE_O_ACTION_MASK) == RTFILE_O_CREATE_REPLACE) 3410 rc = rtFsFatFile_New(p This->Core.pVol, pThis, &DirEntry, offEntryInDir, fOpen, phVfsFile);3569 rc = rtFsFatFile_New(pShared->Core.pVol, pShared, &DirEntry, offEntryInDir, fOpen, phVfsFile); 3411 3570 else 3412 3571 rc = VERR_ALREADY_EXISTS; … … 3432 3591 || (fOpen & RTFILE_O_ACTION_MASK) == RTFILE_O_CREATE_REPLACE) ) 3433 3592 { 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); 3435 3594 if (RT_SUCCESS(rc)) 3436 rc = rtFsFatFile_New(p This->Core.pVol, pThis, &DirEntry, offEntryInDir, fOpen, phVfsFile);3595 rc = rtFsFatFile_New(pShared->Core.pVol, pShared, &DirEntry, offEntryInDir, fOpen, phVfsFile); 3437 3596 } 3438 3597 return rc; … … 3494 3653 * Try locate the entry. 3495 3654 */ 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); 3501 3661 Log2(("rtFsFatDir_QueryEntryInfo: FindEntry(,%s,) -> %Rrc\n", pszEntry, rc)); 3502 3662 if (RT_SUCCESS(rc)) … … 3508 3668 RTFSFATOBJ TmpObj; 3509 3669 RT_ZERO(TmpObj); 3510 rtFsFatObj_InitFromDirEntry(&TmpObj, &DirEntry, offEntryInDir, p This->Core.pVol);3670 rtFsFatObj_InitFromDirEntry(&TmpObj, &DirEntry, offEntryInDir, pShared->Core.pVol); 3511 3671 rc = rtFsFatObj_QueryInfo(&TmpObj, pObjInfo, enmAddAttr); 3512 3672 } … … 3570 3730 "FatDir", 3571 3731 rtFsFatDir_Close, 3572 rtFsFat Obj_QueryInfo,3732 rtFsFatDir_QueryInfo, 3573 3733 RTVFSOBJOPS_VERSION 3574 3734 }, … … 3598 3758 3599 3759 3760 3761 3600 3762 /** 3601 3763 * Adds an open child to the parent directory. … … 3607 3769 * @param pDir The directory. 3608 3770 * @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 */ 3773 static void rtFsFatDirShrd_AddOpenChild(PRTFSFATDIRSHRD pDir, PRTFSFATOBJ pChild) 3774 { 3775 rtFsFatDirShrd_Retain(pDir); 3776 3629 3777 RTListAppend(&pDir->OpenChildren, &pChild->Entry); 3630 3778 pChild->pParentDir = pDir; … … 3641 3789 * objects to be released recursively (parent dir and the volume). 3642 3790 * 3643 * @sa rtFsFatDir _AddOpenChild3644 */ 3645 static void rtFsFatDir _RemoveOpenChild(PRTFSFATDIRpDir, PRTFSFATOBJ pChild)3791 * @sa rtFsFatDirShrd_AddOpenChild 3792 */ 3793 static void rtFsFatDirShrd_RemoveOpenChild(PRTFSFATDIRSHRD pDir, PRTFSFATOBJ pChild) 3646 3794 { 3647 3795 AssertReturnVoid(pChild->pParentDir == pDir); … … 3649 3797 pChild->pParentDir = NULL; 3650 3798 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 */ 3822 static 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 */ 3949 static 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. 3676 3977 * 3677 3978 * @returns IPRT status code. … … 3690 3991 * @param cbDir The size of the directory. 3691 3992 * @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 */ 3994 static 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); 3812 4011 } 3813 4012 … … 3823 4022 PRTFSFATVOL pThis = (PRTFSFATVOL)pvThis; 3824 4023 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) 3828 4027 { 3829 4028 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; 3835 4037 3836 4038 RTVfsFileRelease(pThis->hVfsBacking); … … 3852 4054 3853 4055 /** 3854 * @interface_method_impl{RTVFSOPS,pfnOpenRoo }4056 * @interface_method_impl{RTVFSOPS,pfnOpenRoot} 3855 4057 */ 3856 4058 static DECLCALLBACK(int) rtFsFatVol_OpenRoot(void *pvThis, PRTVFSDIR phVfsDir) 3857 4059 { 3858 4060 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); 3866 4064 } 3867 4065 … … 4485 4683 pThis->cRootDirEntries = UINT32_MAX; 4486 4684 pThis->cbRootDir = 0; 4487 pThis->hVfsRootDir = NIL_RTVFSDIR;4488 4685 pThis->pRootDir = NULL; 4489 4686 … … 4558 4755 */ 4559 4756 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); 4563 4759 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); 4567 4762 return rc; 4568 4763 }
Note:
See TracChangeset
for help on using the changeset viewer.