public FileAllocationTable(FatType type, Stream stream, ushort firstFatSector, uint fatSize, byte numFats, byte activeFat) { _stream = stream; _firstFatSector = firstFatSector; _numFats = numFats; _stream.Position = (firstFatSector + (fatSize * activeFat)) * Utilities.SectorSize; _buffer = new FatBuffer(type, Utilities.ReadFully(_stream, (int)(fatSize * Utilities.SectorSize))); }
/// <summary> /// Creates a formatted hard disk partition in a stream. /// </summary> /// <param name="stream">The stream to write the new file system to.</param> /// <param name="label">The volume label for the partition (or null).</param> /// <param name="diskGeometry">The geometry of the disk containing the partition.</param> /// <param name="firstSector">The starting sector number of this partition (hide's sectors in other partitions).</param> /// <param name="sectorCount">The number of sectors in this partition.</param> /// <param name="reservedSectors">The number of reserved sectors at the start of the partition.</param> /// <returns>An object that provides access to the newly created partition file system.</returns> public static FatFileSystem FormatPartition( Stream stream, string label, Geometry diskGeometry, int firstSector, int sectorCount, short reservedSectors) { long pos = stream.Position; long ticks = DateTime.UtcNow.Ticks; uint volId = (uint)((ticks & 0xFFFF) | (ticks >> 32)); byte sectorsPerCluster; FatType fatType; ushort maxRootEntries; /* * Write the BIOS Parameter Block (BPB) - a single sector */ byte[] bpb = new byte[512]; if (sectorCount <= 8400) { throw new ArgumentException("Requested size is too small for a partition"); } else if (sectorCount < 1024 * 1024) { fatType = FatType.Fat16; maxRootEntries = 512; if (sectorCount <= 32680) { sectorsPerCluster = 2; } else if (sectorCount <= 262144) { sectorsPerCluster = 4; } else if (sectorCount <= 524288) { sectorsPerCluster = 8; } else { sectorsPerCluster = 16; } if (reservedSectors < 1) { reservedSectors = 1; } } else { fatType = FatType.Fat32; maxRootEntries = 0; if (sectorCount <= 532480) { sectorsPerCluster = 1; } else if (sectorCount <= 16777216) { sectorsPerCluster = 8; } else if (sectorCount <= 33554432) { sectorsPerCluster = 16; } else if (sectorCount <= 67108864) { sectorsPerCluster = 32; } else { sectorsPerCluster = 64; } if (reservedSectors < 32) { reservedSectors = 32; } } WriteBPB(bpb, (uint)sectorCount, fatType, maxRootEntries, (uint)firstSector, (ushort)reservedSectors, sectorsPerCluster, diskGeometry, false, volId, label); stream.Write(bpb, 0, bpb.Length); /* * Skip the reserved sectors */ stream.Position = pos + (((ushort)reservedSectors) * Utilities.SectorSize); /* * Write both FAT copies */ byte[] fat = new byte[CalcFatSize((uint)sectorCount, fatType, sectorsPerCluster) * Utilities.SectorSize]; FatBuffer fatBuffer = new FatBuffer(fatType, fat); fatBuffer.SetNext(0, 0xFFFFFFF8); fatBuffer.SetEndOfChain(1); if (fatType >= FatType.Fat32) { // Mark cluster 2 as End-of-chain (i.e. root directory // is a single cluster in length) fatBuffer.SetEndOfChain(2); } stream.Write(fat, 0, fat.Length); stream.Write(fat, 0, fat.Length); /* * Write the (empty) root directory */ uint rootDirSectors; if (fatType < FatType.Fat32) { rootDirSectors = (uint)(((maxRootEntries * 32) + Utilities.SectorSize - 1) / Utilities.SectorSize); } else { rootDirSectors = sectorsPerCluster; } byte[] rootDir = new byte[rootDirSectors * Utilities.SectorSize]; stream.Write(rootDir, 0, rootDir.Length); /* * Make sure the stream is at least as large as the partition requires. */ if (stream.Length < pos + (sectorCount * Utilities.SectorSize)) { stream.SetLength(pos + (sectorCount * Utilities.SectorSize)); } /* * Give the caller access to the new file system */ stream.Position = pos; return new FatFileSystem(stream); }
/// <summary> /// Creates a formatted floppy disk image in a stream. /// </summary> /// <param name="stream">The stream to write the blank image to.</param> /// <param name="type">The type of floppy to create.</param> /// <param name="label">The volume label for the floppy (or null).</param> /// <returns>An object that provides access to the newly created floppy disk image.</returns> public static FatFileSystem FormatFloppy(Stream stream, FloppyDiskType type, string label) { long pos = stream.Position; long ticks = DateTime.UtcNow.Ticks; uint volId = (uint)((ticks & 0xFFFF) | (ticks >> 32)); // Write the BIOS Parameter Block (BPB) - a single sector byte[] bpb = new byte[512]; uint sectors; if (type == FloppyDiskType.DoubleDensity) { sectors = 1440; WriteBPB(bpb, sectors, FatType.Fat12, 224, 0, 1, 1, new Geometry(80, 2, 9), true, volId, label); } else if (type == FloppyDiskType.HighDensity) { sectors = 2880; WriteBPB(bpb, sectors, FatType.Fat12, 224, 0, 1, 1, new Geometry(80, 2, 18), true, volId, label); } else if (type == FloppyDiskType.Extended) { sectors = 5760; WriteBPB(bpb, sectors, FatType.Fat12, 224, 0, 1, 1, new Geometry(80, 2, 36), true, volId, label); } else { throw new ArgumentException("Unrecognised Floppy Disk type", "type"); } stream.Write(bpb, 0, bpb.Length); // Write both FAT copies uint fatSize = CalcFatSize(sectors, FatType.Fat12, 1); byte[] fat = new byte[fatSize * Utilities.SectorSize]; FatBuffer fatBuffer = new FatBuffer(FatType.Fat12, fat); fatBuffer.SetNext(0, 0xFFFFFFF0); fatBuffer.SetEndOfChain(1); stream.Write(fat, 0, fat.Length); stream.Write(fat, 0, fat.Length); // Write the (empty) root directory uint rootDirSectors = ((224 * 32) + Utilities.SectorSize - 1) / Utilities.SectorSize; byte[] rootDir = new byte[rootDirSectors * Utilities.SectorSize]; stream.Write(rootDir, 0, rootDir.Length); // Write a single byte at the end of the disk to ensure the stream is at least as big // as needed for this disk image. stream.Position = pos + (sectors * Utilities.SectorSize) - 1; stream.WriteByte(0); // Give the caller access to the new file system stream.Position = pos; return new FatFileSystem(stream); }