Changeset 69659 in vbox
- Timestamp:
- Nov 11, 2017 3:07:04 PM (7 years ago)
- svn:sync-xref-src-repo-rev:
- 119024
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Runtime/common/fs/fatvfs.cpp
r69631 r69659 88 88 /** Pointer to a FAT directory instance. */ 89 89 typedef struct RTFSFATDIRSHRD *PRTFSFATDIRSHRD; 90 /** Pointer to a FAT volume (VFS instance data). */ 91 typedef struct RTFSFATVOL *PRTFSFATVOL; 90 92 91 93 … … 293 295 typedef struct RTFSFATCLUSTERMAPCACHE 294 296 { 295 /** Number of cache entries . */297 /** Number of cache entries (power of two). */ 296 298 uint32_t cEntries; 297 /** The max size of data in a cache entry. */ 299 /** This shift count to use in the first step of the index calculation. */ 300 uint32_t cEntryIndexShift; 301 /** The AND mask to use in the second step of the index calculation. */ 302 uint32_t fEntryIndexMask; 303 /** The max size of data in a cache entry (power of two). */ 298 304 uint32_t cbEntry; 305 /** The AND mask to use to get the entry offset. */ 306 uint32_t fEntryOffsetMask; 299 307 /** Dirty bitmap shift count. */ 300 308 uint32_t cDirtyShift; 301 309 /** The dirty cache line size (multiple of two). */ 302 310 uint32_t cbDirtyLine; 311 /** The FAT size. */ 312 uint32_t cbFat; 313 /** Pointer to the volume (for disk access). */ 314 PRTFSFATVOL pVol; 303 315 /** The cache name. */ 304 316 const char *pszName; … … 420 432 FAT32INFOSECTOR Fat32InfoSector; 421 433 } RTFSFATVOL; 422 /** Pointer to a FAT volume (VFS instance data). */423 typedef RTFSFATVOL *PRTFSFATVOL;424 434 /** Pointer to a const FAT volume (VFS instance data). */ 425 435 typedef RTFSFATVOL const *PCRTFSFATVOL; … … 777 787 * Figure the cache size. Keeping it _very_ simple for now as we just need 778 788 * something that works, not anything the performs like crazy. 789 * 790 * Note! Lowering the max cache size below 128KB will break ASSUMPTIONS in the FAT16 791 * and eventually FAT12 code. 779 792 */ 780 793 uint32_t cEntries; 794 uint32_t cEntryIndexShift; 795 uint32_t fEntryIndexMask; 781 796 uint32_t cbEntry = pThis->cbFat; 797 uint32_t fEntryOffsetMask; 782 798 if (cbEntry <= _512K) 783 cEntries = 1; 799 { 800 cEntries = 1; 801 cEntryIndexShift = 0; 802 fEntryIndexMask = 0; 803 fEntryOffsetMask = UINT32_MAX; 804 } 784 805 else 785 806 { 786 807 Assert(pThis->cbSector < _512K / 8); 787 cEntries = 8; 788 cbEntry = pThis->cbSector; 808 cEntries = 8; 809 cEntryIndexShift = 9; 810 fEntryIndexMask = cEntries - 1; 811 AssertReturn(RT_IS_POWER_OF_TWO(cEntries), VERR_INTERNAL_ERROR_4); 812 813 cbEntry = pThis->cbSector; 814 fEntryOffsetMask = pThis->cbSector - 1; 815 AssertReturn(RT_IS_POWER_OF_TWO(cbEntry), VERR_INTERNAL_ERROR_5); 789 816 } 790 817 … … 796 823 if (!pCache) 797 824 return RTErrInfoSet(pErrInfo, VERR_NO_MEMORY, "Failed to allocate FAT cache"); 798 pCache->cEntries = cEntries; 799 pCache->cbEntry = cbEntry; 825 pCache->cEntries = cEntries; 826 pCache->fEntryIndexMask = fEntryIndexMask; 827 pCache->cEntryIndexShift = cEntryIndexShift; 828 pCache->cbEntry = cbEntry; 829 pCache->fEntryOffsetMask = fEntryOffsetMask; 830 pCache->pVol = pThis; 831 pCache->cbFat = pThis->cbFat; 800 832 801 833 unsigned i = cEntries; … … 814 846 pCache->aEntries[i].bmDirty = 0; 815 847 } 848 Log3(("rtFsFatClusterMap_Create: cbFat=%#RX32 cEntries=%RU32 cEntryIndexShift=%RU32 fEntryIndexMask=%#RX32\n", 849 pCache->cbFat, pCache->cEntries, pCache->cEntryIndexShift, pCache->fEntryIndexMask)); 850 Log3(("rtFsFatClusterMap_Create: cbEntries=%#RX32 fEntryOffsetMask=%#RX32\n", pCache->cbEntry, pCache->fEntryOffsetMask)); 816 851 817 852 /* … … 829 864 pCache->cbDirtyLine <<= 1; 830 865 } 866 Assert(pCache->cEntries == 1 || pCache->cbDirtyLine == pThis->cbSector); 867 Log3(("rtFsFatClusterMap_Create: cbDirtyLine=%#RX32 cDirtyShift=%u\n", pCache->cbDirtyLine, pCache->cDirtyShift)); 831 868 832 869 /* … … 976 1013 977 1014 978 #if 0 /* unused */ 979 /** 980 * Flushes out all dirty lines in the file allocation table (cluster map) cache.1015 /** 1016 * Flushes out all dirty lines in the file allocation table (cluster map) cache 1017 * entry. 981 1018 * 982 1019 * This is typically called prior to reusing the cache entry. … … 990 1027 return rtFsFatClusterMap_FlushWorker(pThis, iEntry, iEntry); 991 1028 } 992 #endif 1029 1030 1031 /** 1032 * Gets a pointer to a FAT entry. 1033 * 1034 * @returns IPRT status code. On failure, we're currently kind of screwed. 1035 * @param pCache The FAT cache. 1036 * @param pThis The FAT volume instance. 1037 * @param offFat The FAT byte offset to get the entry off. 1038 * @param ppbEntry Where to return the pointer to the entry. 1039 */ 1040 static int rtFsFatClusterMap_GetEntry(PRTFSFATCLUSTERMAPCACHE pCache, PRTFSFATVOL pThis, uint32_t offFat, uint8_t **ppbEntry) 1041 { 1042 int rc; 1043 if (offFat < pThis->cbFat) 1044 { 1045 uint32_t const iEntry = (offFat >> pCache->cEntryIndexShift) & pCache->fEntryIndexMask; 1046 uint32_t const offInEntry = offFat & pCache->fEntryOffsetMask; 1047 uint32_t const offFatEntry = offFat - offInEntry; 1048 1049 *ppbEntry = pCache->aEntries[iEntry].pbData + offInEntry; 1050 1051 /* If it's already ready, return immediately. */ 1052 if (pCache->aEntries[iEntry].offFat == offFatEntry) 1053 { 1054 Log3(("rtFsFatClusterMap_GetEntry: Hit entry %u for offFat=%#RX32\n", iEntry, offFat)); 1055 return VINF_SUCCESS; 1056 } 1057 1058 /* Do we need to flush it? */ 1059 rc = VINF_SUCCESS; 1060 if ( pCache->aEntries[iEntry].bmDirty != 0 1061 && pCache->aEntries[iEntry].offFat != UINT32_MAX) 1062 { 1063 Log3(("rtFsFatClusterMap_GetEntry: Flushing entry %u for offFat=%#RX32\n", iEntry, offFat)); 1064 rc = rtFsFatClusterMap_FlushEntry(pThis, iEntry); 1065 } 1066 if (RT_SUCCESS(rc)) 1067 { 1068 pCache->aEntries[iEntry].bmDirty = 0; 1069 1070 /* Read in the entry from disk */ 1071 rc = RTVfsFileReadAt(pThis->hVfsBacking, pThis->aoffFats[0] + offFatEntry, pCache->aEntries[iEntry].pbData, 1072 pCache->cbEntry, NULL); 1073 if (RT_SUCCESS(rc)) 1074 { 1075 Log3(("rtFsFatClusterMap_GetEntry: Loaded entry %u for offFat=%#RX32\n", iEntry, offFat)); 1076 pCache->aEntries[iEntry].offFat = offFatEntry; 1077 return VINF_SUCCESS; 1078 } 1079 /** @todo We can try other FAT copies here... */ 1080 LogRel(("rtFsFatClusterMap_GetEntry: Error loading entry %u for offFat=%#RX32 (%#64RX32 LB %#x): %Rrc\n", 1081 iEntry, offFat, pThis->aoffFats[0] + offFatEntry, pCache->cbEntry, rc)); 1082 pCache->aEntries[iEntry].offFat = UINT32_MAX; 1083 } 1084 } 1085 else 1086 rc = VERR_OUT_OF_RANGE; 1087 *ppbEntry = NULL; 1088 return rc; 1089 } 1090 993 1091 994 1092 … … 1119 1217 PRTFSFATCHAIN pChain) 1120 1218 { 1121 RT_NOREF(pFatCache, pVol, idxCluster, pChain); 1122 return VERR_NOT_IMPLEMENTED; 1219 /* Special case for empty files. */ 1220 if (idxCluster == 0) 1221 return VINF_SUCCESS; 1222 1223 /* Work cluster by cluster. */ 1224 for (;;) 1225 { 1226 /* Validate the cluster, checking for end of file. */ 1227 if ( idxCluster >= pVol->cClusters 1228 || idxCluster < FAT_FIRST_DATA_CLUSTER) 1229 { 1230 if (idxCluster >= FAT_FIRST_FAT32_EOC) 1231 return VINF_SUCCESS; 1232 return VERR_VFS_BOGUS_OFFSET; 1233 } 1234 1235 /* Add cluster to chain. */ 1236 int rc = rtFsFatChain_Append(pChain, idxCluster); 1237 if (RT_FAILURE(rc)) 1238 return rc; 1239 1240 /* Get the next cluster. */ 1241 uint8_t *pbEntry; 1242 rc = rtFsFatClusterMap_GetEntry(pFatCache, pVol, idxCluster * 4, &pbEntry); 1243 if (RT_SUCCESS(rc)) 1244 idxCluster = RT_MAKE_U32_FROM_U8(pbEntry[0], pbEntry[1], pbEntry[2], pbEntry[3]); 1245 else 1246 return rc; 1247 } 1123 1248 } 1124 1249 … … 4164 4289 { 4165 4290 rc = RTUtf16CalcUtf8LenEx(wszName, cwcName, &cchName); 4166 if (RT_FAILURE(rc)) 4167 { 4168 fLongName = false; 4169 cwcName = 0; 4170 } 4291 if (RT_SUCCESS(rc)) 4292 fLongName = true; 4171 4293 } 4172 4294 if (!fLongName)
Note:
See TracChangeset
for help on using the changeset viewer.