public void Create_CreateFileSystemAndReadFile_Success() { // The minimum number of clusters for Fat32 is 65525. const int amountOfClusters = 65525; using (MemoryStream disk = new MemoryStream()) { BootSector boot = new BootSector(); boot.FatSize = (uint)Math.Ceiling(amountOfClusters / (double)boot.BytesPerSector); boot.Sectors = (uint)boot.SectorsPerCluster * amountOfClusters + boot.ReservedSectors + boot.FatSize; Fat32FileSystem.Create(disk, boot); byte[] bytes = new byte[4600]; // Use multiple clusters. Random random = new Random(); random.NextBytes(bytes); using (MemoryStream expected = new MemoryStream(bytes)) { Fat32FileSystem system = new Fat32FileSystem(disk); system.Create("Data.bin"); using (Stream file = system.Open("Data.bin")) { expected.CopyTo(file); file.Flush(); } using (Stream file = system.Open("Data.bin")) FileAssert.AreEqual(expected, file); } } }
/// <summary> /// Initializes a new instance of the <see cref="Fat32FileSystem"/> class. /// </summary> /// <param name="stream">The stream containing the image of the file system.</param> /// <exception cref="ArgumentNullException"> /// <paramref name="stream"/> is null. /// </exception> /// <exception cref="ArgumentException"> /// <paramref name="stream"/> cannot be read or written or seeked. /// </exception> public Fat32FileSystem(Stream stream) : base(stream) { boot = ReadStructure <BootSector>(0); info = ReadStructure <FileSystemInfo>(boot.FileSystemInfoSector * boot.BytesPerSector); if (!info.IsFileSystemInfo) { throw new ArgumentException("File System Info is corrupted.", nameof(stream)); } }
/// <summary> /// Creates Fat32 file system on the <paramref name="stream"/>. /// </summary> /// <param name="stream">The stream the file system is written on.</param> /// <param name="boot">The boot sector of the file system.</param> /// <exception cref="ArgumentNullException"> /// <paramref name="stream"/> or <paramref name="boot"/> is null. /// </exception> public static void Create(Stream stream, BootSector boot) { if (stream == null) { throw new ArgumentNullException(nameof(stream)); } if (boot == null) { throw new ArgumentNullException(nameof(boot)); } if (boot.Fats != 1) { throw new ArgumentOutOfRangeException(nameof(boot), "This must be 1."); } byte[] bytes = Structures.ToBytes(boot); stream.Position = 0; stream.Write(bytes, 0, bytes.Length); bytes = Structures.ToBytes(new FileSystemInfo()); stream.Position = boot.FileSystemInfoSector * boot.BytesPerSector; stream.Write(bytes, 0, bytes.Length); FileEntry volume = new FileEntry(); volume.ShortName = "SD Card"; volume.Attributes = FileAttributes.VolumeId; uint firstDataSector = boot.ReservedSectors + (boot.Fats * boot.FatSize); uint firstByteOfRootCluster = ((boot.RootCluster - 2) * boot.SectorsPerCluster) + firstDataSector; bytes = Structures.ToBytes(volume); stream.Position = firstByteOfRootCluster; stream.Write(bytes, 0, bytes.Length); // Allocate the root cluster. bytes = BitConverter.GetBytes(0xFFFFFFFF); stream.Position = boot.ReservedSectors * boot.BytesPerSector + boot.RootCluster * 4; stream.Write(bytes, 0, bytes.Length); // Place signature. bytes = BitConverter.GetBytes((ushort)0xAA55); stream.Position = 510; stream.Write(bytes, 0, bytes.Length); // Reach the end of the disk to allocated it. stream.Position = boot.Sectors * boot.BytesPerSector; stream.WriteByte(0); }