public static BootSector Read(IBlockDevice device) { var b = new byte[512]; var bb = new MemoryStream(b); device.Read(0, bb); bb.Position = 510; if (bb.ReadByte() != 0x55) { throw new IOException( "missing boot sector signature"); } bb.Position = 511; if (bb.ReadByte() != 0xaa) { throw new IOException( "missing boot sector signature"); } bb.Position = SECTORS_PER_CLUSTER_OFFSET; var sectorsPerCluster = (byte)bb.ReadByte(); if (sectorsPerCluster <= 0) { throw new IOException( "suspicious sectors per cluster count " + sectorsPerCluster); } var rootDirEntriesB = new byte[2]; bb.Position = Fat16BootSector.ROOT_DIR_ENTRIES_OFFSET; bb.Read(rootDirEntriesB, 0, 2); if (!BitConverter.IsLittleEndian) { Array.Reverse(rootDirEntriesB, 0, 2); } int rootDirEntries = BitConverter.ToUInt16(rootDirEntriesB, 0); var rootDirSectors = ((rootDirEntries * 32) + (device.GetSectorSize() - 1)) / device.GetSectorSize(); var total16B = new byte[2]; bb.Position = TOTAL_SECTORS_16_OFFSET; bb.Read(total16B, 0, 2); if (!BitConverter.IsLittleEndian) { Array.Reverse(total16B, 0, 2); } int total16 = BitConverter.ToUInt16(total16B, 0); var total32B = new byte[4]; bb.Position = TOTAL_SECTORS_32_OFFSET; bb.Read(total32B, 0, 4); if (!BitConverter.IsLittleEndian) { Array.Reverse(total32B, 0, 4); } long total32 = BitConverter.ToUInt32(total32B, 0); var totalSectors = total16 == 0 ? total32 : total16; var fatSz16B = new byte[2]; bb.Position = Fat16BootSector.SECTORS_PER_FAT_OFFSET; bb.Read(fatSz16B, 0, 2); if (!BitConverter.IsLittleEndian) { Array.Reverse(fatSz16B, 0, 2); } int fatSz16 = BitConverter.ToUInt16(fatSz16B, 0); var fatSz32B = new byte[4]; bb.Position = Fat32BootSector.SECTORS_PER_FAT_OFFSET; bb.Read(fatSz32B, 0, 4); if (!BitConverter.IsLittleEndian) { Array.Reverse(fatSz32B, 0, 4); } long fatSz32 = BitConverter.ToUInt32(fatSz32B, 0); var fatSz = fatSz16 == 0 ? fatSz32 : fatSz16; var reservedSectorsB = new byte[2]; bb.Position = RESERVED_SECTORS_OFFSET; bb.Read(reservedSectorsB, 0, 2); if (!BitConverter.IsLittleEndian) { Array.Reverse(reservedSectorsB, 0, 2); } int reservedSectors = BitConverter.ToUInt16(reservedSectorsB, 0); bb.Position = FAT_COUNT_OFFSET; var fatCount = bb.ReadByte(); var dataSectors = totalSectors - (reservedSectors + (fatCount * fatSz) + rootDirSectors); var clusterCount = dataSectors / sectorsPerCluster; var result = (clusterCount > Fat16BootSector.MAX_FAT16_CLUSTERS) ? (BootSector) new Fat32BootSector(device) : (BootSector) new Fat16BootSector(device); result.Read(); return(result); }
/// <summary> /// Initializes the boot sector and file system for the device. The file /// system created by this method will always be in read-write mode. /// </summary> /// <returns>the file system that was created</returns> /// <exception cref="System.IO.IOException">IOException on write error</exception> public FatFileSystem Format() { var sectorSize = device.GetSectorSize(); var totalSectors = (int)(device.GetSize() / sectorSize); FsInfoSector fsi; BootSector bs; if (sectorsPerCluster == 0) { throw new Exception(); } if (fatType == FatType.BaseFat32) { bs = new Fat32BootSector(device); InitBootSector(bs); var f32Bs = (Fat32BootSector)bs; f32Bs.SetFsInfoSectorNr(1); f32Bs.SetSectorsPerFat(SectorsPerFat(0, totalSectors)); var rnd = new Random(); f32Bs.SetFileSystemId(rnd.Next()); f32Bs.SetVolumeLabel(label); /* create FS info sector */ fsi = FsInfoSector.Create(f32Bs); } else { bs = new Fat16BootSector(device); InitBootSector(bs); var f16Bs = (Fat16BootSector)bs; var rootDirEntries = RootDirectorySize( device.GetSectorSize(), totalSectors); f16Bs.SetRootDirEntryCount(rootDirEntries); f16Bs.SetSectorsPerFat(SectorsPerFat(rootDirEntries, totalSectors)); if (label != null) { f16Bs.SetVolumeLabel(label); } fsi = null; } // bs.write(); if (fatType == FatType.BaseFat32) { var f32Bs = (Fat32BootSector)bs; /* possibly writes the boot sector copy */ f32Bs.WriteCopy(device); } var fat = Fat.Create(bs, 0); AbstractDirectory rootDirStore; if (fatType == FatType.BaseFat32) { rootDirStore = ClusterChainDirectory.CreateRoot(fat); fsi.SetFreeClusterCount(fat.GetFreeClusterCount()); fsi.SetLastAllocatedCluster(fat.GetLastAllocatedCluster()); fsi.Write(); } else { rootDirStore = Fat16RootDirectory.Create((Fat16BootSector)bs); } var rootDir = new FatLfnDirectory(rootDirStore, fat, false); rootDir.Flush(); for (var i = 0; i < bs.GetNrFats(); i++) { fat.WriteCopy(FatUtils.GetFatOffset(bs, i)); } bs.Write(); var fs = FatFileSystem.Read(device, false); if (label != null) { fs.SetVolumeLabel(label); } fs.Flush(); return(fs); }