Ignore:
Timestamp:
11/10/2008 12:27:47 AM (5 years ago)
Author:
lowjoel
Message:

Implemented Recycle Bin erasure: modified patch by cjax (Kasra Nassiri)

File:
1 edited

Legend:

Unmodified
Added
Removed
  • branches/eraser6/Manager/DirectExecutor.cs

    r482 r485  
    33 * Copyright 2008 The Eraser Project 
    44 * Original Author: Joel Low <lowjoel@users.sourceforge.net> 
    5  * Modified By: 
     5 * Modified By: Kasra Nassiri <cjax@users.sourceforge.net> @17/10/2008 
     6 * Modified By:  
    67 *  
    78 * This file is part of Eraser. 
     
    251252                        //Check if the task is recurring. If it is, check if we missed it. 
    252253                        if (currentTask.Schedule is RecurringSchedule) 
    253                             ScheduleTask(currentTask);   
     254                            ScheduleTask(currentTask); 
    254255                    } 
    255256 
     
    313314                                else if (target is Task.FilesystemObject) 
    314315                                    EraseFilesystemObject(task, (Task.FilesystemObject)target, progress); 
    315                                 else if (target is Task.RecycleBin) 
    316                                     EraseRecycleBin(task, (Task.RecycleBin)target); 
    317316                                else 
    318317                                    throw new ArgumentException("Unknown erasure target."); 
     
    413412        } 
    414413 
    415         public static List<string> GetFiles(DirectoryInfo root) 
    416         {            
    417             List<string> files = new List<string>(); 
    418  
    419             foreach (FileSystemInfo fsInfo in root.GetFileSystemInfos()) 
    420                 try 
    421                 { 
    422                     if (fsInfo is FileInfo) 
    423                     { 
    424                         FileInfo file = (FileInfo)fsInfo; 
    425                         if (Eraser.Util.File.IsProtectedSystemFile(file.FullName)) 
    426                             ; 
    427                         else 
    428                         { 
    429                             foreach (string i in Util.File.GetADSes(file)) 
    430                                 files.Add(file.FullName + ':' + i); 
    431  
    432                             files.Add(file.FullName); 
    433                         } 
    434                     } 
    435                     else if (fsInfo is DirectoryInfo) 
    436                     { 
    437                         DirectoryInfo dir = (DirectoryInfo)fsInfo; 
    438                         foreach (DirectoryInfo subDir in dir.GetDirectories()) 
    439                             files.AddRange(GetFiles(subDir)); 
    440                     } 
    441                 } 
    442                 catch (UnauthorizedAccessException) 
    443                 { 
    444                 } 
    445                 catch (IOException) 
    446                 { 
    447                 } 
    448             return files; 
    449         } 
    450  
    451414        /// <summary> 
    452415        /// Executes a unused space erase. 
     
    533496                            GenerateRandomFileName(18); 
    534497                    while (System.IO.File.Exists(currFile)); 
    535                      
     498 
    536499                    //Create the stream 
    537500                    using (FileStream stream = new FileStream(currFile, 
     
    540503                        //Set the length of the file to be the amount of free space left 
    541504                        //or the maximum size of one of these dumps. 
    542                         stream.SetLength(Math.Min(ErasureMethod.FreeSpaceFileUnit, 
    543                             volInfo.AvailableFreeSpace)); 
     505                        long streamLength = Math.Min(ErasureMethod.FreeSpaceFileUnit, 
     506                            volInfo.AvailableFreeSpace); 
     507 
     508                        //Handle IO exceptions gracefully, because the filesystem 
     509                        //may require more space than demanded by us for file allocation. 
     510                        while (true) 
     511                            try 
     512                            { 
     513                                stream.SetLength(streamLength); 
     514                                break; 
     515                            } 
     516                            catch (IOException) 
     517                            { 
     518                                long amountToReduce = 32 * volInfo.ClusterSize; 
     519                                if (streamLength > amountToReduce) 
     520                                    streamLength -= amountToReduce; 
     521                                else 
     522                                    throw; 
     523                            } 
    544524 
    545525                        //Then run the erase task 
     
    586566                RemoveFolder(info); 
    587567            } 
    588              
     568 
    589569            //new NotImplementedException(): clear directory entries: Eraser.cpp@2348 
    590570        } 
     
    593573        private delegate void ClusterTipsEraseProgress(int currentFile, 
    594574            string currentFilePath, int totalFiles); 
    595         private delegate void threadPoolHandler(ThreadPoolArgs args); 
    596  
    597         struct ThreadPoolArgs 
    598         { 
    599             public ThreadPoolArgs(Task _task, String _file, 
    600                 ErasureMethod _method, 
    601                 ClusterTipsEraseProgress _callBack) 
    602             { 
    603                 task = _task; 
    604                 file = _file; 
    605                 method = _method; 
    606                 callBack = _callBack; 
    607             } 
    608  
    609             public Task task; 
    610             public String file; 
    611             public ErasureMethod method; 
    612             public ClusterTipsEraseProgress callBack; 
    613                          
    614             public static void resetPool() 
    615             { 
    616                 ObjectCount = TObjectCount = Mapped = 0; 
    617             } 
    618  
    619             public static long Mapped = 0; 
    620             public static long TObjectCount = 0; 
    621             public static long ObjectCount = 0; 
    622             public static object ThreadLock = new object(); 
    623             public static EventWaitHandle Handle = new AutoResetEvent(true); 
    624         } 
    625          
     575 
    626576        private static void EraseClusterTips(Task task, Task.UnusedSpace target, 
    627577            ErasureMethod method, ClusterTipsEraseProgress callback) 
     
    633583            subFolders = delegate(DirectoryInfo info) 
    634584            { 
    635                 foreach (FileSystemInfo fsInfo in info.GetFileSystemInfos()) 
    636585                try 
    637586                { 
    638                     if (fsInfo is FileInfo) 
    639                     { 
    640                         FileInfo file = (FileInfo)fsInfo; 
     587                    foreach (FileInfo file in info.GetFiles()) 
    641588                        if (Eraser.Util.File.IsProtectedSystemFile(file.FullName)) 
    642                             task.Log.Add(new LogEntry(string.Format("\"{0}\" did not have its cluster tips " + 
    643                                 "erased, because it is a protected system file", file.FullName), LogLevel.INFORMATION)); 
     589                            task.Log.Add(new LogEntry(string.Format("{0} did not have its cluster tips " + 
     590                                "erased, because it is a system file", file.FullName), LogLevel.INFORMATION)); 
    644591                        else 
    645592                        { 
     
    649596                            files.Add(file.FullName); 
    650597                        } 
    651                     } 
    652                     else if (fsInfo is DirectoryInfo) 
    653                     { 
    654                         DirectoryInfo dir = (DirectoryInfo)fsInfo; 
    655                         foreach (DirectoryInfo subDir in dir.GetDirectories()) 
    656                             subFolders(subDir); 
    657                     } 
    658                     else 
    659                         throw new NotImplementedException("Unknown FileSystemInfo type"); 
     598 
     599                    foreach (DirectoryInfo subDirInfo in info.GetDirectories()) 
     600                        subFolders(subDirInfo); 
    660601                } 
    661602                catch (UnauthorizedAccessException e) 
    662603                { 
    663                     task.Log.Add(new LogEntry(string.Format("\"{0}\" did not have its cluster tips erased because of " + 
    664                         ": {1}", info.FullName, e.Message), LogLevel.ERROR)); 
     604                    task.Log.Add(new LogEntry(string.Format("{0} did not have its cluster tips erased because of " + 
     605                        "the following error: {1}", info.FullName, e.Message), LogLevel.ERROR)); 
    665606                } 
    666607                catch (IOException e) 
    667608                { 
    668                     task.Log.Add(new LogEntry(string.Format("\"{0}\" did not have its cluster tips erased because of " + 
    669                         ": {1}", info.FullName, e.Message), LogLevel.ERROR)); 
     609                    task.Log.Add(new LogEntry(string.Format("{0} did not have its cluster tips erased because of " + 
     610                        "the following error: {1}", info.FullName, e.Message), LogLevel.ERROR)); 
    670611                } 
    671612            }; 
    672      
     613 
    673614            subFolders(new DirectoryInfo(target.Drive)); 
    674             ThreadPoolArgs.Handle.WaitOne(); 
    675  
    676  
    677             foreach (string file in files) 
    678                 EraseClusterTips(task, target, method, callback); 
    679  
     615 
     616            //For every file, erase the cluster tips. 
     617            for (int i = 0, j = files.Count; i != j; ++i) 
     618            { 
     619                try 
     620                { 
     621                    EraseFileClusterTips(files[i], method); 
     622                } 
     623                catch (Exception e) 
     624                { 
     625                    task.Log.Add(new LogEntry(string.Format("{0} did not have its cluster tips " + 
     626                        "erased. The error returned was: {1}", files[i], e.Message), LogLevel.ERROR)); 
     627                } 
     628                callback(i, files[i], files.Count); 
     629            } 
    680630        } 
    681631 
    682632        /// <summary> 
    683633        /// Erases the cluster tips of the given file. 
    684         /// This method is used for thread-pool tests 
    685634        /// </summary> 
    686635        /// <param name="file">The file to erase.</param> 
    687636        /// <param name="method">The erasure method to use.</param> 
    688         private static void EraseFileClusterTips(object args) 
    689         { 
    690             lock (ThreadPoolArgs.ThreadLock) 
    691             { 
    692                 ThreadPoolArgs arguments = (ThreadPoolArgs)args; 
     637        private static void EraseFileClusterTips(string file, ErasureMethod method) 
     638        { 
     639            //Get the file access times 
     640            StreamInfo streamInfo = new StreamInfo(file); 
     641            DateTime lastAccess = DateTime.MinValue, lastWrite = DateTime.MinValue, 
     642                     created = DateTime.MinValue; 
     643            { 
     644                FileInfo info = streamInfo.File; 
     645                if (info != null) 
     646                { 
     647                    lastAccess = info.LastAccessTime; 
     648                    lastWrite = info.LastWriteTime; 
     649                    created = info.CreationTime; 
     650                } 
     651            } 
     652 
     653            //Create the stream, lengthen the file, then tell the erasure method 
     654            //to erase the tips. 
     655            using (FileStream stream = streamInfo.Open(FileMode.Open, FileAccess.Write)) 
     656            { 
     657                long fileLength = stream.Length; 
     658                long fileArea = GetFileArea(file); 
    693659 
    694660                try 
    695661                { 
    696                     //Get the file access times 
    697                     StreamInfo streamInfo = new StreamInfo(arguments.file); 
    698                     DateTime lastAccess = DateTime.MinValue, lastWrite = DateTime.MinValue, 
    699                              created = DateTime.MinValue; 
    700                     { 
    701                         FileInfo info = streamInfo.File; 
    702                         if (info != null) 
    703                         { 
    704                             lastAccess = info.LastAccessTime; 
    705                             lastWrite = info.LastWriteTime; 
    706                             created = info.CreationTime; 
    707                         } 
    708                     } 
    709  
    710                     //Create the stream, lengthen the file, then tell the erasure method 
    711                     //to erase the tips. 
    712                     using (FileStream stream = streamInfo.Open(FileMode.Open, FileAccess.Write)) 
    713                     { 
    714                         long fileLength = stream.Length; 
    715                         long fileArea = GetFileArea(arguments.file); 
    716  
    717                         try 
    718                         { 
    719                             stream.SetLength(fileArea); 
    720                             stream.Seek(fileLength, SeekOrigin.Begin); 
    721  
    722                             //Erase the file 
    723                             arguments.method.Erase(stream, long.MaxValue, PRNGManager.GetInstance( 
    724                                 ManagerLibrary.Instance.Settings.ActivePRNG), null); 
    725                         } 
    726                         finally 
    727                         { 
    728                             //Make sure the file is restored! 
    729                             stream.SetLength(fileLength); 
    730                         } 
    731                     } 
    732  
    733                     //Set the file times 
    734                     FileInfo fileInfo = streamInfo.File; 
    735                     if (fileInfo != null) 
    736                     { 
    737                         fileInfo.LastAccessTime = lastAccess; 
    738                         fileInfo.LastWriteTime = lastWrite; 
    739                         fileInfo.CreationTime = created; 
    740                     } 
    741  
    742                     arguments.callBack((int)Interlocked.Read(ref ThreadPoolArgs.ObjectCount), 
    743                         arguments.file, 
    744                         (int)(Interlocked.Read(ref ThreadPoolArgs.TObjectCount) 
    745                         + Interlocked.Read(ref ThreadPoolArgs.ObjectCount))); 
    746  
    747                     Interlocked.Decrement(ref ThreadPoolArgs.ObjectCount); 
    748                 } 
    749                 catch (Exception e) 
    750                 { 
    751                     arguments.task.Log.Add(new LogEntry(string.Format("\"{0}\" did not have its cluster tips " + 
    752                         "erased because: {1}", arguments.file, e.Message), LogLevel.ERROR)); 
    753                 } 
    754             } 
    755             if (Interlocked.Read(ref ThreadPoolArgs.ObjectCount) == -1 && 
    756                 Interlocked.Read(ref ThreadPoolArgs.Mapped) == 1) 
    757                 ThreadPoolArgs.Handle.Set(); 
    758         } 
    759  
     662                    stream.SetLength(fileArea); 
     663                    stream.Seek(fileLength, SeekOrigin.Begin); 
     664 
     665                    //Erase the file 
     666                    method.Erase(stream, long.MaxValue, PRNGManager.GetInstance( 
     667                        ManagerLibrary.Instance.Settings.ActivePRNG), null); 
     668                } 
     669                finally 
     670                { 
     671                    //Make sure the file is restored! 
     672                    stream.SetLength(fileLength); 
     673                } 
     674            } 
     675 
     676            //Set the file times 
     677            FileInfo fileInfo = streamInfo.File; 
     678            if (fileInfo != null) 
     679            { 
     680                fileInfo.LastAccessTime = lastAccess; 
     681                fileInfo.LastWriteTime = lastWrite; 
     682                fileInfo.CreationTime = created; 
     683            } 
     684        } 
     685         
    760686        /// <summary> 
    761687        /// Erases the old MFT or FAT records. This creates small one-byte files 
     
    809735                throw new NotImplementedException("Could not erase old file system " + 
    810736                    "records: Unsupported File system"); 
    811         } 
    812  
    813  
    814         /// <summary> 
    815         /// Erases the files in the RecycleBin of ALL dirves. 
    816         /// TODO: Add individual drive selection. (or should we?) 
    817         /// </summary> 
    818         /// <param name="task"></param> 
    819         /// <param name="target"></param> 
    820         private void EraseRecycleBin(Task task, Task.RecycleBin target) 
    821         { 
    822             //progress report 
    823             bool isReadOnly; 
    824             long dataTotal = 0; 
    825  
    826             //Retrieve the list of files to erase. 
    827             List<Task.RecycleBin.DirectoryDictionary> directories = target.GetPaths(task); 
    828  
    829             TaskProgressEventArgs eventArgs = new TaskProgressEventArgs(task); 
    830  
    831             //Record the start of the erasure pass so we can calculate speed of erasures 
    832             EraseProgressManager statistics = new EraseProgressManager(task); 
    833                          
    834             //Get the erasure method if the user specified he wants the default. 
    835             ErasureMethod method = target.Method; 
    836             if (method == null) 
    837                 method = ErasureMethodManager.GetInstance(ManagerLibrary.Instance.Settings.DefaultFileErasureMethod); 
    838  
    839             //Calculate the total amount of data required to finish the wipe. 
    840             foreach (Task.RecycleBin.DirectoryDictionary d in directories) 
    841                 dataTotal += d.size; 
    842             dataTotal = method.CalculateEraseDataSize(null, dataTotal); 
    843  
    844             foreach (Task.RecycleBin.DirectoryDictionary dir in directories) 
    845             { 
    846                 foreach (string file in dir.files) 
    847                 { 
    848                     try 
    849                     { 
    850                         StreamInfo info = new StreamInfo(file); 
    851  
    852                         //Remove the read-only flag, if it is set. 
    853                         if (isReadOnly = info.IsReadOnly) info.IsReadOnly = false; 
    854  
    855                         try 
    856                         { 
    857                             // create the file stream, and call the erasure method to write to 
    858                             // the stream. 
    859                             using (FileStream strm = info.Open(FileMode.Open, FileAccess.Write, 
    860                                 FileShare.None, FileOptions.WriteThrough)) 
    861                             { 
    862                                 // set the end of the stream after the wrap-round the cluster size 
    863                                 strm.SetLength(GetFileArea(file)); 
    864  
    865                                 // nothing to do continue 
    866                                 if (strm.Length == 0) continue; 
    867                              
    868                                 // erase the file. 
    869                                 long itemWritten = 0, itemTotal = method.CalculateEraseDataSize(null, strm.Length); 
    870                                 method.Erase(strm, long.MaxValue, 
    871                                     PRNGManager.GetInstance(ManagerLibrary.Instance.Settings.ActivePRNG), 
    872                                     delegate(long lastWritten, int currentPass) 
    873                                     { 
    874                                         statistics.DataWritten += lastWritten; 
    875                                         eventArgs.currentItemPass = currentPass; 
    876  
    877                                         eventArgs.currentItemProgress = (int) 
    878                                             (((double)(itemWritten += lastWritten) * 100) / (double)itemTotal + 0.5); 
    879  
    880                                         eventArgs.overallProgress = (int) 
    881                                             ((double)(statistics.DataWritten * 100) / (double)dataTotal + 0.5); 
    882  
    883                                         if (statistics.Speed != 0) 
    884                                         { 
    885                                             eventArgs.timeLeft = (int) 
    886                                                 ((double)((double)dataTotal - (double)statistics.DataWritten) 
    887                                                 / (double)statistics.Speed + 0.5); 
    888                                         } 
    889                                         else 
    890                                         { 
    891                                             eventArgs.timeLeft = -1; 
    892                                         } 
    893  
    894                                         task.OnProgressChanged(eventArgs); 
    895  
    896                                         lock (currentTask) 
    897                                             if (currentTask.cancelled) 
    898                                                 throw new FatalException("The task was cancelled."); 
    899                                     }  
    900                                 ); 
    901                                  
    902                                 // set the length of the file to 0. 
    903                                 strm.Seek(0, SeekOrigin.Begin); 
    904                                 strm.SetLength(0); 
    905                             } 
    906  
    907                             // remove the file. 
    908                             FileInfo fileInfo = info.File; 
    909                             if (fileInfo != null) 
    910                                 RemoveFile(fileInfo); 
    911                         } 
    912                         finally 
    913                         { 
    914                             // re-set the read-only flag 
    915                             info.IsReadOnly = isReadOnly; 
    916                         } 
    917                     } 
    918                     catch (Exception e) 
    919                     { 
    920                         // show as much exception info as possible 
    921                         task.Log.Add(new LogEntry(string.Format("\"{0}\": Error {Message:{1},InnerException:{2},Source:{3},StackTrace:{4},TargetSite:{5}}", file, 
    922                             e.Message, e.InnerException, e.Source, e.StackTrace, e.TargetSite), LogLevel.ERROR)); 
    923                     } 
    924                 } 
    925                 RemoveFolder(new DirectoryInfo(dir.directory)); 
    926             } 
    927737        } 
    928738 
     
    12381048                if (entries[index] is DirectoryInfo) 
    12391049                    result = GetRandomFileName((DirectoryInfo)entries[index]); 
    1240                 else  
     1050                else 
    12411051                    result = ((FileInfo)entries[index]).FullName; 
    12421052            } 
Note: See TracChangeset for help on using the changeset viewer.