VirtualBox

Changeset 66674 in vbox for trunk/src/VBox/Runtime/common


Ignore:
Timestamp:
Apr 25, 2017 3:29:11 PM (8 years ago)
Author:
vboxsync
Message:

fatvfs.cpp: Can modify existing files.

File:
1 edited

Legend:

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

    r66672 r66674  
    132132    /** Pointer to the volume. */
    133133    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;
    134138} RTFSFATOBJ;
    135139typedef RTFSFATOBJ *PRTFSFATOBJ;
     
    138142{
    139143    /** Core FAT object info.  */
    140     RTFSFATOBJ      Core;
     144    RTFSFATOBJ          Core;
    141145    /** 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;
    147147} RTFSFATFILE;
    148148typedef RTFSFATFILE *PRTFSFATFILE;
     
    419419*   Internal Functions                                                                                                           *
    420420*********************************************************************************************************************************/
    421 static int rtFsFatFile_FlushMetaData(PRTFSFATFILE pThis);
    422421static void rtFsFatDir_AddOpenChild(PRTFSFATDIR pDir, PRTFSFATOBJ pChild);
    423422static void rtFsFatDir_RemoveOpenChild(PRTFSFATDIR pDir, PRTFSFATOBJ pChild);
     
    445444
    446445
     446#ifdef RT_STRICT
     447/**
     448 * Assert chain consistency.
     449 */
     450static 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
    447467/**
    448468 * Initializes an empty cluster chain.
     
    486506    return VINF_SUCCESS;
    487507}
     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 */
     517static 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
    488529
    489530
     
    593634}
    594635
    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 */
     643static 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 */
     661static 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
    614671
    615672/**
     
    713770{
    714771    PRTFSFATCLUSTERMAPCACHE pCache = pThis->pFatCache;
     772
    715773
    716774    /*
     
    748806                            && offEntry)
    749807                        {
     808                            Assert(SgBuf.cSegs > 0);
    750809                            Assert(   (uintptr_t)aSgSegs[SgBuf.cSegs - 1].pvSeg + aSgSegs[SgBuf.cSegs - 1].cbSeg
    751810                                   == (uintptr_t)&pCache->aEntries[iEntry].pbData[offEntry]);
     
    755814                        else
    756815                        {
     816                            /* Starting new job? */
     817                            if (off == UINT64_MAX)
     818                            {
     819                                off = offDirtyLine;
     820                                Assert(SgBuf.cSegs == 0);
     821                            }
    757822                            /* flush if not adjacent or if we're out of segments. */
    758                             if (   offDirtyLine != offEdge
    759                                 || SgBuf.cSegs >= RT_ELEMENTS(aSgSegs))
     823                            else if (   offDirtyLine != offEdge
     824                                     || SgBuf.cSegs >= RT_ELEMENTS(aSgSegs))
    760825                            {
    761826                                int rc2 = RTVfsFileSgWrite(pThis->hVfsBacking, off, &SgBuf, true /*fBlocking*/, NULL);
     
    764829                                RTSgBufReset(&SgBuf);
    765830                                SgBuf.cSegs = 0;
     831                                off = offDirtyLine;
    766832                            }
    767833
     
    777843                            break;
    778844                    }
     845                    iDirtyLine <<= 1;
     846                    offEntry += pCache->cbDirtyLine;
    779847                }
    780                 iDirtyLine++;
    781                 offEntry += pCache->cbDirtyLine;
     848                Assert(!bmDirty);
    782849            }
    783850        }
     
    9631030
    9641031
     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 */
     1039DECLINLINE(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
    9651046/** Sets a FAT12 cluster value. */
    9661047static int rtFsFatClusterMap_SetCluster12(PRTFSFATCLUSTERMAPCACHE pFatCache, PRTFSFATVOL pVol,
     
    9791060    if (idxCluster & 1)
    9801061    {
    981         pbFat[offFat]     = (0x0f | pbFat[offFat]) | ((uValue & 0xf) << 4);
     1062        pbFat[offFat]     = ((uint8_t)0x0f & pbFat[offFat]) | ((uint8_t)uValue << 4);
    9821063        pbFat[offFat + 1] = (uint8_t)(uValue >> 4);
    9831064    }
     
    9851066    {
    9861067        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);
    9881069    }
    9891070
    9901071    /* 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);
    9931074
    9941075    return VINF_SUCCESS;
     
    10531134        case RTFSFATTYPE_FAT16: return rtFsFatClusterMap_SetCluster16(pThis->pFatCache, pThis, idxCluster, 0);
    10541135        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 */
     1144static 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 */
     1239static 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 */
     1250static 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 */
     1267static 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);
    10551277        default: AssertFailedReturn(VERR_INTERNAL_ERROR_3);
    10561278    }
     
    11111333{
    11121334    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;
    11181342    rtFsFatDosDateTimeToSpec(&pObj->ModificationTime, pDirEntry->uModifyDate, pDirEntry->uModifyTime, 0, pVol);
    11191343    rtFsFatDosDateTimeToSpec(&pObj->BirthTime, pDirEntry->uBirthDate, pDirEntry->uBirthTime, pDirEntry->uBirthCentiseconds, pVol);
     
    11361360{
    11371361    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;
    11431369    RTTimeSpecSetDosSeconds(&pObj->AccessTime, 0);
    11441370    RTTimeSpecSetDosSeconds(&pObj->ModificationTime, 0);
     
    11481374
    11491375/**
     1376 * Flushes FAT object meta data.
     1377 *
     1378 * @returns IPRT status code
     1379 * @param   pObj            The common object structure.
     1380 */
     1381static 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/**
    11501403 * Worker for rtFsFatFile_Close and rtFsFatDir_Close that does common work.
    11511404 *
     
    11551408static int rtFsFatObj_Close(PRTFSFATOBJ pObj)
    11561409{
     1410    int rc = rtFsFatObj_FlushMetaData(pObj);
    11571411    if (pObj->pParentDir)
    11581412        rtFsFatDir_RemoveOpenChild(pObj->pParentDir, pObj);
    1159     return VINF_SUCCESS;
     1413    return rc;
    11601414}
    11611415
     
    11671421{
    11681422    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);
    11721424}
    11731425
     
    13101562
    13111563    /*
    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?
    13141565     */
    13151566    int rc = VINF_SUCCESS;
     
    13171568    AssertReturn(pObj->pParentDir, VERR_INTERNAL_ERROR_2);
    13181569    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;
    13251582    }
    13261583    else
     
    13381595            }
    13391596
    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);
    13491598        }
     1599        pObj->fMaybeDirtyFat = true;
    13501600    }
    13511601    if (RT_SUCCESS(rc))
    13521602    {
     1603        /*
     1604         * Update the object size, since we've got the right number of clusters backing it now.
     1605         */
     1606        pObj->cbObject = cbFile;
     1607
    13531608        /*
    13541609         * Update the directory entry.
     
    13601615        {
    13611616            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;
    13641618            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
    13701626            rc = rtFsFatDir_PutEntryAfterUpdate(pObj->pParentDir, pDirEntry, uWriteLock);
     1627            pObj->fMaybeDirtyDirEnt = true;
    13711628        }
    13721629    }
     
    14521709
    14531710/**
    1454  * Flushes file meta data.
    1455  *
    1456  * @returns IPRT status code
    1457  * @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 /**
    14741711 * @interface_method_impl{RTVFSIOSTREAMOPS,pfnFlush}
    14751712 */
     
    14771714{
    14781715    PRTFSFATFILE pThis = (PRTFSFATFILE)pvThis;
    1479     int rc1 = rtFsFatFile_FlushMetaData(pThis);
     1716    int rc1 = rtFsFatObj_FlushMetaData(&pThis->Core);
    14801717    int rc2 = RTVfsFileFlush(pThis->Core.pVol->hVfsBacking);
    14811718    return RT_FAILURE(rc1) ? rc1 : rc2;
     
    16811918         */
    16821919        rtFsFatObj_InitFromDirEntry(&pNewFile->Core, pDirEntry, offEntryInDir, pThis);
    1683         pNewFile->offFile           = 0;
    1684         pNewFile->fMaybeDirtyFat    = false;
    1685         pNewFile->fMaybeDirtyDirEnt = false;
     1920        pNewFile->offFile = 0;
    16861921        rc = rtFsFatClusterMap_ReadClusterChain(pThis, RTFSFAT_GET_CLUSTER(pDirEntry, pThis), &pNewFile->Core.Clusters);
    16871922        if (RT_SUCCESS(rc))
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