Ejemplo n.º 1
0
        public void Write(int index, byte[] data)
        {
            if (!IsFile)
            {
                throw new Exception("Must be a file to write bytes!");
            }

            // Make sure the cache is filled!
            LoadBlocks();

            // Extend the blocks if necessarry
            int initialFileLength = FileLength;
            int finalFileLength   = Math.Max(index + data.Length, initialFileLength);

            VirtualBlock.ExtendBlocks(drive, blocks, initialFileLength, finalFileLength);

            // Write the data to the blocks
            VirtualBlock.WriteBlockData(drive, blocks, index, data);


            //Write the blocks
            CommitBlocks();

            // Update file length in file node sector
            // Make sure to incease the file length as needed
            if (finalFileLength > initialFileLength)
            {
                (sector as FILE_NODE).FileSize = finalFileLength;
                drive.Disk.WriteSector(nodeSector, sector.RawBytes);
            }
        }
Ejemplo n.º 2
0
        public void Write(int index, byte[] data)
        {
            // Make sure this is a file
            if (!IsFile)
            {
                throw new Exception("Must write to a file!");
            }

            // Load the cache of blocks for the file
            LoadBlocks();

            // Grow the cached blocks if needed
            int finalLength = Math.Max(FileLength, index + data.Length);

            VirtualBlock.ExtendBlocks(drive, blocks, FileLength, finalLength);

            // Write the bytes to the cache
            VirtualBlock.WriteBlockData(drive, blocks, index, data);

            // Flush the cache of blocks
            CommitBlocks();

            // Adjust file size as needed
            if (finalLength > FileLength)
            {
                (sector as FILE_NODE).FileSize = index + data.Length;
                drive.Disk.WriteSector(nodeSector, sector.RawBytes);
            }
        }
Ejemplo n.º 3
0
        public static void ExtendBlocks(VirtualDrive drive, List <VirtualBlock> blocks, int initialFileLength, int finalFileLength)
        {
            // if current number of blocks is too small, then append more blocks as needed
            // allocate free sectors for each new block
            int finalBlockCount  = BlocksNeeded(drive, finalFileLength);
            int additionalBlocks = finalBlockCount - blocks.Count;

            if (additionalBlocks > 0)
            {
                int[] freeSectorAddresses = drive.GetNextFreeSectors(additionalBlocks);

                VirtualBlock prevBlock = blocks.Last();
                foreach (int i in freeSectorAddresses)
                {
                    // connect sectors
                    prevBlock.sector.NextSectorAt = i;
                    prevBlock.dirty = true;

                    // create new block
                    DATA_SECTOR  dataSector = new DATA_SECTOR(drive.Disk.BytesPerSector, 0, new byte[] { 0 });
                    VirtualBlock newBlock   = new VirtualBlock(drive, i, dataSector, true);

                    // add to the end of block list
                    blocks.Add(newBlock);

                    // prepare next block
                    prevBlock = newBlock;
                }
            }
        }
Ejemplo n.º 4
0
        public void Write(int index, byte[] data)
        {
            //writes data bytes to the file starting at the index byte

            //fill cache by read current data from disk for this file
            LoadBlocks();

            //if data to be writen is beyond the end of the current number of blocks, extend blocks
            int currentFileLength = FileLength;
            int newFileLength     = Math.Max(currentFileLength, index + data.Length);

            VirtualBlock.ExtendBlocks(drive, blocks, currentFileLength, newFileLength);

            //copy data from cache to blocks
            VirtualBlock.WriteBlockData(drive, blocks, index, data);

            //commit cache back to disk
            CommitBlocks();

            if (newFileLength > currentFileLength)
            {
                (sector as FILE_NODE).FileSize = newFileLength;
                drive.Disk.WriteSector(nodeSector, sector.RawBytes);
            }
        }
Ejemplo n.º 5
0
        private void LoadBlocks()
        {
            // read data secvtors from disk and create virtual blocks in memory

            //check if cahce is up to date
            if (blocks != null)
            {
                return;
            }

            //instantiate an empty cache
            blocks = new List <VirtualBlock>();

            //loop through data sectors for this file
            int nextDataSectorAt = DataSectorAt;

            while (nextDataSectorAt != 0)
            {
                //read sector
                DATA_SECTOR dataSector = DATA_SECTOR.CreateFromBytes(drive.Disk.ReadSector(nextDataSectorAt));
                //create virtual block to cache
                VirtualBlock block = new VirtualBlock(drive, nextDataSectorAt, dataSector);
                //add block to cache
                blocks.Add(block);

                //get the address of the next daa scetor
                nextDataSectorAt = dataSector.NextSectorAt;
            }
        }
Ejemplo n.º 6
0
        public static void WriteBlockData(VirtualDrive drive, List <VirtualBlock> blocks, int startIndex, byte[] data)
        {
            int bdps             = drive.BytesPerDataSector;
            int totalBytesToCopy = data.Length;

            // Part 1: Find the first block to be written and write the first chunk to the end of it
            int          blockIndex = (startIndex / bdps);            // Index of the first block to be written
            VirtualBlock block      = blocks[blockIndex];


            // Copy the first chunk into the first block
            int toStart     = startIndex % bdps;                          // Where to start in the first block
            int bytesToCopy = Math.Min(totalBytesToCopy, bdps - toStart); // How many bytes to copy into the first block
            int fromStart   = 0;

            byte[] db = block.sector.DataBytes;
            CopyBytes(bytesToCopy, data, fromStart, db, toStart);
            block.sector.DataBytes = db;
            block.dirty            = true;

            // Move on to the next chunk of data
            fromStart += bytesToCopy;

            // Part 2: Loop hoguh the middle blokcj and overwrite them completly with full chunks of data
            while (fromStart < (totalBytesToCopy - bdps))
            {
                // Next block
                block = blocks[++blockIndex];

                // Copy next chunk
                bytesToCopy = bdps;     // Full block
                toStart     = 0;        // Overwrite starting at beginning of block
                db          = block.sector.DataBytes;
                CopyBytes(bytesToCopy, data, fromStart, db, toStart);
                block.sector.DataBytes = db;
                block.dirty            = true;

                // Move on to the next chunk of data
                fromStart += bytesToCopy;
            }

            // Part 3: Write the first part of the last block with the final chunk
            if (fromStart < totalBytesToCopy)
            {
                // Next block
                block = blocks[++blockIndex];

                // Copy last chunk
                bytesToCopy = totalBytesToCopy - fromStart;
                toStart     = 0;                                        // Overwrite starting at beginning of block
                db          = block.sector.DataBytes;
                CopyBytes(bytesToCopy, data, fromStart, db, toStart);
                block.sector.DataBytes = db;
                block.dirty            = true;
            }
        }
Ejemplo n.º 7
0
        public byte[] Read(int index, int length)
        {
            //reads length data bytes from file starting at index byte

            //fill cache by read current data from disk for this file
            LoadBlocks();

            //copy data from blocks
            return(VirtualBlock.ReadBlockData(drive, blocks, index, length));
        }
Ejemplo n.º 8
0
        public static byte[] ReadBlockData(VirtualDrive drive, List <VirtualBlock> blocks, int startIndex, int length)
        {
            //given list of blocks in memory copy length bytes from blocks, starting at start index

            //allocate resulting data array
            byte[] data = new byte[length];

            //case 1: initial bytes from middle of block to end of block
            //copy from block, starting somewhere to begining of data array

            int fromIndex = startIndex % drive.BytesPerDataSector;                       //where we start copying from the block?

            int copyCount = Math.Min(data.Length, drive.BytesPerDataSector - fromIndex); //min of data length and the # of bytes left

            int          firstBlocktoRead = startIndex / drive.BytesPerDataSector;       //the first block to be writen?
            VirtualBlock block            = blocks[firstBlocktoRead];

            int toStart = 0;                                            //index in data to start at

            CopyBytes(copyCount, block.Data, fromIndex, data, toStart); //change clone

            toStart += copyCount;                                       //update to where to copy to next

            //case 2: read all bytes in block
            int nextBlocktoRead = firstBlocktoRead + 1;  //the next block to be writen?

            copyCount = drive.BytesPerDataSector;

            while (toStart + copyCount < data.Length)
            {
                block = blocks[nextBlocktoRead];
                nextBlocktoRead++;

                fromIndex = 0;
                CopyBytes(copyCount, block.Data, fromIndex, data, toStart); //change clone
                toStart += copyCount;                                       //update to where to copy to next
            }

            //there is still data left to copy
            if (toStart < data.Length)
            {
                //case 3: final bytes from beginning of block to middle of that block

                int finalIndex       = (startIndex + data.Length);
                int finalBlockToRead = finalIndex / drive.BytesPerDataSector;
                block     = blocks[finalBlockToRead];
                copyCount = finalIndex % drive.BytesPerDataSector; //where to stop reading

                fromIndex = 0;

                CopyBytes(copyCount, block.Data, fromIndex, data, toStart);
            }

            return(data);
        }
Ejemplo n.º 9
0
        public static void WriteBlockData(VirtualDrive drive, List <VirtualBlock> blocks, int startIndex, byte[] data)
        {
            //given list of blocks in memory copy data bytes starting at start index

            //case 1: initial bytes from middle of block to end of block

            int toStart = startIndex % drive.BytesPerDataSector;                       //where we start copying in the block?

            int copyCount = Math.Min(data.Length, drive.BytesPerDataSector - toStart); //min of data length and the # of bytes left

            int          firstBlocktoWrite = startIndex / drive.BytesPerDataSector;    //the first block to be writen?
            VirtualBlock block             = blocks[firstBlocktoWrite];

            int fromIndex = 0;                                  //index in data to start at

            byte[] to = block.Data;                             //data clones

            CopyBytes(copyCount, data, fromIndex, to, toStart); //change clone
            block.Data = to;                                    //write back changed data set dirty
            fromIndex += copyCount;                             //update to where to copy to next

            //case 2: overwrite all bytes in block
            int nextBlocktoWrite = firstBlocktoWrite + 1; //the next block to be writen?

            copyCount = drive.BytesPerDataSector;
            toStart   = 0;

            while (fromIndex + copyCount < data.Length)
            {
                block = blocks[nextBlocktoWrite];
                nextBlocktoWrite++;

                to = block.Data;

                CopyBytes(copyCount, data, fromIndex, to, toStart); //change clone
                block.Data = to;                                    //write back changed data set dirty
                fromIndex += copyCount;                             //update to where to copy to next
            }

            //there is still data left to copy
            if (fromIndex < data.Length)
            {
                //case 3: final bytes from beginning of block to middle of that block

                int finalIndex = (startIndex + data.Length);
                block     = blocks[nextBlocktoWrite];
                copyCount = finalIndex % drive.BytesPerDataSector;
                to        = block.Data; //data clones
                toStart   = 0;

                CopyBytes(copyCount, data, fromIndex, to, toStart); //change clone
                block.Data = to;                                    //write back changed data set dirty
            }
        }
Ejemplo n.º 10
0
        public static byte[] ReadBlockData(VirtualDrive drive, List <VirtualBlock> blocks, int startIndex, int length)
        {
            int bdps             = drive.BytesPerDataSector;
            int totalBytesToCopy = length;

            // Create the result byte[] to return at the end
            byte[] result = new byte[length];

            // Part 1: Find the first block to be read and read the first chunk to the end of it
            int          blockIndex = startIndex / bdps;            // Index of the first block to be read
            VirtualBlock block      = blocks[blockIndex];


            // Copy the first chunk into the first block
            int fromStart   = startIndex % bdps;                               // Where to start in the first block
            int bytesToCopy = Math.Min(totalBytesToCopy, bdps - fromStart);    // How many bytes to copy into the first block
            int toStart     = 0;

            CopyBytes(bytesToCopy, block.Data, fromStart, result, toStart);

            // Move on to the next chunk of data
            toStart += bytesToCopy;

            // Part 2: Loop hoguh the middle blokcj and overwrite them completly with full chunks of data
            while (toStart < (totalBytesToCopy - bdps))
            {
                // Next block
                block = blocks[++blockIndex];

                // Copy next chunk
                bytesToCopy = bdps;     // Full block
                fromStart   = 0;        // Overwrite starting at beginning of block
                CopyBytes(bytesToCopy, block.Data, fromStart, result, toStart);

                // Move on to the next chunk of data
                toStart += bytesToCopy;
            }

            // Part 3: Read the first part of the last block with the final chunk
            if (toStart < totalBytesToCopy)
            {
                // Next block
                block = blocks[++blockIndex];

                // Copy last chunk
                bytesToCopy = totalBytesToCopy - toStart;
                fromStart   = 0;                                          // Overwrite starting at beginning of block
                CopyBytes(bytesToCopy, block.Data, fromStart, result, toStart);
            }

            return(result);
        }
Ejemplo n.º 11
0
        public byte[] Read(int index, int length)
        {
            if (!IsFile)
            {
                throw new Exception("Must be a file to read bytes!");
            }

            // Make sure the cache is filled
            LoadBlocks();

            // Copy the data from the blocks
            byte[] result = VirtualBlock.ReadBlockData(drive, blocks, index, length);

            // Return the data
            return(result);
        }
Ejemplo n.º 12
0
        public static void WriteBlockData(VirtualDrive drive, List <VirtualBlock> blocks, int startIndex, byte[] data)
        {
            // Write data into the list of blocks, starting at index

            // calculate starting block and ending block
            int blockSize  = drive.BytesPerDataSector;
            int startBlock = startIndex / blockSize;
            int endBlock   = (startIndex + data.Length) / blockSize;

            // Write data to first block
            int fromStart = 0;

            VirtualBlock vb = blocks[startBlock];

            byte[] blockData = vb.Data;
            // Overwrite old data


            int toStart   = startIndex % blockSize;
            int copyCount = Math.Min(data.Length, blockSize - toStart);

            CopyBytes(copyCount, data, fromStart, blockData, toStart);

            // Put new data in
            vb.Data = blockData;

            fromStart += copyCount;


            // Write data to each affected block
            for (int i = startBlock + 1; i <= endBlock; i++)
            {
                vb        = blocks[i];
                blockData = vb.Data;

                // Overwrite old data

                toStart   = 0;
                copyCount = Math.Min((data.Length - fromStart), blockSize - toStart);
                CopyBytes(copyCount, data, fromStart, blockData, toStart);

                // Put new data in
                vb.Data = blockData;

                fromStart += copyCount;
            }
        }
Ejemplo n.º 13
0
        public byte[] Read(int index, int length)
        {
            // Make sure this is a file
            if (!IsFile)
            {
                throw new Exception("Must read from a file!");
            }
            // Check for reading past end
            if ((index + length) > FileLength)
            {
                throw new Exception("Can't read beyond end of file! /n");
            }

            // Load the cache of blocks for the file
            LoadBlocks();

            // Write the bytes to the cache
            return(VirtualBlock.ReadBlockData(drive, blocks, index, length));
        }
Ejemplo n.º 14
0
        private void LoadBlocks()
        {
            if (blocks == null)
            {
                blocks = new List <VirtualBlock>();

                // find data sectors
                int dataSectorAddr = sector.FirstDataAt;
                while (dataSectorAddr != 0)
                {
                    DATA_SECTOR  dataSector = DATA_SECTOR.CreateFromBytes(drive.Disk.ReadSector(dataSectorAddr));
                    VirtualBlock block      = new VirtualBlock(drive, dataSectorAddr, dataSector);
                    blocks.Add(block);

                    // Go on to next data sector
                    dataSectorAddr = dataSector.NextSectorAt;
                }
            }
        }
Ejemplo n.º 15
0
        public static byte[] ReadBlockData(VirtualDrive drive, List <VirtualBlock> blocks, int startIndex, int length)
        {
            // Read data from list of blocks
            // Assumes block list contains all data
            // Assumes list of blcoks is long enough

            byte[] result     = new byte[length];
            int    blockSize  = drive.BytesPerDataSector;
            int    startBlock = startIndex / blockSize;
            int    endBlock   = (startIndex + length) / blockSize;
            int    toStart    = 0;

            // Read data from first block

            VirtualBlock vb = blocks[startBlock];

            byte[] blockData = vb.Data;

            // Copy data from here
            int fromStart = startIndex % blockSize;
            int copyCount = Math.Min(length, blockSize - fromStart);

            CopyBytes(copyCount, blockData, fromStart, result, toStart);

            toStart += copyCount;


            // read data from rest of blocks
            for (int i = startBlock + 1; i <= endBlock; i++)
            {
                vb        = blocks[i];
                blockData = vb.Data;

                // Overwrite result data with this block's data
                fromStart = 0;
                copyCount = Math.Min((length - toStart), blockSize);
                CopyBytes(copyCount, blockData, fromStart, result, toStart);

                toStart += copyCount;
            }

            return(result);
        }
Ejemplo n.º 16
0
        public static void ExtendBlocks(VirtualDrive drive, List <VirtualBlock> blocks, int initialFileLength, int finalFileLength)
        {
            // If the file length has grown...
            if (finalFileLength > initialFileLength)
            {
                // ...and if we need ore blocks...
                int finalBlockCount = BlocksNeeded(drive, finalFileLength);
                if (finalBlockCount > blocks.Count)
                {
                    // how many new blocks to do what we need to do?
                    int neededNewBlocks = finalBlockCount - blocks.Count;

                    // Get needed number of free sectors
                    int[] freeSectors = drive.GetNextFreeSectors(neededNewBlocks);

                    // Allocate and connect them up
                    VirtualBlock previousBlock = blocks.Last();
                    for (int i = 0; i < neededNewBlocks; i++)
                    {
                        // write out the previousBlock to connect it to this new block
                        previousBlock.sector.NextSectorAt = freeSectors[i];
                        previousBlock.dirty = true;


                        // instantiate new DATA_SECTOR
                        DATA_SECTOR newDataSector = new DATA_SECTOR(drive.Disk.BytesPerSector, 0, null);

                        // instantiate new VirtualBlock
                        VirtualBlock newBlock = new VirtualBlock(drive, freeSectors[i], newDataSector, true);

                        // Add new VirtualBlocks to the list of blocks
                        blocks.Add(newBlock);

                        // Update prev block
                        previousBlock = newBlock;
                    }
                }
            }
        }
Ejemplo n.º 17
0
        private void LoadBlocks()
        {
            // Read each block if not alread in cache
            if (blocks == null)
            {
                // The cache is currently empty, so create and fill it!
                blocks = new List <VirtualBlock>();

                // Read the data sectors off the disk for this file and...
                int dataSectorAt = sector.FirstDataAt;
                while (dataSectorAt != 0)
                {
                    // ...create VirtualBlocks for them and add to the cache
                    DATA_SECTOR  dataSector = DATA_SECTOR.CreateFromBytes(drive.Disk.ReadSector(dataSectorAt));
                    VirtualBlock vb         = new VirtualBlock(drive, dataSectorAt, dataSector);
                    blocks.Add(vb);

                    // Go on to the next data sector
                    dataSectorAt = dataSector.NextSectorAt;
                }
            }
        }