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); }
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])); } }
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); } }
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); }
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); }
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); }