예제 #1
0
        private void WriteFileData(BuilderContext context)
        {
            Stream outStream = context.RawStream;

            bool disposeSource = false;

            try
            {
                if (_source == null)
                {
                    var locator = new LocalFileLocator(string.Empty);
                    _source       = locator.Open(_sourcePath, FileMode.Open, FileAccess.Read, FileShare.Read);
                    disposeSource = true;
                }

                if (_source.Position != 0)
                {
                    _source.Position = 0;
                }

                long startPos      = outStream.Position;
                int  bufferedBytes = StreamUtilities.ReadMaximum(_source, context.IoBuffer, 0, context.DataBlockSize);

                if (bufferedBytes < context.DataBlockSize)
                {
                    // Fragment - less than one complete block of data
                    _inode.StartBlock = 0xFFFFFFFF;

                    _inode.FragmentKey = context.WriteFragment(bufferedBytes, out _inode.FragmentOffset);
                    _inode.FileSize    = (uint)bufferedBytes;
                }
                else
                {
                    // At least one full block, no fragments used
                    _inode.FragmentKey = 0xFFFFFFFF;

                    _lengths          = new List <uint>();
                    _inode.StartBlock = (uint)startPos;
                    _inode.FileSize   = bufferedBytes;
                    while (bufferedBytes > 0)
                    {
                        _lengths.Add(context.WriteDataBlock(context.IoBuffer, 0, bufferedBytes));
                        bufferedBytes    = StreamUtilities.ReadMaximum(_source, context.IoBuffer, 0, context.DataBlockSize);
                        _inode.FileSize += (uint)bufferedBytes;
                    }
                }
            }
            finally
            {
                if (disposeSource)
                {
                    _source.Dispose();
                }
            }
        }
예제 #2
0
        /// <summary>
        /// Detects if a stream contains a valid UDF file system.
        /// </summary>
        /// <param name="data">The stream to inspect.</param>
        /// <returns><c>true</c> if the stream contains a UDF file system, else false.</returns>
        public static bool Detect(Stream data)
        {
            if (data.Length < IsoUtilities.SectorSize)
            {
                return(false);
            }

            long vdpos = 0x8000; // Skip lead-in

            byte[] buffer = new byte[IsoUtilities.SectorSize];

            bool validDescriptor = true;
            bool foundUdfMarker  = false;

            BaseVolumeDescriptor bvd;

            while (validDescriptor)
            {
                data.Position = vdpos;
                int numRead = StreamUtilities.ReadMaximum(data, buffer, 0, IsoUtilities.SectorSize);
                if (numRead != IsoUtilities.SectorSize)
                {
                    break;
                }

                bvd = new BaseVolumeDescriptor(buffer, 0);
                switch (bvd.StandardIdentifier)
                {
                case "NSR02":
                case "NSR03":
                    foundUdfMarker = true;
                    break;

                case "BEA01":
                case "BOOT2":
                case "CD001":
                case "CDW02":
                case "TEA01":
                    break;

                default:
                    validDescriptor = false;
                    break;
                }

                vdpos += IsoUtilities.SectorSize;
            }

            return(foundUdfMarker);
        }
        private Metablock ReadMetaBlock(long pos)
        {
            Metablock block = _metablockCache.GetBlock(pos);

            if (block.Available >= 0)
            {
                return(block);
            }

            Stream stream = _context.RawStream;

            stream.Position = pos;

            byte[] buffer = StreamUtilities.ReadExact(stream, 2);

            int  readLen      = EndianUtilities.ToUInt16LittleEndian(buffer, 0);
            bool isCompressed = (readLen & 0x8000) == 0;

            readLen &= 0x7FFF;
            if (readLen == 0)
            {
                readLen = 0x8000;
            }

            block.NextBlockStart = pos + readLen + 2;

            if (isCompressed)
            {
                if (_ioBuffer == null || readLen > _ioBuffer.Length)
                {
                    _ioBuffer = new byte[readLen];
                }

                StreamUtilities.ReadExact(stream, _ioBuffer, 0, readLen);

                using (
                    ZlibStream zlibStream = new ZlibStream(new MemoryStream(_ioBuffer, 0, readLen, false),
                                                           CompressionMode.Decompress, true))
                {
                    block.Available = StreamUtilities.ReadMaximum(zlibStream, block.Data, 0, MetadataBufferSize);
                }
            }
            else
            {
                block.Available = StreamUtilities.ReadMaximum(stream, block.Data, 0, readLen);
            }

            return(block);
        }
예제 #4
0
        public AttributeDefinitions(File file)
        {
            _attrDefs = new Dictionary <AttributeType, AttributeDefinitionRecord>();

            byte[] buffer = new byte[AttributeDefinitionRecord.Size];
            using (Stream s = file.OpenStream(AttributeType.Data, null, FileAccess.Read))
            {
                while (StreamUtilities.ReadMaximum(s, buffer, 0, buffer.Length) == buffer.Length)
                {
                    AttributeDefinitionRecord record = new AttributeDefinitionRecord();
                    record.Read(buffer, 0);

                    // NULL terminator record
                    if (record.Type != AttributeType.None)
                    {
                        _attrDefs.Add(record.Type, record);
                    }
                }
            }
        }
예제 #5
0
        /// <summary>
        /// Detects if a stream contains a valid ISO file system.
        /// </summary>
        /// <param name="data">The stream to inspect.</param>
        /// <returns><c>true</c> if the stream contains an ISO file system, else false.</returns>
        public static bool Detect(Stream data, int sectorSize)
        {
            byte[] buffer = new byte[sectorSize];

            if (data.Length < 0x8000 + sectorSize)
            {
                return(false);
            }

            data.Position = 0x8000;
            int numRead = StreamUtilities.ReadMaximum(data, buffer, 0, sectorSize);

            if (numRead != sectorSize)
            {
                return(false);
            }

            BaseVolumeDescriptor bvd = new BaseVolumeDescriptor(buffer, 0);

            return(bvd.StandardIdentifier == BaseVolumeDescriptor.Iso9660StandardIdentifier);
        }
        private Block ReadBlock(long pos, int diskLen)
        {
            Block block = _blockCache.GetBlock(pos);

            if (block.Available >= 0)
            {
                return(block);
            }

            Stream stream = _context.RawStream;

            stream.Position = pos;

            int  readLen      = diskLen & 0x00FFFFFF;
            bool isCompressed = (diskLen & 0x01000000) == 0;

            if (isCompressed)
            {
                if (_ioBuffer == null || readLen > _ioBuffer.Length)
                {
                    _ioBuffer = new byte[readLen];
                }

                StreamUtilities.ReadExact(stream, _ioBuffer, 0, readLen);

                using (
                    ZlibStream zlibStream = new ZlibStream(new MemoryStream(_ioBuffer, 0, readLen, false),
                                                           CompressionMode.Decompress, true))
                {
                    block.Available = StreamUtilities.ReadMaximum(zlibStream, block.Data, 0, (int)_context.SuperBlock.BlockSize);
                }
            }
            else
            {
                StreamUtilities.ReadExact(stream, block.Data, 0, readLen);
                block.Available = readLen;
            }

            return(block);
        }
예제 #7
0
        private static bool SearchLabel(Stream content, out PhysicalVolumeLabel pvLabel)
        {
            pvLabel          = null;
            content.Position = 0;
            byte[] buffer = new byte[SECTOR_SIZE];
            for (uint i = 0; i < 4; i++)
            {
                if (StreamUtilities.ReadMaximum(content, buffer, 0, SECTOR_SIZE) != SECTOR_SIZE)
                {
                    return(false);
                }

                var label = EndianUtilities.BytesToString(buffer, 0x0, 0x8);
                if (label == PhysicalVolumeLabel.LABEL_ID)
                {
                    pvLabel = new PhysicalVolumeLabel();
                    pvLabel.ReadFrom(buffer, 0x0);
                    if (pvLabel.Sector != i)
                    {
                        //Invalid PV Sector;
                        return(false);
                    }
                    if (pvLabel.Crc != pvLabel.CalculatedCrc)
                    {
                        //Invalid PV CRC
                        return(false);
                    }
                    if (pvLabel.Label2 != PhysicalVolumeLabel.LVM2_LABEL)
                    {
                        //Invalid LVM2 Label
                        return(false);
                    }
                    return(true);
                }
            }
            return(false);
        }
예제 #8
0
        public static bool TryRead(Stream logStream, out LogEntry entry)
        {
            long position = logStream.Position;

            byte[] sectorBuffer = new byte[LogSectorSize];
            if (StreamUtilities.ReadMaximum(logStream, sectorBuffer, 0, sectorBuffer.Length) != sectorBuffer.Length)
            {
                entry = null;
                return(false);
            }

            uint sig = EndianUtilities.ToUInt32LittleEndian(sectorBuffer, 0);

            if (sig != LogEntryHeader.LogEntrySignature)
            {
                entry = null;
                return(false);
            }

            LogEntryHeader header = new LogEntryHeader();

            header.ReadFrom(sectorBuffer, 0);

            if (!header.IsValid || header.EntryLength > logStream.Length)
            {
                entry = null;
                return(false);
            }

            byte[] logEntryBuffer = new byte[header.EntryLength];
            Array.Copy(sectorBuffer, logEntryBuffer, LogSectorSize);

            StreamUtilities.ReadExact(logStream, logEntryBuffer, LogSectorSize, logEntryBuffer.Length - LogSectorSize);

            EndianUtilities.WriteBytesLittleEndian(0, logEntryBuffer, 4);
            if (header.Checksum !=
                Crc32LittleEndian.Compute(Crc32Algorithm.Castagnoli, logEntryBuffer, 0, (int)header.EntryLength))
            {
                entry = null;
                return(false);
            }

            int dataPos = MathUtilities.RoundUp((int)header.DescriptorCount * 32 + 64, LogSectorSize);

            List <Descriptor> descriptors = new List <Descriptor>();

            for (int i = 0; i < header.DescriptorCount; ++i)
            {
                int        offset = i * 32 + 64;
                Descriptor descriptor;

                uint descriptorSig = EndianUtilities.ToUInt32LittleEndian(logEntryBuffer, offset);
                switch (descriptorSig)
                {
                case Descriptor.ZeroDescriptorSignature:
                    descriptor = new ZeroDescriptor();
                    break;

                case Descriptor.DataDescriptorSignature:
                    descriptor = new DataDescriptor(logEntryBuffer, dataPos);
                    dataPos   += LogSectorSize;
                    break;

                default:
                    entry = null;
                    return(false);
                }

                descriptor.ReadFrom(logEntryBuffer, offset);
                if (!descriptor.IsValid(header.SequenceNumber))
                {
                    entry = null;
                    return(false);
                }

                descriptors.Add(descriptor);
            }

            entry = new LogEntry(position, header, descriptors);
            return(true);
        }
예제 #9
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);
        }