private static void DeepScanFile(string directory, RvFile tFile) { string filename = Path.Combine(directory, tFile.Name); int errorCode = UnCompFiles.CheckSumRead(filename, true, out tFile.CRC, out tFile.MD5, out tFile.SHA1); if (errorCode == 32) { tFile.GotStatus = GotStatus.FileLocked; return; } if (errorCode != 0) { ReportError.Show("File: " + filename + " Error: " + new Win32Exception(errorCode).Message + ". Scan Aborted."); _fileErrorAbort = true; return; } tFile.FileStatusSet(FileStatus.SizeVerified | FileStatus.CRCVerified | FileStatus.SHA1Verified | FileStatus.MD5Verified); }
private static void ChdManCheck(string directory, RvFile tFile) { string filename = Path.Combine(directory, tFile.Name); if (!tFile.FileStatusIs(FileStatus.SHA1CHDFromHeader)) { return; } _bgw.ReportProgress(0, new bgwText2(filename)); string error; CHD.CHDManCheck res = CHD.ChdmanCheck(filename, _bgw, out error); switch (res) { case CHD.CHDManCheck.Good: tFile.FileStatusSet(FileStatus.SHA1CHDVerified); return; case CHD.CHDManCheck.Corrupt: _bgw.ReportProgress(0, new bgwShowError(filename, error)); tFile.GotStatus = GotStatus.Corrupt; return; case CHD.CHDManCheck.CHDReturnError: case CHD.CHDManCheck.CHDUnknownError: _bgw.ReportProgress(0, new bgwShowError(filename, error)); return; case CHD.CHDManCheck.ChdmanNotFound: return; case CHD.CHDManCheck.CHDNotFound: ReportError.Show("File: " + filename + " Error: Not Found scan Aborted."); _fileErrorAbort = true; return; default: ReportError.UnhandledExceptionHandler(error); return; } }
private static void SetMissingStatus(RvBase dbChild) { if (dbChild.FileRemove() == EFile.Delete) { ReportError.SendAndShow("Error is Set Mssing Status in DatUpdate"); return; } FileType ft = dbChild.FileType; if (ft == FileType.Zip || ft == FileType.Dir) { RvDir dbDir = (RvDir)dbChild; for (int i = 0; i < dbDir.ChildCount; i++) { SetMissingStatus(dbDir.Child(i)); } } }
public static int CompareName(RvBase var1, RvBase var2) { int retv = TrrntZipStringCompare(var1.Name, var2.Name); if (retv != 0) { return(retv); } FileType f1 = var1.FileType; FileType f2 = var2.FileType; if (f1 == FileType.ZipFile) { if (f2 != FileType.ZipFile) { ReportError.SendAndShow("Incompatible Compare type"); } return(Math.Sign(string.Compare(var1.Name, var2.Name, StringComparison.Ordinal))); } return(f1.CompareTo(f2)); }
/* * private static void SetInDat(RvDir tDir) * { * tDir.DatStatus = DatStatus.InDatCollect; * if (tDir.Parent != null) * SetInDat(tDir.Parent); * } */ private static Boolean MergeInDat(RvDir dbDat, RvDir newDat, out RvDat conflict, bool checkOnly) { conflict = null; int dbIndex = 0; int newIndex = 0; while (dbIndex < dbDat.ChildCount || newIndex < newDat.ChildCount) { RvBase dbChild = null; RvBase newDatChild = null; int res = 0; if (dbIndex < dbDat.ChildCount && newIndex < newDat.ChildCount) { dbChild = dbDat.Child(dbIndex); // are files newDatChild = newDat.Child(newIndex); // is from a dat item res = DBHelper.CompareName(dbChild, newDatChild); } else if (newIndex < newDat.ChildCount) { newDatChild = newDat.Child(newIndex); res = 1; } else if (dbIndex < dbDat.ChildCount) { dbChild = dbDat.Child(dbIndex); res = -1; } if (res == 0) { if (dbChild == null || newDatChild == null) { SendAndShowDat(Resources.DatUpdate_MergeInDat_Error_in_Logic, dbDat.FullName); break; } List <RvBase> dbDats = new List <RvBase>(); List <RvBase> newDats = new List <RvBase>(); int dbDatsCount = 1; int newDatsCount = 1; dbDats.Add(dbChild); newDats.Add(newDatChild); while (dbIndex + dbDatsCount < dbDat.ChildCount && DBHelper.CompareName(dbChild, dbDat.Child(dbIndex + dbDatsCount)) == 0) { dbDats.Add(dbDat.Child(dbIndex + dbDatsCount)); dbDatsCount += 1; } while (newIndex + newDatsCount < newDat.ChildCount && DBHelper.CompareName(newDatChild, newDat.Child(newIndex + newDatsCount)) == 0) { newDats.Add(newDat.Child(newIndex + newDatsCount)); newDatsCount += 1; } if (dbDatsCount > 1 || newDatsCount > 1) { ReportError.SendAndShow("Double Name Found"); } for (int indexdb = 0; indexdb < dbDatsCount; indexdb++) { if (dbDats[indexdb].DatStatus == DatStatus.NotInDat) { continue; } if (checkOnly) { conflict = dbChild.Dat; return(true); } SendAndShowDat(Resources.DatUpdate_MergeInDat_Unkown_Update_Dat_Status + dbChild.DatStatus, dbDat.FullName); break; } if (!checkOnly) { for (int indexNewDats = 0; indexNewDats < newDatsCount; indexNewDats++) { if (newDats[indexNewDats].SearchFound) { continue; } for (int indexDbDats = 0; indexDbDats < dbDatsCount; indexDbDats++) { if (dbDats[indexDbDats].SearchFound) { continue; } bool matched = FullCompare(dbDats[indexDbDats], newDats[indexNewDats]); if (!matched) { continue; } dbDats[indexDbDats].DatAdd(newDats[indexNewDats]); FileType ft = dbChild.FileType; if (ft == FileType.Zip || ft == FileType.Dir) { RvDir dChild = (RvDir)dbChild; RvDir dNewChild = (RvDir)newDatChild; MergeInDat(dChild, dNewChild, out conflict, checkOnly); } dbDats[indexDbDats].SearchFound = true; newDats[indexNewDats].SearchFound = true; } } for (int indexNewDats = 0; indexNewDats < newDatsCount; indexNewDats++) { if (newDats[indexNewDats].SearchFound) { continue; } dbDat.ChildAdd(newDats[indexNewDats], dbIndex); dbChild = dbDat.Child(dbIndex); SetMissingStatus(dbChild); dbIndex++; } } dbIndex += dbDatsCount; newIndex += newDatsCount; } if (res == 1) { if (!checkOnly) { dbDat.ChildAdd(newDatChild, dbIndex); dbChild = dbDat.Child(dbIndex); SetMissingStatus(dbChild); dbIndex++; } newIndex++; } if (res == -1) { dbIndex++; } } return(false); }
public static void UpdateDat(object sender, DoWorkEventArgs e) { try { _bgw = sender as BackgroundWorker; if (_bgw == null) { return; } Program.SyncCont = e.Argument as SynchronizationContext; if (Program.SyncCont == null) { _bgw = null; return; } _bgw.ReportProgress(0, new bgwText("Clearing DB Status")); RepairStatus.ReportStatusReset(DB.DirTree); _datCount = 0; _bgw.ReportProgress(0, new bgwText("Finding Dats")); RvDir datRoot = new RvDir(FileType.Dir) { Name = "RomVault", DatStatus = DatStatus.InDatCollect }; // build a datRoot tree of the DAT's in DatRoot, and count how many dats are found if (!RecursiveDatTree(datRoot, out _datCount)) { _bgw.ReportProgress(0, new bgwText("Dat Update Complete")); _bgw = null; Program.SyncCont = null; return; } _bgw.ReportProgress(0, new bgwText("Scanning Dats")); _datsProcessed = 0; // now compare the database DAT's with datRoot removing any old DAT's RemoveOldDats(DB.DirTree.Child(0), datRoot); // next clean up the File status removing any old DAT's RemoveOldDatsCleanUpFiles(DB.DirTree.Child(0)); _bgw.ReportProgress(0, new bgwSetRange(_datCount - 1)); // next add in new DAT and update the files UpdateDatList((RvDir)DB.DirTree.Child(0), datRoot); // finally remove any unneeded DIR's from the TreeView RemoveOldTree(DB.DirTree.Child(0)); _bgw.ReportProgress(0, new bgwText("Updating Cache")); DB.Write(); _bgw.ReportProgress(0, new bgwText("Dat Update Complete")); _bgw = null; Program.SyncCont = null; } catch (Exception exc) { ReportError.UnhandledExceptionHandler(exc); if (_bgw != null) { _bgw.ReportProgress(0, new bgwText("Updating Cache")); } DB.Write(); if (_bgw != null) { _bgw.ReportProgress(0, new bgwText("Complete")); } _bgw = null; Program.SyncCont = null; } }
/// <summary> /// Add the new DAT's into the DAT list /// And merge in the new DAT data into the database /// </summary> /// <param name="dbDir">The Current database dir</param> /// <param name="tmpDir">A temp directory containing the DAT found in this directory in DatRoot</param> private static void AddNewDats(RvDir dbDir, RvDir tmpDir) { bool autoAddDirectory = (tmpDir.DirDatCount) > 1; int dbIndex = 0; int scanIndex = 0; Debug.WriteLine(""); Debug.WriteLine("Scanning for Adding new DATS"); while (dbIndex < dbDir.DirDatCount || scanIndex < tmpDir.DirDatCount) { RvDat dbDat = null; RvDat fileDat = null; int res = 0; if (dbIndex < dbDir.DirDatCount && scanIndex < tmpDir.DirDatCount) { dbDat = dbDir.DirDat(dbIndex); fileDat = tmpDir.DirDat(scanIndex); res = DBHelper.DatCompare(dbDat, fileDat); Debug.WriteLine("Checking " + dbDat.GetData(RvDat.DatData.DatFullName) + " : and " + fileDat.GetData(RvDat.DatData.DatFullName) + " : " + res); } else if (scanIndex < tmpDir.DirDatCount) { fileDat = tmpDir.DirDat(scanIndex); res = 1; Debug.WriteLine("Checking : and " + fileDat.GetData(RvDat.DatData.DatFullName) + " : " + res); } else if (dbIndex < dbDir.DirDatCount) { dbDat = dbDir.DirDat(dbIndex); res = -1; Debug.WriteLine("Checking " + dbDat.GetData(RvDat.DatData.DatFullName) + " : and : " + res); } switch (res) { case 0: _datsProcessed++; _bgw.ReportProgress(_datsProcessed); _bgw.ReportProgress(0, new bgwText("Dat : " + Path.GetFileNameWithoutExtension(fileDat.GetData(RvDat.DatData.DatFullName)))); Debug.WriteLine("Correct"); // Should already be set as correct above dbDat.Status = DatUpdateStatus.Correct; dbIndex++; scanIndex++; break; case 1: _datsProcessed++; _bgw.ReportProgress(_datsProcessed); _bgw.ReportProgress(0, new bgwText("Scanning New Dat : " + Path.GetFileNameWithoutExtension(fileDat.GetData(RvDat.DatData.DatFullName)))); Debug.WriteLine("Adding new DAT"); if (UpdateDatFile(fileDat, autoAddDirectory, dbDir)) { dbIndex++; } scanIndex++; break; case -1: // This should not happen as deleted dat have been removed above //dbIndex++; ReportError.SendAndShow(Resources.DatUpdate_UpdateDatList_ERROR_Deleting_a_DAT_that_should_already_be_deleted); break; } } }
private static bool RecursiveDatTree(RvDir tDir, out int datCount) { datCount = 0; string strPath = tDir.DatFullName; if (!Directory.Exists(strPath)) { ReportError.Show(Resources.DatUpdate_UpdateDatList_Path + strPath + Resources.DatUpdate_UpdateDatList_Not_Found); return(false); } DirectoryInfo oDir = new DirectoryInfo(strPath); FileInfo[] oFilesIn = oDir.GetFiles("*.dat", false); datCount += oFilesIn.Length; foreach (FileInfo file in oFilesIn) { RvDat tDat = new RvDat(); tDat.AddData(RvDat.DatData.DatFullName, file.FullName); tDat.TimeStamp = file.LastWriteTime; tDir.DirDatAdd(tDat); } oFilesIn = oDir.GetFiles("*.xml", false); datCount += oFilesIn.Length; foreach (FileInfo file in oFilesIn) { RvDat tDat = new RvDat(); tDat.AddData(RvDat.DatData.DatFullName, file.FullName); tDat.TimeStamp = file.LastWriteTime; tDir.DirDatAdd(tDat); } if (tDir.DirDatCount > 1) { for (int i = 0; i < tDir.DirDatCount; i++) { tDir.DirDat(i).AutoAddDirectory = true; } } DirectoryInfo[] oSubDir = oDir.GetDirectories(false); foreach (DirectoryInfo t in oSubDir) { RvDir cDir = new RvDir(FileType.Dir) { Name = t.Name, DatStatus = DatStatus.InDatCollect }; int index = tDir.ChildAdd(cDir); int retDatCount; RecursiveDatTree(cDir, out retDatCount); datCount += retDatCount; if (retDatCount == 0) { tDir.ChildRemove(index); } } return(true); }
private void PaintTree(RvDir pTree, Graphics g, Rectangle t) { int y = pTree.Tree.RTree.Top - _vScroll; if (pTree.Tree.RTree.IntersectsWith(t)) { Pen p = new Pen(Brushes.Gray, 1) { DashStyle = DashStyle.Dot }; string lTree = pTree.Tree.TreeBranches; for (int j = 0; j < lTree.Length; j++) { int x = j * 18 - _hScroll; string cTree = lTree.Substring(j, 1); switch (cTree) { case "│": g.DrawLine(p, x + 9, y, x + 9, y + 16); break; case "├": case "└": g.DrawLine(p, x + 9, y, x + 9, y + 16); g.DrawLine(p, x + 9, y + 16, x + 27, y + 16); break; } } } if (!pTree.Tree.RExpand.IsEmpty) { if (pTree.Tree.RExpand.IntersectsWith(t)) { g.DrawImage(pTree.Tree.TreeExpanded ? rvImages.ExpandBoxMinus : rvImages.ExpandBoxPlus, RSub(pTree.Tree.RExpand, _hScroll, _vScroll)); } } if (pTree.Tree.RChecked.IntersectsWith(t)) { switch (pTree.Tree.Checked) { case RvTreeRow.TreeSelect.Disabled: g.DrawImage(rvImages.TickBoxDisabled, RSub(pTree.Tree.RChecked, _hScroll, _vScroll)); break; case RvTreeRow.TreeSelect.UnSelected: g.DrawImage(rvImages.TickBoxUnTicked, RSub(pTree.Tree.RChecked, _hScroll, _vScroll)); break; case RvTreeRow.TreeSelect.Selected: g.DrawImage(rvImages.TickBoxTicked, RSub(pTree.Tree.RChecked, _hScroll, _vScroll)); break; } } if (pTree.Tree.RIcon.IntersectsWith(t)) { int icon = 2; if (pTree.DirStatus.HasInToSort()) { icon = 4; } else if (!pTree.DirStatus.HasCorrect()) { icon = 1; } else if (!pTree.DirStatus.HasMissing()) { icon = 3; } Bitmap bm; if (pTree.Dat == null && pTree.DirDatCount != 1) // Directory above DAT's in Tree { bm = rvImages.GetBitmap("DirectoryTree" + icon); } else if (pTree.Dat == null && pTree.DirDatCount == 1) // Directory that contains DAT's { bm = rvImages.GetBitmap("Tree" + icon); } else if (pTree.Dat != null && pTree.DirDatCount == 0) // Directories made by a DAT { bm = rvImages.GetBitmap("Tree" + icon); } else { ReportError.SendAndShow("Unknown Tree settings in DisplayTree."); bm = null; } if (bm != null) { g.DrawImage(bm, RSub(pTree.Tree.RIcon, _hScroll, _vScroll)); } } Rectangle recBackGround = new Rectangle(pTree.Tree.RText.X, pTree.Tree.RText.Y, Width - pTree.Tree.RText.X + _hScroll, pTree.Tree.RText.Height); if (recBackGround.IntersectsWith(t)) { string thistxt; if (pTree.Dat == null && pTree.DirDatCount != 1) // Directory above DAT's in Tree { thistxt = pTree.Name; } else if (pTree.Dat == null && pTree.DirDatCount == 1) // Directory that contains DAT's { thistxt = pTree.Name + ": " + pTree.DirDat(0).GetData(RvDat.DatData.Description) + " ( Have:" + pTree.DirStatus.CountCorrect() + " \\ Missing: " + pTree.DirStatus.CountMissing() + " )"; } // pTree.Parent.DirDatCount>1: This should probably be a test like parent contains Dat else if (pTree.Dat != null && pTree.Dat.AutoAddDirectory && pTree.Parent.DirDatCount > 1) { thistxt = pTree.Name + ": " + pTree.Dat.GetData(RvDat.DatData.Description) + " ( Have:" + pTree.DirStatus.CountCorrect() + " \\ Missing: " + pTree.DirStatus.CountMissing() + " )"; } else if (pTree.Dat != null && pTree.DirDatCount == 0) // Directories made by a DAT { thistxt = pTree.Name + " ( Have:" + pTree.DirStatus.CountCorrect() + " \\ Missing: " + pTree.DirStatus.CountMissing() + " )"; } else { ReportError.SendAndShow("Unknown Tree settings in DisplayTree."); thistxt = ""; } if (_lSelected != null && pTree.TreeFullName == _lSelected.TreeFullName) { g.FillRectangle(new SolidBrush(Color.FromArgb(51, 153, 255)), RSub(recBackGround, _hScroll, _vScroll)); g.DrawString(thistxt, new Font("Microsoft Sans Serif", 8), Brushes.White, pTree.Tree.RText.Left - _hScroll, pTree.Tree.RText.Top + 1 - _vScroll); } else { g.DrawString(thistxt, new Font("Microsoft Sans Serif", 8), Brushes.Black, pTree.Tree.RText.Left - _hScroll, pTree.Tree.RText.Top + 1 - _vScroll); } } if (pTree.Tree.TreeExpanded) { for (int i = 0; i < pTree.ChildCount; i++) { RvBase tBase = pTree.Child(i); if (tBase is RvDir) { RvDir tDir = (RvDir)tBase; if (tDir.Tree != null) { PaintTree(tDir, g, t); } } } } }
public static void Compare(RvDir dbDir, RvDir fileDir, bool report, bool enableCancel) { string fullDir = dbDir.FullName; FileType ft = dbDir.FileType; // now we scan down the dbDir and the scanDir, comparing them. // if we find a match we mark dbDir as found. // if we are missing a file in scanDir we mark that file in dbDir as missing. // if we find extra files in scanDir we add it to dbDir and mark it as unknown. // we also recurse into any sub directories. int dbIndex = 0; int fileIndex = 0; while (dbIndex < dbDir.ChildCount || fileIndex < fileDir.ChildCount) { RvBase dbChild = null; RvBase fileChild = null; int res = 0; if (dbIndex < dbDir.ChildCount && fileIndex < fileDir.ChildCount) { dbChild = dbDir.Child(dbIndex); fileChild = fileDir.Child(fileIndex); res = DBHelper.CompareName(dbChild, fileChild); } else if (fileIndex < fileDir.ChildCount) { //Get any remaining filedir's fileChild = fileDir.Child(fileIndex); res = 1; } else if (dbIndex < dbDir.ChildCount) { //Get any remaining dbDir's dbChild = dbDir.Child(dbIndex); res = -1; } if (report) { if (fileChild != null) { long timenow = DateTime.Now.Ticks; if ((timenow - _lastUpdateTime) > (TimeSpan.TicksPerSecond / 10)) { _lastUpdateTime = timenow; _bgw.ReportProgress(0, new bgwValue2(fileIndex)); _bgw.ReportProgress(0, new bgwText2(Path.Combine(fullDir, fileChild.Name))); } } } // if this file was found in the DB switch (res) { case 0: if (dbChild == null || fileChild == null) { ReportError.SendAndShow(Resources.FileScanning_CheckADir_Error_in_File_Scanning_Code); break; } //Complete MultiName Compare List <RvBase> dbs = new List <RvBase>(); List <RvBase> files = new List <RvBase>(); int dbsCount = 1; int filesCount = 1; dbs.Add(dbChild); files.Add(fileChild); while (dbIndex + dbsCount < dbDir.ChildCount && DBHelper.CompareName(dbChild, dbDir.Child(dbIndex + dbsCount)) == 0) { dbs.Add(dbDir.Child(dbIndex + dbsCount)); dbsCount += 1; } while (fileIndex + filesCount < fileDir.ChildCount && DBHelper.CompareName(fileChild, fileDir.Child(fileIndex + filesCount)) == 0) { files.Add(fileDir.Child(fileIndex + filesCount)); filesCount += 1; } for (int indexfile = 0; indexfile < filesCount; indexfile++) { if (files[indexfile].SearchFound) { continue; } for (int indexdb = 0; indexdb < dbsCount; indexdb++) { if (dbs[indexdb].SearchFound) { continue; } bool matched = FullCompare(dbs[indexdb], files[indexfile], false, fullDir, EScanLevel); if (!matched) { continue; } MatchFound(dbs[indexdb], files[indexfile]); dbs[indexdb].SearchFound = true; files[indexfile].SearchFound = true; } if (files[indexfile].SearchFound) { continue; } for (int indexdb = 0; indexdb < dbsCount; indexdb++) { if (dbs[indexdb].SearchFound) { continue; } bool matched = FullCompare(dbs[indexdb], files[indexfile], true, fullDir, EScanLevel); if (!matched) { continue; } MatchFound(dbs[indexdb], files[indexfile]); dbs[indexdb].SearchFound = true; files[indexfile].SearchFound = true; } } for (int indexdb = 0; indexdb < dbsCount; indexdb++) { if (dbs[indexdb].SearchFound) { dbIndex++; continue; } DBFileNotFound(dbs[indexdb], dbDir, ref dbIndex); } for (int indexfile = 0; indexfile < filesCount; indexfile++) { if (files[indexfile].SearchFound) { continue; } NewFileFound(files[indexfile], dbDir, dbIndex); dbIndex++; } fileIndex += filesCount; break; case 1: NewFileFound(fileChild, dbDir, dbIndex); dbIndex++; fileIndex++; break; case -1: DBFileNotFound(dbChild, dbDir, ref dbIndex); break; } if (_fileErrorAbort) { return; } if (enableCancel && !DBTypeGet.isCompressedDir(ft) && _bgw.CancellationPending) { return; } } }
public static void ScanFiles(object sender, DoWorkEventArgs e) { #if !Debug try { #endif _fileErrorAbort = false; _cacheSaveTimer = new Stopwatch(); _cacheSaveTimer.Reset(); if (Settings.CacheSaveTimerEnabled) { _cacheSaveTimer.Start(); } _bgw = sender as BackgroundWorker; if (_bgw == null) { return; } Program.SyncCont = e.Argument as SynchronizationContext; if (Program.SyncCont == null) { _bgw = null; return; } _bgw.ReportProgress(0, new bgwText("Clearing DB Status")); RepairStatus.ReportStatusReset(DB.DirTree); _bgw.ReportProgress(0, new bgwText("Finding Dir's to Scan")); //Next get a list of all the directories to be scanned List <RvDir> lstDir = new List <RvDir>(); DBHelper.GetSelectedDirList(ref lstDir); _bgw.ReportProgress(0, new bgwText("Scanning Dir's")); _bgw.ReportProgress(0, new bgwSetRange(lstDir.Count - 1)); //Scan the list of directories. for (int i = 0; i < lstDir.Count; i++) { _bgw.ReportProgress(i); _bgw.ReportProgress(0, new bgwText("Scanning Dir : " + lstDir[i].FullName)); string lDir = lstDir[i].FullName; Console.WriteLine(lDir); if (Directory.Exists(lDir)) { CheckADir(lstDir[i], true); } else { MarkAsMissing(lstDir[i]); } if (_bgw.CancellationPending || _fileErrorAbort) { break; } } _bgw.ReportProgress(0, new bgwText("Updating Cache")); DB.Write(); _bgw.ReportProgress(0, new bgwText("File Scan Complete")); _bgw = null; Program.SyncCont = null; #if !Debug } catch (Exception exc) { ReportError.UnhandledExceptionHandler(exc); if (_bgw != null) { _bgw.ReportProgress(0, new bgwText("Updating Cache")); } DB.Write(); if (_bgw != null) { _bgw.ReportProgress(0, new bgwText("Complete")); } _bgw = null; Program.SyncCont = null; } #endif }
private static void CheckADir(RvDir dbDir, bool report) { if (_cacheSaveTimer.Elapsed.TotalMinutes > Settings.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: { fileDir = new RvDir(ft); // open the zip file ZipFile checkZ = new ZipFile(); 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 ".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); }
private static void ListCheckSHA1CHD(List <RvFile> lstRomTableSortedSHA1CHD, int start, int length) { if (lstRomTableSortedSHA1CHD.Count == 0) { return; } List <RvFile> missingFiles = new List <RvFile>(); // files we done have have that we need List <RvFile> correctFiles = new List <RvFile>(); // files we have that are in the correct place List <RvFile> unNeededFiles = new List <RvFile>(); // files we have that are not in the correct place List <RvFile> inToSortFiles = new List <RvFile>(); // files we have that are in tosort List <RvFile> allGotFiles = new List <RvFile>(); // all files we have List <RvFile> corruptFiles = new List <RvFile>(); // corrupt files that we do not need, a corrupt file is missing if it is needed // set the found status of this file for (int iLoop = 0; iLoop < length; iLoop++) { RvFile tFile = lstRomTableSortedSHA1CHD[start + iLoop]; switch (tFile.RepStatus) { case RepStatus.Missing: missingFiles.Add(tFile); // these are checked in step 1 to fixes from the allGotFiles List. break; case RepStatus.Correct: correctFiles.Add(tFile); break; case RepStatus.Corrupt: case RepStatus.MoveToCorrupt: if (tFile.DatStatus == DatStatus.InDatCollect) { missingFiles.Add(tFile); // corrupt files that are also InDatcollect are treated as missing files, and a fix should be found. } else { corruptFiles.Add(tFile); // all other corrupt files should be deleted or moved to tosort/corrupt } break; case RepStatus.UnNeeded: case RepStatus.Unknown: case RepStatus.MoveToSort: case RepStatus.InToSort: case RepStatus.Delete: case RepStatus.NeededForFix: case RepStatus.Rename: if (tFile.IsInToSort) { inToSortFiles.Add(tFile); } else { unNeededFiles.Add(tFile); } break; case RepStatus.NotCollected: break; case RepStatus.Ignore: break; // Ignore File default: ReportError.SendAndShow(Resources.FindFixes_ListCheck_Unknown_test_status + tFile.DatFullName + Resources.Comma + tFile.DatStatus + Resources.Comma + tFile.RepStatus); break; } } allGotFiles.AddRange(correctFiles); allGotFiles.AddRange(unNeededFiles); allGotFiles.AddRange(inToSortFiles); #region Step 1 Check the Missing files from the allGotFiles List. // check to see if we can find any of the missing files in the gotFiles list. // if we find them mark them as CanBeFixed, foreach (RvFile missingFile in missingFiles) { if (allGotFiles.Count > 0) { missingFile.RepStatus = (missingFile.RepStatus == RepStatus.Corrupt) || (missingFile.RepStatus == RepStatus.MoveToCorrupt) ? RepStatus.CorruptCanBeFixed : RepStatus.CanBeFixed; } } #endregion #region Step 2 Check all corrupt files. // if we have a correct version of the corrupt file then the corrput file can just be deleted, // otherwise if the corrupt file is not already in ToSort it should be moved out to ToSort. // we can only check corrupt files using the CRC from the ZIP header, as it is corrupt so we cannot get a correct SHA1 / MD5 to check with foreach (RvFile corruptFile in corruptFiles) { if (allGotFiles.Count > 0) { corruptFile.RepStatus = RepStatus.Delete; } if ((corruptFile.RepStatus == RepStatus.Corrupt) && (corruptFile.DatStatus != DatStatus.InToSort)) { corruptFile.RepStatus = RepStatus.MoveToCorrupt; } } #endregion #region Step 3 Check if unNeeded files are needed for a fix, otherwise delete them or move them to tosort foreach (RvFile unNeededFile in unNeededFiles) { // check if the unNeededFile is needed to fix a missing file if (missingFiles.Count > 0) { unNeededFile.RepStatus = RepStatus.NeededForFix; continue; } // now that we know this file is not needed for a fix if we have a correct version of it, it can be deleted. if (correctFiles.Count > 0) { // this probably should check its old state if (unNeededFile.RepStatus != RepStatus.NeededForFix) { unNeededFile.RepStatus = RepStatus.Delete; } continue; } if (inToSortFiles.Count > 0) { if (unNeededFile.RepStatus != RepStatus.NeededForFix) { unNeededFile.RepStatus = RepStatus.Delete; } continue; } // otherwise move the file out to ToSort if (unNeededFile.RepStatus != RepStatus.NeededForFix) { unNeededFile.RepStatus = RepStatus.MoveToSort; } } #endregion #region Step 4 Check if ToSort files are needed for a fix, otherwise delete them or leave them in tosort foreach (RvFile inToSortFile in inToSortFiles) { // check if the ToSortFile is needed to fix a missing file if (missingFiles.Count > 0) { inToSortFile.RepStatus = RepStatus.NeededForFix; continue; } // now that we know this file is not needed for a fix do a CRC only find against correct files to see if this file can be deleted. if (correctFiles.Count <= 0) { continue; } if (inToSortFile.RepStatus != RepStatus.NeededForFix) { inToSortFile.RepStatus = RepStatus.Delete; } // otherwise leave the file in ToSort } #endregion }
public static void ScanFiles(object sender, DoWorkEventArgs e) { try { _bgw = sender as BackgroundWorker; if (_bgw == null) { return; } Program.SyncCont = e.Argument as SynchronizationContext; if (Program.SyncCont == null) { _bgw = null; return; } _bgw.ReportProgress(0, new bgwText("Clearing DB Status")); RepairStatus.ReportStatusReset(DB.DirTree); List <RvFile> lstRomTableSortedCRCSize; List <RvFile> lstRomTableSortedSHA1CHD; _bgw.ReportProgress(0, new bgwText("Loading Rom List")); DBHelper.GetSelectedFilesSortCRCSize(out lstRomTableSortedCRCSize); DBHelper.GetSelectedFilesSortSHA1CHD(out lstRomTableSortedSHA1CHD); _bgw.ReportProgress(0, new bgwText("Scanning for Fixes")); _bgw.ReportProgress(0, new bgwSetRange(lstRomTableSortedCRCSize.Count)); int romIndex0 = 0; int romIndex1 = 1; while (romIndex1 < lstRomTableSortedCRCSize.Count) { if (romIndex1 % 100 == 0) { _bgw.ReportProgress(romIndex1); } if (!ArrByte.bCompare(lstRomTableSortedCRCSize[romIndex0].CRC, lstRomTableSortedCRCSize[romIndex1].CRC) || (lstRomTableSortedCRCSize[romIndex0].Size != lstRomTableSortedCRCSize[romIndex1].Size)) { ListCheck(lstRomTableSortedCRCSize, romIndex0, romIndex1 - romIndex0); romIndex0 = romIndex1; } romIndex1++; } ListCheck(lstRomTableSortedCRCSize, romIndex0, romIndex1 - romIndex0); _bgw.ReportProgress(0, new bgwSetRange(lstRomTableSortedSHA1CHD.Count)); romIndex0 = 0; romIndex1 = 1; while (romIndex1 < lstRomTableSortedSHA1CHD.Count) { if (romIndex1 % 100 == 0) { _bgw.ReportProgress(romIndex1); } if (!ArrByte.bCompare(lstRomTableSortedSHA1CHD[romIndex0].SHA1CHD, lstRomTableSortedSHA1CHD[romIndex1].SHA1CHD)) { ListCheckSHA1CHD(lstRomTableSortedSHA1CHD, romIndex0, romIndex1 - romIndex0); romIndex0 = romIndex1; } romIndex1++; } ListCheckSHA1CHD(lstRomTableSortedSHA1CHD, romIndex0, romIndex1 - romIndex0); _bgw = null; Program.SyncCont = null; } catch (Exception exc) { ReportError.UnhandledExceptionHandler(exc); if (_bgw != null) { _bgw.ReportProgress(0, new bgwText("Updating Cache")); } DB.Write(); if (_bgw != null) { _bgw.ReportProgress(0, new bgwText("Complete")); } _bgw = null; Program.SyncCont = null; } }
public static void ListCheck(List <RvFile> lstRomTableSortedCRC, int start, int length) { if (lstRomTableSortedCRC.Count == 0) { return; } List <RvFile> missingFiles = new List <RvFile>(); // files we dont have that we need List <RvFile> correctFiles = new List <RvFile>(); // files we have that are in the correct place List <RvFile> unNeededFiles = new List <RvFile>(); // files we have that are not in the correct place List <RvFile> inToSortFiles = new List <RvFile>(); // files we have that are in tosort List <RvFile> allGotFiles = new List <RvFile>(); // all files we have List <RvFile> corruptFiles = new List <RvFile>(); // corrupt files that we do not need, a corrupt file is missing if it is needed // set the found status of this file for (int iLoop = 0; iLoop < length; iLoop++) { RvFile tFile = lstRomTableSortedCRC[start + iLoop]; switch (tFile.RepStatus) { case RepStatus.UnScanned: break; case RepStatus.Missing: missingFiles.Add(tFile); // these are checked in step 1 to fixes from the allGotFiles List. break; case RepStatus.Correct: correctFiles.Add(tFile); break; case RepStatus.Corrupt: if (tFile.DatStatus == DatStatus.InDatCollect) { missingFiles.Add(tFile); // corrupt files that are also InDatcollect are treated as missing files, and a fix should be found. } else { corruptFiles.Add(tFile); // all other corrupt files should be deleted or moved to tosort/corrupt } break; case RepStatus.UnNeeded: case RepStatus.Unknown: unNeededFiles.Add(tFile); break; case RepStatus.NotCollected: break; case RepStatus.InToSort: inToSortFiles.Add(tFile); break; case RepStatus.Ignore: break; // Ignore File default: ReportError.SendAndShow(Resources.FindFixes_ListCheck_Unknown_test_status + tFile.DatFullName + Resources.Comma + tFile.DatStatus + Resources.Comma + tFile.RepStatus); break; } } allGotFiles.AddRange(correctFiles); allGotFiles.AddRange(unNeededFiles); allGotFiles.AddRange(inToSortFiles); #region Step 1 Check the Missing files from the allGotFiles List. // check to see if we can find any of the missing files in the gotFiles list. // if we find them mark them as CanBeFixed, // or if they are missing corrupt files set then as corruptCanBefixed foreach (RvFile missingFile in missingFiles) { if (DBHelper.IsZeroLengthFile(missingFile)) { missingFile.RepStatus = missingFile.RepStatus == RepStatus.Corrupt ? RepStatus.CorruptCanBeFixed : RepStatus.CanBeFixed; continue; } foreach (RvFile gotFile in allGotFiles) { if (!CheckIfMissingFileCanBeFixedByGotFile(missingFile, gotFile)) { continue; } missingFile.RepStatus = missingFile.RepStatus == RepStatus.Corrupt ? RepStatus.CorruptCanBeFixed : RepStatus.CanBeFixed; break; } if (missingFile.RepStatus == RepStatus.Corrupt) { missingFile.RepStatus = RepStatus.MoveToCorrupt; } } #endregion #region Step 2 Check all corrupt files. // if we have a correct version of the corrupt file then the corrput file can just be deleted, // otherwise if the corrupt file is not already in ToSort it should be moved out to ToSort. // we can only check corrupt files using the CRC from the ZIP header, as it is corrupt so we cannot get a correct SHA1 / MD5 to check with foreach (RvFile corruptFile in corruptFiles) { if (allGotFiles.Count > 0) { corruptFile.RepStatus = RepStatus.Delete; } if ((corruptFile.RepStatus == RepStatus.Corrupt) && (corruptFile.DatStatus != DatStatus.InToSort)) { corruptFile.RepStatus = RepStatus.MoveToCorrupt; } } #endregion #region Step 3 Check if unNeeded files are needed for a fix, otherwise delete them or move them to tosort foreach (RvFile unNeededFile in unNeededFiles) { /* * // check if we have a confirmed SHA1 / MD5 match of this file, and if we do we just mark this file to be deleted. * foreach (RvFile correctFile in correctFiles) * { * if (!FindSHA1MD5MatchingFiles(unNeededFile, correctFile)) continue; * unNeededFile.RepStatus = RepStatus.Delete; * break; * } * if (unNeededFile.RepStatus == RepStatus.Delete) continue; */ if (DBHelper.IsZeroLengthFile(unNeededFile)) { unNeededFile.RepStatus = RepStatus.Delete; continue; } // check if the unNeededFile is needed to fix a missing file foreach (RvFile missingFile in missingFiles) { if (!CheckIfMissingFileCanBeFixedByGotFile(missingFile, unNeededFile)) { continue; } unNeededFile.RepStatus = RepStatus.NeededForFix; break; } if (unNeededFile.RepStatus == RepStatus.NeededForFix) { continue; } // now that we know this file is not needed for a fix do a CRC only find against correct files to see if this file can be deleted. foreach (RvFile correctFile in correctFiles) { if (!CheckIfGotfileAndMatchingFileAreFullMatches(unNeededFile, correctFile)) { continue; } unNeededFile.RepStatus = RepStatus.Delete; break; } if (unNeededFile.RepStatus == RepStatus.Delete) { continue; } // and finally see if the file is already in ToSort, and if it is deleted. foreach (RvFile inToSortFile in inToSortFiles) { if (!CheckIfGotfileAndMatchingFileAreFullMatches(unNeededFile, inToSortFile)) { continue; } unNeededFile.RepStatus = RepStatus.Delete; break; } if (unNeededFile.RepStatus == RepStatus.Delete) { continue; } // otherwise move the file out to ToSort unNeededFile.RepStatus = RepStatus.MoveToSort; } #endregion #region Step 4 Check if ToSort files are needed for a fix, otherwise delete them or leave them in tosort foreach (RvFile inToSortFile in inToSortFiles) { /* * // check if we have a confirmed SHA1 / MD5 match of this file, and if we do we just mark this file to be deleted. * foreach (RvFile correctFile in correctFiles) * { * if (!FindSHA1MD5MatchingFiles(inToSortFile, correctFile)) continue; * inToSortFile.RepStatus = RepStatus.Delete; * break; * } * if (inToSortFile.RepStatus == RepStatus.Delete) continue; */ // check if the ToSortFile is needed to fix a missing file foreach (RvFile missingFile in missingFiles) { if (!CheckIfMissingFileCanBeFixedByGotFile(missingFile, inToSortFile)) { continue; } inToSortFile.RepStatus = RepStatus.NeededForFix; break; } if (inToSortFile.RepStatus == RepStatus.NeededForFix) { continue; } // now that we know this file is not needed for a fix do a CRC only find against correct files to see if this file can be deleted. foreach (RvFile correctFile in correctFiles) { if (!CheckIfGotfileAndMatchingFileAreFullMatches(inToSortFile, correctFile)) { continue; } inToSortFile.RepStatus = RepStatus.Delete; break; } // otherwise leave the file in ToSort } #endregion //need to check here for roms that just need renamed inside the one ZIP //this prevents Zips from self deadlocking for (int iLoop0 = 0; iLoop0 < length; iLoop0++) { if (lstRomTableSortedCRC[start + iLoop0].RepStatus != RepStatus.NeededForFix) { continue; } for (int iLoop1 = 0; iLoop1 < length; iLoop1++) { if (lstRomTableSortedCRC[start + iLoop1].RepStatus != RepStatus.CanBeFixed) { continue; } if (!CheckIfMissingFileCanBeFixedByGotFile(lstRomTableSortedCRC[start + iLoop1], lstRomTableSortedCRC[start + iLoop0])) { continue; } if (DBHelper.RomFromSameGame(lstRomTableSortedCRC[start + iLoop0], lstRomTableSortedCRC[start + iLoop1])) { lstRomTableSortedCRC[start + iLoop0].RepStatus = RepStatus.Rename; } } } }