예제 #1
0
        internal static PackagedFileInfo CreateFromEntry(FileEntry15 entry, Stream dataStream)
        {
            var info = new PackagedFileInfo
            {
                PackageStream    = dataStream,
                OffsetInFile     = entry.OffsetInFile,
                SizeOnDisk       = entry.SizeOnDisk,
                UncompressedSize = entry.UncompressedSize,
                ArchivePart      = 0,
                Flags            = entry.Flags,
                Crc   = entry.Crc,
                Solid = false
            };

            int nameLen;

            for (nameLen = 0; nameLen < entry.Name.Length && entry.Name[nameLen] != 0; nameLen++)
            {
            }
            info.Name = Encoding.UTF8.GetString(entry.Name, 0, nameLen);

            uint compressionMethod = entry.Flags & 0x0F;

            if (compressionMethod > 2 || (entry.Flags & ~0x7F) != 0)
            {
                string msg = $"File '{info.Name}' has unsupported flags: {entry.Flags}";
                throw new InvalidDataException(msg);
            }

            return(info);
        }
예제 #2
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]));
            }
        }
예제 #3
0
        public void WriteV15(FileStream mainStream)
        {
            var header = new LSPKHeader15
            {
                Version = (uint)Version
            };

            using (var writer = new BinaryWriter(mainStream, new UTF8Encoding(), true))
            {
                writer.Write(Package.Signature);
                BinUtils.WriteStruct(writer, ref header);
            }

            long totalSize   = _package.Files.Sum(p => (long)p.Size());
            long currentSize = 0;

            var writtenFiles = new List <PackagedFileInfo>();

            foreach (AbstractFileInfo file in _package.Files)
            {
                WriteProgress(file, currentSize, totalSize);
                writtenFiles.Add(WriteFile(file));
                currentSize += (long)file.Size();
            }

            using (var writer = new BinaryWriter(mainStream, new UTF8Encoding(), true))
            {
                byte[] fileListBuf;
                using (var fileList = new MemoryStream())
                    using (var fileListWriter = new BinaryWriter(fileList))
                    {
                        foreach (PackagedFileInfo file in writtenFiles)
                        {
                            FileEntry15 entry = file.MakeEntryV15();
                            BinUtils.WriteStruct(fileListWriter, ref entry);
                        }

                        fileListBuf = fileList.ToArray();
                    }

                byte[] compressedFileList = LZ4Codec.EncodeHC(fileListBuf, 0, fileListBuf.Length);

                header.FileListOffset = (UInt64)mainStream.Position;
                writer.Write((UInt32)writtenFiles.Count);
                writer.Write((UInt32)compressedFileList.Length);
                writer.Write(compressedFileList);

                header.FileListSize = (UInt32)(mainStream.Position - (long)header.FileListOffset);
                header.Priority     = _package.Metadata.Priority;
                header.Flags        = (byte)_package.Metadata.Flags;
                header.Md5          = ComputeArchiveHash();
                mainStream.Seek(4, SeekOrigin.Begin);
                BinUtils.WriteStruct(writer, ref header);
            }
        }
예제 #4
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);
        }
예제 #5
0
        internal FileEntry15 MakeEntryV15()
        {
            var entry = new FileEntry15
            {
                Name             = new byte[256],
                OffsetInFile     = OffsetInFile,
                SizeOnDisk       = SizeOnDisk,
                UncompressedSize = (Flags & 0x0F) == 0 ? 0 : UncompressedSize,
                Flags            = Flags,
                Crc      = Crc,
                Unknown1 = 0,
                Unknown2 = 0
            };

            byte[] encodedName = Encoding.UTF8.GetBytes(Name.Replace('\\', '/'));
            Array.Copy(encodedName, entry.Name, encodedName.Length);

            return(entry);
        }
예제 #6
0
        private void WriteFileListV15(BinaryWriter metadataWriter, List <PackagedFileInfo> files)
        {
            byte[] fileListBuf;
            using (var fileList = new MemoryStream())
                using (var fileListWriter = new BinaryWriter(fileList))
                {
                    foreach (PackagedFileInfo file in files)
                    {
                        FileEntry15 entry = file.MakeEntryV15();
                        BinUtils.WriteStruct(fileListWriter, ref entry);
                    }

                    fileListBuf = fileList.ToArray();
                }

            byte[] compressedFileList = LZ4Codec.EncodeHC(fileListBuf, 0, fileListBuf.Length);

            metadataWriter.Write((UInt32)files.Count);
            metadataWriter.Write((UInt32)compressedFileList.Length);
            metadataWriter.Write(compressedFileList);
        }