VirtualBox

Changeset 69659 in vbox


Ignore:
Timestamp:
Nov 11, 2017 3:07:04 PM (7 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
119024
Message:

fatvfs.cpp: Able to read FAT32 now. Fixed long name bug in ReadDir.

File:
1 edited

Legend:

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

    r69631 r69659  
    8888/** Pointer to a FAT directory instance. */
    8989typedef struct RTFSFATDIRSHRD *PRTFSFATDIRSHRD;
     90/** Pointer to a FAT volume (VFS instance data). */
     91typedef struct RTFSFATVOL *PRTFSFATVOL;
    9092
    9193
     
    293295typedef struct RTFSFATCLUSTERMAPCACHE
    294296{
    295     /** Number of cache entries. */
     297    /** Number of cache entries (power of two). */
    296298    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). */
    298304    uint32_t                cbEntry;
     305    /** The AND mask to use to get the entry offset. */
     306    uint32_t                fEntryOffsetMask;
    299307    /** Dirty bitmap shift count. */
    300308    uint32_t                cDirtyShift;
    301309    /** The dirty cache line size (multiple of two). */
    302310    uint32_t                cbDirtyLine;
     311    /** The FAT size. */
     312    uint32_t                cbFat;
     313    /** Pointer to the volume (for disk access). */
     314    PRTFSFATVOL             pVol;
    303315    /** The cache name. */
    304316    const char             *pszName;
     
    420432    FAT32INFOSECTOR Fat32InfoSector;
    421433} RTFSFATVOL;
    422 /** Pointer to a FAT volume (VFS instance data). */
    423 typedef RTFSFATVOL *PRTFSFATVOL;
    424434/** Pointer to a const FAT volume (VFS instance data). */
    425435typedef RTFSFATVOL const *PCRTFSFATVOL;
     
    777787     * Figure the cache size.  Keeping it _very_ simple for now as we just need
    778788     * 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.
    779792     */
    780793    uint32_t cEntries;
     794    uint32_t cEntryIndexShift;
     795    uint32_t fEntryIndexMask;
    781796    uint32_t cbEntry = pThis->cbFat;
     797    uint32_t fEntryOffsetMask;
    782798    if (cbEntry <= _512K)
    783         cEntries = 1;
     799    {
     800        cEntries         = 1;
     801        cEntryIndexShift = 0;
     802        fEntryIndexMask  = 0;
     803        fEntryOffsetMask = UINT32_MAX;
     804    }
    784805    else
    785806    {
    786807        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);
    789816    }
    790817
     
    796823    if (!pCache)
    797824        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;
    800832
    801833    unsigned i = cEntries;
     
    814846        pCache->aEntries[i].bmDirty = 0;
    815847    }
     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));
    816851
    817852    /*
     
    829864        pCache->cbDirtyLine <<= 1;
    830865    }
     866    Assert(pCache->cEntries == 1 || pCache->cbDirtyLine == pThis->cbSector);
     867    Log3(("rtFsFatClusterMap_Create: cbDirtyLine=%#RX32 cDirtyShift=%u\n", pCache->cbDirtyLine, pCache->cDirtyShift));
    831868
    832869    /*
     
    9761013
    9771014
    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.
    9811018 *
    9821019 * This is typically called prior to reusing the cache entry.
     
    9901027    return rtFsFatClusterMap_FlushWorker(pThis, iEntry, iEntry);
    9911028}
    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 */
     1040static 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
    9931091
    9941092
     
    11191217                                                    PRTFSFATCHAIN pChain)
    11201218{
    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    }
    11231248}
    11241249
     
    41644289                {
    41654290                    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;
    41714293                }
    41724294                if (!fLongName)
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