Example #1
0
        private Chunk GetChunk(long position, out int chunk, out int block, out int sector)
        {
            long chunkSize = (1L << 23) * _metadata.LogicalSectorSize;
            int chunkRatio = (int)(chunkSize / _metadata.FileParameters.BlockSize);

            chunk = (int)(position / chunkSize);
            long chunkOffset = position % chunkSize;

            block = (int)(chunkOffset / _fileParameters.BlockSize);
            int blockOffset = (int)(chunkOffset % _fileParameters.BlockSize);

            sector = (int)(blockOffset / _metadata.LogicalSectorSize);

            Chunk result = _chunks[chunk];
            if (result == null)
            {
                result = new Chunk(_batStream, _fileStream, _freeSpaceTable, _fileParameters, chunk, chunkRatio);
                _chunks[chunk] = result;
            }

            return result;
        }
Example #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 = StreamUtilities.ReadMaximum(_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 = StreamUtilities.ReadMaximum(_fileStream, buffer, offset + totalRead, toRead);
                    }
                    else
                    {
                        _parentStream.Position = _position + totalRead;
                        read = StreamUtilities.ReadMaximum(_parentStream, buffer, offset + totalRead, toRead);
                    }

                    totalRead += read;
                }
                else if (blockStatus == PayloadBlockStatus.NotPresent)
                {
                    _parentStream.Position = _position + totalRead;
                    int read = StreamUtilities.ReadMaximum(_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);
        }