Пример #1
0
        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)));
        }
Пример #2
0
        /// <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);
        }
Пример #3
0
        /// <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);
        }