mirror of
https://github.com/claunia/SabreTools.git
synced 2025-12-16 19:14:27 +00:00
Internal Fixes, etc. (#20)
* Start removing mixed usages
* Check for directories before opening
* Fix writing
* Kinda fix rebuild
* One more try
* Better internal handling
* Slighty fix a couple more things
* Update RVWorld Compress code to db7d750bba
* Fix build
Co-authored-by: Matt Nadareski <mnadareski@mparticle.com>
This commit is contained in:
293
SabreTools.Library/External/Compress/SevenZip/SevenZipWriteClose.cs
vendored
Normal file
293
SabreTools.Library/External/Compress/SevenZip/SevenZipWriteClose.cs
vendored
Normal file
@@ -0,0 +1,293 @@
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
using Compress.SevenZip.Compress.LZMA;
|
||||
using Compress.SevenZip.Structure;
|
||||
using Compress.Utils;
|
||||
using Zstandard.Net;
|
||||
|
||||
namespace Compress.SevenZip
|
||||
{
|
||||
public partial class SevenZ
|
||||
{
|
||||
private void Create7ZStructure()
|
||||
{
|
||||
int fileCount = _localFiles.Count;
|
||||
|
||||
//FileInfo
|
||||
_header.FileInfo = new Structure.FileInfo
|
||||
{
|
||||
Names = new string[fileCount]
|
||||
};
|
||||
|
||||
ulong emptyStreamCount = 0;
|
||||
ulong emptyFileCount = 0;
|
||||
for (int i = 0; i < fileCount; i++)
|
||||
{
|
||||
_header.FileInfo.Names[i] = _localFiles[i].FileName;
|
||||
|
||||
if (_localFiles[i].UncompressedSize != 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!_localFiles[i].IsDirectory)
|
||||
{
|
||||
emptyFileCount += 1;
|
||||
}
|
||||
|
||||
emptyStreamCount += 1;
|
||||
}
|
||||
ulong outFileCount = (ulong)_localFiles.Count - emptyStreamCount;
|
||||
|
||||
_header.FileInfo.EmptyStreamFlags = null;
|
||||
_header.FileInfo.EmptyFileFlags = null;
|
||||
_header.FileInfo.Attributes = null;
|
||||
|
||||
if (emptyStreamCount > 0)
|
||||
{
|
||||
if (emptyStreamCount != emptyFileCount) //then we found directories and need to set the attributes
|
||||
{
|
||||
_header.FileInfo.Attributes = new uint[fileCount];
|
||||
}
|
||||
|
||||
if (emptyFileCount > 0)
|
||||
{
|
||||
_header.FileInfo.EmptyFileFlags = new bool[emptyStreamCount];
|
||||
}
|
||||
|
||||
emptyStreamCount = 0;
|
||||
_header.FileInfo.EmptyStreamFlags = new bool[fileCount];
|
||||
for (int i = 0; i < fileCount; i++)
|
||||
{
|
||||
if (_localFiles[i].UncompressedSize != 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (_localFiles[i].IsDirectory)
|
||||
{
|
||||
if (_header.FileInfo.Attributes != null)
|
||||
_header.FileInfo.Attributes[i] = 0x10; // set attributes to directory
|
||||
}
|
||||
else
|
||||
{
|
||||
if (_header.FileInfo.EmptyFileFlags != null)
|
||||
_header.FileInfo.EmptyFileFlags[emptyStreamCount] = true; // set empty file flag
|
||||
}
|
||||
|
||||
_header.FileInfo.EmptyStreamFlags[i] = true;
|
||||
emptyStreamCount += 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//StreamsInfo
|
||||
_header.StreamsInfo = new StreamsInfo { PackPosition = 0 };
|
||||
|
||||
//StreamsInfo.PackedStreamsInfo
|
||||
if (_compressed)
|
||||
{
|
||||
_header.StreamsInfo.PackedStreams = new PackedStreamInfo[1];
|
||||
_header.StreamsInfo.PackedStreams[0] = new PackedStreamInfo { PackedSize = _packStreamSize };
|
||||
}
|
||||
else
|
||||
{
|
||||
_header.StreamsInfo.PackedStreams = new PackedStreamInfo[outFileCount];
|
||||
int fileIndex = 0;
|
||||
for (int i = 0; i < fileCount; i++)
|
||||
{
|
||||
if (_localFiles[i].UncompressedSize == 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
_header.StreamsInfo.PackedStreams[fileIndex++] = new PackedStreamInfo { PackedSize = _localFiles[i].UncompressedSize };
|
||||
}
|
||||
}
|
||||
//StreamsInfo.PackedStreamsInfo, no CRC or StreamPosition required
|
||||
|
||||
if (_compressed)
|
||||
{
|
||||
//StreamsInfo.Folders
|
||||
_header.StreamsInfo.Folders = new Folder[1];
|
||||
|
||||
//StreamsInfo.Folders.Coder
|
||||
// flags 0x23
|
||||
|
||||
Folder folder = new Folder
|
||||
{
|
||||
BindPairs = null,
|
||||
Coders = new[] {
|
||||
new Coder {
|
||||
Method = new byte[] { 3, 1, 1 },
|
||||
NumInStreams = 1,
|
||||
NumOutStreams = 1,
|
||||
Properties = _codeMSbytes
|
||||
}
|
||||
},
|
||||
PackedStreamIndices = new[] { (ulong)0 },
|
||||
UnpackedStreamSizes = new[] { _unpackedStreamSize },
|
||||
UnpackedStreamInfo = new UnpackedStreamInfo[outFileCount],
|
||||
UnpackCRC = null
|
||||
};
|
||||
|
||||
switch (_lzmaStream)
|
||||
{
|
||||
case LzmaStream _:
|
||||
folder.Coders[0].Method = new byte[] { 3, 1, 1 };
|
||||
break;
|
||||
case ZstandardStream _:
|
||||
folder.Coders[0].Method = new byte[] { 4, 247, 17, 1 };
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
int fileIndex = 0;
|
||||
for (int i = 0; i < fileCount; i++)
|
||||
{
|
||||
if (_localFiles[i].UncompressedSize == 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
UnpackedStreamInfo unpackedStreamInfo = new UnpackedStreamInfo
|
||||
{
|
||||
UnpackedSize = _localFiles[i].UncompressedSize,
|
||||
Crc = Util.bytestouint(_localFiles[i].CRC)
|
||||
};
|
||||
folder.UnpackedStreamInfo[fileIndex++] = unpackedStreamInfo;
|
||||
}
|
||||
_header.StreamsInfo.Folders[0] = folder;
|
||||
}
|
||||
else
|
||||
{
|
||||
_header.StreamsInfo.Folders = new Folder[outFileCount];
|
||||
int fileIndex = 0;
|
||||
for (int i = 0; i < fileCount; i++)
|
||||
{
|
||||
if (_localFiles[i].UncompressedSize == 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
Folder folder = new Folder
|
||||
{
|
||||
BindPairs = null,
|
||||
Coders = new[] {
|
||||
new Coder {
|
||||
Method = new byte[] {0},
|
||||
NumInStreams = 1,
|
||||
NumOutStreams = 1,
|
||||
Properties = null
|
||||
}
|
||||
},
|
||||
PackedStreamIndices = new[] { (ulong)i },
|
||||
UnpackedStreamSizes = new[] { _localFiles[i].UncompressedSize },
|
||||
UnpackCRC = null,
|
||||
|
||||
UnpackedStreamInfo = new[] {
|
||||
new UnpackedStreamInfo {
|
||||
UnpackedSize = _localFiles[i].UncompressedSize,
|
||||
Crc = Util.bytestouint(_localFiles[i].CRC)
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
_header.StreamsInfo.Folders[fileIndex++] = folder;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
private void CloseWriting7Zip()
|
||||
{
|
||||
if (_compressed)
|
||||
{
|
||||
_lzmaStream.Close();
|
||||
}
|
||||
|
||||
_packStreamSize = (ulong)_zipFs.Position - _packStreamStart;
|
||||
|
||||
Create7ZStructure();
|
||||
|
||||
byte[] newHeaderByte;
|
||||
using (Stream headerMem = new MemoryStream())
|
||||
{
|
||||
using (BinaryWriter headerBw = new BinaryWriter(headerMem, Encoding.UTF8, true))
|
||||
{
|
||||
_header.WriteHeader(headerBw);
|
||||
|
||||
newHeaderByte = new byte[headerMem.Length];
|
||||
headerMem.Position = 0;
|
||||
headerMem.Read(newHeaderByte, 0, newHeaderByte.Length);
|
||||
}
|
||||
}
|
||||
|
||||
uint mainHeaderCRC = CRC.CalculateDigest(newHeaderByte, 0, (uint)newHeaderByte.Length);
|
||||
|
||||
#region Header Compression
|
||||
long packedHeaderPos = _zipFs.Position;
|
||||
LzmaEncoderProperties ep = new LzmaEncoderProperties(true, GetDictionarySizeFromUncompressedSize((ulong)newHeaderByte.Length), 64);
|
||||
LzmaStream lzs = new LzmaStream(ep, false, _zipFs);
|
||||
byte[] lzmaStreamProperties = lzs.Properties;
|
||||
lzs.Write(newHeaderByte, 0, newHeaderByte.Length);
|
||||
lzs.Close();
|
||||
|
||||
StreamsInfo streamsInfo = new StreamsInfo
|
||||
{
|
||||
PackPosition = (ulong)(packedHeaderPos - _baseOffset),
|
||||
Folders = new[] {
|
||||
new Folder {
|
||||
BindPairs = new BindPair[0],
|
||||
Coders = new [] {
|
||||
new Coder {
|
||||
Method = new byte[] { 3, 1, 1 },
|
||||
NumInStreams = 1,
|
||||
NumOutStreams = 1,
|
||||
Properties = lzmaStreamProperties
|
||||
}
|
||||
},
|
||||
UnpackedStreamSizes = new[] {(ulong) newHeaderByte.Length},
|
||||
UnpackCRC = mainHeaderCRC
|
||||
}
|
||||
},
|
||||
PackedStreams = new[] {
|
||||
new PackedStreamInfo
|
||||
{
|
||||
PackedSize = (ulong)(_zipFs.Position - packedHeaderPos),
|
||||
StreamPosition = 0
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
using (Stream headerMem = new MemoryStream())
|
||||
{
|
||||
using (BinaryWriter bw = new BinaryWriter(headerMem, Encoding.UTF8, true))
|
||||
{
|
||||
bw.Write((byte)HeaderProperty.kEncodedHeader);
|
||||
streamsInfo.WriteHeader(bw);
|
||||
|
||||
newHeaderByte = new byte[headerMem.Length];
|
||||
headerMem.Position = 0;
|
||||
headerMem.Read(newHeaderByte, 0, newHeaderByte.Length);
|
||||
|
||||
}
|
||||
}
|
||||
mainHeaderCRC = CRC.CalculateDigest(newHeaderByte, 0, (uint)newHeaderByte.Length);
|
||||
#endregion
|
||||
|
||||
|
||||
using (BinaryWriter bw = new BinaryWriter(_zipFs, Encoding.UTF8, true))
|
||||
{
|
||||
ulong headerPosition = (ulong)_zipFs.Position + 32; //tzip header is 32 bytes
|
||||
WriteRomVault7Zip(bw, headerPosition, (ulong)newHeaderByte.Length, mainHeaderCRC);
|
||||
|
||||
_zipFs.Write(newHeaderByte, 0, newHeaderByte.Length);
|
||||
_signatureHeader.WriteFinal(bw, headerPosition, (ulong)newHeaderByte.Length, mainHeaderCRC);
|
||||
}
|
||||
_zipFs.Flush();
|
||||
_zipFs.Close();
|
||||
_zipFs.Dispose();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user