Changeset 66669 in vbox for trunk/src/VBox/Runtime
- Timestamp:
- Apr 25, 2017 6:29:00 AM (8 years ago)
- svn:sync-xref-src-repo-rev:
- 115042
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Runtime/common/filesystem/fatvfs.cpp
r66652 r66669 291 291 /** Byte offset of the bootsector relative to the start of the file. */ 292 292 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; 293 301 /** Set if read-only mode. */ 294 302 bool fReadOnly; … … 366 374 /** Pointer to a FAT volume (VFS instance data). */ 367 375 typedef RTFSFATVOL *PRTFSFATVOL; 376 /** Pointer to a const FAT volume (VFS instance data). */ 377 typedef RTFSFATVOL const *PCRTFSFATVOL; 368 378 369 379 … … 402 412 *********************************************************************************************************************************/ 403 413 static void rtFsFatDir_AddOpenChild(PRTFSFATDIR pDir, PRTFSFATOBJ pChild); 414 static void rtFsFatDir_RemoveOpenChild(PRTFSFATDIR pDir, PRTFSFATOBJ pChild); 404 415 static int rtFsFatDir_New(PRTFSFATVOL pThis, PRTFSFATDIR pParentDir, PCFATDIRENTRY pDirEntry, uint32_t offEntryInDir, 405 416 uint32_t idxCluster, uint64_t offDisk, uint32_t cbDir, PRTVFSDIR phVfsDir, PRTFSFATDIR *ppDir); … … 435 446 pChain->cClusters = 0; 436 447 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 */ 458 static 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; 437 475 } 438 476 … … 749 787 750 788 /** 789 * Worker for rtFsFatClusterMap_ReadClusterChain handling FAT12. 790 */ 791 static 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. */ 804 RTAssertMsg2("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 */ 833 static 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 */ 844 static 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 /** 751 853 * Reads a cluster chain into memory 752 854 * … … 764 866 pChain->cbChain = 0; 765 867 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 */ 888 static void rtFsFatDosDateTimeToSpec(PRTTIMESPEC pTimeSpec, uint16_t uDate, uint16_t uTime, 889 uint8_t cCentiseconds, PCRTFSFATVOL pVol) 776 890 { 777 891 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; 787 903 if (cCentiseconds > 0 && cCentiseconds < 200) /* screw complicated stuff for now. */ 788 904 { … … 796 912 797 913 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 */ 929 static void rtFsFatObj_InitFromDirEntry(PRTFSFATOBJ pObj, PCFATDIRENTRY pDirEntry, uint32_t offEntryInDir, PRTFSFATVOL pVol) 802 930 { 803 931 RTListInit(&pObj->Entry); 804 932 pObj->pParentDir = NULL; 805 pObj->pVol = p This;933 pObj->pVol = pVol; 806 934 pObj->offEntryInDir = offEntryInDir; 807 935 pObj->fAttrib = ((RTFMODE)pDirEntry->fAttrib << RTFS_DOS_SHIFT) & RTFS_DOS_MASK_OS2; 808 936 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 */ 954 static void rtFsFatObj_InitDummy(PRTFSFATOBJ pObj, uint32_t cbObject, RTFMODE fAttrib, PRTFSFATVOL pVol) 816 955 { 817 956 RTListInit(&pObj->Entry); 818 957 pObj->pParentDir = NULL; 819 pObj->pVol = p This;820 pObj->offEntryInDir = offEntryInDir;958 pObj->pVol = pVol; 959 pObj->offEntryInDir = UINT32_MAX; 821 960 pObj->fAttrib = fAttrib; 822 961 pObj->cbObject = cbObject; … … 828 967 829 968 /** 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 */ 974 static int rtFsFatObj_Close(PRTFSFATOBJ pObj) 975 { 976 if (pObj->pParentDir) 977 rtFsFatDir_RemoveOpenChild(pObj->pParentDir, pObj); 978 return VINF_SUCCESS; 979 } 980 981 982 /** 830 983 * @interface_method_impl{RTVFSOBJOPS,pfnClose} 831 984 */ … … 833 986 { 834 987 PRTFSFATFILE pThis = (PRTFSFATFILE)pvThis; 835 RT_NOREF(pThis); 836 return VERR_NOT_IMPLEMENTED; 988 return rtFsFatObj_Close(&pThis->Core); 837 989 } 838 990 … … 1469 1621 { 1470 1622 PRTFSFATDIR pThis = (PRTFSFATDIR)pvThis; 1623 int rc; 1471 1624 if (pThis->paEntries) 1472 1625 { 1473 /** @todo flush */ 1474 1626 rc = rtFsFatDir_Flush(pThis); 1475 1627 RTMemFree(pThis->paEntries); 1476 1628 pThis->paEntries = NULL; 1477 1629 } 1478 return VINF_SUCCESS; 1630 else 1631 rc = VINF_SUCCESS; 1632 1633 rtFsFatObj_Close(&pThis->Core); 1634 return rc; 1479 1635 } 1480 1636 … … 1794 1950 rtFsFatObj_InitFromDirEntry(&pNewDir->Core, pDirEntry, offEntryInDir, pThis); 1795 1951 else 1796 rtFsFatObj_InitDummy(&pNewDir->Core, offEntryInDir,cbDir, RTFS_DOS_DIRECTORY, pThis);1952 rtFsFatObj_InitDummy(&pNewDir->Core, cbDir, RTFS_DOS_DIRECTORY, pThis); 1797 1953 1798 1954 pNewDir->hVfsSelf = *phVfsDir; … … 2543 2699 pThis->cbBacking = 0; 2544 2700 pThis->offBootSector = offBootSector; 2701 pThis->offNanoUTC = RTTimeLocalDeltaNano(); 2702 pThis->offMinUTC = pThis->offNanoUTC / RT_NS_1MIN; 2545 2703 pThis->fReadOnly = fReadOnly; 2546 2704 pThis->cReservedSectors = 1;
Note:
See TracChangeset
for help on using the changeset viewer.