protected override void Run()
{
// The directory in which we assemble the log files from the server before repackaging them
// in a single zip file.
string extractTempDir = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName());
try
{
// Calculate total bytes to save
long bytesToExtract = 1, bytesExtracted = 0;
foreach (string inputFile in Directory.GetFiles(_inputTempFolder))
{
bytesToExtract += new FileInfo(inputFile).Length;
}
// Create temp dir for extracted stuff
if (Directory.Exists(extractTempDir))
{
Directory.Delete(extractTempDir);
}
Directory.CreateDirectory(extractTempDir);
// Extract each of the raw server files to the temp extraction directory
foreach (string inputFile in Directory.GetFiles(_inputTempFolder))
{
if (inputFile.ToLowerInvariant().EndsWith(".tar"))
{
// Un-tar it. SharpZipLib doesn't account for illegal filenames or characters in
// filenames (e.g. ':'in Windows), so first we stream the tar to a new tar,
// sanitizing any bad filenames as we go.
// We also need to record the modification times of all the files, so that we can
// restore them into the final zip.
string outFilename = inputFile.Substring(0, inputFile.Length - 4);
if (outFilename.Length == 0)
outFilename = Path.GetRandomFileName();
string outputDir = Path.Combine(extractTempDir, Path.GetFileName(outFilename));
string sanitizedTar = Path.GetTempFileName();
using (ArchiveIterator tarIterator = ArchiveFactory.Reader(ArchiveFactory.Type.Tar, File.OpenRead(inputFile)))
{
using (ArchiveWriter tarWriter = ArchiveFactory.Writer(ArchiveFactory.Type.Tar, File.OpenWrite(sanitizedTar)))
{
Dictionary<string, string> usedNames = new Dictionary<string, string>();
while (tarIterator.HasNext())
{
if (Cancelling)
{
throw new CancelledException();
}
using( MemoryStream ms = new MemoryStream() )
{
tarIterator.ExtractCurrentFile(ms);
string saneName = SanitizeTarName(tarIterator.CurrentFileName(), usedNames);
tarWriter.Add(ms, saneName);
ModTimes[Path.Combine(outputDir, saneName)] = tarIterator.CurrentFileModificationTime();
}
}
}
}
// Now extract the sanitized tar
using(FileStream fs = File.OpenRead(sanitizedTar))
{
using (ArchiveIterator tarIterator = ArchiveFactory.Reader(ArchiveFactory.Type.Tar, fs))
{
Directory.CreateDirectory(outputDir);
tarIterator.ExtractAllContents(outputDir);
bytesToCompress += Core.Helpers.GetDirSize(new DirectoryInfo(outputDir));
}
}
}
else
{
// Just copy vanilla input files unmodified to the temp directory
string outputFile = Path.Combine(extractTempDir, Path.GetFileName(inputFile));
File.Copy(inputFile, outputFile);
ModTimes[outputFile] = new FileInfo(inputFile).LastWriteTimeUtc;
bytesToCompress += new FileInfo(outputFile).Length;
}
bytesExtracted += new FileInfo(inputFile).Length;
File.Delete(inputFile);
this.PercentComplete = (int)(50.0 * bytesExtracted / bytesToExtract);
if (Cancelling)
{
throw new CancelledException();
}
}
// Now zip up all the temporarily extracted files into a single zip file for the user
log.DebugFormat("Packing {0} of bug report files into zip file {1}",
Util.DiskSizeString(bytesToCompress), _destFile);
LogDescriptionChanges = false;
try
{
ZipToOutputFile(extractTempDir);
PercentComplete = 100;
// Only cleanup files if it succeeded (or cancelled)
CleanupFiles(extractTempDir);
}
finally
{
LogDescriptionChanges = true;
}
if (Cancelling)
throw new CancelledException();
}
catch (CancelledException)
{
throw;
}
catch (Exception exn)
{
ZipToOutputFile(_inputTempFolder);
PercentComplete = 100;
log.ErrorFormat("An exception was trapped while creating a server status report: " + exn.Message);
throw new Exception(Messages.STATUS_REPORT_ZIP_FAILED);
}
}