public FatDirectoryEntry CreateSub(Fat fat) { var chain = new ClusterChain(fat, false); chain.SetChainLength(1); var entry = FatDirectoryEntry.Create(true); entry.SetStartCluster(chain.GetStartCluster()); var dir = new ClusterChainDirectory(chain, false); /* add "." entry */ var dot = FatDirectoryEntry.Create(true); dot.SetShortName(ShortName.Dot); dot.SetStartCluster(dir.GetStorageCluster()); CopyDateTimeFields(entry, dot); dir.AddEntry(dot); /* add ".." entry */ var dotDot = FatDirectoryEntry.Create(true); dotDot.SetShortName(ShortName.DotDot); dotDot.SetStartCluster(GetStorageCluster()); CopyDateTimeFields(entry, dotDot); dir.AddEntry(dotDot); dir.Flush(); return(entry); }
/// <summary> /// Constructor for FatFileSystem in specified readOnly mode /// </summary> /// <param name="device">the <see cref="IBlockDevice"/> holding the file system</param> /// <param name="readOnly"></param> /// <param name="ignoreFatDifferences"></param> /// <exception cref="IOException">IOException on read error</exception> private FatFileSystem(IBlockDevice device, bool readOnly, bool ignoreFatDifferences) : base(readOnly) { bs = BootSector.Read(device); if (bs.GetNrFats() <= 0) { throw new IOException( "boot sector says there are no FATs"); } filesOffset = FatUtils.GetFilesOffset(bs); fatType = bs.GetFatType(); fat = Fat.Read(bs, 0); if (!ignoreFatDifferences) { for (var i = 1; i < bs.GetNrFats(); i++) { var tmpFat = Fat.Read(bs, i); if (!fat.Equals(tmpFat)) { throw new IOException("FAT " + i + " differs from FAT 0"); } } } if (fatType == FatType.BaseFat32) { var f32Bs = (Fat32BootSector)bs; var rootDirFile = new ClusterChain(fat, f32Bs.GetRootDirFirstCluster(), IsReadOnly()); rootDirStore = ClusterChainDirectory.ReadRoot(rootDirFile); fsiSector = FsInfoSector.Read(f32Bs); if (fsiSector.GetFreeClusterCount() != fat.GetFreeClusterCount()) { throw new IOException("free cluster count mismatch - fat: " + fat.GetFreeClusterCount() + " - fsinfo: " + fsiSector.GetFreeClusterCount()); } } else { rootDirStore = Fat16RootDirectory.Read((Fat16BootSector)bs, readOnly); fsiSector = null; } rootDir = new FatLfnDirectory(rootDirStore, fat, IsReadOnly()); }
/// <summary> /// Reads a <see cref="Fat"/> as specified by a <see cref="BootSector"/>. /// </summary> /// <param name="bs">the boot sector specifying the <see cref="Fat"/> layout</param> /// <param name="fatNr">the number of the <see cref="Fat"/> to read</param> /// <returns>the <see cref="Fat"/> that was read</returns> /// <exception cref="IOException">IOException on read error</exception> /// <exception cref="ArgumentException">ArgumentException if fatNr is greater than /// <see cref="BootSector.GetNrFats"/></exception> public static Fat Read(BootSector bs, int fatNr) { if (fatNr > bs.GetNrFats()) { throw new ArgumentException( "boot sector says there are only " + bs.GetNrFats() + " FATs when reading FAT #" + fatNr); } var fatOffset = FatUtils.GetFatOffset(bs, fatNr); var result = new Fat(bs, fatOffset); result.Read(); return(result); }
private static ClusterChainDirectory Read(FatDirectoryEntry entry, Fat fat) { if (!entry.IsDirectory()) { throw new ArgumentException(entry + " is no directory"); } var chain = new ClusterChain( fat, entry.GetStartCluster(), entry.IsReadonlyFlag()); var result = new ClusterChainDirectory(chain, false); result.Read(); return(result); }
internal static FatFile Get(Fat fat, FatDirectoryEntry entry) { if (entry.IsDirectory()) { throw new ArgumentException(entry + " is a directory"); } var cc = new ClusterChain( fat, entry.GetStartCluster(), entry.IsReadonlyFlag()); if (entry.GetLength() > cc.GetLengthOnDisk()) { throw new IOException( "entry is larger than associated cluster chain"); } return(new FatFile(entry, cc)); }
public ClusterChain(Fat fat, long startCluster, bool readOnly) : base(readOnly) { this.fat = fat; if (startCluster != 0) { this.fat.TestCluster(startCluster); if (this.fat.IsFreeCluster(startCluster)) { throw new ArgumentException( "cluster " + startCluster + " is free"); } } device = fat.GetDevice(); dataOffset = FatUtils.GetFilesOffset(fat.GetBootSector()); this.startCluster = startCluster; clusterSize = fat.GetBootSector().GetBytesPerCluster(); }
/// <summary> /// Creates a new <see cref="Fat"/> as specified by a <see cref="BootSector"/>. /// </summary> /// <param name="bs">the boot sector specifying the <see cref="Fat"/> layout</param> /// <param name="fatNr">the number of the <see cref="Fat"/> to create</param> /// <returns>the <see cref="Fat"/> that was created</returns> /// <exception cref="IOException">IOException on write error</exception> /// <exception cref="ArgumentException">ArgumentException if fatNr is greater than /// <see cref="BootSector.GetNrFats"/></exception> public static Fat Create(BootSector bs, int fatNr) { if (fatNr > bs.GetNrFats()) { throw new ArgumentException( "boot sector says there are only " + bs.GetNrFats() + " FATs when creating FAT #" + fatNr); } var fatOffset = FatUtils.GetFatOffset(bs, fatNr); var result = new Fat(bs, fatOffset); if (bs.GetDataClusterCount() > result.entries.Length) { throw new IOException("FAT too small for device"); } result.Init(bs.GetMediumDescriptor()); result.Write(); return(result); }
public static ClusterChainDirectory CreateRoot(Fat fat) { if (fat.GetFatType() != FatType.BaseFat32) { throw new ArgumentException( "only FAT32 stores root directory in a cluster chain"); } var bs = (Fat32BootSector)fat.GetBootSector(); var cc = new ClusterChain(fat, false); cc.SetChainLength(1); bs.SetRootDirFirstCluster(cc.GetStartCluster()); var result = new ClusterChainDirectory(cc, true); result.Flush(); return(result); }
internal FatLfnDirectory(AbstractDirectory dir, Fat fat, bool readOnly) : base(readOnly) { if ((dir == null) || (fat == null)) { throw new NullReferenceException(); } this.fat = fat; this.Dir = dir; shortNameIndex = new Dictionary <ShortName, FatLfnDirectoryEntry>(); longNameIndex = new Dictionary <string, FatLfnDirectoryEntry>(); entryToFile = new Dictionary <FatDirectoryEntry, FatFile>(); entryToDirectory = new Dictionary <FatDirectoryEntry, FatLfnDirectory>(); usedNames = new HashSet <string>(); dbg = new Dummy83BufferGenerator(); ParseLfn(); }
/// <summary> /// Creates a new <see cref="ClusterChain"/> that contains no clusters. /// </summary> /// <param name="fat">the <see cref="Fat"/> that holds the new chain</param> /// <param name="readOnly">if the chain should be created read-only</param> public ClusterChain(Fat fat, bool readOnly) : this(fat, 0, readOnly) { }
/// <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); }