Changeset 66674 in vbox for trunk/src/VBox/Runtime/common
- Timestamp:
- Apr 25, 2017 3:29:11 PM (8 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Runtime/common/filesystem/fatvfs.cpp
r66672 r66674 132 132 /** Pointer to the volume. */ 133 133 struct RTFSFATVOL *pVol; 134 /** Set if we've maybe dirtied the FAT. */ 135 bool fMaybeDirtyFat; 136 /** Set if we've maybe dirtied the directory entry. */ 137 bool fMaybeDirtyDirEnt; 134 138 } RTFSFATOBJ; 135 139 typedef RTFSFATOBJ *PRTFSFATOBJ; … … 138 142 { 139 143 /** Core FAT object info. */ 140 RTFSFATOBJ Core;144 RTFSFATOBJ Core; 141 145 /** The current file offset. */ 142 uint32_t offFile; 143 /** Set if we've maybe dirtied the FAT. */ 144 bool fMaybeDirtyFat; 145 /** Set if we've maybe dirtied the directory entry. */ 146 bool fMaybeDirtyDirEnt; 146 uint32_t offFile; 147 147 } RTFSFATFILE; 148 148 typedef RTFSFATFILE *PRTFSFATFILE; … … 419 419 * Internal Functions * 420 420 *********************************************************************************************************************************/ 421 static int rtFsFatFile_FlushMetaData(PRTFSFATFILE pThis);422 421 static void rtFsFatDir_AddOpenChild(PRTFSFATDIR pDir, PRTFSFATOBJ pChild); 423 422 static void rtFsFatDir_RemoveOpenChild(PRTFSFATDIR pDir, PRTFSFATOBJ pChild); … … 445 444 446 445 446 #ifdef RT_STRICT 447 /** 448 * Assert chain consistency. 449 */ 450 static bool rtFsFatChain_AssertValid(PCRTFSFATCHAIN pChain) 451 { 452 bool fRc = true; 453 uint32_t cParts = 0; 454 PRTFSFATCHAINPART pPart; 455 RTListForEach(&pChain->ListParts, pPart, RTFSFATCHAINPART, ListEntry) 456 cParts++; 457 458 uint32_t cExpected = (pChain->cClusters + RTFSFATCHAINPART_ENTRIES - 1) / RTFSFATCHAINPART_ENTRIES; 459 AssertMsgStmt(cExpected == cParts, ("cExpected=%#x cParts=%#x\n", cExpected, cParts), fRc = false); 460 AssertMsgStmt(pChain->cbChain == (pChain->cClusters << pChain->cClusterByteShift), 461 ("cExpected=%#x cParts=%#x\n", cExpected, cParts), fRc = false); 462 return fRc; 463 } 464 #endif /* RT_STRICT */ 465 466 447 467 /** 448 468 * Initializes an empty cluster chain. … … 486 506 return VINF_SUCCESS; 487 507 } 508 509 510 /** 511 * Reduces the number of clusters in the chain to @a cClusters. 512 * 513 * @param pChain The chain. 514 * @param cClustersNew The new cluster count. Must be equal or smaller to 515 * the current number of clusters. 516 */ 517 static void rtFsFatChain_Shrink(PRTFSFATCHAIN pChain, uint32_t cClustersNew) 518 { 519 uint32_t cOldParts = (pChain->cClusters + RTFSFATCHAINPART_ENTRIES - 1) / RTFSFATCHAINPART_ENTRIES; 520 uint32_t cNewParts = (cClustersNew + RTFSFATCHAINPART_ENTRIES - 1) / RTFSFATCHAINPART_ENTRIES; 521 Assert(cOldParts >= cNewParts); 522 while (cOldParts-- > cNewParts) 523 RTMemFree(RTListRemoveLast(&pChain->ListParts, RTFSFATCHAINPART, ListEntry)); 524 pChain->cClusters = cClustersNew; 525 pChain->cbChain = cClustersNew << pChain->cClusterByteShift; 526 Assert(rtFsFatChain_AssertValid(pChain)); 527 } 528 488 529 489 530 … … 593 634 } 594 635 595 #ifdef RT_STRICT 596 /** 597 * Assert chain consistency. 598 */ 599 static bool rtFsFatChain_AssertValid(PCRTFSFATCHAIN pChain) 600 { 601 bool fRc = true; 602 uint32_t cParts = 0; 603 PRTFSFATCHAINPART pPart; 604 RTListForEach(&pChain->ListParts, pPart, RTFSFATCHAINPART, ListEntry) 605 cParts++; 606 607 uint32_t cExpected = (pChain->cClusters + RTFSFATCHAINPART_ENTRIES - 1) / RTFSFATCHAINPART_ENTRIES; 608 AssertMsgStmt(cExpected == cParts, ("cExpected=%#x cParts=%#x\n", cExpected, cParts), fRc = false); 609 AssertMsgStmt(pChain->cbChain == (pChain->cClusters << pChain->cClusterByteShift), 610 ("cExpected=%#x cParts=%#x\n", cExpected, cParts), fRc = false); 611 return fRc; 612 } 613 #endif /* RT_STRICT */ 636 637 /** 638 * Gets the first cluster. 639 * 640 * @returns The cluster number, UINT32_MAX if empty 641 * @param pChain The chain. 642 */ 643 static uint32_t rtFsFatChain_GetFirstCluster(PCRTFSFATCHAIN pChain) 644 { 645 if (pChain->cClusters > 0) 646 { 647 PRTFSFATCHAINPART pPart = RTListGetFirst(&pChain->ListParts, RTFSFATCHAINPART, ListEntry); 648 return pPart->aEntries[0]; 649 } 650 return UINT32_MAX; 651 } 652 653 654 655 /** 656 * Gets the last cluster. 657 * 658 * @returns The cluster number, UINT32_MAX if empty 659 * @param pChain The chain. 660 */ 661 static uint32_t rtFsFatChain_GetLastCluster(PCRTFSFATCHAIN pChain) 662 { 663 if (pChain->cClusters > 0) 664 { 665 PRTFSFATCHAINPART pPart = RTListGetLast(&pChain->ListParts, RTFSFATCHAINPART, ListEntry); 666 return pPart->aEntries[(pChain->cClusters - 1) % RTFSFATCHAINPART_ENTRIES]; 667 } 668 return UINT32_MAX; 669 } 670 614 671 615 672 /** … … 713 770 { 714 771 PRTFSFATCLUSTERMAPCACHE pCache = pThis->pFatCache; 772 715 773 716 774 /* … … 748 806 && offEntry) 749 807 { 808 Assert(SgBuf.cSegs > 0); 750 809 Assert( (uintptr_t)aSgSegs[SgBuf.cSegs - 1].pvSeg + aSgSegs[SgBuf.cSegs - 1].cbSeg 751 810 == (uintptr_t)&pCache->aEntries[iEntry].pbData[offEntry]); … … 755 814 else 756 815 { 816 /* Starting new job? */ 817 if (off == UINT64_MAX) 818 { 819 off = offDirtyLine; 820 Assert(SgBuf.cSegs == 0); 821 } 757 822 /* flush if not adjacent or if we're out of segments. */ 758 if ( offDirtyLine != offEdge759 || SgBuf.cSegs >= RT_ELEMENTS(aSgSegs))823 else if ( offDirtyLine != offEdge 824 || SgBuf.cSegs >= RT_ELEMENTS(aSgSegs)) 760 825 { 761 826 int rc2 = RTVfsFileSgWrite(pThis->hVfsBacking, off, &SgBuf, true /*fBlocking*/, NULL); … … 764 829 RTSgBufReset(&SgBuf); 765 830 SgBuf.cSegs = 0; 831 off = offDirtyLine; 766 832 } 767 833 … … 777 843 break; 778 844 } 845 iDirtyLine <<= 1; 846 offEntry += pCache->cbDirtyLine; 779 847 } 780 iDirtyLine++; 781 offEntry += pCache->cbDirtyLine; 848 Assert(!bmDirty); 782 849 } 783 850 } … … 963 1030 964 1031 1032 /** 1033 * Sets bmDirty for entry @a iEntry. 1034 * 1035 * @param pFatCache The FAT cache. 1036 * @param iEntry The cache entry. 1037 * @param offEntry The offset into the cache entry that was dirtied. 1038 */ 1039 DECLINLINE(void) rtFsFatClusterMap_SetDirtyByte(PRTFSFATCLUSTERMAPCACHE pFatCache, uint32_t iEntry, uint32_t offEntry) 1040 { 1041 uint8_t iLine = offEntry / pFatCache->cbDirtyLine; 1042 pFatCache->aEntries[iEntry].bmDirty |= RT_BIT_64(iLine); 1043 } 1044 1045 965 1046 /** Sets a FAT12 cluster value. */ 966 1047 static int rtFsFatClusterMap_SetCluster12(PRTFSFATCLUSTERMAPCACHE pFatCache, PRTFSFATVOL pVol, … … 979 1060 if (idxCluster & 1) 980 1061 { 981 pbFat[offFat] = ( 0x0f | pbFat[offFat]) | ((uValue & 0xf)<< 4);1062 pbFat[offFat] = ((uint8_t)0x0f & pbFat[offFat]) | ((uint8_t)uValue << 4); 982 1063 pbFat[offFat + 1] = (uint8_t)(uValue >> 4); 983 1064 } … … 985 1066 { 986 1067 pbFat[offFat] = (uint8_t)uValue; 987 pbFat[offFat + 1] = ( 0xf0 | pbFat[offFat + 1]) | ((uValue >> 8) | 0xf);1068 pbFat[offFat + 1] = ((uint8_t)0xf0 & pbFat[offFat + 1]) | (uint8_t)(uValue >> 8); 988 1069 } 989 1070 990 1071 /* Update the dirty bits. */ 991 pFatCache->aEntries[0].bmDirty |= RT_BIT_64(offFat >> pFatCache->cDirtyShift);992 pFatCache->aEntries[0].bmDirty |= RT_BIT_64((offFat + 1) >> pFatCache->cDirtyShift);1072 rtFsFatClusterMap_SetDirtyByte(pFatCache, 0, offFat); 1073 rtFsFatClusterMap_SetDirtyByte(pFatCache, 0, offFat + 1); 993 1074 994 1075 return VINF_SUCCESS; … … 1053 1134 case RTFSFATTYPE_FAT16: return rtFsFatClusterMap_SetCluster16(pThis->pFatCache, pThis, idxCluster, 0); 1054 1135 case RTFSFATTYPE_FAT32: return rtFsFatClusterMap_SetCluster32(pThis->pFatCache, pThis, idxCluster, 0); 1136 default: AssertFailedReturn(VERR_INTERNAL_ERROR_3); 1137 } 1138 } 1139 1140 1141 /** 1142 * Worker for rtFsFatClusterMap_AllocateCluster that handles FAT12. 1143 */ 1144 static int rtFsFatClusterMap_AllocateCluster12(PRTFSFATCLUSTERMAPCACHE pFatCache, PRTFSFATVOL pVol, 1145 uint32_t idxPrevCluster, uint32_t *pidxCluster) 1146 { 1147 /* ASSUME that for FAT12 we cache the whole FAT in a single entry. That 1148 way we don't need to deal with entries in different sectors and whatnot. */ 1149 AssertReturn(pFatCache->cEntries == 1, VERR_INTERNAL_ERROR_4); 1150 AssertReturn(pFatCache->cbEntry == pVol->cbFat, VERR_INTERNAL_ERROR_4); 1151 AssertReturn(pFatCache->aEntries[0].offFat == 0, VERR_INTERNAL_ERROR_4); 1152 1153 /* 1154 * Check that the previous cluster is a valid chain end. 1155 */ 1156 uint8_t *pbFat = pFatCache->aEntries[0].pbData; 1157 uint32_t offFatPrev; 1158 if (idxPrevCluster != UINT32_MAX) 1159 { 1160 offFatPrev = idxPrevCluster * 3 / 2; 1161 uint32_t idxPrevValue; 1162 if (idxPrevCluster & 1) 1163 idxPrevValue = (pbFat[offFatPrev] >> 4) | ((uint32_t)pbFat[offFatPrev + 1] << 4); 1164 else 1165 idxPrevValue = pbFat[offFatPrev] | ((uint32_t)(pbFat[offFatPrev + 1] & 0x0f) << 8); 1166 AssertReturn(idxPrevValue >= FAT_FIRST_FAT12_EOC, VERR_VFS_BOGUS_OFFSET); 1167 } 1168 else 1169 offFatPrev = UINT32_MAX; 1170 1171 /* 1172 * Search cluster by cluster from the start (it's small, so easy trumps 1173 * complicated optimizations). 1174 */ 1175 uint32_t idxCluster = FAT_FIRST_DATA_CLUSTER; 1176 uint32_t offFat = 3; 1177 while (idxCluster < pVol->cClusters) 1178 { 1179 if (idxCluster & 1) 1180 { 1181 if ( (pbFat[offFat] & 0xf0) != 0 1182 || pbFat[offFat + 1] != 0) 1183 { 1184 offFat += 2; 1185 idxCluster++; 1186 continue; 1187 } 1188 1189 /* Set EOC. */ 1190 pbFat[offFat] |= 0xf0; 1191 pbFat[offFat + 1] = 0xff; 1192 } 1193 else if ( pbFat[offFat] 1194 || pbFat[offFat + 1] & 0x0f) 1195 { 1196 offFat += 1; 1197 idxCluster++; 1198 continue; 1199 } 1200 else 1201 { 1202 /* Set EOC. */ 1203 pbFat[offFat] = 0xff; 1204 pbFat[offFat + 1] |= 0x0f; 1205 } 1206 1207 /* Update the dirty bits. */ 1208 rtFsFatClusterMap_SetDirtyByte(pFatCache, 0, offFat); 1209 rtFsFatClusterMap_SetDirtyByte(pFatCache, 0, offFat + 1); 1210 1211 /* Chain it on the previous cluster. */ 1212 if (idxPrevCluster != UINT32_MAX) 1213 { 1214 if (idxPrevCluster & 1) 1215 { 1216 pbFat[offFatPrev] = (pbFat[offFatPrev] & (uint8_t)0x0f) | (uint8_t)(idxCluster << 4); 1217 pbFat[offFatPrev + 1] = (uint8_t)(idxCluster >> 4); 1218 } 1219 else 1220 { 1221 pbFat[offFatPrev] = (uint8_t)idxCluster; 1222 pbFat[offFatPrev + 1] = (pbFat[offFatPrev] & (uint8_t)0xf0) | ((uint8_t)(idxCluster >> 8) & (uint8_t)0x0f); 1223 } 1224 rtFsFatClusterMap_SetDirtyByte(pFatCache, 0, offFatPrev); 1225 rtFsFatClusterMap_SetDirtyByte(pFatCache, 0, offFatPrev + 1); 1226 } 1227 1228 *pidxCluster = idxCluster; 1229 return VINF_SUCCESS; 1230 } 1231 1232 return VERR_DISK_FULL; 1233 } 1234 1235 1236 /** 1237 * Worker for rtFsFatClusterMap_AllocateCluster that handles FAT16. 1238 */ 1239 static int rtFsFatClusterMap_AllocateCluster16(PRTFSFATCLUSTERMAPCACHE pFatCache, PRTFSFATVOL pVol, 1240 uint32_t idxPrevCluster, uint32_t *pidxCluster) 1241 { 1242 RT_NOREF(pFatCache, pVol, idxPrevCluster, pidxCluster); 1243 return VERR_NOT_IMPLEMENTED; 1244 } 1245 1246 1247 /** 1248 * Worker for rtFsFatClusterMap_AllocateCluster that handles FAT32. 1249 */ 1250 static int rtFsFatClusterMap_AllocateCluster32(PRTFSFATCLUSTERMAPCACHE pFatCache, PRTFSFATVOL pVol, 1251 uint32_t idxPrevCluster, uint32_t *pidxCluster) 1252 { 1253 RT_NOREF(pFatCache, pVol, idxPrevCluster, pidxCluster); 1254 return VERR_NOT_IMPLEMENTED; 1255 } 1256 1257 1258 /** 1259 * Allocates a cluster an appends it to the chain given by @a idxPrevCluster. 1260 * 1261 * @returns IPRT status code. 1262 * @retval VERR_DISK_FULL if no more available clusters. 1263 * @param pThis The FAT volume instance. 1264 * @param idxPrevCluster The previous cluster, UINT32_MAX if first. 1265 * @param pidxCluster Where to return the cluster number on success. 1266 */ 1267 static int rtFsFatClusterMap_AllocateCluster(PRTFSFATVOL pThis, uint32_t idxPrevCluster, uint32_t *pidxCluster) 1268 { 1269 AssertReturn(idxPrevCluster == UINT32_MAX || (idxPrevCluster >= FAT_FIRST_DATA_CLUSTER && idxPrevCluster < pThis->cClusters), 1270 VERR_INTERNAL_ERROR_5); 1271 *pidxCluster = UINT32_MAX; 1272 switch (pThis->enmFatType) 1273 { 1274 case RTFSFATTYPE_FAT12: return rtFsFatClusterMap_AllocateCluster12(pThis->pFatCache, pThis, idxPrevCluster, pidxCluster); 1275 case RTFSFATTYPE_FAT16: return rtFsFatClusterMap_AllocateCluster16(pThis->pFatCache, pThis, idxPrevCluster, pidxCluster); 1276 case RTFSFATTYPE_FAT32: return rtFsFatClusterMap_AllocateCluster32(pThis->pFatCache, pThis, idxPrevCluster, pidxCluster); 1055 1277 default: AssertFailedReturn(VERR_INTERNAL_ERROR_3); 1056 1278 } … … 1111 1333 { 1112 1334 RTListInit(&pObj->Entry); 1113 pObj->pParentDir = NULL; 1114 pObj->pVol = pVol; 1115 pObj->offEntryInDir = offEntryInDir; 1116 pObj->fAttrib = ((RTFMODE)pDirEntry->fAttrib << RTFS_DOS_SHIFT) & RTFS_DOS_MASK_OS2; 1117 pObj->cbObject = pDirEntry->cbFile; 1335 pObj->pParentDir = NULL; 1336 pObj->pVol = pVol; 1337 pObj->offEntryInDir = offEntryInDir; 1338 pObj->fAttrib = ((RTFMODE)pDirEntry->fAttrib << RTFS_DOS_SHIFT) & RTFS_DOS_MASK_OS2; 1339 pObj->cbObject = pDirEntry->cbFile; 1340 pObj->fMaybeDirtyFat = false; 1341 pObj->fMaybeDirtyDirEnt = false; 1118 1342 rtFsFatDosDateTimeToSpec(&pObj->ModificationTime, pDirEntry->uModifyDate, pDirEntry->uModifyTime, 0, pVol); 1119 1343 rtFsFatDosDateTimeToSpec(&pObj->BirthTime, pDirEntry->uBirthDate, pDirEntry->uBirthTime, pDirEntry->uBirthCentiseconds, pVol); … … 1136 1360 { 1137 1361 RTListInit(&pObj->Entry); 1138 pObj->pParentDir = NULL; 1139 pObj->pVol = pVol; 1140 pObj->offEntryInDir = UINT32_MAX; 1141 pObj->fAttrib = fAttrib; 1142 pObj->cbObject = cbObject; 1362 pObj->pParentDir = NULL; 1363 pObj->pVol = pVol; 1364 pObj->offEntryInDir = UINT32_MAX; 1365 pObj->fAttrib = fAttrib; 1366 pObj->cbObject = cbObject; 1367 pObj->fMaybeDirtyFat = false; 1368 pObj->fMaybeDirtyDirEnt = false; 1143 1369 RTTimeSpecSetDosSeconds(&pObj->AccessTime, 0); 1144 1370 RTTimeSpecSetDosSeconds(&pObj->ModificationTime, 0); … … 1148 1374 1149 1375 /** 1376 * Flushes FAT object meta data. 1377 * 1378 * @returns IPRT status code 1379 * @param pObj The common object structure. 1380 */ 1381 static int rtFsFatObj_FlushMetaData(PRTFSFATOBJ pObj) 1382 { 1383 int rc = VINF_SUCCESS; 1384 if (pObj->fMaybeDirtyFat) 1385 { 1386 rc = rtFsFatClusterMap_Flush(pObj->pVol); 1387 if (RT_SUCCESS(rc)) 1388 pObj->fMaybeDirtyFat = false; 1389 } 1390 if (pObj->fMaybeDirtyDirEnt) 1391 { 1392 int rc2 = rtFsFatDir_Flush(pObj->pParentDir); 1393 if (RT_SUCCESS(rc2)) 1394 pObj->fMaybeDirtyDirEnt = false; 1395 else if (RT_SUCCESS(rc)) 1396 rc = rc2; 1397 } 1398 return rc; 1399 } 1400 1401 1402 /** 1150 1403 * Worker for rtFsFatFile_Close and rtFsFatDir_Close that does common work. 1151 1404 * … … 1155 1408 static int rtFsFatObj_Close(PRTFSFATOBJ pObj) 1156 1409 { 1410 int rc = rtFsFatObj_FlushMetaData(pObj); 1157 1411 if (pObj->pParentDir) 1158 1412 rtFsFatDir_RemoveOpenChild(pObj->pParentDir, pObj); 1159 return VINF_SUCCESS;1413 return rc; 1160 1414 } 1161 1415 … … 1167 1421 { 1168 1422 PRTFSFATFILE pThis = (PRTFSFATFILE)pvThis; 1169 int rc1 = rtFsFatFile_FlushMetaData(pThis); 1170 int rc2 = rtFsFatObj_Close(&pThis->Core); 1171 return RT_FAILURE(rc1) ? rc1 : rc2; 1423 return rtFsFatObj_Close(&pThis->Core); 1172 1424 } 1173 1425 … … 1310 1562 1311 1563 /* 1312 * We need to at least update the directory entry, but quite likely allocate 1313 * or release clusters. 1564 * Do we need to allocate or free clusters? 1314 1565 */ 1315 1566 int rc = VINF_SUCCESS; … … 1317 1568 AssertReturn(pObj->pParentDir, VERR_INTERNAL_ERROR_2); 1318 1569 if (pObj->Clusters.cClusters == cClustersNew) 1319 { 1320 pObj->cbObject = cbFile; 1321 } 1322 else if (pObj->cbObject < cbFile) 1323 { 1324 AssertFailed(); 1570 { /* likely when writing small bits at a time. */ } 1571 else if (pObj->Clusters.cClusters < cClustersNew) 1572 { 1573 /* Allocate and append new clusters. */ 1574 do 1575 { 1576 uint32_t idxCluster; 1577 rc = rtFsFatClusterMap_AllocateCluster(pObj->pVol, rtFsFatChain_GetLastCluster(&pObj->Clusters), &idxCluster); 1578 if (RT_SUCCESS(rc)) 1579 rc = rtFsFatChain_Append(&pObj->Clusters, idxCluster); 1580 } while (pObj->Clusters.cClusters < cClustersNew && RT_SUCCESS(rc)); 1581 pObj->fMaybeDirtyFat = true; 1325 1582 } 1326 1583 else … … 1338 1595 } 1339 1596 1340 /* Update the chain structure. */ 1341 uint32_t cOldParts = (pObj->Clusters.cClusters + RTFSFATCHAINPART_ENTRIES - 1) / RTFSFATCHAINPART_ENTRIES; 1342 uint32_t cNewParts = (cClustersNew + RTFSFATCHAINPART_ENTRIES - 1) / RTFSFATCHAINPART_ENTRIES; 1343 Assert(cOldParts >= cNewParts); 1344 while (cOldParts-- > cNewParts) 1345 RTMemFree(RTListRemoveLast(&pObj->Clusters.ListParts, RTFSFATCHAINPART, ListEntry)); 1346 pObj->Clusters.cClusters = cClustersNew; 1347 pObj->Clusters.cbChain = pObj->Clusters.cClusters << pObj->Clusters.cClusterByteShift; 1348 Assert(rtFsFatChain_AssertValid(&pObj->Clusters)); 1597 rtFsFatChain_Shrink(&pObj->Clusters, cClustersNew); 1349 1598 } 1599 pObj->fMaybeDirtyFat = true; 1350 1600 } 1351 1601 if (RT_SUCCESS(rc)) 1352 1602 { 1603 /* 1604 * Update the object size, since we've got the right number of clusters backing it now. 1605 */ 1606 pObj->cbObject = cbFile; 1607 1353 1608 /* 1354 1609 * Update the directory entry. … … 1360 1615 { 1361 1616 pDirEntry->cbFile = cbFile; 1362 /** @todo figure out if setting the cluster to 0 is the right way to deal 1363 * with empty files... */ 1617 uint32_t idxFirstCluster; 1364 1618 if (cClustersNew == 0) 1365 { 1366 pDirEntry->idxCluster = 0; 1367 if (pObj->pVol->enmFatType >= RTFSFATTYPE_FAT32) 1368 pDirEntry->u.idxClusterHigh = 0; 1369 } 1619 idxFirstCluster = 0; /** @todo figure out if setting the cluster to 0 is the right way to deal with empty files... */ 1620 else 1621 idxFirstCluster = rtFsFatChain_GetFirstCluster(&pObj->Clusters); 1622 pDirEntry->idxCluster = (uint16_t)idxFirstCluster; 1623 if (pObj->pVol->enmFatType >= RTFSFATTYPE_FAT32) 1624 pDirEntry->u.idxClusterHigh = (uint16_t)(idxFirstCluster >> 16); 1625 1370 1626 rc = rtFsFatDir_PutEntryAfterUpdate(pObj->pParentDir, pDirEntry, uWriteLock); 1627 pObj->fMaybeDirtyDirEnt = true; 1371 1628 } 1372 1629 } … … 1452 1709 1453 1710 /** 1454 * Flushes file meta data.1455 *1456 * @returns IPRT status code1457 * @param pThis The file.1458 */1459 static int rtFsFatFile_FlushMetaData(PRTFSFATFILE pThis)1460 {1461 int rc = VINF_SUCCESS;1462 if (pThis->fMaybeDirtyFat)1463 rc = rtFsFatClusterMap_Flush(pThis->Core.pVol);1464 if (pThis->fMaybeDirtyDirEnt)1465 {1466 int rc2 = rtFsFatDir_Flush(pThis->Core.pParentDir);1467 if (RT_FAILURE(rc2) && RT_SUCCESS(rc))1468 rc = rc2;1469 }1470 return rc;1471 }1472 1473 /**1474 1711 * @interface_method_impl{RTVFSIOSTREAMOPS,pfnFlush} 1475 1712 */ … … 1477 1714 { 1478 1715 PRTFSFATFILE pThis = (PRTFSFATFILE)pvThis; 1479 int rc1 = rtFsFat File_FlushMetaData(pThis);1716 int rc1 = rtFsFatObj_FlushMetaData(&pThis->Core); 1480 1717 int rc2 = RTVfsFileFlush(pThis->Core.pVol->hVfsBacking); 1481 1718 return RT_FAILURE(rc1) ? rc1 : rc2; … … 1681 1918 */ 1682 1919 rtFsFatObj_InitFromDirEntry(&pNewFile->Core, pDirEntry, offEntryInDir, pThis); 1683 pNewFile->offFile = 0; 1684 pNewFile->fMaybeDirtyFat = false; 1685 pNewFile->fMaybeDirtyDirEnt = false; 1920 pNewFile->offFile = 0; 1686 1921 rc = rtFsFatClusterMap_ReadClusterChain(pThis, RTFSFAT_GET_CLUSTER(pDirEntry, pThis), &pNewFile->Core.Clusters); 1687 1922 if (RT_SUCCESS(rc))
Note:
See TracChangeset
for help on using the changeset viewer.