Ejemplo n.º 1
0
        /// <summary>
        /// Creates or opens a TransactedCompoundFile using the filename specified.
        /// </summary>
        public TransactedCompoundFile(Options options)
        {
            _options         = options.Clone();
            _sync            = new object();
            BlockSize        = _options.BlockSize;
            BlocksPerSection = BlockSize >> 2;
            SectionSize      = BlockSize * BlocksPerSection;

            _freeHandles    = new OrdinalList();
            _freeBlocks     = new OrdinalList();
            _reservedBlocks = new OrdinalList();

            _stream =
                new FileStream(
                    _options.FilePath,
                    _options.CreateNew ? FileMode.Create : FileMode.Open,
                    _options.ReadOnly ? FileAccess.Read : FileAccess.ReadWrite,
                    _options.ReadOnly ? FileShare.ReadWrite : FileShare.Read,
                    8,
                    _options.FileOptions
                    );
            _fcommit = _fput = fput;
            _fget    = ReadBytes;

            try
            {
                LoadSections(_stream);
                if (_sections.Length == 0)
                {
                    AddSection();
                }
            }
            catch
            {
                _stream.Dispose();
                throw;
            }

            if (!_options.CommitOnWrite)
            {
                _fcommit = null;
            }

            _readers = new StreamCache(
                new FileStreamFactory(_options.FilePath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite, 8, FileOptions.None),
                4);
        }
Ejemplo n.º 2
0
            public void GetFree(ICollection <int> freeHandles, ICollection <int> usedBlocks, FGet fget)
            {
                int baseHandle = unchecked (BlocksPerSection * _sectionIndex);

                //reserved: first and last block
                usedBlocks.Add(baseHandle);
                usedBlocks.Add(baseHandle + BlocksPerSection - 1);

                for (int handle = 1; handle < BlocksPerSection - 1; handle++)
                {
                    uint data = ReadUInt32(handle);
                    if (data == 0)
                    {
                        freeHandles.Add(baseHandle + handle);
                    }
                    else
                    {
                        BlockRef block   = new BlockRef(data, BlockSize);
                        int      blockId = (int)block.Identity & 0x0FFFFFFF;

                        if (block.Count == 16)
                        {
                            long position = (long)BlocksPerSection * BlockSize * block.Section;
                            position += BlockSize * block.Offset;
                            byte[] header = new byte[BlockHeaderSize];
                            if (BlockHeaderSize != fget(position, header, 0, header.Length))
                            {
                                throw new InvalidDataException();
                            }
                            block.ActualBlocks = (int)GetUInt32(header, OffsetOfBlockCount);
                        }

                        for (uint i = 0; i < block.ActualBlocks; i++)
                        {
                            usedBlocks.Add(blockId++);
                        }
                    }
                }
            }
Ejemplo n.º 3
0
            public Stream Read(ref BlockRef block, bool headerOnly, FGet fget)
            {
                bool retry;

                byte[] bytes;
                int    readBytes, headerSize, length;

                do
                {
                    retry = false;
                    long position = _sectionPosition + (BlockSize * block.Offset);
                    bytes = new byte[headerOnly ? BlockHeaderSize : block.ActualBlocks * BlockSize];

                    readBytes = fget(position, bytes, 0, bytes.Length);
                    if (readBytes < BlockHeaderSize)
                    {
                        throw new InvalidDataException();
                    }

                    headerSize = bytes[OffsetOfHeaderSize];
                    length     = (int)GetUInt32(bytes, OffsetOfLength) & 0x00FFFFFF;

                    block.ActualBlocks = (int)GetUInt32(bytes, OffsetOfBlockCount);
                    uint blockId = GetUInt32(bytes, OffsetOfBlockId);

                    if (headerSize < BlockHeaderSize || blockId != block.Identity ||
                        ((block.Count < 16 && block.ActualBlocks != block.Count) ||
                         (block.Count == 16 && block.ActualBlocks < 16)))
                    {
                        throw new InvalidDataException();
                    }

                    if (block.ActualBlocks != Math.Max(1, (length + headerSize + BlockSize - 1) / BlockSize))
                    {
                        throw new InvalidDataException();
                    }

                    if (headerOnly)
                    {
                        return(null);
                    }
                    if (readBytes < length + headerSize)
                    {
                        retry = bytes.Length != block.ActualBlocks * BlockSize;
                    }
                } while (retry);

                if (readBytes < length + headerSize)
                {
                    throw new InvalidDataException();
                }

                Crc32 crc = new Crc32();

                crc.Add(bytes, headerSize, length);
                if ((uint)crc.Value != GetUInt32(bytes, OffsetOfCrc32))
                {
                    throw new InvalidDataException();
                }

                return(new MemoryStream(bytes, headerSize, length, false, false));
            }