/// <summary> /// Initializes a new FAT file. /// </summary> /// <param name="aFileSystem">The FAT file system to which the file belongs.</param> /// <param name="parent">The parent directory of the file.</param> /// <param name="aName">The name of the file.</param> /// <param name="aSize">The size of the file.</param> /// <param name="aFirstCluster">The first cluster number of the file.</param> /// <remarks> /// Size is UInt32 because FAT doesn't support bigger. Don't change to UInt64. /// </remarks> public FATFile(FATFileSystem aFileSystem, FATDirectory parent, FOS_System.String aName, UInt32 aSize, UInt32 aFirstCluster) : base(aFileSystem, parent, aName, aSize) { TheFATFileSystem = aFileSystem; FirstClusterNum = aFirstCluster; }
/// <summary> /// Formats the specified partition as FAT32. /// </summary> /// <param name="thePartition">The partition to format.</param> public static void FormatPartitionAsFAT32(Partition thePartition) { #if FATFS_TRACE BasicConsole.WriteLine(((FOS_System.String)"Creating block array... Block size: ") + thePartition.BlockSize); #endif byte[] newBPBData = thePartition.TheDiskDevice.NewBlockArray(1); #if FATFS_TRACE BasicConsole.WriteLine("Block array created."); #endif //FAT signature newBPBData[510] = 0x55; newBPBData[511] = 0xAA; //Bytes per sector - 512 UInt16 bytesPerSector = 512; newBPBData[11] = (byte)(bytesPerSector); newBPBData[12] = (byte)(bytesPerSector >> 8); ulong partitionSize = thePartition.BlockCount * thePartition.BlockSize; #if FATFS_TRACE BasicConsole.WriteLine(((FOS_System.String)"partitionSize: ") + partitionSize); #endif byte sectorsPerCluster = 0x1; //See http://www.win.tue.nl/~aeb/linux/fs/fat/fat-1.html if (partitionSize < 0x10400000UL /*(260MiB)*/) { sectorsPerCluster = 0x1; //1 } else if (partitionSize < 0x200000000 /*(8GiB)*/) { sectorsPerCluster = 0x8; //8 } else if (partitionSize < 0x400000000UL /*(16GiB)*/) { sectorsPerCluster = 0x10; //16 } else if (partitionSize < 0x800000000UL /*(32GiB)*/) { sectorsPerCluster = 0x20; //32 } else if (partitionSize < 0x20000000000UL /*(2TiB)*/) { sectorsPerCluster = 0x40; //64 } //Max. 2TB - if greater, then error! else { ExceptionMethods.Throw(new Exceptions.NotSupportedException("Drive too big! Max. size 2TB for FAT32.")); } //Sectors per cluster - 32 KiB clusters = 64 sectors per cluster newBPBData[13] = sectorsPerCluster; //Reserved sector count - 32 for FAT32 (by convention... and FAT32 does not imply 32 sectors) UInt16 reservedSectors = 32; newBPBData[14] = (byte)(reservedSectors); newBPBData[15] = (byte)(reservedSectors >> 8); //Number of FATs - always 2 newBPBData[16] = 0x02; //Root entry count - always 0 for FAT32 // - Do nothing //Total sector count // - At newBPBData[19] - N/A for FAT32 // - Do nothing // - At newBPBData[32] - Total number of sectors in the file system uint totalSectors = (uint)thePartition.BlockCount; newBPBData[32] = (byte)(totalSectors); newBPBData[33] = (byte)(totalSectors >> 8); newBPBData[34] = (byte)(totalSectors >> 16); newBPBData[35] = (byte)(totalSectors >> 24); //FAT sector count // - At newBPBData[22] - always 0 for FAT32 // - At newBPBData[36] - See calculation below //FAT sector count = 2 * RoundUp(Number of bytes for 1 FAT / Bytes per sector) #if FATFS_TRACE BasicConsole.WriteLine(((FOS_System.String)"totalSectors: ") + totalSectors + ", reservedSectors: " + reservedSectors + ", sectorsPerCluster: " + sectorsPerCluster + ", bytesPerSector: " + bytesPerSector); #endif // Number of bytes for 2 FAT = 4 * Number of data clusters // = 4 * (RndDown((totalSectors - ReservedSectors) / sectorsPerCluster) - RndUp(Clusters for 2 FATs)) // bytesPer2FAT = 4 * (X - RndUp((bytesPerFAT * 2) / bytesPerCluster)) // bytesPer2FAT = (4 * X * bytesPerCluster) / (bytesPerCluster + 8) uint dataClusters = (totalSectors - reservedSectors) / sectorsPerCluster; #if FATFS_TRACE BasicConsole.WriteLine(((FOS_System.String)"dataClusters: ") + dataClusters); #endif uint bytesPerCluster = (uint)sectorsPerCluster * bytesPerSector; #if FATFS_TRACE BasicConsole.WriteLine(((FOS_System.String)"bytesPerCluster: ") + bytesPerCluster); BasicConsole.WriteLine(((FOS_System.String)"4 * dataClusters: ") + (4 * dataClusters)); BasicConsole.WriteLine(((FOS_System.String)"4 * dataClusters * bytesPerCluster: ") + (4 * dataClusters * bytesPerCluster)); BasicConsole.WriteLine(((FOS_System.String)"bytesPerCluster + 8: ") + (bytesPerCluster + 8)); #endif uint bytesPer2FAT = (uint)Math.Divide((4 * (ulong)dataClusters * bytesPerCluster), (bytesPerCluster + 8)); //Calculation rounds down #if FATFS_TRACE BasicConsole.WriteLine(((FOS_System.String)"bytesPer2FAT: ") + bytesPer2FAT); #endif uint FATSectorCount = bytesPer2FAT / bytesPerSector; #if FATFS_TRACE BasicConsole.WriteLine(((FOS_System.String)"FATSectorCount: ") + FATSectorCount); #endif newBPBData[36] = (byte)(FATSectorCount); newBPBData[37] = (byte)(FATSectorCount >> 8); newBPBData[38] = (byte)(FATSectorCount >> 16); newBPBData[39] = (byte)(FATSectorCount >> 24); #if FATFS_TRACE BasicConsole.WriteLine(((FOS_System.String)"totalSectors: ") + totalSectors + ", reservedSectors: " + reservedSectors + ", sectorsPerCluster: " + sectorsPerCluster + ", bytesPerSector: " + bytesPerSector + ", bytesPerCluster: " + bytesPerCluster + ", dataClusters: " + dataClusters + ", bytesPer2FAT: " + bytesPer2FAT + ", FATSectorCount: " + FATSectorCount); BasicConsole.DelayOutput(10); #endif //Root cluster (number/index - min value is 2) newBPBData[44] = 0x02; #if FATFS_TRACE BasicConsole.WriteLine("Writing new BPB..."); BasicConsole.DelayOutput(1); #endif thePartition.WriteBlock(0UL, 1U, newBPBData); #if FATFS_TRACE BasicConsole.WriteLine("Written new BPB. Attempting to load new file system..."); #endif thePartition.CleanCaches(); FATFileSystem fs = new FATFileSystem(thePartition); if (!fs.IsValid) { #if FATFS_TRACE BasicConsole.WriteLine("Failed to format properly. Scrubbing new BPB..."); #endif thePartition.WriteBlock(0UL, 1U, null); #if FATFS_TRACE BasicConsole.WriteLine("Scrub done."); #endif ExceptionMethods.Throw(new FOS_System.Exception("Failed to format properly! FATFileSystem did not recognise system as valid.")); } else if (fs.FATType != FATTypeEnum.FAT32) { #if FATFS_TRACE BasicConsole.WriteLine("Failed to format properly. Scrubbing new BPB..."); #endif byte[] scrubBPB = thePartition.TheDiskDevice.NewBlockArray(1); thePartition.WriteBlock(0UL, 1U, scrubBPB); #if FATFS_TRACE BasicConsole.WriteLine("Scrub done."); #endif ExceptionMethods.Throw(new FOS_System.Exception(((FOS_System.String)"Failed to format properly! FATFileSystem recognised incorrect FAT type. Type recognised: ") + (uint)fs.FATType)); } #if FATFS_TRACE BasicConsole.WriteLine("FAT recognised. Setting up empty FAT table..."); try { #endif //Mark all clusters as empty fs.ThePartition.WriteBlock(fs.ReservedSectorCount, FATSectorCount, null); #if FATFS_TRACE } catch { BasicConsole.WriteLine("Failed to clear potentially pre-existing FAT table! File system may not function as expected."); FOS_System.GC.Cleanup(); FOS_System.GC.Cleanup(); } BasicConsole.WriteLine("Marking root directory cluster as used..."); #endif //Mark root cluster as being 1 cluster in size. fs.SetFATEntryAndSave(2, GetFATEntryEOFValue(FATTypeEnum.FAT32)); #if FATFS_TRACE BasicConsole.WriteLine("Done. Clearing the root directory..."); #endif //Empty the root directory (in case of junk data) fs.WriteCluster(2, null); #if FATFS_TRACE BasicConsole.WriteLine("Format complete."); #endif fs.thePartition.CleanCaches(); }
/// <summary> /// Initializes a new FAT directory. /// </summary> /// <param name="aFileSystem">The FAT file system to which the directory belongs.</param> /// <param name="parent">The FAT directory which is the parent of the directory. Null for the root directory.</param> /// <param name="aName">The name of the directory.</param> /// <param name="aFirstCluster">The first cluster number of the directory.</param> public FATDirectory(FATFileSystem aFileSystem, FATDirectory parent, FOS_System.String aName, UInt32 aFirstCluster) : base(aFileSystem, parent, aName) { _theFile = new FATFile(aFileSystem, parent, Name, 0, aFirstCluster) { IsDirectoryFile = true }; }