[ALL] Allow for original Dates to be written again in zipfiles

This commit is contained in:
Matt Nadareski
2016-10-14 16:58:15 -07:00
parent cbbab3518c
commit 1a998d575c
12 changed files with 245 additions and 115 deletions

View File

@@ -47,54 +47,50 @@ namespace SabreTools
List<DatItem> datItems = df.Files[key]; List<DatItem> datItems = df.Files[key];
foreach (Rom rom in datItems) foreach (Rom rom in datItems)
{ {
bool add = false; string query = "SELECT id FROM data WHERE size=" + rom.Size
if (onlyNeeded) + " AND (crc=\"" + rom.CRC + "\" OR crc=\"null\")"
{ + " AND (md5=\"" + rom.MD5 + "\" OR md5=\"null\")"
string query = @" + " AND (sha1=\"" + rom.SHA1 + "\" OR sha1=\"null\")"
SELECT crcsha1.crc, md5sha1.md5, md5sha1.sha1 FROM crcsha1 + " AND indepot=0";
JOIN md5sha1 ON crcsha1.sha1=md5sha1.sha1 SqliteCommand slc = new SqliteCommand(query, dbc);
WHERE crcsha1.crc=""" + rom.CRC + @""" SqliteDataReader sldr = slc.ExecuteReader();
OR md5sha1.md5=""" + rom.MD5 + @"""
OR md5sha1.sha1=""" + rom.SHA1 + "\"";
SqliteCommand slc = new SqliteCommand(query, dbc);
SqliteDataReader sldr = slc.ExecuteReader();
// If a row is returned, add the file and change the existence // If a row is returned, add the file and change the existence
if (sldr.HasRows) if (sldr.HasRows)
{
sldr.Read();
long id = sldr.GetInt64(0);
string squery = "UPDATE data SET indepot=1 WHERE id=" + id;
SqliteCommand sslc = new SqliteCommand(squery, dbc);
sslc.ExecuteNonQuery();
sslc.Dispose();
// Add the rom to the files that need to be rebuilt
if (need.Files.ContainsKey(key))
{ {
add = true; need.Files[key].Add(rom);
}
else
{
List<DatItem> temp = new List<DatItem>();
temp.Add(rom);
need.Files.Add(key, temp);
} }
} }
else
// If it doesn't exist, and we're not adding only needed files
else if (!onlyNeeded)
{ {
add = true; string squery = "INSERT INTO data (size, crc, md5, sha1, indepot) VALUES ("
} + rom.Size + ","
+ "\"" + (rom.CRC == "" ? "null" : rom.CRC) + "\","
// If we're supposed to add the file to the depot, add it to the list + "\"" + (rom.MD5 == "" ? "null" : rom.MD5) + "\","
if (add) + "\"" + (rom.SHA1 == "" ? "null" : rom.SHA1) + "\","
{ + "1)";
_logger.User("Adding file \"" + rom.Name + "\" to the database"); SqliteCommand sslc = new SqliteCommand(squery, dbc);
sslc.ExecuteNonQuery();
// Insert new or updated information into the database sslc.Dispose();
string query = "INSERT OR IGNORE INTO crc (crc) VALUES (\"" + rom.CRC + "\")";
SqliteCommand slc = new SqliteCommand(query, dbc);
slc.ExecuteNonQuery();
query = "INSERT OR IGNORE INTO md5 (md5) VALUES (\"" + rom.MD5 + "\")";
slc = new SqliteCommand(query, dbc);
slc.ExecuteNonQuery();
query = "INSERT OR IGNORE INTO sha1 (sha1) VALUES (\"" + rom.SHA1 + "\")";
slc = new SqliteCommand(query, dbc);
slc.ExecuteNonQuery();
query = "INSERT OR IGNORE INTO crcsha1 (crc, sha1) VALUES (\"" + rom.CRC + "\", \"" + rom.SHA1 + "\")";
slc = new SqliteCommand(query, dbc);
slc.ExecuteNonQuery();
query = "INSERT OR IGNORE INTO md5sha1 (md5, sha1) VALUES (\"" + rom.MD5 + "\", \"" + rom.SHA1 + "\")";
slc = new SqliteCommand(query, dbc);
slc.ExecuteNonQuery();
// Add the rom to the files that need to be rebuilt // Add the rom to the files that need to be rebuilt
if (need.Files.ContainsKey(key)) if (need.Files.ContainsKey(key))
@@ -113,7 +109,7 @@ WHERE crcsha1.crc=""" + rom.CRC + @"""
// Create the sorting object to use and rebuild the needed files // Create the sorting object to use and rebuild the needed files
ArchiveScanLevel asl = ArchiveTools.GetArchiveScanLevelFromNumbers(0, 0, 0, 0); ArchiveScanLevel asl = ArchiveTools.GetArchiveScanLevelFromNumbers(0, 0, 0, 0);
SimpleSort ss = new SimpleSort(need, onlyDirs, _depots.Keys.ToList()[0], _tmpdir, false, false, false, false, true, true, asl, false, _logger); SimpleSort ss = new SimpleSort(need, onlyDirs, _depots.Keys.ToList()[0], _tmpdir, false, false, false, false, false, true, true, asl, false, _logger);
ss.StartProcessing(); ss.StartProcessing();
} }
@@ -152,12 +148,57 @@ WHERE crcsha1.crc=""" + rom.CRC + @"""
Directory.CreateDirectory(outputFolder); Directory.CreateDirectory(outputFolder);
} }
// Get the depots that are online // Then get all hashes associated with this DAT
List<string> onlineDepots = _depots.Where(d => d.Value.Item2).Select(d => d.Key).ToList(); string query = "SELECT sha1 FROM dats JOIN data ON dats.id=data.id WHERE hash=\"" + key + "\"";
SqliteCommand slc = new SqliteCommand(query, dbc);
SqliteDataReader sldr = slc.ExecuteReader();
if (sldr.HasRows)
{
while (sldr.Read())
{
string sha1 = sldr.GetString(0);
string filename = Path.Combine(sha1.Substring(0, 2), sha1.Substring(2, 2), sha1.Substring(4, 2), sha1.Substring(6, 2), sha1 + ".gz");
// Loop over the depots and rebuild as needed // Find the first depot that contains the folder
SimpleSort ss = new SimpleSort(datFile, onlineDepots, outputFolder, _tmpdir, false, false, false, false, copy, copy, asl, false, _logger); foreach (string depot in _depots.Keys)
ss.StartProcessing(); {
// If the depot is online, check it
if (_depots[depot].Item2)
{
if (File.Exists(Path.Combine(depot, filename)))
{
if (copy)
{
if (!Directory.Exists(Path.Combine(outputFolder, Path.GetDirectoryName(filename))))
{
Directory.CreateDirectory(Path.Combine(outputFolder, Path.GetDirectoryName(filename)));
}
try
{
File.Copy(Path.Combine(depot, filename), Path.Combine(outputFolder, filename), true);
}
catch { }
}
else
{
ArchiveTools.ExtractArchive(Path.Combine(depot, filename), _tmpdir, asl, _logger);
}
continue;
}
}
}
}
}
// Now that we have extracted everything, we rebuild to the output folder
if (!copy)
{
List<string> temp = new List<string>();
temp.Add(_tmpdir);
SimpleSort ss = new SimpleSort(datFile, temp, outputFolder, "", false, false, false, false, true, false, false, asl, false, _logger);
ss.StartProcessing();
}
} }
dbc.Dispose(); dbc.Dispose();
@@ -264,7 +305,7 @@ WHERE crcsha1.crc=""" + rom.CRC + @"""
// Now, search for each of them and return true or false for each // Now, search for each of them and return true or false for each
foreach (string input in crc) foreach (string input in crc)
{ {
string query = "SELECT * FROM crc WHERE crc=\"" + input + "\""; string query = "SELECT * FROM data WHERE crc=\"" + input + "\"";
SqliteCommand slc = new SqliteCommand(query, dbc); SqliteCommand slc = new SqliteCommand(query, dbc);
SqliteDataReader sldr = slc.ExecuteReader(); SqliteDataReader sldr = slc.ExecuteReader();
if (sldr.HasRows) if (sldr.HasRows)
@@ -281,7 +322,7 @@ WHERE crcsha1.crc=""" + rom.CRC + @"""
} }
foreach (string input in md5) foreach (string input in md5)
{ {
string query = "SELECT * FROM md5 WHERE md5=\"" + input + "\""; string query = "SELECT * FROM data WHERE md5=\"" + input + "\"";
SqliteCommand slc = new SqliteCommand(query, dbc); SqliteCommand slc = new SqliteCommand(query, dbc);
SqliteDataReader sldr = slc.ExecuteReader(); SqliteDataReader sldr = slc.ExecuteReader();
if (sldr.HasRows) if (sldr.HasRows)
@@ -298,7 +339,7 @@ WHERE crcsha1.crc=""" + rom.CRC + @"""
} }
foreach (string input in sha1) foreach (string input in sha1)
{ {
string query = "SELECT * FROM sha1 WHERE sha1=\"" + input + "\""; string query = "SELECT * FROM data WHERE sha1=\"" + input + "\"";
SqliteCommand slc = new SqliteCommand(query, dbc); SqliteCommand slc = new SqliteCommand(query, dbc);
SqliteDataReader sldr = slc.ExecuteReader(); SqliteDataReader sldr = slc.ExecuteReader();
if (sldr.HasRows) if (sldr.HasRows)

View File

@@ -285,6 +285,7 @@ namespace SabreTools.Helper
helptext.Add(" -t=, --temp= Set the temporary directory to use"); helptext.Add(" -t=, --temp= Set the temporary directory to use");
helptext.Add(" -d, --delete Delete input files"); helptext.Add(" -d, --delete Delete input files");
helptext.Add(" -qs, --quick Enable quick scanning of archives"); helptext.Add(" -qs, --quick Enable quick scanning of archives");
helptext.Add(" -ad, --add-date Add original dates from DAT, if possible");
helptext.Add(" -v, --verify Enable verification of output directory"); helptext.Add(" -v, --verify Enable verification of output directory");
helptext.Add(" -c, --convert Enable conversion of input files to TGZ"); helptext.Add(" -c, --convert Enable conversion of input files to TGZ");
helptext.Add(" Note: If a DAT is used, only files NOT included will rebuild"); helptext.Add(" Note: If a DAT is used, only files NOT included will rebuild");

View File

@@ -181,6 +181,7 @@ namespace SabreTools.Helper
public const uint EndOfCentralDirSignature = 0x06054b50; public const uint EndOfCentralDirSignature = 0x06054b50;
public const uint Zip64EndOfCentralDirSignature = 0x06064b50; public const uint Zip64EndOfCentralDirSignature = 0x06064b50;
public const uint Zip64EndOfCentralDirectoryLocator = 0x07064b50; public const uint Zip64EndOfCentralDirectoryLocator = 0x07064b50;
public const uint TorrentZipFileDateTime = 0x2198BC00;
#endregion #endregion

View File

@@ -760,11 +760,12 @@ namespace SabreTools.Helper
/// <param name="streamSize">Size of the stream regardless of compression</param> /// <param name="streamSize">Size of the stream regardless of compression</param>
/// <param name="compressionMethod">Compression method to compare against</param> /// <param name="compressionMethod">Compression method to compare against</param>
/// <returns>Status of the underlying stream</returns> /// <returns>Status of the underlying stream</returns>
public ZipReturn OpenReadStream(int index, bool raw, out Stream stream, out ulong streamSize, out CompressionMethod compressionMethod) public ZipReturn OpenReadStream(int index, bool raw, out Stream stream, out ulong streamSize, out CompressionMethod compressionMethod, out uint lastMod)
{ {
// Set all of the defaults // Set all of the defaults
streamSize = 0; streamSize = 0;
compressionMethod = CompressionMethod.Stored; compressionMethod = CompressionMethod.Stored;
lastMod = 0;
_readIndex = index; _readIndex = index;
stream = null; stream = null;
@@ -783,7 +784,7 @@ namespace SabreTools.Helper
} }
// Now return the results of opening the local file // Now return the results of opening the local file
return _entries[index].OpenReadStream(raw, out stream, out streamSize, out compressionMethod); return _entries[index].OpenReadStream(raw, out stream, out streamSize, out compressionMethod, out lastMod);
} }
/// <summary> /// <summary>
@@ -795,7 +796,7 @@ namespace SabreTools.Helper
/// <param name="streamSize">Size of the stream regardless of compression</param> /// <param name="streamSize">Size of the stream regardless of compression</param>
/// <param name="compressionMethod">Compression method to compare against</param> /// <param name="compressionMethod">Compression method to compare against</param>
/// <returns>Status of the underlying stream</returns> /// <returns>Status of the underlying stream</returns>
public ZipReturn OpenReadStreamQuick(ulong pos, bool raw, out Stream stream, out ulong streamSize, out CompressionMethod compressionMethod) public ZipReturn OpenReadStreamQuick(ulong pos, bool raw, out Stream stream, out ulong streamSize, out CompressionMethod compressionMethod, out uint lastMod)
{ {
// Get the temporary entry based on the defined position // Get the temporary entry based on the defined position
ZipFileEntry tempEntry = new ZipFileEntry(_zipstream); ZipFileEntry tempEntry = new ZipFileEntry(_zipstream);
@@ -812,12 +813,13 @@ namespace SabreTools.Helper
stream = null; stream = null;
streamSize = 0; streamSize = 0;
compressionMethod = CompressionMethod.Stored; compressionMethod = CompressionMethod.Stored;
lastMod = 0;
return zr; return zr;
} }
_readIndex = 0; _readIndex = 0;
// Return the file stream if it worked // Return the file stream if it worked
return tempEntry.OpenReadStream(raw, out stream, out streamSize, out compressionMethod); return tempEntry.OpenReadStream(raw, out stream, out streamSize, out compressionMethod, out lastMod);
} }
/// <summary> /// <summary>
@@ -838,7 +840,8 @@ namespace SabreTools.Helper
/// <param name="compressionMethod">Compression method to compare against</param> /// <param name="compressionMethod">Compression method to compare against</param>
/// <param name="stream">Output stream representing the correctly compressed stream</param> /// <param name="stream">Output stream representing the correctly compressed stream</param>
/// <returns>Status of the underlying stream</returns> /// <returns>Status of the underlying stream</returns>
public ZipReturn OpenWriteStream(bool raw, bool torrentZip, string filename, ulong uncompressedSize, CompressionMethod compressionMethod, out Stream stream) public ZipReturn OpenWriteStream(bool raw, bool torrentZip, string filename, ulong uncompressedSize,
CompressionMethod compressionMethod, out Stream stream, uint lastMod = Constants.TorrentZipFileDateTime)
{ {
// Check to see if the stream is writable // Check to see if the stream is writable
stream = null; stream = null;
@@ -848,7 +851,7 @@ namespace SabreTools.Helper
} }
// Open the entry stream based on the current position // Open the entry stream based on the current position
ZipFileEntry zfe = new ZipFileEntry(_zipstream, filename); ZipFileEntry zfe = new ZipFileEntry(_zipstream, filename, lastMod: lastMod);
ZipReturn zr = zfe.OpenWriteStream(raw, torrentZip, uncompressedSize, compressionMethod, out stream); ZipReturn zr = zfe.OpenWriteStream(raw, torrentZip, uncompressedSize, compressionMethod, out stream);
_entries.Add(zfe); _entries.Add(zfe);

View File

@@ -23,8 +23,7 @@ namespace SabreTools.Helper
private ArchiveVersion _versionMadeBy; private ArchiveVersion _versionMadeBy;
private ArchiveVersion _versionNeeded; private ArchiveVersion _versionNeeded;
private GeneralPurposeBitFlag _generalPurposeBitFlag; private GeneralPurposeBitFlag _generalPurposeBitFlag;
private ushort _lastModFileTime; private uint _lastMod;
private ushort _lastModFileDate;
private uint _crc; private uint _crc;
private ulong _compressedSize; private ulong _compressedSize;
private ulong _uncompressedSize; private ulong _uncompressedSize;
@@ -56,15 +55,10 @@ namespace SabreTools.Helper
get { return _generalPurposeBitFlag; } get { return _generalPurposeBitFlag; }
private set { _generalPurposeBitFlag = value; } private set { _generalPurposeBitFlag = value; }
} }
public ushort LastModFileTime public uint LastMod
{ {
get { return _lastModFileTime; } get { return _lastMod; }
set { _lastModFileTime = value; } set { _lastMod = value; }
}
public ushort LastModFileDate
{
get { return _lastModFileDate; }
set { _lastModFileDate = value; }
} }
public byte[] CRC public byte[] CRC
{ {
@@ -135,14 +129,13 @@ namespace SabreTools.Helper
/// </summary> /// </summary>
/// <param name="zipstream">Stream representing the entry</param> /// <param name="zipstream">Stream representing the entry</param>
/// <param name="filename">Internal filename to use</param> /// <param name="filename">Internal filename to use</param>
public ZipFileEntry(Stream zipstream, string filename) public ZipFileEntry(Stream zipstream, string filename, uint lastMod = Constants.TorrentZipFileDateTime)
{ {
_zip64 = false; _zip64 = false;
_zipstream = zipstream; _zipstream = zipstream;
_generalPurposeBitFlag = GeneralPurposeBitFlag.DeflatingMaximumCompression; _generalPurposeBitFlag = GeneralPurposeBitFlag.DeflatingMaximumCompression;
_compressionMethod = CompressionMethod.Deflated; _compressionMethod = CompressionMethod.Deflated;
_lastModFileTime = 48128; _lastMod = lastMod;
_lastModFileDate = 8600;
FileName = filename; FileName = filename;
} }
@@ -181,8 +174,7 @@ namespace SabreTools.Helper
} }
// Keep reading available information, skipping the unnecessary // Keep reading available information, skipping the unnecessary
_lastModFileTime = br.ReadUInt16(); _lastMod = br.ReadUInt32();
_lastModFileDate = br.ReadUInt16();
_crc = br.ReadUInt32(); _crc = br.ReadUInt32();
_compressedSize = br.ReadUInt32(); _compressedSize = br.ReadUInt32();
_uncompressedSize = br.ReadUInt32(); _uncompressedSize = br.ReadUInt32();
@@ -356,8 +348,7 @@ namespace SabreTools.Helper
bw.Write(versionNeededToExtract); bw.Write(versionNeededToExtract);
bw.Write((ushort)_generalPurposeBitFlag); bw.Write((ushort)_generalPurposeBitFlag);
bw.Write((ushort)_compressionMethod); bw.Write((ushort)_compressionMethod);
bw.Write(_lastModFileTime); bw.Write(_lastMod);
bw.Write(_lastModFileDate);
bw.Write(_crc); bw.Write(_crc);
bw.Write(compressedSize32); bw.Write(compressedSize32);
bw.Write(uncompressedSize32); bw.Write(uncompressedSize32);
@@ -413,11 +404,7 @@ namespace SabreTools.Helper
{ {
return ZipReturn.ZipLocalFileHeaderError; return ZipReturn.ZipLocalFileHeaderError;
} }
if (br.ReadUInt16() != _lastModFileTime) if (br.ReadUInt32() != _lastMod)
{
return ZipReturn.ZipLocalFileHeaderError;
}
if (br.ReadUInt16() != _lastModFileDate)
{ {
return ZipReturn.ZipLocalFileHeaderError; return ZipReturn.ZipLocalFileHeaderError;
} }
@@ -616,8 +603,7 @@ namespace SabreTools.Helper
} }
_compressionMethod = (CompressionMethod)br.ReadUInt16(); _compressionMethod = (CompressionMethod)br.ReadUInt16();
_lastModFileTime = br.ReadUInt16(); _lastMod = br.ReadUInt32();
_lastModFileDate = br.ReadUInt16();
_crc = br.ReadUInt32(); _crc = br.ReadUInt32();
_compressedSize = br.ReadUInt32(); _compressedSize = br.ReadUInt32();
_uncompressedSize = br.ReadUInt32(); _uncompressedSize = br.ReadUInt32();
@@ -736,8 +722,7 @@ namespace SabreTools.Helper
bw.Write(versionNeededToExtract); bw.Write(versionNeededToExtract);
bw.Write((ushort)_generalPurposeBitFlag); bw.Write((ushort)_generalPurposeBitFlag);
bw.Write((ushort)_compressionMethod); bw.Write((ushort)_compressionMethod);
bw.Write(_lastModFileTime); bw.Write(_lastMod);
bw.Write(_lastModFileDate);
_crc32Location = (ulong)_zipstream.Position; _crc32Location = (ulong)_zipstream.Position;
@@ -780,10 +765,11 @@ namespace SabreTools.Helper
/// <param name="streamSize">Size of the stream regardless of compression</param> /// <param name="streamSize">Size of the stream regardless of compression</param>
/// <param name="compressionMethod">Compression method to compare against</param> /// <param name="compressionMethod">Compression method to compare against</param>
/// <returns>Status of the underlying stream</returns> /// <returns>Status of the underlying stream</returns>
public ZipReturn OpenReadStream(bool raw, out Stream stream, out ulong streamSize, out CompressionMethod compressionMethod) public ZipReturn OpenReadStream(bool raw, out Stream stream, out ulong streamSize, out CompressionMethod compressionMethod, out uint lastMod)
{ {
streamSize = 0; streamSize = 0;
compressionMethod = _compressionMethod; compressionMethod = _compressionMethod;
lastMod = _lastMod;
_readStream = null; _readStream = null;
_zipstream.Seek((long)_dataLocation, SeekOrigin.Begin); _zipstream.Seek((long)_dataLocation, SeekOrigin.Begin);
@@ -834,6 +820,7 @@ namespace SabreTools.Helper
/// <param name="uncompressedSize">Uncompressed size of the stream</param> /// <param name="uncompressedSize">Uncompressed size of the stream</param>
/// <param name="compressionMethod">Compression method to compare against</param> /// <param name="compressionMethod">Compression method to compare against</param>
/// <param name="stream">Output stream representing the correctly compressed stream</param> /// <param name="stream">Output stream representing the correctly compressed stream</param>
/// <param name="tzip">True if the file should use the TorrentZip date (default), false otherwise</param>
/// <returns>Status of the underlying stream</returns> /// <returns>Status of the underlying stream</returns>
public ZipReturn OpenWriteStream(bool raw, bool torrentZip, ulong uncompressedSize, CompressionMethod compressionMethod, out Stream stream) public ZipReturn OpenWriteStream(bool raw, bool torrentZip, ulong uncompressedSize, CompressionMethod compressionMethod, out Stream stream)
{ {

View File

@@ -14,6 +14,7 @@ namespace SabreTools.Helper
private string _outDir; private string _outDir;
private string _tempDir; private string _tempDir;
private bool _quickScan; private bool _quickScan;
private bool _date;
private bool _toFolder; private bool _toFolder;
private bool _verify; private bool _verify;
private bool _delete; private bool _delete;
@@ -37,6 +38,7 @@ namespace SabreTools.Helper
/// <param name="outDir">Output directory to use to build to</param> /// <param name="outDir">Output directory to use to build to</param>
/// <param name="tempDir">Temporary directory for archive extraction</param> /// <param name="tempDir">Temporary directory for archive extraction</param>
/// <param name="quickScan">True to enable external scanning of archives, false otherwise</param> /// <param name="quickScan">True to enable external scanning of archives, false otherwise</param>
/// <param name="date">True if the date from the DAT should be used if available, false otherwise</param>
/// <param name="toFolder">True if files should be output to folder, false otherwise</param> /// <param name="toFolder">True if files should be output to folder, false otherwise</param>
/// <param name="verify">True if output directory should be checked instead of rebuilt to, false otherwise</param> /// <param name="verify">True if output directory should be checked instead of rebuilt to, false otherwise</param>
/// <param name="delete">True if input files should be deleted, false otherwise</param> /// <param name="delete">True if input files should be deleted, false otherwise</param>
@@ -46,7 +48,7 @@ namespace SabreTools.Helper
/// <param name="updateDat">True if the updated DAT should be output, false otherwise</param> /// <param name="updateDat">True if the updated DAT should be output, false otherwise</param>
/// <param name="logger">Logger object for file and console output</param> /// <param name="logger">Logger object for file and console output</param>
public SimpleSort(DatFile datdata, List<string> inputs, string outDir, string tempDir, public SimpleSort(DatFile datdata, List<string> inputs, string outDir, string tempDir,
bool quickScan, bool toFolder, bool verify, bool delete, bool tgz, bool romba, bool quickScan, bool date, bool toFolder, bool verify, bool delete, bool tgz, bool romba,
ArchiveScanLevel archiveScanLevel, bool updateDat, Logger logger) ArchiveScanLevel archiveScanLevel, bool updateDat, Logger logger)
{ {
_datdata = datdata; _datdata = datdata;
@@ -54,6 +56,7 @@ namespace SabreTools.Helper
_outDir = (outDir == "" ? "Rebuild" : outDir); _outDir = (outDir == "" ? "Rebuild" : outDir);
_tempDir = (String.IsNullOrEmpty(tempDir) ? Path.Combine(Path.GetTempPath(), Path.GetRandomFileName()) : tempDir); _tempDir = (String.IsNullOrEmpty(tempDir) ? Path.Combine(Path.GetTempPath(), Path.GetRandomFileName()) : tempDir);
_quickScan = quickScan; _quickScan = quickScan;
_date = date;
_toFolder = toFolder; _toFolder = toFolder;
_verify = verify; _verify = verify;
_delete = delete; _delete = delete;
@@ -356,7 +359,7 @@ namespace SabreTools.Helper
} }
else else
{ {
ArchiveTools.WriteToArchive(input, _outDir, found, _logger); ArchiveTools.WriteToArchive(input, _outDir, found, _logger, date: _date);
} }
} }
} }
@@ -373,7 +376,7 @@ namespace SabreTools.Helper
Rom drom = FileTools.GetFileInfo(newinput, _logger); Rom drom = FileTools.GetFileInfo(newinput, _logger);
// If we have a blank RomData, it's an error // If we have a blank RomData, it's an error
if (drom.Name == null) if (String.IsNullOrEmpty(drom.Name))
{ {
return false; return false;
} }
@@ -423,7 +426,7 @@ namespace SabreTools.Helper
} }
else else
{ {
ArchiveTools.WriteToArchive(newinput, _outDir, found, _logger); ArchiveTools.WriteToArchive(newinput, _outDir, found, _logger, date: _date);
} }
} }
@@ -473,7 +476,7 @@ namespace SabreTools.Helper
} }
else else
{ {
ArchiveTools.WriteToArchive(input, _outDir, newfound, _logger); ArchiveTools.WriteToArchive(input, _outDir, newfound, _logger, date: _date);
} }
} }
} }

View File

@@ -709,6 +709,12 @@ Options:
quicker than extracting all files to the temp folder. On the downside, it can only quicker than extracting all files to the temp folder. On the downside, it can only
get the CRC and size from most archive formats, leading to possible issues. get the CRC and size from most archive formats, leading to possible issues.
-ad, --add-date Write dates for each file parsed, if available
If this flag is set, the the date in the DAT will be used for the output file
instead of the standard date and time for TorrentZip. This will technically
invalidate the output files as proper TorrentZip files because the date will not
match the standard.
-v, --verify Enable verification of output directory -v, --verify Enable verification of output directory
This overrides the default rebuilding and only requires the DAT and the output folder. This overrides the default rebuilding and only requires the DAT and the output folder.
Here, the DAT is used to verify the output directory directly and then output a Here, the DAT is used to verify the output directory directly and then output a

View File

@@ -153,8 +153,9 @@ namespace SabreTools.Helper
Stream readStream; Stream readStream;
ulong streamsize = 0; ulong streamsize = 0;
CompressionMethod cm = CompressionMethod.Stored; CompressionMethod cm = CompressionMethod.Stored;
uint lastMod = 0;
zr = zf.OpenReadStream(i, false, out readStream, out streamsize, out cm); zr = zf.OpenReadStream(i, false, out readStream, out streamsize, out cm, out lastMod);
FileStream writeStream = File.OpenWrite(Path.Combine(tempDir, zf.Entries[i].FileName)); FileStream writeStream = File.OpenWrite(Path.Combine(tempDir, zf.Entries[i].FileName));
@@ -290,8 +291,9 @@ namespace SabreTools.Helper
Stream readStream; Stream readStream;
ulong streamsize = 0; ulong streamsize = 0;
CompressionMethod cm = CompressionMethod.Stored; CompressionMethod cm = CompressionMethod.Stored;
uint lastMod = 0;
zr = zf.OpenReadStream(i, false, out readStream, out streamsize, out cm); zr = zf.OpenReadStream(i, false, out readStream, out streamsize, out cm, out lastMod);
byte[] ibuffer = new byte[_bufferSize]; byte[] ibuffer = new byte[_bufferSize];
int ilen; int ilen;
@@ -745,8 +747,9 @@ namespace SabreTools.Helper
/// <param name="outDir">Output directory to build to</param> /// <param name="outDir">Output directory to build to</param>
/// <param name="rom">RomData representing the new information</param> /// <param name="rom">RomData representing the new information</param>
/// <param name="logger">Logger object for file and console output</param> /// <param name="logger">Logger object for file and console output</param>
/// <param name="date">True if the date from the DAT should be used if available, false otherwise (default)</param>
/// <returns>True if the archive was written properly, false otherwise</returns> /// <returns>True if the archive was written properly, false otherwise</returns>
public static bool WriteToArchive(string inputFile, string outDir, Rom rom, Logger logger) public static bool WriteToArchive(string inputFile, string outDir, Rom rom, Logger logger, bool date = false)
{ {
// Wrap the individual inputs into lists // Wrap the individual inputs into lists
List<string> inputFiles = new List<string>(); List<string> inputFiles = new List<string>();
@@ -754,7 +757,7 @@ namespace SabreTools.Helper
List<Rom> roms = new List<Rom>(); List<Rom> roms = new List<Rom>();
roms.Add(rom); roms.Add(rom);
return WriteToArchive(inputFiles, outDir, roms, logger); return WriteToArchive(inputFiles, outDir, roms, logger, date: date);
} }
/// <summary> /// <summary>
@@ -764,8 +767,9 @@ namespace SabreTools.Helper
/// <param name="outDir">Output directory to build to</param> /// <param name="outDir">Output directory to build to</param>
/// <param name="rom">List of Rom representing the new information</param> /// <param name="rom">List of Rom representing the new information</param>
/// <param name="logger">Logger object for file and console output</param> /// <param name="logger">Logger object for file and console output</param>
/// <param name="date">True if the date from the DAT should be used if available, false otherwise (default)</param>
/// <returns>True if the archive was written properly, false otherwise</returns> /// <returns>True if the archive was written properly, false otherwise</returns>
public static bool WriteToArchive(List<string> inputFiles, string outDir, List<Rom> roms, Logger logger) public static bool WriteToArchive(List<string> inputFiles, string outDir, List<Rom> roms, Logger logger, bool date = false)
{ {
bool success = false; bool success = false;
string tempFile = Path.GetTempFileName(); string tempFile = Path.GetTempFileName();
@@ -827,7 +831,26 @@ namespace SabreTools.Helper
// Open the input file for reading // Open the input file for reading
Stream freadStream = File.Open(inputFiles[index], FileMode.Open, FileAccess.Read, FileShare.ReadWrite); Stream freadStream = File.Open(inputFiles[index], FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
ulong istreamSize = (ulong)(new FileInfo(inputFiles[index]).Length); ulong istreamSize = (ulong)(new FileInfo(inputFiles[index]).Length);
zipFile.OpenWriteStream(false, true, roms[index].Name.Replace('\\', '/'), istreamSize, CompressionMethod.Deflated, out writeStream);
DateTime dt = DateTime.Now;
if (date && !String.IsNullOrEmpty(roms[index].Date) && DateTime.TryParse(roms[index].Date.Replace('\\', '/'), out dt))
{
// https://referencesource.microsoft.com/#WindowsBase/Base/MS/Internal/IO/Zip/ZipIOBlockManager.cs,760eb7714f02c41e
uint msDosDateTime = 0;
msDosDateTime |= (((uint)dt.Second) / 2) & 0x1F;
msDosDateTime |= (((uint)dt.Minute) & 0x3F) << 5;
msDosDateTime |= (((uint)dt.Hour) & 0x1F) << 11;
msDosDateTime |= (((uint)dt.Day) & 0x1F) << 16;
msDosDateTime |= (((uint)dt.Month) & 0xF) << 21;
msDosDateTime |= (((uint)(dt.Year - 1980)) & 0x7F) << 25;
zipFile.OpenWriteStream(false, false, roms[index].Name.Replace('\\', '/'), istreamSize,
CompressionMethod.Deflated, out writeStream, lastMod: msDosDateTime);
}
else
{
zipFile.OpenWriteStream(false, true, roms[index].Name.Replace('\\', '/'), istreamSize, CompressionMethod.Deflated, out writeStream);
}
// Copy the input stream to the output // Copy the input stream to the output
byte[] ibuffer = new byte[_bufferSize]; byte[] ibuffer = new byte[_bufferSize];
@@ -893,7 +916,26 @@ namespace SabreTools.Helper
// Open the input file for reading // Open the input file for reading
Stream freadStream = File.Open(inputFiles[-index - 1], FileMode.Open, FileAccess.Read, FileShare.ReadWrite); Stream freadStream = File.Open(inputFiles[-index - 1], FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
ulong istreamSize = (ulong)(new FileInfo(inputFiles[-index - 1]).Length); ulong istreamSize = (ulong)(new FileInfo(inputFiles[-index - 1]).Length);
zipFile.OpenWriteStream(false, true, roms[-index - 1].Name.Replace('\\', '/'), istreamSize, CompressionMethod.Deflated, out writeStream);
DateTime dt = DateTime.Now;
if (date && !String.IsNullOrEmpty(roms[-index - 1].Date) && DateTime.TryParse(roms[-index - 1].Date.Replace('\\', '/'), out dt))
{
// https://referencesource.microsoft.com/#WindowsBase/Base/MS/Internal/IO/Zip/ZipIOBlockManager.cs,760eb7714f02c41e
uint msDosDateTime = 0;
msDosDateTime |= (((uint)dt.Second) / 2) & 0x1F;
msDosDateTime |= (((uint)dt.Minute) & 0x3F) << 5;
msDosDateTime |= (((uint)dt.Hour) & 0x1F) << 11;
msDosDateTime |= (((uint)dt.Day) & 0x1F) << 16;
msDosDateTime |= (((uint)dt.Month) & 0xF) << 21;
msDosDateTime |= (((uint)(dt.Year - 1980)) & 0x7F) << 25;
zipFile.OpenWriteStream(false, false, roms[-index - 1].Name.Replace('\\', '/'), istreamSize,
CompressionMethod.Deflated, out writeStream, lastMod: msDosDateTime);
}
else
{
zipFile.OpenWriteStream(false, true, roms[-index - 1].Name.Replace('\\', '/'), istreamSize, CompressionMethod.Deflated, out writeStream);
}
// Copy the input stream to the output // Copy the input stream to the output
byte[] ibuffer = new byte[_bufferSize]; byte[] ibuffer = new byte[_bufferSize];
@@ -912,10 +954,12 @@ namespace SabreTools.Helper
{ {
// Instantiate the streams // Instantiate the streams
CompressionMethod icompressionMethod = CompressionMethod.Stored; CompressionMethod icompressionMethod = CompressionMethod.Stored;
uint lastMod = 0;
ulong istreamSize = 0; ulong istreamSize = 0;
Stream zreadStream; Stream zreadStream;
oldZipFile.OpenReadStream(index, false, out zreadStream, out istreamSize, out icompressionMethod); oldZipFile.OpenReadStream(index, false, out zreadStream, out istreamSize, out icompressionMethod, out lastMod);
zipFile.OpenWriteStream(false, true, oldZipFile.Filename(index), istreamSize, CompressionMethod.Deflated, out writeStream); zipFile.OpenWriteStream(false, lastMod == Constants.TorrentZipFileDateTime, oldZipFile.Filename(index),
istreamSize, CompressionMethod.Deflated, out writeStream, lastMod: lastMod);
// Copy the input stream to the output // Copy the input stream to the output
byte[] ibuffer = new byte[_bufferSize]; byte[] ibuffer = new byte[_bufferSize];

View File

@@ -4,6 +4,7 @@ using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using System.Runtime.InteropServices;
using System.Security.Cryptography; using System.Security.Cryptography;
using System.Xml; using System.Xml;
using System.Xml.Schema; using System.Xml.Schema;

View File

@@ -550,6 +550,30 @@ namespace SabreTools.Helper
return hexOutput; return hexOutput;
} }
/// <summary>
/// Adapted from 7-zip Source Code: CPP/Windows/TimeUtils.cpp:FileTimeToDosTime
/// </summary>
public static uint ConvertDateTimeToMsDosTimeFormat(DateTime dateTime)
{
uint year = (uint)((dateTime.Year - 1980) % 128);
uint mon = (uint)dateTime.Month;
uint day = (uint)dateTime.Day;
uint hour = (uint)dateTime.Hour;
uint min = (uint)dateTime.Minute;
uint sec = (uint)dateTime.Second;
return (year << 25) | (mon << 21) | (day << 16) | (hour << 11) | (min << 5) | (sec >> 1);
}
/// <summary>
/// Adapted from 7-zip Source Code: CPP/Windows/TimeUtils.cpp:DosTimeToFileTime
/// </summary>
public static DateTime ConvertMsDosTimeFormatToDateTime(uint msDosDateTime)
{
return new DateTime((int)(1980 + (msDosDateTime >> 25)), (int)((msDosDateTime >> 21) & 0xF), (int)((msDosDateTime >> 16) & 0x1F),
(int)((msDosDateTime >> 11) & 0x1F), (int)((msDosDateTime >> 5) & 0x3F), (int)((msDosDateTime & 0x1F) * 2));
}
/// <summary> /// <summary>
/// Determines a text file's encoding by analyzing its byte order mark (BOM). /// Determines a text file's encoding by analyzing its byte order mark (BOM).
/// Defaults to ASCII when detection of the text file's endianness fails. /// Defaults to ASCII when detection of the text file's endianness fails.

View File

@@ -18,6 +18,7 @@ namespace SabreTools
/// <param name="outDir">Output directory (empty for default directory)</param> /// <param name="outDir">Output directory (empty for default directory)</param>
/// <param name="tempDir">Temporary directory for archive extraction</param> /// <param name="tempDir">Temporary directory for archive extraction</param>
/// <param name="delete">True if input files should be deleted, false otherwise</param> /// <param name="delete">True if input files should be deleted, false otherwise</param>
/// <param name="tgz">True to output files in TorrentGZ format, false for TorrentZip</param>
/// <param name="romba">True if files should be output in Romba depot folders, false otherwise</param> /// <param name="romba">True if files should be output in Romba depot folders, false otherwise</param>
/// <param name="sevenzip">Integer representing the archive handling level for 7z</param> /// <param name="sevenzip">Integer representing the archive handling level for 7z</param>
/// <param name="gz">Integer representing the archive handling level for GZip</param> /// <param name="gz">Integer representing the archive handling level for GZip</param>
@@ -25,19 +26,25 @@ namespace SabreTools
/// <param name="zip">Integer representing the archive handling level for Zip</param> /// <param name="zip">Integer representing the archive handling level for Zip</param>
/// <param name="logger">Logger object for file and console output</param> /// <param name="logger">Logger object for file and console output</param>
public static bool InitConvertFolder(List<string> datfiles, List<string> inputs, string outDir, string tempDir, bool delete, public static bool InitConvertFolder(List<string> datfiles, List<string> inputs, string outDir, string tempDir, bool delete,
bool romba, int sevenzip, int gz, int rar, int zip, Logger logger) bool tgz, bool romba, int sevenzip, int gz, int rar, int zip, Logger logger)
{ {
// Get the archive scanning level
ArchiveScanLevel asl = ArchiveTools.GetArchiveScanLevelFromNumbers(sevenzip, gz, rar, zip);
DateTime start = DateTime.Now;
logger.User("Populating internal DAT...");
// Add all of the input DATs into one huge internal DAT // Add all of the input DATs into one huge internal DAT
DatFile datdata = new DatFile(); DatFile datdata = new DatFile();
foreach (string datfile in datfiles) foreach (string datfile in datfiles)
{ {
datdata.Parse(datfile, 99, 99, logger, keep: true, softlist: true); datdata.Parse(datfile, 99, 99, logger, keep: true, softlist: true);
} }
logger.User("Populating complete in " + DateTime.Now.Subtract(start).ToString(@"hh\:mm\:ss\.fffff"));
// Get the archive scanning level
ArchiveScanLevel asl = ArchiveTools.GetArchiveScanLevelFromNumbers(sevenzip, gz, rar, zip);
// Get all individual files from the inputs // Get all individual files from the inputs
start = DateTime.Now;
logger.User("Organizing input files...");
List<string> newinputs = new List<string>(); List<string> newinputs = new List<string>();
foreach (string input in inputs) foreach (string input in inputs)
{ {
@@ -53,9 +60,10 @@ namespace SabreTools
} }
} }
} }
logger.User("Organizing complete in " + DateTime.Now.Subtract(start).ToString(@"hh\:mm\:ss\.fffff"));
SimpleSort ss = new SimpleSort(datdata, newinputs, outDir, tempDir, false, false, false, SimpleSort ss = new SimpleSort(datdata, newinputs, outDir, tempDir, false, false,
delete, false, romba, asl, false, logger); false, false, delete, tgz, romba, asl, false, logger);
return ss.Convert(); return ss.Convert();
} }
@@ -285,32 +293,37 @@ namespace SabreTools
/// <param name="outDir">Output directory to use to build to</param> /// <param name="outDir">Output directory to use to build to</param>
/// <param name="tempDir">Temporary directory for archive extraction</param> /// <param name="tempDir">Temporary directory for archive extraction</param>
/// <param name="quickScan">True to enable external scanning of archives, false otherwise</param> /// <param name="quickScan">True to enable external scanning of archives, false otherwise</param>
/// <param name="date">True if the date from the DAT should be used if available, false otherwise</param>
/// <param name="sevenzip">Integer representing the archive handling level for 7z</param> /// <param name="sevenzip">Integer representing the archive handling level for 7z</param>
/// <param name="toFolder">True if files should be output to folder, false otherwise</param> /// <param name="toFolder">True if files should be output to folder, false otherwise</param>
/// <param name="verify">True if output directory should be checked instead of rebuilt to, false otherwise</param> /// <param name="verify">True if output directory should be checked instead of rebuilt to, false otherwise</param>
/// <param name="delete">True if input files should be deleted, false otherwise</param> /// <param name="delete">True if input files should be deleted, false otherwise</param>
/// <param name="torrentX">True is for TorrentZip, False is for TorrentGZ, Null is for standard zip</param> /// <param name="tgz">True to output files in TorrentGZ format, false for TorrentZip</param>
/// <param name="romba">True if files should be output in Romba depot folders, false otherwise</param> /// <param name="romba">True if files should be output in Romba depot folders, false otherwise</param>
/// <param name="gz">Integer representing the archive handling level for GZip</param> /// <param name="gz">Integer representing the archive handling level for GZip</param>
/// <param name="rar">Integer representing the archive handling level for RAR</param> /// <param name="rar">Integer representing the archive handling level for RAR</param>
/// <param name="zip">Integer representing the archive handling level for Zip</param> /// <param name="zip">Integer representing the archive handling level for Zip</param>
/// <param name="updateDat">True if the updated DAT should be output, false otherwise</param> /// <param name="updateDat">True if the updated DAT should be output, false otherwise</param>
/// <param name="logger">Logger object for file and console output</param> /// <param name="logger">Logger object for file and console output</param>
private static void InitSortVerify(List<string> datfiles, List<string> inputs, string outDir, string tempDir, bool quickScan, private static void InitSortVerify(List<string> datfiles, List<string> inputs, string outDir, string tempDir, bool quickScan, bool date,
bool toFolder, bool verify, bool delete, bool tgz, bool romba, int sevenzip, int gz, int rar, int zip, bool updateDat, Logger logger) bool toFolder, bool verify, bool delete, bool tgz, bool romba, int sevenzip, int gz, int rar, int zip, bool updateDat, Logger logger)
{ {
// Get the archive scanning level // Get the archive scanning level
ArchiveScanLevel asl = ArchiveTools.GetArchiveScanLevelFromNumbers(sevenzip, gz, rar, zip); ArchiveScanLevel asl = ArchiveTools.GetArchiveScanLevelFromNumbers(sevenzip, gz, rar, zip);
DateTime start = DateTime.Now;
logger.User("Populating internal DAT...");
// Add all of the input DATs into one huge internal DAT // Add all of the input DATs into one huge internal DAT
DatFile datdata = new DatFile(); DatFile datdata = new DatFile();
foreach (string datfile in datfiles) foreach (string datfile in datfiles)
{ {
datdata.Parse(datfile, 99, 99, logger, keep: true, softlist: true); datdata.Parse(datfile, 99, 99, logger, keep: true, softlist: true);
} }
logger.User("Populating complete in " + DateTime.Now.Subtract(start).ToString(@"hh\:mm\:ss\.fffff"));
SimpleSort ss = new SimpleSort(datdata, inputs, outDir, tempDir, quickScan, toFolder, verify, SimpleSort ss = new SimpleSort(datdata, inputs, outDir, tempDir, quickScan, date,
delete, tgz, romba, asl, updateDat, logger); toFolder, verify, delete, tgz, romba, asl, updateDat, logger);
ss.StartProcessing(); ss.StartProcessing();
} }

View File

@@ -43,6 +43,7 @@ namespace SabreTools
// Set all default values // Set all default values
bool help = false, bool help = false,
convert = false, convert = false,
date = false,
delete = false, delete = false,
quickScan = false, quickScan = false,
romba = false, romba = false,
@@ -70,6 +71,10 @@ namespace SabreTools
case "--help": case "--help":
help = true; help = true;
break; break;
case "-ad":
case "--add-date":
date = true;
break;
case "-c": case "-c":
case "--convert": case "--convert":
convert = true; convert = true;
@@ -201,7 +206,7 @@ namespace SabreTools
{ {
if (datfiles.Count > 0) if (datfiles.Count > 0)
{ {
InitSortVerify(datfiles, inputs, outDir, tempDir, quickScan, toFolder, InitSortVerify(datfiles, inputs, outDir, tempDir, quickScan, date, toFolder,
verify, delete, tgz, romba, sevenzip, gz, rar, zip, updateDat, logger); verify, delete, tgz, romba, sevenzip, gz, rar, zip, updateDat, logger);
} }
else else
@@ -275,8 +280,8 @@ namespace SabreTools
} }
logger.User("Organizing complete in " + DateTime.Now.Subtract(start).ToString(@"hh\:mm\:ss\.fffff")); logger.User("Organizing complete in " + DateTime.Now.Subtract(start).ToString(@"hh\:mm\:ss\.fffff"));
SimpleSort ss = new SimpleSort(datdata, newinputs, outDir, tempDir, false, false, false, SimpleSort ss = new SimpleSort(datdata, newinputs, outDir, tempDir, false, false,
delete, tgz, romba, asl, false, logger); false, false, delete, tgz, romba, asl, false, logger);
return ss.Convert(); return ss.Convert();
} }
@@ -288,6 +293,7 @@ namespace SabreTools
/// <param name="outDir">Output directory to use to build to</param> /// <param name="outDir">Output directory to use to build to</param>
/// <param name="tempDir">Temporary directory for archive extraction</param> /// <param name="tempDir">Temporary directory for archive extraction</param>
/// <param name="quickScan">True to enable external scanning of archives, false otherwise</param> /// <param name="quickScan">True to enable external scanning of archives, false otherwise</param>
/// <param name="date">True if the date from the DAT should be used if available, false otherwise</param>
/// <param name="sevenzip">Integer representing the archive handling level for 7z</param> /// <param name="sevenzip">Integer representing the archive handling level for 7z</param>
/// <param name="toFolder">True if files should be output to folder, false otherwise</param> /// <param name="toFolder">True if files should be output to folder, false otherwise</param>
/// <param name="verify">True if output directory should be checked instead of rebuilt to, false otherwise</param> /// <param name="verify">True if output directory should be checked instead of rebuilt to, false otherwise</param>
@@ -299,7 +305,7 @@ namespace SabreTools
/// <param name="zip">Integer representing the archive handling level for Zip</param> /// <param name="zip">Integer representing the archive handling level for Zip</param>
/// <param name="updateDat">True if the updated DAT should be output, false otherwise</param> /// <param name="updateDat">True if the updated DAT should be output, false otherwise</param>
/// <param name="logger">Logger object for file and console output</param> /// <param name="logger">Logger object for file and console output</param>
private static void InitSortVerify(List<string> datfiles, List<string> inputs, string outDir, string tempDir, bool quickScan, private static void InitSortVerify(List<string> datfiles, List<string> inputs, string outDir, string tempDir, bool quickScan, bool date,
bool toFolder, bool verify, bool delete, bool tgz, bool romba, int sevenzip, int gz, int rar, int zip, bool updateDat, Logger logger) bool toFolder, bool verify, bool delete, bool tgz, bool romba, int sevenzip, int gz, int rar, int zip, bool updateDat, Logger logger)
{ {
// Get the archive scanning level // Get the archive scanning level
@@ -316,8 +322,8 @@ namespace SabreTools
} }
logger.User("Populating complete in " + DateTime.Now.Subtract(start).ToString(@"hh\:mm\:ss\.fffff")); logger.User("Populating complete in " + DateTime.Now.Subtract(start).ToString(@"hh\:mm\:ss\.fffff"));
SimpleSort ss = new SimpleSort(datdata, inputs, outDir, tempDir, quickScan, toFolder, verify, SimpleSort ss = new SimpleSort(datdata, inputs, outDir, tempDir, quickScan, date,
delete, tgz, romba, asl, updateDat, logger); toFolder, verify, delete, tgz, romba, asl, updateDat, logger);
ss.StartProcessing(); ss.StartProcessing();
} }
} }