VirtualBox

Changeset 66669 in vbox for trunk/src/VBox/Runtime


Ignore:
Timestamp:
Apr 25, 2017 6:29:00 AM (8 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
115042
Message:

iprt,fatvfs: a bit more code.

File:
1 edited

Legend:

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

    r66652 r66669  
    291291    /** Byte offset of the bootsector relative to the start of the file. */
    292292    uint64_t        offBootSector;
     293    /** The UTC offset in nanoseconds to use for this file system (FAT traditionally
     294     * stores timestamps in local time).
     295     * @remarks This may need improving later. */
     296    int64_t         offNanoUTC;
     297    /** The UTC offset in minutes to use for this file system (FAT traditionally
     298     * stores timestamps in local time).
     299     * @remarks This may need improving later. */
     300    int32_t         offMinUTC;
    293301    /** Set if read-only mode. */
    294302    bool            fReadOnly;
     
    366374/** Pointer to a FAT volume (VFS instance data). */
    367375typedef RTFSFATVOL *PRTFSFATVOL;
     376/** Pointer to a const FAT volume (VFS instance data). */
     377typedef RTFSFATVOL const *PCRTFSFATVOL;
    368378
    369379
     
    402412*********************************************************************************************************************************/
    403413static void rtFsFatDir_AddOpenChild(PRTFSFATDIR pDir, PRTFSFATOBJ pChild);
     414static void rtFsFatDir_RemoveOpenChild(PRTFSFATDIR pDir, PRTFSFATOBJ pChild);
    404415static int  rtFsFatDir_New(PRTFSFATVOL pThis, PRTFSFATDIR pParentDir, PCFATDIRENTRY pDirEntry, uint32_t offEntryInDir,
    405416                           uint32_t idxCluster, uint64_t offDisk, uint32_t cbDir, PRTVFSDIR phVfsDir, PRTFSFATDIR *ppDir);
     
    435446    pChain->cClusters           = 0;
    436447    RTListInit(&pChain->ListParts);
     448}
     449
     450
     451/**
     452 * Appends a cluster to a cluster chain.
     453 *
     454 * @returns IPRT status code.
     455 * @param   pChain              The chain.
     456 * @param   idxCluster          The cluster to append.
     457 */
     458static int rtFsFatChain_Append(PRTFSFATCHAIN pChain, uint32_t idxCluster)
     459{
     460    PRTFSFATCHAINPART pPart;
     461    uint32_t idxLast = pChain->cClusters % RT_ELEMENTS(pPart->aEntries);
     462    if (idxLast != 0)
     463        pPart = RTListGetLast(&pChain->ListParts, RTFSFATCHAINPART, ListEntry);
     464    else
     465    {
     466        pPart = (PRTFSFATCHAINPART)RTMemAllocZ(sizeof(*pPart));
     467        if (!pPart)
     468            return VERR_NO_MEMORY;
     469        RTListAppend(&pChain->ListParts, &pPart->ListEntry);
     470    }
     471    pPart->aEntries[idxLast] = idxCluster;
     472    pChain->cClusters++;
     473    pChain->cbChain += pChain->cbCluster;
     474    return VINF_SUCCESS;
    437475}
    438476
     
    749787
    750788/**
     789 * Worker for rtFsFatClusterMap_ReadClusterChain handling FAT12.
     790 */
     791static int rtFsFatClusterMap_Fat12_ReadClusterChain(PRTFSFATCLUSTERMAPCACHE pFatCache, PRTFSFATVOL pVol, uint32_t idxCluster,
     792                                                    PRTFSFATCHAIN pChain)
     793{
     794    /* ASSUME that for FAT12 we cache the whole FAT in a single entry.  That
     795       way we don't need to deal with entries in different sectors and whatnot.  */
     796    AssertReturn(pFatCache->cEntries == 1, VERR_INTERNAL_ERROR_4);
     797    AssertReturn(pFatCache->cbEntry == pVol->cbFat, VERR_INTERNAL_ERROR_4);
     798    AssertReturn(pFatCache->aEntries[0].offFat == 0, VERR_INTERNAL_ERROR_4);
     799
     800    uint8_t const *pbFat = pFatCache->aEntries[0].pbData;
     801    for (;;)
     802    {
     803        /* Validate the cluster, checking for end of file. */
     804RTAssertMsg2("idxCluster=%#x cClusters=%#x\n", idxCluster, pVol->cClusters);
     805        if (   idxCluster >= pVol->cClusters
     806            || idxCluster <  FAT_FIRST_DATA_CLUSTER)
     807        {
     808            if (idxCluster >= FAT_FIRST_FAT12_EOC)
     809                return VINF_SUCCESS;
     810            return VERR_VFS_BOGUS_OFFSET;
     811        }
     812
     813        /* Add cluster to chain.  */
     814        int rc = rtFsFatChain_Append(pChain, idxCluster);
     815        if (RT_FAILURE(rc))
     816            return rc;
     817
     818        /* Next cluster. */
     819        bool     fOdd   = idxCluster & 1;
     820        uint32_t offFat = idxCluster * 2 / 3;
     821        idxCluster = RT_MAKE_U16(pbFat[offFat], pbFat[offFat + 1]);
     822        if (fOdd)
     823            idxCluster >>= 4;
     824        else
     825            idxCluster &= 0x0fff;
     826    }
     827}
     828
     829
     830/**
     831 * Worker for rtFsFatClusterMap_ReadClusterChain handling FAT16.
     832 */
     833static int rtFsFatClusterMap_Fat16_ReadClusterChain(PRTFSFATCLUSTERMAPCACHE pFatCache, PRTFSFATVOL pVol, uint32_t idxCluster,
     834                                                    PRTFSFATCHAIN pChain)
     835{
     836    RT_NOREF(pFatCache, pVol, idxCluster, pChain);
     837    return VERR_NOT_IMPLEMENTED;
     838}
     839
     840
     841/**
     842 * Worker for rtFsFatClusterMap_ReadClusterChain handling FAT32.
     843 */
     844static int rtFsFatClusterMap_Fat32_ReadClusterChain(PRTFSFATCLUSTERMAPCACHE pFatCache, PRTFSFATVOL pVol, uint32_t idxCluster,
     845                                                    PRTFSFATCHAIN pChain)
     846{
     847    RT_NOREF(pFatCache, pVol, idxCluster, pChain);
     848    return VERR_NOT_IMPLEMENTED;
     849}
     850
     851
     852/**
    751853 * Reads a cluster chain into memory
    752854 *
     
    764866    pChain->cbChain             = 0;
    765867    RTListInit(&pChain->ListParts);
    766 
    767     if (   idxFirstCluster >= pThis->cClusters
    768         && idxFirstCluster >= FAT_FIRST_DATA_CLUSTER)
    769         return VERR_VFS_BOGUS_OFFSET;
    770 
    771     return VERR_NOT_IMPLEMENTED;
    772 }
    773 
    774 
    775 static void rtFsFatDosDateTimeToSpec(PRTTIMESPEC pTimeSpec, uint16_t uDate, uint16_t uTime, uint8_t cCentiseconds)
     868    switch (pThis->enmFatType)
     869    {
     870        case RTFSFATTYPE_FAT12: return rtFsFatClusterMap_Fat12_ReadClusterChain(pThis->pFatCache, pThis, idxFirstCluster, pChain);
     871        case RTFSFATTYPE_FAT16: return rtFsFatClusterMap_Fat16_ReadClusterChain(pThis->pFatCache, pThis, idxFirstCluster, pChain);
     872        case RTFSFATTYPE_FAT32: return rtFsFatClusterMap_Fat32_ReadClusterChain(pThis->pFatCache, pThis, idxFirstCluster, pChain);
     873        default:
     874            AssertFailedReturn(VERR_INTERNAL_ERROR_2);
     875    }
     876}
     877
     878
     879/**
     880 * Converts a FAT timestamp into an IPRT timesspec.
     881 *
     882 * @param   pTimeSpec       Where to return the IRPT time.
     883 * @param   uDate           The date part of the FAT timestamp.
     884 * @param   uTime           The time part of the FAT timestamp.
     885 * @param   cCentiseconds   Centiseconds part if applicable (0 otherwise).
     886 * @param   pVol            The volume.
     887 */
     888static void rtFsFatDosDateTimeToSpec(PRTTIMESPEC pTimeSpec, uint16_t uDate, uint16_t uTime,
     889                                     uint8_t cCentiseconds, PCRTFSFATVOL pVol)
    776890{
    777891    RTTIME Time;
    778     Time.offUTC     = 0;
    779     Time.i32Year    = 1980 + (uDate >> 9);
    780     Time.u8Month    = ((uDate >> 5) & 0xf);
    781     Time.u8WeekDay  = UINT8_MAX;
    782     Time.u16YearDay = UINT16_MAX;
    783     Time.u8MonthDay = RT_MAX(uDate & 0x1f, 1);
    784     Time.u8Hour     = uTime >> 11;
    785     Time.u8Minute   = (uTime >> 5) & 0x3f;
    786     Time.u8Second   = (uTime & 0x1f) << 1;
     892    Time.fFlags         = RTTIME_FLAGS_TYPE_UTC;
     893    Time.offUTC         = 0;
     894    Time.i32Year        = 1980 + (uDate >> 9);
     895    Time.u8Month        = RT_MAX((uDate >> 5) & 0xf, 1);
     896    Time.u8MonthDay     = RT_MAX(uDate & 0x1f, 1);
     897    Time.u8WeekDay      = UINT8_MAX;
     898    Time.u16YearDay     = 0;
     899    Time.u8Hour         = uTime >> 11;
     900    Time.u8Minute       = (uTime >> 5) & 0x3f;
     901    Time.u8Second       = (uTime & 0x1f) << 1;
     902    Time.u32Nanosecond  = 0;
    787903    if (cCentiseconds > 0 && cCentiseconds < 200) /* screw complicated stuff for now. */
    788904    {
     
    796912
    797913    RTTimeImplode(pTimeSpec, RTTimeNormalize(&Time));
    798 }
    799 
    800 
    801 static void rtFsFatObj_InitFromDirEntry(PRTFSFATOBJ pObj, PCFATDIRENTRY pDirEntry, uint32_t offEntryInDir, PRTFSFATVOL pThis)
     914    RTTimeSpecAddNano(pTimeSpec, pVol->offNanoUTC);
     915}
     916
     917
     918/**
     919 * Initialization of a RTFSFATOBJ structure from a FAT directory entry.
     920 *
     921 * @note    The RTFSFATOBJ::pParentDir and RTFSFATOBJ::Clusters members are
     922 *          properly initialized elsewhere.
     923 *
     924 * @param   pObj            The structure to initialize.
     925 * @param   pParentDir      The parent directory.
     926 * @param   offEntryInDir   The offset in the parent directory.
     927 * @param   pVol            The volume.
     928 */
     929static void rtFsFatObj_InitFromDirEntry(PRTFSFATOBJ pObj, PCFATDIRENTRY pDirEntry, uint32_t offEntryInDir, PRTFSFATVOL pVol)
    802930{
    803931    RTListInit(&pObj->Entry);
    804932    pObj->pParentDir    = NULL;
    805     pObj->pVol          = pThis;
     933    pObj->pVol          = pVol;
    806934    pObj->offEntryInDir = offEntryInDir;
    807935    pObj->fAttrib       = ((RTFMODE)pDirEntry->fAttrib << RTFS_DOS_SHIFT) & RTFS_DOS_MASK_OS2;
    808936    pObj->cbObject      = pDirEntry->cbFile;
    809     rtFsFatDosDateTimeToSpec(&pObj->ModificationTime, pDirEntry->uAccessDate, pDirEntry->uModifyTime, 0);
    810     rtFsFatDosDateTimeToSpec(&pObj->BirthTime, pDirEntry->uBirthDate, pDirEntry->uBirthTime, pDirEntry->uBirthCentiseconds);
    811     rtFsFatDosDateTimeToSpec(&pObj->AccessTime, pDirEntry->uAccessDate, 0, 0);
    812 }
    813 
    814 
    815 static void rtFsFatObj_InitDummy(PRTFSFATOBJ pObj, uint32_t offEntryInDir, uint32_t cbObject, RTFMODE fAttrib, PRTFSFATVOL pThis)
     937    rtFsFatDosDateTimeToSpec(&pObj->ModificationTime, pDirEntry->uModifyDate, pDirEntry->uModifyTime, 0, pVol);
     938    rtFsFatDosDateTimeToSpec(&pObj->BirthTime, pDirEntry->uBirthDate, pDirEntry->uBirthTime, pDirEntry->uBirthCentiseconds, pVol);
     939    rtFsFatDosDateTimeToSpec(&pObj->AccessTime, pDirEntry->uAccessDate, 0, 0, pVol);
     940}
     941
     942
     943/**
     944 * Dummy initialization of a RTFSFATOBJ structure.
     945 *
     946 * @note    The RTFSFATOBJ::pParentDir and RTFSFATOBJ::Clusters members are
     947 *          properly initialized elsewhere.
     948 *
     949 * @param   pObj            The structure to initialize.
     950 * @param   cbObject        The object size.
     951 * @param   fAttrib         The attributes.
     952 * @param   pVol            The volume.
     953 */
     954static void rtFsFatObj_InitDummy(PRTFSFATOBJ pObj, uint32_t cbObject, RTFMODE fAttrib, PRTFSFATVOL pVol)
    816955{
    817956    RTListInit(&pObj->Entry);
    818957    pObj->pParentDir    = NULL;
    819     pObj->pVol          = pThis;
    820     pObj->offEntryInDir = offEntryInDir;
     958    pObj->pVol          = pVol;
     959    pObj->offEntryInDir = UINT32_MAX;
    821960    pObj->fAttrib       = fAttrib;
    822961    pObj->cbObject      = cbObject;
     
    828967
    829968/**
     969 * Worker for rtFsFatFile_Close and rtFsFatDir_Close that does common work.
     970 *
     971 * @returns IPRT status code.
     972 * @param   pObj            The common object structure.
     973 */
     974static int rtFsFatObj_Close(PRTFSFATOBJ pObj)
     975{
     976    if (pObj->pParentDir)
     977        rtFsFatDir_RemoveOpenChild(pObj->pParentDir, pObj);
     978    return VINF_SUCCESS;
     979}
     980
     981
     982/**
    830983 * @interface_method_impl{RTVFSOBJOPS,pfnClose}
    831984 */
     
    833986{
    834987    PRTFSFATFILE pThis = (PRTFSFATFILE)pvThis;
    835     RT_NOREF(pThis);
    836     return VERR_NOT_IMPLEMENTED;
     988    return rtFsFatObj_Close(&pThis->Core);
    837989}
    838990
     
    14691621{
    14701622    PRTFSFATDIR pThis = (PRTFSFATDIR)pvThis;
     1623    int rc;
    14711624    if (pThis->paEntries)
    14721625    {
    1473         /** @todo flush */
    1474 
     1626        rc = rtFsFatDir_Flush(pThis);
    14751627        RTMemFree(pThis->paEntries);
    14761628        pThis->paEntries = NULL;
    14771629    }
    1478     return VINF_SUCCESS;
     1630    else
     1631        rc = VINF_SUCCESS;
     1632
     1633    rtFsFatObj_Close(&pThis->Core);
     1634    return rc;
    14791635}
    14801636
     
    17941950            rtFsFatObj_InitFromDirEntry(&pNewDir->Core, pDirEntry, offEntryInDir, pThis);
    17951951        else
    1796             rtFsFatObj_InitDummy(&pNewDir->Core, offEntryInDir, cbDir, RTFS_DOS_DIRECTORY, pThis);
     1952            rtFsFatObj_InitDummy(&pNewDir->Core, cbDir, RTFS_DOS_DIRECTORY, pThis);
    17971953
    17981954        pNewDir->hVfsSelf           = *phVfsDir;
     
    25432699    pThis->cbBacking            = 0;
    25442700    pThis->offBootSector        = offBootSector;
     2701    pThis->offNanoUTC           = RTTimeLocalDeltaNano();
     2702    pThis->offMinUTC            = pThis->offNanoUTC / RT_NS_1MIN;
    25452703    pThis->fReadOnly            = fReadOnly;
    25462704    pThis->cReservedSectors     = 1;
Note: See TracChangeset for help on using the changeset viewer.

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette