[FileTools, SimpleSort, ZipFile/Entry] TorrentZip works! Mostly!

Writing to torrentzip works but for some reason the compressed streams are not being generated at the correct size. This is odd and seems to only affect newly added files and not ones copied from other archives. Also, found some glaring flaws in the headered output that explains why I was having issues previously. Typos D=
This commit is contained in:
Matt Nadareski
2016-09-16 11:37:55 -07:00
parent 444fc1696b
commit c69dddbc26
4 changed files with 313 additions and 286 deletions

View File

@@ -337,6 +337,7 @@ namespace SabreTools.Helper
else else
{ {
FileTools.WriteToArchive(input, _outdir, found); FileTools.WriteToArchive(input, _outdir, found);
//FileTools.WriteTorrentZip(input, _outdir, found, _logger);
} }
} }
} }
@@ -404,12 +405,14 @@ namespace SabreTools.Helper
else else
{ {
FileTools.WriteToArchive(newinput, _outdir, found); FileTools.WriteToArchive(newinput, _outdir, found);
//FileTools.WriteTorrentZip(newinput, _outdir, found, _logger);
} }
} }
// Then output the headered rom (renamed) // Then output the headered rom (renamed)
Rom newfound = found; Rom newfound = found;
newfound.Name = Path.GetFileNameWithoutExtension(newfound.Name) + " (" + rom.HashData.CRC + ")" + Path.GetExtension(newfound.Name); newfound.Name = Path.GetFileNameWithoutExtension(newfound.Name) + " (" + rom.HashData.CRC + ")" + Path.GetExtension(newfound.Name);
newfound.HashData = rom.HashData;
// Add rom to the matched list // Add rom to the matched list
key = newfound.HashData.Size + "-" + newfound.HashData.CRC; key = newfound.HashData.Size + "-" + newfound.HashData.CRC;
@@ -450,6 +453,7 @@ namespace SabreTools.Helper
else else
{ {
FileTools.WriteToArchive(input, _outdir, newfound); FileTools.WriteToArchive(input, _outdir, newfound);
//FileTools.WriteTorrentZip(input, _outdir, newfound, _logger);
} }
} }
} }
@@ -535,7 +539,8 @@ namespace SabreTools.Helper
} }
else else
{ {
FileTools.WriteToArchive(outfile, _outdir, found); FileTools.WriteToArchive(input, _outdir, found);
//FileTools.WriteTorrentZip(input, _outdir, found, _logger);
} }
try try

View File

@@ -86,6 +86,10 @@ namespace SabreTools.Helper
{ {
return _entries[i].SHA1; return _entries[i].SHA1;
} }
public bool Contains(string n)
{
return _entries.Contains(new ZipFileEntry(new MemoryStream(), n, true));
}
#endregion #endregion
@@ -658,6 +662,8 @@ namespace SabreTools.Helper
torrentZip &= zfe.TorrentZip; torrentZip &= zfe.TorrentZip;
} }
_centerDirSize = (ulong)_zipstream.Position - _centerDirStart;
// Then get the central directory hash // Then get the central directory hash
OptimizedCRC ocrc = new OptimizedCRC(); OptimizedCRC ocrc = new OptimizedCRC();
byte[] buffer = new byte[_centerDirSize]; byte[] buffer = new byte[_centerDirSize];
@@ -674,7 +680,6 @@ namespace SabreTools.Helper
_zipstream.Position = currentPosition; _zipstream.Position = currentPosition;
// Now set more of the information // Now set more of the information
_centerDirSize = (ulong)_zipstream.Position - _centerDirStart;
_fileComment = (torrentZip ? Encoding.ASCII.GetBytes(("TORRENTZIPPED-" + calculatedCrc).ToCharArray()) : new byte[0]); _fileComment = (torrentZip ? Encoding.ASCII.GetBytes(("TORRENTZIPPED-" + calculatedCrc).ToCharArray()) : new byte[0]);
_zipStatus = (torrentZip ? ZipStatus.TorrentZip : ZipStatus.None); _zipStatus = (torrentZip ? ZipStatus.TorrentZip : ZipStatus.None);

View File

@@ -399,190 +399,189 @@ namespace SabreTools.Helper
_torrentZip = true; _torrentZip = true;
// Open the stream for reading // Open the stream for reading
using (BinaryReader br = new BinaryReader(_zipstream)) BinaryReader br = new BinaryReader(_zipstream);
// Set the position of the writer based on the entry information
br.BaseStream.Seek((long)_relativeOffset, SeekOrigin.Begin);
// If the first bytes aren't a local file header, log and return
if (br.ReadUInt32() != Constants.LocalFileHeaderSignature)
{ {
// Set the position of the writer based on the entry information return ZipReturn.ZipLocalFileHeaderError;
br.BaseStream.Seek((long)_relativeOffset, SeekOrigin.Begin); }
// If the first bytes aren't a local file header, log and return // Now read in available information, comparing to the known data
if (br.ReadUInt32() != Constants.LocalFileHeaderSignature) if (br.ReadUInt16() != (ushort)_versionNeeded)
{ {
return ZipReturn.ZipLocalFileHeaderError; return ZipReturn.ZipLocalFileHeaderError;
} }
if (br.ReadUInt16() != (ushort)_generalPurposeBitFlag)
{
_torrentZip = false;
}
if (br.ReadUInt16() != (ushort)_compressionMethod)
{
return ZipReturn.ZipLocalFileHeaderError;
}
if (br.ReadUInt16() != _lastModFileTime)
{
return ZipReturn.ZipLocalFileHeaderError;
}
if (br.ReadUInt16() != _lastModFileDate)
{
return ZipReturn.ZipLocalFileHeaderError;
}
if ((_generalPurposeBitFlag & GeneralPurposeBitFlag.ZeroedCRCAndSize) == 0 && br.ReadUInt32() != _crc)
{
return ZipReturn.ZipLocalFileHeaderError;
}
// Now read in available information, comparing to the known data uint readCompressedSize = br.ReadUInt32();
if (br.ReadUInt16() != (ushort)_versionNeeded) // If we have Zip64, the compressed size should be 0xffffffff
{ if (_zip64 && readCompressedSize != 0xffffffff && readCompressedSize != _compressedSize)
return ZipReturn.ZipLocalFileHeaderError; {
} return ZipReturn.ZipLocalFileHeaderError;
if (br.ReadUInt16() != (ushort)_generalPurposeBitFlag) }
{ // If we have the zeroed flag set, then no size should be included
_torrentZip = false; if ((_generalPurposeBitFlag & GeneralPurposeBitFlag.ZeroedCRCAndSize) == GeneralPurposeBitFlag.ZeroedCRCAndSize && readCompressedSize != 0)
} {
if (br.ReadUInt16() != (ushort)_compressionMethod) return ZipReturn.ZipLocalFileHeaderError;
{ }
return ZipReturn.ZipLocalFileHeaderError; // If we don't have the zeroed flag set, then the size should match
} if ((_generalPurposeBitFlag & GeneralPurposeBitFlag.ZeroedCRCAndSize) == 0 && readCompressedSize != _compressedSize)
if (br.ReadUInt16() != _lastModFileTime) {
{ return ZipReturn.ZipLocalFileHeaderError;
return ZipReturn.ZipLocalFileHeaderError; }
}
if (br.ReadUInt16() != _lastModFileDate)
{
return ZipReturn.ZipLocalFileHeaderError;
}
if ((_generalPurposeBitFlag & GeneralPurposeBitFlag.ZeroedCRCAndSize) == 0 && br.ReadUInt32() != _crc)
{
return ZipReturn.ZipLocalFileHeaderError;
}
uint readCompressedSize = br.ReadUInt32(); uint readUncompressedSize = br.ReadUInt32();
// If we have Zip64, the compressed size should be 0xffffffff // If we have Zip64, the uncompressed size should be 0xffffffff
if (_zip64 && readCompressedSize != 0xffffffff && readCompressedSize != _compressedSize) if (_zip64 && readUncompressedSize != 0xffffffff && readUncompressedSize != _compressedSize)
{
return ZipReturn.ZipLocalFileHeaderError;
}
// If we have the zeroed flag set, then no size should be included
if ((_generalPurposeBitFlag & GeneralPurposeBitFlag.ZeroedCRCAndSize) == GeneralPurposeBitFlag.ZeroedCRCAndSize && readUncompressedSize != 0)
{
return ZipReturn.ZipLocalFileHeaderError;
}
// If we don't have the zeroed flag set, then the size should match
if ((_generalPurposeBitFlag & GeneralPurposeBitFlag.ZeroedCRCAndSize) == 0 && readUncompressedSize != _uncompressedSize)
{
return ZipReturn.ZipLocalFileHeaderError;
}
ushort fileNameLength = br.ReadUInt16();
ushort extraFieldLength = br.ReadUInt16();
byte[] fileNameBytes = br.ReadBytes(fileNameLength);
string tempFileName = ((_generalPurposeBitFlag & GeneralPurposeBitFlag.LanguageEncodingFlag) == 0
? Encoding.ASCII.GetString(fileNameBytes)
: Encoding.UTF8.GetString(fileNameBytes, 0, fileNameLength));
byte[] extraField = br.ReadBytes(extraFieldLength);
/*
Full disclosure: this next section is in GordonJ's work but I honestly
have no idea everything that it does. It seems to do something to figure
out if it's Zip64, or possibly check for random things but it uses the
extra field for this, which I do not fully understand. It's copied in
its entirety below in the hope that it makes things better...
*/
_zip64 = false;
int pos = 0;
while (extraFieldLength > pos)
{
ushort type = BitConverter.ToUInt16(extraField, pos);
pos += 2;
ushort blockLength = BitConverter.ToUInt16(extraField, pos);
pos += 2;
switch (type)
{ {
return ZipReturn.ZipLocalFileHeaderError; case 0x0001:
} Zip64 = true;
// If we have the zeroed flag set, then no size should be included if (readUncompressedSize == 0xffffffff)
if ((_generalPurposeBitFlag & GeneralPurposeBitFlag.ZeroedCRCAndSize) == GeneralPurposeBitFlag.ZeroedCRCAndSize && readCompressedSize != 0) {
{ ulong tLong = BitConverter.ToUInt64(extraField, pos);
return ZipReturn.ZipLocalFileHeaderError; if (tLong != UncompressedSize)
}
// If we don't have the zeroed flag set, then the size should match
if ((_generalPurposeBitFlag & GeneralPurposeBitFlag.ZeroedCRCAndSize) == 0 && readCompressedSize != _compressedSize)
{
return ZipReturn.ZipLocalFileHeaderError;
}
uint readUncompressedSize = br.ReadUInt32();
// If we have Zip64, the uncompressed size should be 0xffffffff
if (_zip64 && readUncompressedSize != 0xffffffff && readUncompressedSize != _compressedSize)
{
return ZipReturn.ZipLocalFileHeaderError;
}
// If we have the zeroed flag set, then no size should be included
if ((_generalPurposeBitFlag & GeneralPurposeBitFlag.ZeroedCRCAndSize) == GeneralPurposeBitFlag.ZeroedCRCAndSize && readUncompressedSize != 0)
{
return ZipReturn.ZipLocalFileHeaderError;
}
// If we don't have the zeroed flag set, then the size should match
if ((_generalPurposeBitFlag & GeneralPurposeBitFlag.ZeroedCRCAndSize) == 0 && readUncompressedSize != _uncompressedSize)
{
return ZipReturn.ZipLocalFileHeaderError;
}
ushort fileNameLength = br.ReadUInt16();
ushort extraFieldLength = br.ReadUInt16();
byte[] fileNameBytes = br.ReadBytes(fileNameLength);
string tempFileName = ((_generalPurposeBitFlag & GeneralPurposeBitFlag.LanguageEncodingFlag) == 0
? Encoding.ASCII.GetString(fileNameBytes)
: Encoding.UTF8.GetString(fileNameBytes, 0, fileNameLength));
byte[] extraField = br.ReadBytes(extraFieldLength);
/*
Full disclosure: this next section is in GordonJ's work but I honestly
have no idea everything that it does. It seems to do something to figure
out if it's Zip64, or possibly check for random things but it uses the
extra field for this, which I do not fully understand. It's copied in
its entirety below in the hope that it makes things better...
*/
_zip64 = false;
int pos = 0;
while (extraFieldLength > pos)
{
ushort type = BitConverter.ToUInt16(extraField, pos);
pos += 2;
ushort blockLength = BitConverter.ToUInt16(extraField, pos);
pos += 2;
switch (type)
{
case 0x0001:
Zip64 = true;
if (readUncompressedSize == 0xffffffff)
{
ulong tLong = BitConverter.ToUInt64(extraField, pos);
if (tLong != UncompressedSize)
{
return ZipReturn.ZipLocalFileHeaderError;
}
pos += 8;
}
if (readCompressedSize == 0xffffffff)
{
ulong tLong = BitConverter.ToUInt64(extraField, pos);
if (tLong != _compressedSize)
{
return ZipReturn.ZipLocalFileHeaderError;
}
pos += 8;
}
break;
case 0x7075:
//byte version = extraField[pos];
pos += 1;
uint nameCRC32 = BitConverter.ToUInt32(extraField, pos);
pos += 4;
CRC32 crcTest = new CRC32();
crcTest.SlurpBlock(fileNameBytes, 0, fileNameLength);
uint fCRC = (uint)crcTest.Crc32Result;
if (nameCRC32 != fCRC)
{ {
return ZipReturn.ZipLocalFileHeaderError; return ZipReturn.ZipLocalFileHeaderError;
} }
pos += 8;
}
if (readCompressedSize == 0xffffffff)
{
ulong tLong = BitConverter.ToUInt64(extraField, pos);
if (tLong != _compressedSize)
{
return ZipReturn.ZipLocalFileHeaderError;
}
pos += 8;
}
break;
case 0x7075:
//byte version = extraField[pos];
pos += 1;
uint nameCRC32 = BitConverter.ToUInt32(extraField, pos);
pos += 4;
int charLen = blockLength - 5; CRC32 crcTest = new CRC32();
crcTest.SlurpBlock(fileNameBytes, 0, fileNameLength);
uint fCRC = (uint)crcTest.Crc32Result;
tempFileName = Encoding.UTF8.GetString(extraField, pos, charLen); if (nameCRC32 != fCRC)
pos += charLen; {
return ZipReturn.ZipLocalFileHeaderError;
}
break; int charLen = blockLength - 5;
default:
pos += blockLength; tempFileName = Encoding.UTF8.GetString(extraField, pos, charLen);
break; pos += charLen;
}
break;
default:
pos += blockLength;
break;
} }
}
// Back to code I understand // Back to code I understand
if (String.Equals(_fileName, tempFileName, StringComparison.InvariantCulture)) if (!String.Equals(_fileName, tempFileName, StringComparison.InvariantCulture))
{ {
return ZipReturn.ZipLocalFileHeaderError; return ZipReturn.ZipLocalFileHeaderError;
} }
// Set the position of the data // Set the position of the data
_dataLocation = (ulong)_zipstream.Position; _dataLocation = (ulong)_zipstream.Position;
// Now if no other data should be after the data, return // Now if no other data should be after the data, return
if((_generalPurposeBitFlag & GeneralPurposeBitFlag.ZeroedCRCAndSize) == GeneralPurposeBitFlag.ZeroedCRCAndSize) if((_generalPurposeBitFlag & GeneralPurposeBitFlag.ZeroedCRCAndSize) == 0)
{ {
return ZipReturn.ZipGood; return ZipReturn.ZipGood;
} }
// Otherwise, compare the data after the file too // Otherwise, compare the data after the file too
_zipstream.Seek((long)_compressedSize, SeekOrigin.Current); _zipstream.Position += (long)_compressedSize;
// If there's no subheader, read the next thing as crc // If there's no subheader, read the next thing as crc
uint tempCrc = br.ReadUInt32(); uint tempCrc = br.ReadUInt32();
if (tempCrc != Constants.EndOfLocalFileHeaderSignature) if (tempCrc != Constants.EndOfLocalFileHeaderSignature)
{ {
tempCrc = br.ReadUInt32(); tempCrc = br.ReadUInt32();
} }
if (tempCrc != _crc) if (tempCrc != _crc)
{ {
return ZipReturn.ZipLocalFileHeaderError; return ZipReturn.ZipLocalFileHeaderError;
} }
if (br.ReadUInt32() != _compressedSize) if (br.ReadUInt32() != _compressedSize)
{ {
return ZipReturn.ZipLocalFileHeaderError; return ZipReturn.ZipLocalFileHeaderError;
} }
if (br.ReadUInt32() != _uncompressedSize) if (br.ReadUInt32() != _uncompressedSize)
{ {
return ZipReturn.ZipLocalFileHeaderError; return ZipReturn.ZipLocalFileHeaderError;
}
} }
} }
catch catch
@@ -605,105 +604,104 @@ namespace SabreTools.Helper
_torrentZip = true; _torrentZip = true;
// Open the stream for reading // Open the stream for reading
using (BinaryReader br = new BinaryReader(_zipstream)) BinaryReader br = new BinaryReader(_zipstream);
// Set the position of the writer based on the entry information
br.BaseStream.Seek((long)_relativeOffset, SeekOrigin.Begin);
// If the first bytes aren't a local file header, log and return
if (br.ReadUInt32() != Constants.LocalFileHeaderSignature)
{ {
// Set the position of the writer based on the entry information return ZipReturn.ZipLocalFileHeaderError;
br.BaseStream.Seek((long)_relativeOffset, SeekOrigin.Begin);
// If the first bytes aren't a local file header, log and return
if (br.ReadUInt32() != Constants.LocalFileHeaderSignature)
{
return ZipReturn.ZipLocalFileHeaderError;
}
// Now read in available information, ignoring unneeded
_versionNeeded = (ArchiveVersion)br.ReadUInt16();
_generalPurposeBitFlag = (GeneralPurposeBitFlag)br.ReadUInt16();
// If the flag says there's no hash data, then we can't use quick mode
if ((_generalPurposeBitFlag & GeneralPurposeBitFlag.ZeroedCRCAndSize) == GeneralPurposeBitFlag.ZeroedCRCAndSize)
{
return ZipReturn.ZipCannotFastOpen;
}
_compressionMethod = (CompressionMethod)br.ReadUInt16();
_lastModFileTime = br.ReadUInt16();
_lastModFileDate = br.ReadUInt16();
_crc = br.ReadUInt32();
_compressedSize = br.ReadUInt32();
_uncompressedSize = br.ReadUInt32();
ushort fileNameLength = br.ReadUInt16();
ushort extraFieldLength = br.ReadUInt16();
byte[] fileNameBytes = br.ReadBytes(fileNameLength);
_fileName = ((_generalPurposeBitFlag & GeneralPurposeBitFlag.LanguageEncodingFlag) == 0
? Encoding.ASCII.GetString(fileNameBytes)
: Encoding.UTF8.GetString(fileNameBytes, 0, fileNameLength));
byte[] extraField = br.ReadBytes(extraFieldLength);
/*
Full disclosure: this next section is in GordonJ's work but I honestly
have no idea everything that it does. It seems to do something to figure
out if it's Zip64, or possibly check for random things but it uses the
extra field for this, which I do not fully understand. It's copied in
its entirety below in the hope that it makes things better...
*/
_zip64 = false;
int pos = 0;
while (extraFieldLength > pos)
{
ushort type = BitConverter.ToUInt16(extraField, pos);
pos += 2;
ushort blockLength = BitConverter.ToUInt16(extraField, pos);
pos += 2;
switch (type)
{
case 0x0001:
Zip64 = true;
if (_uncompressedSize == 0xffffffff)
{
_uncompressedSize = BitConverter.ToUInt64(extraField, pos);
pos += 8;
}
if (_compressedSize == 0xffffffff)
{
_compressedSize = BitConverter.ToUInt64(extraField, pos);
pos += 8;
}
break;
case 0x7075:
pos += 1;
uint nameCRC32 = BitConverter.ToUInt32(extraField, pos);
pos += 4;
CRC32 crcTest = new CRC32();
crcTest.SlurpBlock(fileNameBytes, 0, fileNameLength);
uint fCRC = (uint)crcTest.Crc32Result;
if (nameCRC32 != fCRC)
{
return ZipReturn.ZipLocalFileHeaderError;
}
int charLen = blockLength - 5;
FileName = Encoding.UTF8.GetString(extraField, pos, charLen);
pos += charLen;
break;
default:
pos += blockLength;
break;
}
}
// Set the position of the data
_dataLocation = (ulong)_zipstream.Position;
} }
// Now read in available information, ignoring unneeded
_versionNeeded = (ArchiveVersion)br.ReadUInt16();
_generalPurposeBitFlag = (GeneralPurposeBitFlag)br.ReadUInt16();
// If the flag says there's no hash data, then we can't use quick mode
if ((_generalPurposeBitFlag & GeneralPurposeBitFlag.ZeroedCRCAndSize) == GeneralPurposeBitFlag.ZeroedCRCAndSize)
{
return ZipReturn.ZipCannotFastOpen;
}
_compressionMethod = (CompressionMethod)br.ReadUInt16();
_lastModFileTime = br.ReadUInt16();
_lastModFileDate = br.ReadUInt16();
_crc = br.ReadUInt32();
_compressedSize = br.ReadUInt32();
_uncompressedSize = br.ReadUInt32();
ushort fileNameLength = br.ReadUInt16();
ushort extraFieldLength = br.ReadUInt16();
byte[] fileNameBytes = br.ReadBytes(fileNameLength);
_fileName = ((_generalPurposeBitFlag & GeneralPurposeBitFlag.LanguageEncodingFlag) == 0
? Encoding.ASCII.GetString(fileNameBytes)
: Encoding.UTF8.GetString(fileNameBytes, 0, fileNameLength));
byte[] extraField = br.ReadBytes(extraFieldLength);
/*
Full disclosure: this next section is in GordonJ's work but I honestly
have no idea everything that it does. It seems to do something to figure
out if it's Zip64, or possibly check for random things but it uses the
extra field for this, which I do not fully understand. It's copied in
its entirety below in the hope that it makes things better...
*/
_zip64 = false;
int pos = 0;
while (extraFieldLength > pos)
{
ushort type = BitConverter.ToUInt16(extraField, pos);
pos += 2;
ushort blockLength = BitConverter.ToUInt16(extraField, pos);
pos += 2;
switch (type)
{
case 0x0001:
Zip64 = true;
if (_uncompressedSize == 0xffffffff)
{
_uncompressedSize = BitConverter.ToUInt64(extraField, pos);
pos += 8;
}
if (_compressedSize == 0xffffffff)
{
_compressedSize = BitConverter.ToUInt64(extraField, pos);
pos += 8;
}
break;
case 0x7075:
pos += 1;
uint nameCRC32 = BitConverter.ToUInt32(extraField, pos);
pos += 4;
CRC32 crcTest = new CRC32();
crcTest.SlurpBlock(fileNameBytes, 0, fileNameLength);
uint fCRC = (uint)crcTest.Crc32Result;
if (nameCRC32 != fCRC)
{
return ZipReturn.ZipLocalFileHeaderError;
}
int charLen = blockLength - 5;
FileName = Encoding.UTF8.GetString(extraField, pos, charLen);
pos += charLen;
break;
default:
pos += blockLength;
break;
}
}
// Set the position of the data
_dataLocation = (ulong)_zipstream.Position;
} }
catch catch
{ {
@@ -750,6 +748,7 @@ namespace SabreTools.Helper
bw.Write((ushort)_compressionMethod); bw.Write((ushort)_compressionMethod);
bw.Write(_lastModFileTime); bw.Write(_lastModFileTime);
bw.Write(_lastModFileDate); bw.Write(_lastModFileDate);
_crc32Location = (ulong)_zipstream.Position; _crc32Location = (ulong)_zipstream.Position;
// Now, write dummy bytes for crc, compressed size, and uncompressed size // Now, write dummy bytes for crc, compressed size, and uncompressed size
@@ -984,8 +983,9 @@ namespace SabreTools.Helper
using (OptimizedCRC crc = new OptimizedCRC()) using (OptimizedCRC crc = new OptimizedCRC())
using (MD5 md5 = System.Security.Cryptography.MD5.Create()) using (MD5 md5 = System.Security.Cryptography.MD5.Create())
using (SHA1 sha1 = System.Security.Cryptography.SHA1.Create()) using (SHA1 sha1 = System.Security.Cryptography.SHA1.Create())
using (BinaryReader fs = new BinaryReader(stream))
{ {
BinaryReader fs = new BinaryReader(stream);
byte[] buffer = new byte[1024]; byte[] buffer = new byte[1024];
int read; int read;
while ((read = fs.Read(buffer, 0, buffer.Length)) > 0) while ((read = fs.Read(buffer, 0, buffer.Length)) > 0)
@@ -999,7 +999,7 @@ namespace SabreTools.Helper
md5.TransformFinalBlock(buffer, 0, 0); md5.TransformFinalBlock(buffer, 0, 0);
sha1.TransformFinalBlock(buffer, 0, 0); sha1.TransformFinalBlock(buffer, 0, 0);
tempCrc = (uint)crc.Value; tempCrc = crc.UnsignedValue;
_md5 = md5.Hash; _md5 = md5.Hash;
_sha1 = sha1.Hash; _sha1 = sha1.Hash;
} }

View File

@@ -129,10 +129,6 @@ namespace SabreTools.Helper
Directory.CreateDirectory(Path.GetDirectoryName(archiveFileName)); Directory.CreateDirectory(Path.GetDirectoryName(archiveFileName));
} }
// Open the input file for reading
readStream = File.OpenRead(inputFile);
ulong streamSize = (ulong)(new FileInfo(inputFile).Length);
// Open or create the archive // Open or create the archive
if (!File.Exists(archiveFileName)) if (!File.Exists(archiveFileName))
{ {
@@ -141,29 +137,50 @@ namespace SabreTools.Helper
else else
{ {
// Open the old archive for reading // Open the old archive for reading
oldZipFile.Open(archiveFileName, new FileInfo(archiveFileName).LastWriteTime.Ticks, false); oldZipFile.Open(archiveFileName, new FileInfo(archiveFileName).LastWriteTime.Ticks, true);
zipFile.Create(archiveFileName + ".new");
// Copy over all files to the new archive // If the old one contains the new file, then just skip out
for (int i = 0; i < oldZipFile.EntriesCount; i++) if (oldZipFile.Contains(rom.Name))
{ {
// Instantiate the streams success = true;
CompressionMethod icompressionMethod = CompressionMethod.Stored; }
ulong istreamSize = 0; // Otherwise, process the old zipfile
oldZipFile.OpenReadStream(i, true, out readStream, out istreamSize, out icompressionMethod); else
zipFile.OpenWriteStream(true, true, oldZipFile.Filename(i), streamSize, CompressionMethod.Deflated, out writeStream); {
zipFile.Create(archiveFileName + ".new");
// Copy the input stream to the output // Copy over all files to the new archive
byte[] ibuffer = new byte[8 * 1024]; for (int i = 0; i < oldZipFile.EntriesCount; i++)
int ilen;
while ((ilen = readStream.Read(ibuffer, 0, ibuffer.Length)) > 0)
{ {
writeStream.Write(ibuffer, 0, ilen); // Instantiate the streams
CompressionMethod icompressionMethod = CompressionMethod.Stored;
ulong istreamSize = 0;
oldZipFile.OpenReadStream(i, false, out readStream, out istreamSize, out icompressionMethod);
zipFile.OpenWriteStream(false, true, oldZipFile.Filename(i), istreamSize, CompressionMethod.Deflated, out writeStream);
// Copy the input stream to the output
byte[] ibuffer = new byte[8 * 1024];
int ilen;
while ((ilen = readStream.Read(ibuffer, 0, ibuffer.Length)) > 0)
{
writeStream.Write(ibuffer, 0, ilen);
}
writeStream.Flush();
zipFile.CloseWriteStream(BitConverter.ToUInt32(oldZipFile.CRC32(i), 0));
} }
} }
} }
// Now open the write stream for the new rom // If the file has already been found, return it
if (success)
{
return success;
}
// Open the input file for reading
readStream = File.OpenRead(inputFile);
ulong streamSize = (ulong)(new FileInfo(inputFile).Length);
zipReturn = zipFile.OpenWriteStream(false, true, rom.Name, streamSize, CompressionMethod.Deflated, out writeStream); zipReturn = zipFile.OpenWriteStream(false, true, rom.Name, streamSize, CompressionMethod.Deflated, out writeStream);
// Copy the input stream to the output // Copy the input stream to the output