Example #1
0
        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);
        }
Example #2
0
        /// <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());
        }
Example #3
0
        /// <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);
        }
Example #4
0
        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);
        }
Example #5
0
        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));
        }
Example #6
0
        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();
        }
Example #7
0
        /// <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);
        }
Example #8
0
        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);
        }
Example #9
0
        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();
        }
Example #10
0
 /// <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);
        }