Exemple #1
0
        public override void Write(byte[] buffer, int offset, int count)
        {
            CheckDisposed();

            if (!CanWrite)
            {
                throw new InvalidOperationException("Attempt to write to read-only VHDX");
            }

            if (_position % _metadata.LogicalSectorSize != 0 || count % _metadata.LogicalSectorSize != 0)
            {
                throw new IOException("Unaligned read");
            }

            int totalWritten = 0;

            while (totalWritten < count)
            {
                int   chunkIndex;
                int   blockIndex;
                int   sectorIndex;
                Chunk chunk = GetChunk(_position + totalWritten, out chunkIndex, out blockIndex, out sectorIndex);

                int blockOffset         = (int)(sectorIndex * _metadata.LogicalSectorSize);
                int blockBytesRemaining = (int)(_fileParameters.BlockSize - blockOffset);

                PayloadBlockStatus blockStatus = chunk.GetBlockStatus(blockIndex);
                if (blockStatus != PayloadBlockStatus.FullyPresent && blockStatus != PayloadBlockStatus.PartiallyPresent)
                {
                    blockStatus = chunk.AllocateSpaceForBlock(blockIndex);
                }

                int toWrite = Math.Min(blockBytesRemaining, count - totalWritten);
                _fileStream.Position = chunk.GetBlockPosition(blockIndex) + blockOffset;
                _fileStream.Write(buffer, offset + totalWritten, toWrite);

                if (blockStatus == PayloadBlockStatus.PartiallyPresent)
                {
                    BlockBitmap bitmap  = chunk.GetBlockBitmap(blockIndex);
                    bool        changed = bitmap.MarkSectorsPresent(sectorIndex, (int)(toWrite / _metadata.LogicalSectorSize));

                    if (changed)
                    {
                        chunk.WriteBlockBitmap(blockIndex);
                    }
                }

                totalWritten += toWrite;
            }

            _position += totalWritten;
        }
Exemple #2
0
        public override int Read(byte[] buffer, int offset, int count)
        {
            CheckDisposed();

            if (_atEof || _position > _length)
            {
                _atEof = true;
                throw new IOException("Attempt to read beyond end of file");
            }

            if (_position == _length)
            {
                _atEof = true;
                return(0);
            }

            if (_position % _metadata.LogicalSectorSize != 0 || count % _metadata.LogicalSectorSize != 0)
            {
                throw new IOException("Unaligned read");
            }

            int totalToRead = (int)Math.Min(_length - _position, count);
            int totalRead   = 0;

            while (totalRead < totalToRead)
            {
                int   chunkIndex;
                int   blockIndex;
                int   sectorIndex;
                Chunk chunk = GetChunk(_position + totalRead, out chunkIndex, out blockIndex, out sectorIndex);

                int blockOffset         = (int)(sectorIndex * _metadata.LogicalSectorSize);
                int blockBytesRemaining = (int)(_fileParameters.BlockSize - blockOffset);

                PayloadBlockStatus blockStatus = chunk.GetBlockStatus(blockIndex);
                if (blockStatus == PayloadBlockStatus.FullyPresent)
                {
                    _fileStream.Position = chunk.GetBlockPosition(blockIndex) + blockOffset;
                    int read = Utilities.ReadFully(_fileStream, buffer, offset + totalRead, Math.Min(blockBytesRemaining, totalToRead - totalRead));

                    totalRead += read;
                }
                else if (blockStatus == PayloadBlockStatus.PartiallyPresent)
                {
                    BlockBitmap bitmap = chunk.GetBlockBitmap(blockIndex);

                    bool present;
                    int  numSectors = bitmap.ContiguousSectors(sectorIndex, out present);
                    int  toRead     = (int)Math.Min(numSectors * _metadata.LogicalSectorSize, totalToRead - totalRead);
                    int  read;

                    if (present)
                    {
                        _fileStream.Position = chunk.GetBlockPosition(blockIndex) + blockOffset;
                        read = Utilities.ReadFully(_fileStream, buffer, offset + totalRead, toRead);
                    }
                    else
                    {
                        _parentStream.Position = _position + totalRead;
                        read = Utilities.ReadFully(_parentStream, buffer, offset + totalRead, toRead);
                    }

                    totalRead += read;
                }
                else if (blockStatus == PayloadBlockStatus.NotPresent)
                {
                    _parentStream.Position = _position + totalRead;
                    int read = Utilities.ReadFully(_parentStream, buffer, offset + totalRead, Math.Min(blockBytesRemaining, totalToRead - totalRead));

                    totalRead += read;
                }
                else
                {
                    int zeroed = Math.Min(blockBytesRemaining, totalToRead - totalRead);
                    Array.Clear(buffer, offset + totalRead, zeroed);
                    totalRead += zeroed;
                }
            }

            _position += totalRead;
            return(totalRead);
        }