Esempio n. 1
0
        private void ReadFileListV15(BinaryReader reader, Package package)
        {
            int numFiles       = reader.ReadInt32();
            int compressedSize = reader.ReadInt32();

            byte[] compressedFileList = reader.ReadBytes(compressedSize);

            int fileBufferSize   = Marshal.SizeOf(typeof(FileEntry15)) * numFiles;
            var uncompressedList = new byte[fileBufferSize];
            int uncompressedSize = LZ4Codec.Decode(compressedFileList, 0, compressedFileList.Length, uncompressedList, 0, fileBufferSize, true);

            if (uncompressedSize != fileBufferSize)
            {
                string msg = $"LZ4 compressor disagrees about the size of file headers; expected {fileBufferSize}, got {uncompressedSize}";
                throw new InvalidDataException(msg);
            }

            var ms  = new MemoryStream(uncompressedList);
            var msr = new BinaryReader(ms);

            var entries = new FileEntry15[numFiles];

            BinUtils.ReadStructs(msr, entries);

            foreach (var entry in entries)
            {
                package.Files.Add(PackagedFileInfo.CreateFromEntry(entry, _streams[entry.ArchivePart]));
            }
        }
Esempio n. 2
0
        private Package ReadPackageV15(FileStream mainStream, BinaryReader reader)
        {
            var package = new Package();
            var header  = BinUtils.ReadStruct <LSPKHeader15>(reader);

            if (header.Version != (ulong)PackageVersion.V15)
            {
                string msg = $"Unsupported package version {header.Version}; this layout is only supported for {PackageVersion.V15}";
                throw new InvalidDataException(msg);
            }

            package.Metadata.Flags    = (PackageFlags)header.Flags;
            package.Metadata.Priority = header.Priority;
            package.Version           = PackageVersion.V15;

            if (_metadataOnly)
            {
                return(package);
            }

            OpenStreams(mainStream, 1);
            mainStream.Seek((long)header.FileListOffset, SeekOrigin.Begin);
            int numFiles       = reader.ReadInt32();
            int compressedSize = reader.ReadInt32();

            byte[] compressedFileList = reader.ReadBytes(compressedSize);

            int fileBufferSize   = Marshal.SizeOf(typeof(FileEntry15)) * numFiles;
            var uncompressedList = new byte[fileBufferSize];
            int uncompressedSize = LZ4Codec.Decode(compressedFileList, 0, compressedFileList.Length, uncompressedList, 0, fileBufferSize, true);

            if (uncompressedSize != fileBufferSize)
            {
                string msg = $"LZ4 compressor disagrees about the size of file headers; expected {fileBufferSize}, got {uncompressedSize}";
                throw new InvalidDataException(msg);
            }

            var ms  = new MemoryStream(uncompressedList);
            var msr = new BinaryReader(ms);

            var entries = new FileEntry15[numFiles];

            BinUtils.ReadStructs(msr, entries);

            foreach (var entry in entries)
            {
                package.Files.Add(PackagedFileInfo.CreateFromEntry(entry, _streams[0]));
            }

            return(package);
        }
Esempio n. 3
0
        private Package ReadPackageV13(FileStream mainStream, BinaryReader reader)
        {
            var package = new Package();
            var header  = BinUtils.ReadStruct <LSPKHeader13>(reader);

            if (header.Version != (ulong)PackageVersion.V13)
            {
                string msg = $"Unsupported package version {header.Version}; this package layout is only supported for {PackageVersion.V13}";
                throw new InvalidDataException(msg);
            }

            package.Metadata.Flags    = (PackageFlags)header.Flags;
            package.Metadata.Priority = header.Priority;
            package.Version           = PackageVersion.V13;

            if (_metadataOnly)
            {
                return(package);
            }

            OpenStreams(mainStream, header.NumParts);
            mainStream.Seek(header.FileListOffset, SeekOrigin.Begin);
            int numFiles       = reader.ReadInt32();
            int fileBufferSize = Marshal.SizeOf(typeof(FileEntry13)) * numFiles;

            byte[] compressedFileList = reader.ReadBytes((int)header.FileListSize - 4);

            var uncompressedList = new byte[fileBufferSize];
            int uncompressedSize = LZ4Codec.Decode(compressedFileList, 0, compressedFileList.Length, uncompressedList, 0, fileBufferSize, true);

            if (uncompressedSize != fileBufferSize)
            {
                string msg = $"LZ4 compressor disagrees about the size of file headers; expected {fileBufferSize}, got {uncompressedSize}";
                throw new InvalidDataException(msg);
            }

            var ms  = new MemoryStream(uncompressedList);
            var msr = new BinaryReader(ms);

            var entries = new FileEntry13[numFiles];

            BinUtils.ReadStructs(msr, entries);

            if ((package.Metadata.Flags & PackageFlags.Solid) == PackageFlags.Solid && numFiles > 0)
            {
                // Calculate compressed frame offset and bounds
                uint totalUncompressedSize = 0;
                uint totalSizeOnDisk       = 0;
                uint firstOffset           = 0xffffffff;
                uint lastOffset            = 0;

                foreach (var entry in entries)
                {
                    totalUncompressedSize += entry.UncompressedSize;
                    totalSizeOnDisk       += entry.SizeOnDisk;
                    if (entry.OffsetInFile < firstOffset)
                    {
                        firstOffset = entry.OffsetInFile;
                    }
                    if (entry.OffsetInFile + entry.SizeOnDisk > lastOffset)
                    {
                        lastOffset = entry.OffsetInFile + entry.SizeOnDisk;
                    }
                }

                if (firstOffset != 7 || lastOffset - firstOffset != totalSizeOnDisk)
                {
                    string msg = $"Incorrectly compressed solid archive; offsets {firstOffset}/{lastOffset}, bytes {totalSizeOnDisk}";
                    throw new InvalidDataException(msg);
                }

                // Decompress all files as a single frame (solid)
                byte[] frame = new byte[lastOffset];
                mainStream.Seek(0, SeekOrigin.Begin);
                mainStream.Read(frame, 0, (int)lastOffset);

                byte[] decompressed       = Native.LZ4FrameCompressor.Decompress(frame);
                var    decompressedStream = new MemoryStream(decompressed);

                // Update offsets to point to the decompressed chunk
                uint offset           = 7;
                uint compressedOffset = 0;
                foreach (var entry in entries)
                {
                    if (entry.OffsetInFile != offset)
                    {
                        throw new InvalidDataException("File list in solid archive not contiguous");
                    }

                    var file = PackagedFileInfo.CreateSolidFromEntry(entry, _streams[entry.ArchivePart], compressedOffset, decompressedStream);
                    package.Files.Add(file);

                    offset           += entry.SizeOnDisk;
                    compressedOffset += entry.UncompressedSize;
                }
            }
            else
            {
                foreach (var entry in entries)
                {
                    package.Files.Add(PackagedFileInfo.CreateFromEntry(entry, _streams[entry.ArchivePart]));
                }
            }

            return(package);
        }