private static void Add7Zip(FileInfo f, DatDir thisDir) { DatDir ZipDir = new DatDir(DatFileType.Dir7Zip) { Name = Path.GetFileNameWithoutExtension(f.Name), DGame = new DatGame() }; ZipDir.DGame.Description = ZipDir.Name; thisDir.ChildAdd(ZipDir); SevenZ zf1 = new SevenZ(); zf1.ZipFileOpen(f.FullName, -1, true); FileScan fs = new FileScan(); List <FileScan.FileResults> fr = fs.Scan(zf1, true, true); for (int i = 0; i < fr.Count; i++) { if (zf1.IsDirectory(i)) { continue; } DatFile df = new DatFile(DatFileType.File7Zip) { Name = zf1.Filename(i), Size = fr[i].Size, CRC = fr[i].CRC, SHA1 = fr[i].SHA1 //df.MD5 = zf.MD5(i) }; ZipDir.ChildAdd(df); } zf1.ZipFileClose(); }
private TrrntZipStatus OpenZip(IO.FileInfo fi, out ICompress zipFile) { string ext = Path.GetExtension(fi.Name); if (ext == ".7z") { zipFile = new SevenZ(); } else { zipFile = new ZipFile(); } ZipReturn zr = zipFile.ZipFileOpen(fi.FullName, fi.LastWriteTime, true); if (zr != ZipReturn.ZipGood) { return(TrrntZipStatus.CorruptZip); } TrrntZipStatus tzStatus = TrrntZipStatus.Unknown; // first check if the file is a trrntip files if (zipFile.ZipStatus == ZipStatus.TrrntZip) { tzStatus |= TrrntZipStatus.ValidTrrntzip; } return(tzStatus); }
/// <inheritdoc/> public override bool IsTorrent() { SevenZ zf = new SevenZ(); ZipReturn zr = zf.ZipFileOpen(this.Filename, -1, true); if (zr != ZipReturn.ZipGood) { throw new Exception(ZipUtils.ZipErrorMessageText(zr)); } return(zf.ZipStatus == ZipStatus.Trrnt7Zip); }
/// <inheritdoc/> public override List <string> GetEmptyFolders() { List <string> empties = new List <string>(); try { SevenZ zf = new SevenZ(); ZipReturn zr = zf.ZipFileOpen(this.Filename, -1, true); if (zr != ZipReturn.ZipGood) { throw new Exception(ZipUtils.ZipErrorMessageText(zr)); } List <(string, bool)> zipEntries = new List <(string, bool)>(); for (int i = 0; i < zf.LocalFilesCount(); i++) { zipEntries.Add((zf.Filename(i), zf.IsDirectory(i))); } zipEntries = zipEntries.OrderBy(p => p.Item1, new NaturalReversedComparer()).ToList(); string lastZipEntry = null; foreach ((string, bool)entry in zipEntries) { // If the current is a superset of last, we skip it if (lastZipEntry != null && lastZipEntry.StartsWith(entry.Item1)) { // No-op } // If the entry is a directory, we add it else { if (entry.Item2) { empties.Add(entry.Item1); } lastZipEntry = entry.Item1; } } } catch (Exception ex) { logger.Error(ex); } return(empties); }
private static ReturnCode OpenOutputZip(RvFile fixZip, string outputZipFilename, out ICompress outputFixZip, out string errorMessage) { outputFixZip = null; if (Path.GetFileName(outputZipFilename) == "__RomVault.tmp") { if (File.Exists(outputZipFilename)) { File.Delete(outputZipFilename); } } else if (File.Exists(outputZipFilename)) { errorMessage = "Rescan needed, Unkown existing file found :" + outputZipFilename; return(ReturnCode.RescanNeeded); } ZipReturn zrf; if (fixZip.FileType == FileType.Zip) { outputFixZip = new Zip(); zrf = outputFixZip.ZipFileCreate(outputZipFilename); } else { outputFixZip = new SevenZ(); zrf = ((SevenZ)outputFixZip).ZipFileCreateFromUncompressedSize(outputZipFilename, Settings.rvSettings.zstd ? SevenZ.sevenZipCompressType.zstd : SevenZ.sevenZipCompressType.lzma, GetUncompressedSize(fixZip)); } if (zrf != ZipReturn.ZipGood) { errorMessage = "Error Opening Write Stream " + zrf; return(ReturnCode.FileSystemError); } errorMessage = ""; return(ReturnCode.Good); }
private TrrntZipStatus OpenZip(FileInfo fi, out ICompress zipFile) { string ext = Path.GetExtension(fi.Name); switch (ext) { case ".iso": zipFile = new File(); break; case ".7z": zipFile = new SevenZ(); break; default: zipFile = new Zip(); break; } ZipReturn zr = zipFile.ZipFileOpen(fi.FullName, fi.LastWriteTime); if (zr != ZipReturn.ZipGood) { return(TrrntZipStatus.CorruptZip); } TrrntZipStatus tzStatus = TrrntZipStatus.Unknown; // first check if the file is a trrntip files if (zipFile.ZipStatus == ZipStatus.TrrntZip) { tzStatus |= TrrntZipStatus.ValidTrrntzip; } return(tzStatus); }
public static ReturnCode DecompressSource7ZipFile(RvFile zZipFileIn, bool includeGood, out string error) { byte[] buffer = new byte[BufferSize]; RvFile cacheDir = DB.RvFileCache(); string fileNameIn = zZipFileIn.FullName; SevenZ zipFileIn = new SevenZ(); ZipReturn zr1 = zipFileIn.ZipFileOpen(fileNameIn, zZipFileIn.TimeStamp, true); if (zr1 != ZipReturn.ZipGood) { error = "Error opening 7zip file for caching"; return(ReturnCode.RescanNeeded); } RvFile outDir = new RvFile(FileType.Dir) { Name = zZipFileIn.Name + ".cache", Parent = cacheDir, DatStatus = DatStatus.InToSort, GotStatus = GotStatus.Got }; int nameDirIndex = 0; while (cacheDir.ChildNameSearch(outDir, out int index) == 0) { nameDirIndex++; outDir.Name = zZipFileIn.Name + ".cache (" + nameDirIndex + ")"; } cacheDir.ChildAdd(outDir); Directory.CreateDirectory(outDir.FullName); for (int i = 0; i < zipFileIn.LocalFilesCount(); i++) { if (zZipFileIn.Child(i).IsDir) { continue; } RvFile thisFile = null; for (int j = 0; j < zZipFileIn.ChildCount; j++) { if (zZipFileIn.Child(j).ZipFileIndex != i) { continue; } thisFile = zZipFileIn.Child(j); break; } if (thisFile == null) { error = "Error opening 7zip file for caching"; return(ReturnCode.RescanNeeded); } bool extract = true; // first check to see if we have a file version of this compressed file somewhere else. foreach (RvFile f in thisFile.FileGroup.Files) { if (f.FileType == FileType.File && f.GotStatus == GotStatus.Got) { extract = false; } } if (!extract) { continue; } extract = false; if (includeGood) { // if this is the file we are fixing then pull out the correct files. if (thisFile.RepStatus == RepStatus.Correct) { extract = true; } } // next check to see if we need this extracted to fix another file foreach (RvFile f in thisFile.FileGroup.Files) { if (f.RepStatus == RepStatus.CanBeFixed) { extract = true; break; } } if (!extract) { continue; } string cleanedName = thisFile.Name; cleanedName = cleanedName.Replace("/", "-"); cleanedName = cleanedName.Replace("\\", "-"); RvFile outFile = new RvFile(FileType.File) { Name = cleanedName, Size = thisFile.Size, CRC = thisFile.CRC, SHA1 = thisFile.SHA1, MD5 = thisFile.MD5, HeaderFileType = thisFile.HeaderFileType, AltSize = thisFile.AltSize, AltCRC = thisFile.AltCRC, AltSHA1 = thisFile.AltSHA1, AltMD5 = thisFile.AltMD5, FileGroup = thisFile.FileGroup }; outFile.SetStatus(DatStatus.InToSort, GotStatus.Got); outFile.FileStatusSet( FileStatus.HeaderFileTypeFromHeader | FileStatus.SizeFromHeader | FileStatus.SizeVerified | FileStatus.CRCFromHeader | FileStatus.CRCVerified | FileStatus.SHA1FromHeader | FileStatus.SHA1Verified | FileStatus.MD5FromHeader | FileStatus.MD5Verified | FileStatus.AltSizeFromHeader | FileStatus.AltSizeVerified | FileStatus.AltCRCFromHeader | FileStatus.AltCRCVerified | FileStatus.AltSHA1FromHeader | FileStatus.AltSHA1Verified | FileStatus.AltMD5FromHeader | FileStatus.AltMD5Verified , thisFile); outFile.RepStatus = RepStatus.NeededForFix; zipFileIn.ZipFileOpenReadStream(i, out Stream readStream, out ulong unCompressedSize); string filenameOut = Path.Combine(outDir.FullName, outFile.Name); ThreadMD5 tmd5 = null; ThreadSHA1 tsha1 = null; ThreadCRC tcrc32 = new ThreadCRC(); if (Settings.rvSettings.FixLevel != EFixLevel.Level1 && Settings.rvSettings.FixLevel != EFixLevel.TrrntZipLevel1) { tmd5 = new ThreadMD5(); tsha1 = new ThreadSHA1(); } int errorCode = FileStream.OpenFileWrite(filenameOut, out Stream writeStream); ulong sizetogo = unCompressedSize; while (sizetogo > 0) { int sizenow = sizetogo > BufferSize ? BufferSize : (int)sizetogo; try { readStream.Read(buffer, 0, sizenow); } catch (Exception ex) { if (ex is ZlibException || ex is DataErrorException) { ZipReturn zr = zipFileIn.ZipFileCloseReadStream(); if (zr != ZipReturn.ZipGood) { error = "Error Closing " + zr + " Stream :" + zipFileIn.ZipFilename; return(ReturnCode.FileSystemError); } zipFileIn.ZipFileClose(); writeStream.Flush(); writeStream.Close(); if (filenameOut != null) { File.Delete(filenameOut); } thisFile.GotStatus = GotStatus.Corrupt; error = "Unexpected corrupt archive file found:\n" + zZipFileIn.FullName + "\nRun Find Fixes, and Fix to continue fixing correctly."; return(ReturnCode.SourceDataStreamCorrupt); } error = "Error reading Source File " + ex.Message; return(ReturnCode.FileSystemError); } tcrc32.Trigger(buffer, sizenow); tmd5?.Trigger(buffer, sizenow); tsha1?.Trigger(buffer, sizenow); tcrc32.Wait(); tmd5?.Wait(); tsha1?.Wait(); try { writeStream.Write(buffer, 0, sizenow); } catch (Exception e) { error = "Error writing out file. " + Environment.NewLine + e.Message; return(ReturnCode.FileSystemError); } sizetogo = sizetogo - (ulong)sizenow; } writeStream.Flush(); writeStream.Close(); writeStream.Dispose(); tcrc32.Finish(); tmd5?.Finish(); tsha1?.Finish(); byte[] bCRC = tcrc32.Hash; byte[] bMD5 = tmd5?.Hash; byte[] bSHA1 = tsha1?.Hash; tcrc32.Dispose(); tmd5?.Dispose(); tsha1?.Dispose(); FileInfo fi = new FileInfo(filenameOut); outFile.TimeStamp = fi.LastWriteTime; if (bCRC != null && thisFile.CRC != null && !ArrByte.BCompare(bCRC, thisFile.CRC)) { // error in file. } if (bMD5 != null && thisFile.MD5 != null && !ArrByte.BCompare(bMD5, thisFile.MD5)) { // error in file. } if (bSHA1 != null && thisFile.SHA1 != null && !ArrByte.BCompare(bSHA1, thisFile.SHA1)) { // error in file. } thisFile.FileGroup.Files.Add(outFile); outDir.ChildAdd(outFile); } zipFileIn.ZipFileClose(); error = ""; return(ReturnCode.Good); }
private static bool ScanAFile(string realFilename, Stream memzip, string displayFilename) { Compress.File.File fStream = new Compress.File.File(); if (string.IsNullOrEmpty(realFilename) && memzip != null) { fStream.ZipFileOpen(memzip); } else { ZipReturn zRet = fStream.ZipFileOpen(realFilename, -1, true); if (zRet != ZipReturn.ZipGood) { return(false); } } bool ret = false; FileScan fScan = new FileScan(); List <FileScan.FileResults> resScan = fScan.Scan(fStream, true, true); HeaderFileType foundFileType = resScan[0].HeaderFileType; if (foundFileType == HeaderFileType.CHD) { // read altheader values from CHD file. } RvFile tFile = new RvFile { Size = resScan[0].Size, CRC = resScan[0].CRC, MD5 = resScan[0].MD5, SHA1 = resScan[0].SHA1, AltType = resScan[0].HeaderFileType, AltSize = resScan[0].AltSize, AltCRC = resScan[0].AltCRC, AltMD5 = resScan[0].AltMD5, AltSHA1 = resScan[0].AltSHA1 }; // test if needed. FindStatus res = RvRomFileMatchup.FileneededTest(tFile); if (res == FindStatus.FileNeededInArchive) { _bgw?.ReportProgress(0, new bgwShowError(displayFilename, "found")); Debug.WriteLine("Reading file as " + tFile.SHA1); string outfile = RomRootDir.Getfilename(tFile.SHA1); gZip gz1 = new gZip(); gz1.ZipFileCreate(outfile); gz1.ExtraData = tFile.SetExtraData(); gz1.ZipFileOpenWriteStream(false, true, "", tFile.Size, 8, out Stream write, null); fStream.ZipFileOpenReadStream(0, out Stream s, out ulong _); // do copy StreamCopier.StreamCopy(s, write, tFile.Size); fStream.ZipFileCloseReadStream(); fStream.ZipFileClose(); gz1.ZipFileCloseWriteStream(tFile.CRC); tFile.CompressedSize = gz1.CompressedSize; gz1.ZipFileClose(); tFile.DBWrite(); ret = true; } else if (res == FindStatus.FoundFileInArchive) { ret = true; } fStream.ZipFileClose(); if (foundFileType == HeaderFileType.ZIP || foundFileType == HeaderFileType.SevenZip || foundFileType == HeaderFileType.GZ) { ICompress fz; switch (foundFileType) { case HeaderFileType.SevenZip: fz = new SevenZ(); break; case HeaderFileType.GZ: fz = new gZip(); break; //case HeaderFileType.ZIP: default: fz = new Zip(); break; } ZipReturn zp; if (string.IsNullOrEmpty(realFilename) && memzip != null) { memzip.Position = 0; zp = fz.ZipFileOpen(memzip); } else { zp = fz.ZipFileOpen(realFilename); } if (zp == ZipReturn.ZipGood) { bool allZipFound = true; for (int i = 0; i < fz.LocalFilesCount(); i++) { LocalFile lf = fz.GetLocalFile(i); ZipReturn openFile = fz.ZipFileOpenReadStream(i, out Stream stream, out ulong streamSize); if (streamSize <= _inMemorySize) { if (openFile == ZipReturn.ZipTryingToAccessADirectory) { continue; } byte[] tmpFile = new byte[streamSize]; stream.Read(tmpFile, 0, (int)streamSize); using (Stream memStream = new MemoryStream(tmpFile, false)) { allZipFound &= ScanAFile(null, memStream, lf.Filename); } } else { string file = Path.Combine(_tmpDir, Guid.NewGuid().ToString()); FileStream.OpenFileWrite(file, out Stream fs); ulong sizetogo = streamSize; while (sizetogo > 0) { int sizenow = sizetogo > (ulong)Buffersize ? Buffersize : (int)sizetogo; stream.Read(Buffer, 0, sizenow); fs.Write(Buffer, 0, sizenow); sizetogo -= (ulong)sizenow; } fs.Close(); allZipFound &= ScanAFile(file, null, lf.Filename); File.Delete(file); } //fz.ZipFileCloseReadStream(); } fz.ZipFileClose(); ret |= allZipFound; } else { ret = false; } } return(ret); }
public static TrrntZipStatus ReZipFiles(List <ZippedFile> zippedFiles, ICompress originalZipFile, byte[] buffer, StatusCallback StatusCallBack, LogCallback LogCallback, int ThreadID) { zipType inputType; if (originalZipFile is ZipFile) { inputType = zipType.zip; } else if (originalZipFile is SevenZ) { inputType = zipType.sevenzip; } else { return(TrrntZipStatus.Unknown); } zipType outputType = Program.OutZip == zipType.both ? inputType : Program.OutZip; int bufferSize = buffer.Length; string filename = originalZipFile.ZipFilename; string tmpFilename = Path.Combine(Path.GetDirectoryName(filename), Path.GetFileNameWithoutExtension(filename) + ".tmp"); string outExt = outputType == zipType.zip ? ".zip" : ".7z"; string outfilename = Path.Combine(Path.GetDirectoryName(filename), Path.GetFileNameWithoutExtension(filename) + outExt); if (inputType != outputType) { if (File.Exists(outfilename)) { LogCallback?.Invoke(ThreadID, "Error output " + outExt + " file already exists"); return(TrrntZipStatus.RepeatFilesFound); } } if (File.Exists(tmpFilename)) { File.Delete(tmpFilename); } ICompress zipFileOut = outputType == zipType.zip ? new ZipFile() : (ICompress) new SevenZ(); try { zipFileOut.ZipFileCreate(tmpFilename); ulong fileSizeTotal = 0; ulong fileSizeProgress = 0; int filePercentReported = 20; foreach (ZippedFile f in zippedFiles) { fileSizeTotal += f.Size; } // by now the zippedFiles have been sorted so just loop over them for (int i = 0; i < zippedFiles.Count; i++) { ZippedFile t = zippedFiles[i]; if (Program.VerboseLogging) { LogCallback?.Invoke(ThreadID, $"{t.Size,15} {t.StringCRC} {t.Name}"); } Stream readStream = null; ulong streamSize = 0; ushort compMethod; ZipFile z = originalZipFile as ZipFile; ZipReturn zrInput = ZipReturn.ZipUntested; if (z != null) { zrInput = z.ZipFileOpenReadStream(t.Index, false, out readStream, out streamSize, out compMethod); } SevenZ z7 = originalZipFile as SevenZ; if (z7 != null) { zrInput = z7.ZipFileOpenReadStream(t.Index, out readStream, out streamSize); } Stream writeStream; ZipReturn zrOutput = zipFileOut.ZipFileOpenWriteStream(false, true, t.Name, streamSize, 8, out writeStream); if ((zrInput != ZipReturn.ZipGood) || (zrOutput != ZipReturn.ZipGood)) { //Error writing local File. zipFileOut.ZipFileClose(); originalZipFile.ZipFileClose(); File.Delete(tmpFilename); return(TrrntZipStatus.CorruptZip); } Stream crcCs = new CrcCalculatorStream(readStream, true); ulong sizetogo = streamSize; while (sizetogo > 0) { int sizenow = sizetogo > (ulong)bufferSize ? bufferSize : (int)sizetogo; fileSizeProgress += (ulong)sizenow; int filePercent = (int)((double)fileSizeProgress / fileSizeTotal * 20); if (filePercent != filePercentReported) { StatusCallBack?.Invoke(ThreadID, filePercent * 5); filePercentReported = filePercent; } crcCs.Read(buffer, 0, sizenow); writeStream.Write(buffer, 0, sizenow); sizetogo = sizetogo - (ulong)sizenow; } writeStream.Flush(); crcCs.Close(); if (z != null) { originalZipFile.ZipFileCloseReadStream(); } uint crc = (uint)((CrcCalculatorStream)crcCs).Crc; if (crc != t.CRC) { return(TrrntZipStatus.CorruptZip); } zipFileOut.ZipFileCloseWriteStream(t.ByteCRC); } StatusCallBack?.Invoke(ThreadID, 100); zipFileOut.ZipFileClose(); originalZipFile.ZipFileClose(); File.Delete(filename); File.Move(tmpFilename, outfilename); return(TrrntZipStatus.ValidTrrntzip); } catch (Exception) { zipFileOut?.ZipFileCloseFailed(); originalZipFile?.ZipFileClose(); return(TrrntZipStatus.CorruptZip); } }
/// <inheritdoc/> public override bool Write(List <string> inputFiles, string outDir, List <BaseFile> baseFiles) { bool success = false; string tempFile = Path.Combine(outDir, $"tmp{Guid.NewGuid()}"); // If either list of roms is null or empty, return if (inputFiles == null || baseFiles == null || inputFiles.Count == 0 || baseFiles.Count == 0) { return(success); } // If the number of inputs is less than the number of available roms, return if (inputFiles.Count < baseFiles.Count) { return(success); } // If one of the files doesn't exist, return foreach (string file in inputFiles) { if (!File.Exists(file)) { return(success); } } // Get the output archive name from the first rebuild rom string archiveFileName = Path.Combine(outDir, Utilities.RemovePathUnsafeCharacters(baseFiles[0].Parent) + (baseFiles[0].Parent.EndsWith(".7z") ? string.Empty : ".7z")); // Set internal variables Stream writeStream = null; SevenZ oldZipFile = new SevenZ(); SevenZ zipFile = new SevenZ(); ZipReturn zipReturn = ZipReturn.ZipGood; try { // If the full output path doesn't exist, create it if (!Directory.Exists(Path.GetDirectoryName(archiveFileName))) { Directory.CreateDirectory(Path.GetDirectoryName(archiveFileName)); } // If the archive doesn't exist, create it and put the single file if (!File.Exists(archiveFileName)) { zipReturn = zipFile.ZipFileCreate(tempFile); // Map all inputs to index Dictionary <string, int> inputIndexMap = new Dictionary <string, int>(); for (int i = 0; i < inputFiles.Count; i++) { inputIndexMap.Add(baseFiles[i].Filename.Replace('\\', '/'), i); } // Sort the keys in TZIP order List <string> keys = inputIndexMap.Keys.ToList(); keys.Sort(ZipUtils.TrrntZipStringCompare); // Now add all of the files in order foreach (string key in keys) { // Get the index mapped to the key int index = inputIndexMap[key]; // Open the input file for reading Stream freadStream = File.OpenRead(inputFiles[index]); ulong istreamSize = (ulong)(new FileInfo(inputFiles[index]).Length); DateTime dt = DateTime.Now; if (UseDates && !string.IsNullOrWhiteSpace(baseFiles[index].Date) && DateTime.TryParse(baseFiles[index].Date.Replace('\\', '/'), out dt)) { long msDosDateTime = Utilities.ConvertDateTimeToMsDosTimeFormat(dt); TimeStamps ts = new TimeStamps { ModTime = msDosDateTime }; zipFile.ZipFileOpenWriteStream(false, false, baseFiles[index].Filename.Replace('\\', '/'), istreamSize, 0, out writeStream, ts); } else { zipFile.ZipFileOpenWriteStream(false, true, baseFiles[index].Filename.Replace('\\', '/'), istreamSize, 0, out writeStream, null); } // Copy the input stream to the output byte[] ibuffer = new byte[_bufferSize]; int ilen; while ((ilen = freadStream.Read(ibuffer, 0, _bufferSize)) > 0) { writeStream.Write(ibuffer, 0, ilen); writeStream.Flush(); } freadStream.Dispose(); zipFile.ZipFileCloseWriteStream(baseFiles[index].CRC); } } // Otherwise, sort the input files and write out in the correct order else { // Open the old archive for reading oldZipFile.ZipFileOpen(archiveFileName, -1, true); // Map all inputs to index Dictionary <string, int> inputIndexMap = new Dictionary <string, int>(); for (int i = 0; i < inputFiles.Count; i++) { var oldZipFileContents = new List <string>(); for (int j = 0; j < oldZipFile.LocalFilesCount(); j++) { oldZipFileContents.Add(oldZipFile.Filename(j)); } // If the old one contains the new file, then just skip out if (oldZipFileContents.Contains(baseFiles[i].Filename.Replace('\\', '/'))) { continue; } inputIndexMap.Add(baseFiles[i].Filename.Replace('\\', '/'), -(i + 1)); } // Then add all of the old entries to it too for (int i = 0; i < oldZipFile.LocalFilesCount(); i++) { inputIndexMap.Add(oldZipFile.Filename(i), i); } // If the number of entries is the same as the old archive, skip out if (inputIndexMap.Keys.Count <= oldZipFile.LocalFilesCount()) { success = true; return(success); } // Otherwise, process the old zipfile zipFile.ZipFileCreate(tempFile); // Get the order for the entries with the new file List <string> keys = inputIndexMap.Keys.ToList(); keys.Sort(ZipUtils.TrrntZipStringCompare); // Copy over all files to the new archive foreach (string key in keys) { // Get the index mapped to the key int index = inputIndexMap[key]; // If we have the input file, add it now if (index < 0) { // Open the input file for reading Stream freadStream = File.OpenRead(inputFiles[-index - 1]); ulong istreamSize = (ulong)(new FileInfo(inputFiles[-index - 1]).Length); DateTime dt = DateTime.Now; if (UseDates && !string.IsNullOrWhiteSpace(baseFiles[-index - 1].Date) && DateTime.TryParse(baseFiles[-index - 1].Date.Replace('\\', '/'), out dt)) { long msDosDateTime = Utilities.ConvertDateTimeToMsDosTimeFormat(dt); TimeStamps ts = new TimeStamps { ModTime = msDosDateTime }; zipFile.ZipFileOpenWriteStream(false, false, baseFiles[-index - 1].Filename.Replace('\\', '/'), istreamSize, 0, out writeStream, ts); } else { zipFile.ZipFileOpenWriteStream(false, true, baseFiles[-index - 1].Filename.Replace('\\', '/'), istreamSize, 0, out writeStream, null); } // Copy the input stream to the output byte[] ibuffer = new byte[_bufferSize]; int ilen; while ((ilen = freadStream.Read(ibuffer, 0, _bufferSize)) > 0) { writeStream.Write(ibuffer, 0, ilen); writeStream.Flush(); } freadStream.Dispose(); zipFile.ZipFileCloseWriteStream(baseFiles[-index - 1].CRC); } // Otherwise, copy the file from the old archive else { // Instantiate the streams oldZipFile.ZipFileOpenReadStream(index, out Stream zreadStream, out ulong istreamSize); zipFile.ZipFileOpenWriteStream(false, true, oldZipFile.Filename(index), istreamSize, 0, out writeStream, null); // Copy the input stream to the output byte[] ibuffer = new byte[_bufferSize]; int ilen; while ((ilen = zreadStream.Read(ibuffer, 0, _bufferSize)) > 0) { writeStream.Write(ibuffer, 0, ilen); writeStream.Flush(); } zipFile.ZipFileCloseWriteStream(oldZipFile.CRC32(index)); } } } // Close the output zip file zipFile.ZipFileClose(); oldZipFile.ZipFileClose(); success = true; } catch (Exception ex) { logger.Error(ex); success = false; } // If the old file exists, delete it and replace if (File.Exists(archiveFileName)) { File.Delete(archiveFileName); } File.Move(tempFile, archiveFileName); return(true); }
/// <inheritdoc/> public override bool CopyAll(string outDir) { bool encounteredErrors = true; try { // Create the temp directory Directory.CreateDirectory(outDir); // Extract all files to the temp directory SevenZ zf = new SevenZ(); ZipReturn zr = zf.ZipFileOpen(this.Filename, -1, true); if (zr != ZipReturn.ZipGood) { throw new Exception(ZipUtils.ZipErrorMessageText(zr)); } for (int i = 0; i < zf.LocalFilesCount() && zr == ZipReturn.ZipGood; i++) { // Open the read stream zr = zf.ZipFileOpenReadStream(i, out Stream readStream, out ulong streamsize); // Create the rest of the path, if needed if (!string.IsNullOrWhiteSpace(Path.GetDirectoryName(zf.Filename(i)))) { Directory.CreateDirectory(Path.Combine(outDir, Path.GetDirectoryName(zf.Filename(i)))); } // If the entry ends with a directory separator, continue to the next item, if any if (zf.Filename(i).EndsWith(Path.DirectorySeparatorChar.ToString()) || zf.Filename(i).EndsWith(Path.AltDirectorySeparatorChar.ToString()) || zf.Filename(i).EndsWith(Path.PathSeparator.ToString())) { zf.ZipFileCloseReadStream(); continue; } FileStream writeStream = File.Create(Path.Combine(outDir, zf.Filename(i))); // If the stream is smaller than the buffer, just run one loop through to avoid issues if (streamsize < _bufferSize) { byte[] ibuffer = new byte[streamsize]; int ilen = readStream.Read(ibuffer, 0, (int)streamsize); writeStream.Write(ibuffer, 0, ilen); writeStream.Flush(); } // Otherwise, we do the normal loop else { int realBufferSize = (streamsize < _bufferSize ? (int)streamsize : _bufferSize); byte[] ibuffer = new byte[realBufferSize]; int ilen; while ((ilen = readStream.Read(ibuffer, 0, realBufferSize)) > 0) { writeStream.Write(ibuffer, 0, ilen); writeStream.Flush(); } } zr = zf.ZipFileCloseReadStream(); writeStream.Dispose(); } zf.ZipFileClose(); encounteredErrors = false; } catch (EndOfStreamException ex) { // Catch this but don't count it as an error because SharpCompress is unsafe logger.Verbose(ex); } catch (InvalidOperationException ex) { logger.Warning(ex); encounteredErrors = true; } catch (Exception ex) { logger.Error(ex); encounteredErrors = true; } return(encounteredErrors); }
public bool FullExtract(string filename, string outDir) { MessageCallBack?.Invoke($"Processing file: {filename}"); if (!string.IsNullOrEmpty(outDir)) { MessageCallBack?.Invoke($"Output dir: {outDir}"); } string ext = Path.GetExtension(filename); ICompress z = null; switch (ext.ToLower()) { case ".zip": z = new Zip(); break; case ".7z": z = new SevenZ(); break; } if (z == null) { MessageCallBack?.Invoke($"Unknown file type {ext}"); return(false); } ZipReturn zRet = z.ZipFileOpen(filename); if (zRet != ZipReturn.ZipGood) { MessageCallBack?.Invoke($"Error opening archive {zRet}"); return(false); } ulong buflen = 409600; byte[] buffer = new byte[buflen]; for (int i = 0; i < z.LocalFilesCount(); i++) { LocalFile lf = z.GetLocalFile(i); byte[] cread = null; string filenameOut = lf.Filename; if (lf.IsDirectory) { string outFullDir = Path.Combine(outDir, filenameOut.Substring(0, filenameOut.Length - 1).Replace('/', '\\')); Directory.CreateDirectory(outFullDir); continue; } else { MessageCallBack?.Invoke($"Extracting {filenameOut}"); string fOut = Path.Combine(outDir, filenameOut.Replace('/', '\\')); string dOut = Path.GetDirectoryName(fOut); if (!string.IsNullOrWhiteSpace(dOut) && !Directory.Exists(dOut)) { Directory.CreateDirectory(dOut); } int errorCode = FileStream.OpenFileWrite(fOut, out Stream sWrite); if (errorCode != 0) { MessageCallBack?.Invoke($"Error opening outputfile {fOut}"); } z.ZipFileOpenReadStream(i, out Stream sRead, out _); CRC crc = new(); ulong sizeToGo = lf.UncompressedSize; while (sizeToGo > 0) { ulong sizeNow = sizeToGo > buflen ? buflen : sizeToGo; int sizeRead = sRead.Read(buffer, 0, (int)sizeNow); crc.SlurpBlock(buffer, 0, sizeRead); sWrite.Write(buffer, 0, sizeRead); sizeToGo -= (ulong)sizeRead; } sWrite.Close(); sWrite.Dispose(); cread = crc.Crc32ResultB; } byte[] fread = lf.CRC; if (cread[0] != fread[0] || cread[1] != fread[1] || cread[2] != fread[2] || cread[3] != fread[3]) { MessageCallBack?.Invoke($"CRC error. Expected {fread.ToHex()} found {cread.ToHex()}"); return(false); } } return(true); }
private static void CheckADir(RvDir dbDir, bool report) { if (_cacheSaveTimer.Elapsed.TotalMinutes > Program.rvSettings.CacheSaveTimePeriod) { _bgw.ReportProgress(0, "Saving Cache"); DB.Write(); _bgw.ReportProgress(0, "Saving Cache Complete"); _cacheSaveTimer.Reset(); _cacheSaveTimer.Start(); } string fullDir = dbDir.FullName; if (report) { _bgw.ReportProgress(0, new bgwText2(fullDir)); } DatStatus chechingDatStatus = dbDir.IsInToSort ? DatStatus.InToSort : DatStatus.NotInDat; // this is a temporary rvDir structure to store the data about the actual directory/files we are scanning // we will first populate this variable with the real file data from the directory, and then compare it // with the data in dbDir. RvDir fileDir = null; Debug.WriteLine(fullDir); FileType ft = dbDir.FileType; #region "Populate fileDir" // if we are scanning a ZIP file then populate scanDir from the ZIP file switch (ft) { case FileType.Zip: case FileType.SevenZip: { fileDir = new RvDir(ft); // open the zip file ICompress checkZ; if (ft == FileType.Zip) { checkZ = new ZipFile(); } else { checkZ = new SevenZ(); } ZipReturn zr = checkZ.ZipFileOpen(fullDir, dbDir.TimeStamp, true); if (zr == ZipReturn.ZipGood) { dbDir.ZipStatus = checkZ.ZipStatus; // to be Scanning a ZIP file means it is either new or has changed. // as the code below only calls back here if that is true. // // Level1: Only use header CRC's // Just get the CRC for the ZIP headers. // // Level2: Fully checksum changed only files // We know this file has been changed to do a full checksum scan. // // Level3: Fully checksum everything // So do a full checksum scan. if ((EScanLevel == eScanLevel.Level2) || (EScanLevel == eScanLevel.Level3)) { checkZ.DeepScan(); } // add all of the file information from the zip file into scanDir for (int i = 0; i < checkZ.LocalFilesCount(); i++) { RvFile tFile = new RvFile(DBTypeGet.FileFromDir(ft)) { Name = checkZ.Filename(i), ZipFileIndex = i, ZipFileHeaderPosition = checkZ.LocalHeader(i), Size = checkZ.UncompressedSize(i), CRC = checkZ.CRC32(i) }; // all 3 levels read the CRC from the ZIP header tFile.SetStatus(chechingDatStatus, GotStatus.Got); tFile.FileStatusSet(FileStatus.SizeFromHeader | FileStatus.CRCFromHeader); // if we are in level 2 or level 3 then do a full CheckSum Scan. if ((EScanLevel == eScanLevel.Level2) || (EScanLevel == eScanLevel.Level3)) { // DeepScan will return ZipReturn.ZipCRCDecodeError if the headers CRC and // the actual CRC do not match. // So we just need to set the MD5 and SHA1 from the ZIP file. zr = checkZ.FileStatus(i); if (zr == ZipReturn.ZipUntested) { _bgw.ReportProgress(0, new bgwShowCorrupt(zr, fullDir + " : " + checkZ.Filename(i))); } else if (zr != ZipReturn.ZipGood) { _bgw.ReportProgress(0, new bgwShowCorrupt(zr, fullDir + " : " + checkZ.Filename(i))); tFile.GotStatus = GotStatus.Corrupt; } else { tFile.MD5 = checkZ.MD5(i); tFile.SHA1 = checkZ.SHA1(i); tFile.FileStatusSet(FileStatus.SizeVerified | FileStatus.CRCVerified | FileStatus.SHA1Verified | FileStatus.MD5Verified); } } fileDir.ChildAdd(tFile); } } else if (zr == ZipReturn.ZipFileLocked) { _bgw.ReportProgress(0, new bgwShowError(fullDir, "Zip File Locked")); dbDir.TimeStamp = 0; dbDir.GotStatus = GotStatus.FileLocked; } else { _bgw.ReportProgress(0, new bgwShowCorrupt(zr, fullDir)); dbDir.GotStatus = GotStatus.Corrupt; } checkZ.ZipFileClose(); } break; case FileType.Dir: { fileDir = new RvDir(FileType.Dir); DirectoryInfo oDir = new DirectoryInfo(fullDir); DirectoryInfo[] oDirs = oDir.GetDirectories(); FileInfo[] oFiles = oDir.GetFiles(); // add all the subdirectories into scanDir foreach (DirectoryInfo dir in oDirs) { RvBase tDir = new RvDir(FileType.Dir) { Name = dir.Name, TimeStamp = dir.LastWriteTime }; tDir.SetStatus(chechingDatStatus, GotStatus.Got); fileDir.ChildAdd(tDir); } // add all the files into scanDir foreach (FileInfo oFile in oFiles) { // if we find any zip files add them as zip files. string fExt = Path.GetExtension(oFile.Name); switch (fExt.ToLower()) { case ".7z": { RvDir tGame = new RvDir(FileType.SevenZip) { Name = Path.GetFileNameWithoutExtension(oFile.Name), TimeStamp = oFile.LastWriteTime }; tGame.SetStatus(chechingDatStatus, GotStatus.Got); fileDir.ChildAdd(tGame); } break; case ".zip": { RvDir tGame = new RvDir(FileType.Zip) { Name = Path.GetFileNameWithoutExtension(oFile.Name), TimeStamp = oFile.LastWriteTime }; tGame.SetStatus(chechingDatStatus, GotStatus.Got); fileDir.ChildAdd(tGame); } break; default: { string fName = oFile.Name; if (fName == "__RomVault.tmp") { File.Delete(oFile.FullName); continue; } // Scanning a file // // Level1 & 2 : (are the same for files) Fully checksum changed only files // Here we are just getting the TimeStamp of the File, and later // if the TimeStamp was not matched we will have to read the files CRC, MD5 & SHA1 // // Level3: Fully checksum everything // Get everything about the file right here so // read CRC, MD5 & SHA1 // add all the files in the sub-directory to scanDir RvFile tFile = new RvFile(FileType.File) { Name = fName, Size = (ulong)oFile.Length, TimeStamp = oFile.LastWriteTime }; tFile.FileStatusSet(FileStatus.SizeVerified); int errorCode = CHD.CheckFile(oFile, out tFile.SHA1CHD, out tFile.MD5CHD, out tFile.CHDVersion); if (errorCode == 0) { if (tFile.SHA1CHD != null) { tFile.FileStatusSet(FileStatus.SHA1CHDFromHeader); } if (tFile.MD5CHD != null) { tFile.FileStatusSet(FileStatus.MD5CHDFromHeader); } tFile.SetStatus(chechingDatStatus, GotStatus.Got); // if we are scanning at Level3 then we get all the info here if (EScanLevel == eScanLevel.Level3) { DeepScanFile(fullDir, tFile); ChdManCheck(fullDir, tFile); } } else if (errorCode == 32) { tFile.GotStatus = GotStatus.FileLocked; _bgw.ReportProgress(0, new bgwShowError(fullDir, "File Locked")); } else { string filename = Path.Combine(fullDir, tFile.Name); ReportError.Show("File: " + filename + " Error: " + new Win32Exception(errorCode).Message + ". Scan Aborted."); _fileErrorAbort = true; return; } fileDir.ChildAdd(tFile); } break; } } } break; default: ReportError.SendAndShow("Un supported file type in CheckADir " + ft); break; } #endregion if (fileDir == null) { ReportError.SendAndShow("Unknown Reading File Type in Dir Scanner"); return; } if (report) { _bgw.ReportProgress(0, new bgwSetRange2(fileDir.ChildCount - 1)); _bgw.ReportProgress(0, new bgwRange2Visible(true)); } if (!DBTypeGet.isCompressedDir(ft) && _bgw.CancellationPending) { return; } Compare(dbDir, fileDir, report, true); }
/// <inheritdoc/> public override List <BaseFile> GetChildren() { List <BaseFile> found = new List <BaseFile>(); string gamename = Path.GetFileNameWithoutExtension(this.Filename); try { SevenZ zf = new SevenZ(); ZipReturn zr = zf.ZipFileOpen(this.Filename, -1, true); if (zr != ZipReturn.ZipGood) { throw new Exception(ZipUtils.ZipErrorMessageText(zr)); } for (int i = 0; i < zf.LocalFilesCount(); i++) { // If the entry is a directory (or looks like a directory), we don't want to open it if (zf.IsDirectory(i) || zf.Filename(i).EndsWith(Path.DirectorySeparatorChar.ToString()) || zf.Filename(i).EndsWith(Path.AltDirectorySeparatorChar.ToString()) || zf.Filename(i).EndsWith(Path.PathSeparator.ToString())) { continue; } // Open the read stream zr = zf.ZipFileOpenReadStream(i, out Stream readStream, out ulong streamsize); // If we get a read error, log it and continue if (zr != ZipReturn.ZipGood) { logger.Warning($"An error occurred while reading archive {this.Filename}: Zip Error - {zr}"); zr = zf.ZipFileCloseReadStream(); continue; } // Create a blank item for the entry BaseFile zipEntryRom = new BaseFile(); // Perform a quickscan, if flagged to if (this.AvailableHashes == Hash.CRC) { zipEntryRom.Size = (long)zf.UncompressedSize(i); zipEntryRom.CRC = zf.CRC32(i); } // Otherwise, use the stream directly else { zipEntryRom = GetInfo(readStream, size: (long)zf.UncompressedSize(i), hashes: this.AvailableHashes, keepReadOpen: true); } // Fill in comon details and add to the list zipEntryRom.Filename = zf.Filename(i); zipEntryRom.Parent = gamename; found.Add(zipEntryRom); } // Dispose of the archive zr = zf.ZipFileCloseReadStream(); zf.ZipFileClose(); } catch (Exception ex) { logger.Error(ex); return(null); } return(found); }
/// <inheritdoc/> public override (MemoryStream, string) CopyToStream(string entryName) { MemoryStream ms = new MemoryStream(); string realEntry = null; try { SevenZ zf = new SevenZ(); ZipReturn zr = zf.ZipFileOpen(this.Filename, -1, true); if (zr != ZipReturn.ZipGood) { throw new Exception(ZipUtils.ZipErrorMessageText(zr)); } for (int i = 0; i < zf.LocalFilesCount() && zr == ZipReturn.ZipGood; i++) { if (zf.Filename(i).Contains(entryName)) { // Open the read stream realEntry = zf.Filename(i); zr = zf.ZipFileOpenReadStream(i, out Stream readStream, out ulong streamsize); // If the stream is smaller than the buffer, just run one loop through to avoid issues if (streamsize < _bufferSize) { byte[] ibuffer = new byte[streamsize]; int ilen = readStream.Read(ibuffer, 0, (int)streamsize); ms.Write(ibuffer, 0, ilen); ms.Flush(); } // Otherwise, we do the normal loop else { byte[] ibuffer = new byte[_bufferSize]; int ilen; while (streamsize > _bufferSize) { ilen = readStream.Read(ibuffer, 0, _bufferSize); ms.Write(ibuffer, 0, ilen); ms.Flush(); streamsize -= _bufferSize; } ilen = readStream.Read(ibuffer, 0, (int)streamsize); ms.Write(ibuffer, 0, ilen); ms.Flush(); } zr = zf.ZipFileCloseReadStream(); } } zf.ZipFileClose(); } catch (Exception ex) { logger.Error(ex); ms = null; realEntry = null; } return(ms, realEntry); }
private static ReturnCode OpenInputStream(RvFile fileIn, bool rawCopy, out ICompress zipFileIn, out bool sourceTrrntzip, out Stream readStream, out ulong streamSize, out ushort compressionMethod, out string error) { zipFileIn = null; sourceTrrntzip = false; readStream = null; streamSize = 0; compressionMethod = 0; if (fileIn.FileType == FileType.ZipFile || fileIn.FileType == FileType.SevenZipFile) // Input is a ZipFile { RvFile zZipFileIn = fileIn.Parent; if (zZipFileIn.FileType != DBTypeGet.DirFromFile(fileIn.FileType)) { error = "File Open but Source File is not correct type, Logic Error."; return(ReturnCode.LogicError); } string fileNameIn = zZipFileIn.FullNameCase; ZipReturn zr1; if (zZipFileIn.FileType == FileType.SevenZip) { sourceTrrntzip = false; zipFileIn = new SevenZ(); zr1 = zipFileIn.ZipFileOpen(fileNameIn, zZipFileIn.FileModTimeStamp); } else { sourceTrrntzip = (zZipFileIn.ZipStatus & ZipStatus.TrrntZip) == ZipStatus.TrrntZip; zipFileIn = new Zip(); zr1 = zipFileIn.ZipFileOpen(fileNameIn, zZipFileIn.FileModTimeStamp, fileIn.ZipFileHeaderPosition == null); } switch (zr1) { case ZipReturn.ZipGood: break; case ZipReturn.ZipErrorFileNotFound: error = "File not found, Rescan required before fixing " + fileIn.Name; return(ReturnCode.RescanNeeded); case ZipReturn.ZipErrorTimeStamp: error = "File has changed, Rescan required before fixing " + fileIn.Name; return(ReturnCode.RescanNeeded); default: error = "Error Open Zip" + zr1 + ", with File " + fileIn.DatTreeFullName; return(ReturnCode.FileSystemError); } if (fileIn.FileType == FileType.SevenZipFile) { ((SevenZ)zipFileIn).ZipFileOpenReadStream(fileIn.ZipFileIndex, out readStream, out streamSize); } else { if (fileIn.ZipFileHeaderPosition != null) { ((Zip)zipFileIn).ZipFileOpenReadStreamQuick((ulong)fileIn.ZipFileHeaderPosition, rawCopy, out readStream, out streamSize, out compressionMethod); } else { ((Zip)zipFileIn).ZipFileOpenReadStream(fileIn.ZipFileIndex, rawCopy, out readStream, out streamSize, out compressionMethod); } } } else // Input is a regular file { string fileNameIn = fileIn.FullName; if (!File.Exists(fileNameIn)) { error = "Rescan needed, File Not Found :" + fileNameIn; return(ReturnCode.RescanNeeded); } FileInfo fileInInfo = new FileInfo(fileNameIn); if (fileInInfo.LastWriteTime != fileIn.FileModTimeStamp) { error = "Rescan needed, File Changed :" + fileNameIn; return(ReturnCode.RescanNeeded); } int errorCode = FileStream.OpenFileRead(fileNameIn, out readStream); if (errorCode != 0) { error = new Win32Exception(errorCode).Message + ". " + fileNameIn; return(ReturnCode.FileSystemError); } if (fileIn.Size == null) { error = "Null File Size found in Fixing File :" + fileNameIn; return(ReturnCode.LogicError); } streamSize = (ulong)fileIn.Size; if ((ulong)readStream.Length != streamSize) { error = "Rescan needed, File Length Changed :" + fileNameIn; return(ReturnCode.RescanNeeded); } } error = ""; return(ReturnCode.Good); }
private static ReturnCode OpenOutputStream(RvFile fileOut, RvFile fileIn, ref ICompress zipFileOut, string zipFilenameOut, ushort compressionMethod, bool rawCopy, bool sourceTrrntzip, out Stream writeStream, out string error) { writeStream = null; if ((fileOut.FileType == FileType.ZipFile) || (fileOut.FileType == FileType.SevenZipFile)) { // if ZipFileOut == null then we have not open the output zip yet so open it from writing. if (zipFileOut == null) { if (Path.GetFileName(zipFilenameOut) == "__RomVault.tmp") { if (File.Exists(zipFilenameOut)) { File.Delete(zipFilenameOut); } } else if (File.Exists(zipFilenameOut)) { error = "Rescan needed, File Changed :" + zipFilenameOut; return(ReturnCode.RescanNeeded); } if (fileOut.FileType == FileType.ZipFile) { zipFileOut = new ZipFile(); } else { zipFileOut = new SevenZ(); } ZipReturn zrf = zipFileOut.ZipFileCreate(zipFilenameOut); if (zrf != ZipReturn.ZipGood) { error = "Error Opening Write Stream " + zrf; return(ReturnCode.FileSystemError); } } else { if (zipFileOut.ZipOpen != ZipOpenType.OpenWrite) { error = "Output Zip File is not set to OpenWrite, Logic Error."; return(ReturnCode.LogicError); } if (zipFileOut.ZipFilename != new FileInfo(zipFilenameOut).FullName) { error = "Output Zip file has changed name from " + zipFileOut.ZipFilename + " to " + zipFilenameOut + ". Logic Error"; return(ReturnCode.LogicError); } } if (fileIn.Size == null) { error = "Null File Size found in Fixing File :" + fileIn.FullName; return(ReturnCode.LogicError); } ZipReturn zr = zipFileOut.ZipFileOpenWriteStream(rawCopy, sourceTrrntzip, fileOut.Name, (ulong)fileIn.Size, compressionMethod, out writeStream); if (zr != ZipReturn.ZipGood) { error = "Error Opening Write Stream " + zr; return(ReturnCode.FileSystemError); } } else { if (File.Exists(zipFilenameOut) && (fileOut.GotStatus != GotStatus.Corrupt)) { error = "Rescan needed, File Changed :" + zipFilenameOut; return(ReturnCode.RescanNeeded); } int errorCode = FileStream.OpenFileWrite(zipFilenameOut, out writeStream); if (errorCode != 0) { error = new Win32Exception(errorCode).Message + ". " + zipFilenameOut; return(ReturnCode.FileSystemError); } } error = ""; return(ReturnCode.Good); }
private static bool ScanAFile(string realFilename, Stream memzip, string displayFilename) { Stream fStream; if (string.IsNullOrEmpty(realFilename) && memzip != null) { fStream = memzip; } else { int errorCode = FileStream.OpenFileRead(realFilename, out fStream); if (errorCode != 0) { return(false); } } bool ret = false; HeaderFileType foundFileType = FileHeaderReader.FileHeaderReader.GetType(fStream, out int offset); fStream.Position = 0; RvFile tFile = UnCompFiles.CheckSumRead(fStream, offset); tFile.AltType = foundFileType; if (foundFileType == HeaderFileType.CHD) { // read altheader values from CHD file. } // test if needed. FindStatus res = RvRomFileMatchup.FileneededTest(tFile); if (res == FindStatus.FileNeededInArchive) { _bgw?.ReportProgress(0, new bgwShowError(displayFilename, "found")); Debug.WriteLine("Reading file as " + tFile.SHA1); GZip gz = new GZip(tFile); string outfile = RomRootDir.Getfilename(tFile.SHA1); fStream.Position = 0; gz.WriteGZip(outfile, fStream, false); tFile.CompressedSize = gz.compressedSize; tFile.DBWrite(); ret = true; } else if (res == FindStatus.FoundFileInArchive) { ret = true; } if (foundFileType == HeaderFileType.ZIP || foundFileType == HeaderFileType.SevenZip || foundFileType == HeaderFileType.GZ) { ICompress fz; switch (foundFileType) { case HeaderFileType.SevenZip: fz = new SevenZ(); break; case HeaderFileType.GZ: fz = new gZip(); break; //case HeaderFileType.ZIP: default: fz = new Zip(); break; } fStream.Position = 0; ZipReturn zp; if (string.IsNullOrEmpty(realFilename) && memzip != null) { zp = fz.ZipFileOpen(memzip); } else { zp = fz.ZipFileOpen(realFilename); } if (zp == ZipReturn.ZipGood) { bool allZipFound = true; for (int i = 0; i < fz.LocalFilesCount(); i++) { ZipReturn openFile = fz.ZipFileOpenReadStream(i, out Stream stream, out ulong streamSize); if (streamSize <= _inMemorySize) { if (openFile == ZipReturn.ZipTryingToAccessADirectory) { continue; } byte[] tmpFile = new byte[streamSize]; stream.Read(tmpFile, 0, (int)streamSize); using (Stream memStream = new MemoryStream(tmpFile, false)) { allZipFound &= ScanAFile(null, memStream, fz.Filename(i)); } } else { string file = Path.Combine(_tmpDir, Guid.NewGuid().ToString()); FileStream.OpenFileWrite(file, out Stream fs); ulong sizetogo = streamSize; while (sizetogo > 0) { int sizenow = sizetogo > (ulong)Buffersize ? Buffersize : (int)sizetogo; stream.Read(Buffer, 0, sizenow); fs.Write(Buffer, 0, sizenow); sizetogo -= (ulong)sizenow; } fs.Close(); allZipFound &= ScanAFile(file, null, fz.Filename(i)); File.Delete(file); } //fz.ZipFileCloseReadStream(); } fz.ZipFileClose(); ret |= allZipFound; } else { ret = false; } } if (!string.IsNullOrEmpty(realFilename) || memzip == null) { fStream.Close(); fStream.Dispose(); } return(ret); }
public static TrrntZipStatus ReZipFiles(List <ZippedFile> zippedFiles, ICompress originalZipFile, byte[] buffer, StatusCallback StatusCallBack, LogCallback LogCallback, int ThreadID) { int bufferSize = buffer.Length; string filename = originalZipFile.ZipFilename; string tmpFilename = Path.GetDirectoryName(filename) + Path.DirectorySeparatorChar + Path.GetFileNameWithoutExtension(filename) + ".tmp"; string outfilename = Path.GetDirectoryName(filename) + Path.DirectorySeparatorChar + Path.GetFileNameWithoutExtension(filename) + ".zip"; if (Path.GetExtension(filename) == ".7z") { if (File.Exists(outfilename)) { LogCallback?.Invoke(ThreadID, "Error output .zip file already exists"); return(TrrntZipStatus.RepeatFilesFound); } } if (IO.File.Exists(tmpFilename)) { IO.File.Delete(tmpFilename); } ICompress zipFileOut = new ZipFile(); try { zipFileOut.ZipFileCreate(tmpFilename); // by now the zippedFiles have been sorted so just loop over them for (int i = 0; i < zippedFiles.Count; i++) { StatusCallBack?.Invoke(ThreadID, (int)((double)(i + 1) / (zippedFiles.Count) * 100)); ZippedFile t = zippedFiles[i]; if (Program.VerboseLogging) { LogCallback?.Invoke(ThreadID, $"{t.Size,15} {t.StringCRC} {t.Name}"); } Stream readStream = null; ulong streamSize = 0; ushort compMethod; ZipFile z = originalZipFile as ZipFile; ZipReturn zrInput = ZipReturn.ZipUntested; if (z != null) { zrInput = z.ZipFileOpenReadStream(t.Index, false, out readStream, out streamSize, out compMethod); } SevenZ z7 = originalZipFile as SevenZ; if (z7 != null) { zrInput = z7.ZipFileOpenReadStream(t.Index, out readStream, out streamSize); } Stream writeStream; ZipReturn zrOutput = zipFileOut.ZipFileOpenWriteStream(false, true, t.Name, streamSize, 8, out writeStream); if (zrInput != ZipReturn.ZipGood || zrOutput != ZipReturn.ZipGood) { //Error writing local File. zipFileOut.ZipFileClose(); originalZipFile.ZipFileClose(); IO.File.Delete(tmpFilename); return(TrrntZipStatus.CorruptZip); } Stream crcCs = new CrcCalculatorStream(readStream, true); ulong sizetogo = streamSize; while (sizetogo > 0) { int sizenow = sizetogo > (ulong)bufferSize ? bufferSize : (int)sizetogo; crcCs.Read(buffer, 0, sizenow); writeStream.Write(buffer, 0, sizenow); sizetogo = sizetogo - (ulong)sizenow; } writeStream.Flush(); crcCs.Close(); if (z != null) { originalZipFile.ZipFileCloseReadStream(); } uint crc = (uint)((CrcCalculatorStream)crcCs).Crc; if (crc != t.CRC) { return(TrrntZipStatus.CorruptZip); } zipFileOut.ZipFileCloseWriteStream(t.ByteCRC); } zipFileOut.ZipFileClose(); originalZipFile.ZipFileClose(); IO.File.Delete(filename); IO.File.Move(tmpFilename, outfilename); return(TrrntZipStatus.ValidTrrntzip); } catch (Exception) { zipFileOut?.ZipFileCloseFailed(); originalZipFile?.ZipFileClose(); return(TrrntZipStatus.CorruptZip); } }
/// <summary> /// Write an input file to a torrent7z archive /// </summary> /// <param name="inputStream">Input stream to be moved</param> /// <param name="outDir">Output directory to build to</param> /// <param name="rom">DatItem representing the new information</param> /// <returns>True if the archive was written properly, false otherwise</returns> public override bool Write(Stream inputStream, string outDir, Rom rom) { bool success = false; string tempFile = Path.Combine(outDir, $"tmp{Guid.NewGuid()}"); // If either input is null or empty, return if (inputStream == null || rom == null || rom.Name == null) { return(success); } // If the stream is not readable, return if (!inputStream.CanRead) { return(success); } // Seek to the beginning of the stream inputStream.Seek(0, SeekOrigin.Begin); // Get the output archive name from the first rebuild rom string archiveFileName = Path.Combine(outDir, Sanitizer.RemovePathUnsafeCharacters(rom.Machine.Name) + (rom.Machine.Name.EndsWith(".7z") ? string.Empty : ".7z")); // Set internal variables Stream writeStream = null; SevenZ oldZipFile = new SevenZ(); SevenZ zipFile = new SevenZ(); ZipReturn zipReturn = ZipReturn.ZipGood; try { // If the full output path doesn't exist, create it if (!Directory.Exists(Path.GetDirectoryName(archiveFileName))) { Directory.CreateDirectory(Path.GetDirectoryName(archiveFileName)); } // If the archive doesn't exist, create it and put the single file if (!File.Exists(archiveFileName)) { inputStream.Seek(0, SeekOrigin.Begin); zipReturn = zipFile.ZipFileCreate(tempFile); // Open the input file for reading ulong istreamSize = (ulong)(inputStream.Length); DateTime dt = DateTime.Now; if (UseDates && !string.IsNullOrWhiteSpace(rom.Date) && DateTime.TryParse(rom.Date.Replace('\\', '/'), out dt)) { uint msDosDateTime = Utilities.ConvertDateTimeToMsDosTimeFormat(dt); zipFile.ZipFileOpenWriteStream(false, false, rom.Name.Replace('\\', '/'), istreamSize, 0, msDosDateTime, out writeStream); } else { zipFile.ZipFileOpenWriteStream(false, true, rom.Name.Replace('\\', '/'), istreamSize, 0, null, out writeStream); } // Copy the input stream to the output byte[] ibuffer = new byte[_bufferSize]; int ilen; while ((ilen = inputStream.Read(ibuffer, 0, _bufferSize)) > 0) { writeStream.Write(ibuffer, 0, ilen); writeStream.Flush(); } zipFile.ZipFileCloseWriteStream(Utilities.StringToByteArray(rom.CRC)); } // Otherwise, sort the input files and write out in the correct order else { // Open the old archive for reading oldZipFile.ZipFileOpen(archiveFileName, -1, true); // Map all inputs to index Dictionary <string, int> inputIndexMap = new Dictionary <string, int>(); var oldZipFileContents = new List <string>(); for (int i = 0; i < oldZipFile.LocalFilesCount(); i++) { oldZipFileContents.Add(oldZipFile.Filename(i)); } // If the old one doesn't contain the new file, then add it if (!oldZipFileContents.Contains(rom.Name.Replace('\\', '/'))) { inputIndexMap.Add(rom.Name.Replace('\\', '/'), -1); } // Then add all of the old entries to it too for (int i = 0; i < oldZipFile.LocalFilesCount(); i++) { inputIndexMap.Add(oldZipFile.Filename(i), i); } // If the number of entries is the same as the old archive, skip out if (inputIndexMap.Keys.Count <= oldZipFile.LocalFilesCount()) { success = true; return(success); } // Otherwise, process the old zipfile zipFile.ZipFileCreate(tempFile); // Get the order for the entries with the new file List <string> keys = inputIndexMap.Keys.ToList(); keys.Sort(ZipFile.TrrntZipStringCompare); // Copy over all files to the new archive foreach (string key in keys) { // Get the index mapped to the key int index = inputIndexMap[key]; // If we have the input file, add it now if (index < 0) { // Open the input file for reading ulong istreamSize = (ulong)(inputStream.Length); DateTime dt = DateTime.Now; if (UseDates && !string.IsNullOrWhiteSpace(rom.Date) && DateTime.TryParse(rom.Date.Replace('\\', '/'), out dt)) { uint msDosDateTime = Utilities.ConvertDateTimeToMsDosTimeFormat(dt); zipFile.ZipFileOpenWriteStream(false, false, rom.Name.Replace('\\', '/'), istreamSize, 0, msDosDateTime, out writeStream); } else { zipFile.ZipFileOpenWriteStream(false, true, rom.Name.Replace('\\', '/'), istreamSize, 0, null, out writeStream); } // Copy the input stream to the output byte[] ibuffer = new byte[_bufferSize]; int ilen; while ((ilen = inputStream.Read(ibuffer, 0, _bufferSize)) > 0) { writeStream.Write(ibuffer, 0, ilen); writeStream.Flush(); } zipFile.ZipFileCloseWriteStream(Utilities.StringToByteArray(rom.CRC)); } // Otherwise, copy the file from the old archive else { // Instantiate the streams oldZipFile.ZipFileOpenReadStream(index, out Stream zreadStream, out ulong istreamSize); zipFile.ZipFileOpenWriteStream(false, true, oldZipFile.Filename(index), istreamSize, 0, null, out writeStream); // Copy the input stream to the output byte[] ibuffer = new byte[_bufferSize]; int ilen; while ((ilen = zreadStream.Read(ibuffer, 0, _bufferSize)) > 0) { writeStream.Write(ibuffer, 0, ilen); writeStream.Flush(); } oldZipFile.ZipFileCloseReadStream(); zipFile.ZipFileCloseWriteStream(oldZipFile.CRC32(index)); } } } // Close the output zip file zipFile.ZipFileClose(); oldZipFile.ZipFileClose(); success = true; } catch (Exception ex) { logger.Error(ex); success = false; } finally { } // If the old file exists, delete it and replace if (File.Exists(archiveFileName)) { FileExtensions.TryDelete(archiveFileName); } File.Move(tempFile, archiveFileName); return(true); }