Changeset 1193


Ignore:
Timestamp:
9/28/2009 5:56:32 AM (5 years ago)
Author:
lowjoel
Message:

-Move the core erasure code to FileSystem?.cs as the code required depends on the underlying file system.
-Fixed MFT resident file erasure - the MFT record was not forced to grow to its maximum size when erasing the resident files so old data could still be left behind.

Location:
trunk/eraser6/Eraser.Manager
Files:
6 edited

Legend:

Unmodified
Added
Removed
  • trunk/eraser6/Eraser.Manager/DirectExecutor.cs

    r1179 r1193  
    478478        } 
    479479 
    480         #region Unused Space erasure functions 
    481480        /// <summary> 
    482481        /// Executes a unused space erase. 
     
    510509            //Get the erasure method if the user specified he wants the default. 
    511510            ErasureMethod method = target.Method; 
    512              
     511 
     512            //Make a folder to dump our temporary files in 
     513            DirectoryInfo info = new DirectoryInfo(target.Drive); 
     514            VolumeInfo volInfo = VolumeInfo.FromMountpoint(target.Drive); 
     515            FileSystem fsManager = FileSystem.Get(volInfo); 
     516            info = info.CreateSubdirectory(Path.GetFileName( 
     517                FileSystem.GenerateRandomFileName(info, 18))); 
     518 
    513519            //Erase the cluster tips of every file on the drive. 
    514520            if (target.EraseClusterTips) 
     
    524530 
    525531                //Define the callback handlers 
    526                 ClusterTipsSearchProgress searchProgress = delegate(string path) 
     532                FileSystem.ClusterTipsSearchProgress searchProgress = delegate(string path) 
    527533                    { 
    528534                        progress.Event.CurrentItemName = path; 
     
    533539                    }; 
    534540 
    535                 ClusterTipsEraseProgress eraseProgress = 
     541                FileSystem.ClusterTipsEraseProgress eraseProgress = 
    536542                    delegate(int currentFile, int totalFiles, string currentFilePath) 
    537543                    { 
     
    550556                    }; 
    551557 
    552                 EraseClusterTips(task, target, method, searchProgress, eraseProgress); 
    553             } 
    554  
    555             //Make a folder to dump our temporary files in 
    556             DirectoryInfo info = new DirectoryInfo(target.Drive); 
    557             VolumeInfo volInfo = VolumeInfo.FromMountpoint(target.Drive); 
    558             FileSystem fsManager = FileSystem.Get(volInfo); 
    559             info = info.CreateSubdirectory(Path.GetFileName( 
    560                 FileSystem.GenerateRandomFileName(info, 18))); 
     558                fsManager.EraseClusterTips(VolumeInfo.FromMountpoint(target.Drive), 
     559                    method, task.Log, searchProgress, eraseProgress); 
     560            } 
    561561 
    562562            try 
     
    604604                        method.Erase(stream, long.MaxValue, 
    605605                            PrngManager.GetInstance(ManagerLibrary.Settings.ActivePrng), 
    606                             delegate(long lastWritten, int currentPass) 
     606                            delegate(long lastWritten, long totalData, int currentPass) 
    607607                            { 
    608608                                progress.Completed = Math.Min(progress.Total, 
     
    663663        } 
    664664 
    665         private delegate void SubFoldersHandler(DirectoryInfo info); 
    666         private delegate void ClusterTipsSearchProgress(string currentPath); 
    667         private delegate void ClusterTipsEraseProgress(int currentFile, int totalFiles, 
    668             string currentFilePath); 
    669  
    670         private static void EraseClusterTips(Task task, UnusedSpaceTarget target, 
    671             ErasureMethod method, ClusterTipsSearchProgress searchCallback, 
    672             ClusterTipsEraseProgress eraseCallback) 
    673         { 
    674             //List all the files which can be erased. 
    675             List<string> files = new List<string>(); 
    676             SubFoldersHandler subFolders = null; 
    677  
    678             subFolders = delegate(DirectoryInfo info) 
    679             { 
    680                 //Check if we've been cancelled 
    681                 if (task.Canceled) 
    682                     throw new OperationCanceledException(S._("The task was cancelled.")); 
    683  
    684                 try 
    685                 { 
    686                     //Skip this directory if it is a reparse point 
    687                     if ((info.Attributes & FileAttributes.ReparsePoint) != 0) 
    688                     { 
    689                         task.Log.LastSessionEntries.Add(new LogEntry(S._("Files in {0} did " + 
    690                             "not have their cluster tips erased because it is a hard link or " + 
    691                             "a symbolic link.", info.FullName), LogLevel.Information)); 
    692                         return; 
    693                     } 
    694  
    695                     foreach (FileInfo file in info.GetFiles()) 
    696                         if (Util.File.IsProtectedSystemFile(file.FullName)) 
    697                             task.Log.LastSessionEntries.Add(new LogEntry(S._("{0} did not have " + 
    698                                 "its cluster tips erased, because it is a system file", 
    699                                 file.FullName), LogLevel.Information)); 
    700                         else if ((file.Attributes & FileAttributes.ReparsePoint) != 0) 
    701                             task.Log.LastSessionEntries.Add(new LogEntry(S._("{0} did not have " + 
    702                                 "its cluster tips erased because it is a hard link or a " + 
    703                                 "symbolic link.", file.FullName), LogLevel.Information)); 
    704                         else if ((file.Attributes & FileAttributes.Compressed) != 0 || 
    705                             (file.Attributes & FileAttributes.Encrypted) != 0 || 
    706                             (file.Attributes & FileAttributes.SparseFile) != 0) 
    707                         { 
    708                             task.Log.LastSessionEntries.Add(new LogEntry(S._("{0} did not have " + 
    709                                 "its cluster tips erased because it is compressed, encrypted " + 
    710                                 "or a sparse file.", file.FullName), LogLevel.Information)); 
    711                         } 
    712                         else 
    713                         { 
    714                             try 
    715                             { 
    716                                 foreach (string i in Util.File.GetADSes(file)) 
    717                                     files.Add(file.FullName + ':' + i); 
    718  
    719                                 files.Add(file.FullName); 
    720                             } 
    721                             catch (UnauthorizedAccessException e) 
    722                             { 
    723                                 task.Log.LastSessionEntries.Add(new LogEntry(S._("{0} did not " + 
    724                                     "have its cluster tips erased because of the following " + 
    725                                     "error: {1}", info.FullName, e.Message), LogLevel.Error)); 
    726                             } 
    727                             catch (IOException e) 
    728                             { 
    729                                 task.Log.LastSessionEntries.Add(new LogEntry(S._("{0} did not " + 
    730                                     "have its cluster tips erased because of the following " + 
    731                                     "error: {1}", info.FullName, e.Message), LogLevel.Error)); 
    732                             } 
    733                         } 
    734  
    735                     foreach (DirectoryInfo subDirInfo in info.GetDirectories()) 
    736                     { 
    737                         searchCallback(subDirInfo.FullName); 
    738                         subFolders(subDirInfo); 
    739                     } 
    740                 } 
    741                 catch (UnauthorizedAccessException e) 
    742                 { 
    743                     task.Log.LastSessionEntries.Add(new LogEntry(S._("{0} did not have its " + 
    744                         "cluster tips erased because of the following error: {1}", 
    745                         info.FullName, e.Message), LogLevel.Error)); 
    746                 } 
    747                 catch (IOException e) 
    748                 { 
    749                     task.Log.LastSessionEntries.Add(new LogEntry(S._("{0} did not have its " + 
    750                         "cluster tips erased because of the following error: {1}", 
    751                         info.FullName, e.Message), LogLevel.Error)); 
    752                 } 
    753             }; 
    754  
    755             subFolders(new DirectoryInfo(target.Drive)); 
    756  
    757             //For every file, erase the cluster tips. 
    758             for (int i = 0, j = files.Count; i != j; ++i) 
    759             { 
    760                 //Get the file attributes for restoring later 
    761                 StreamInfo info = new StreamInfo(files[i]); 
    762                 FileAttributes fileAttr = info.Attributes; 
    763  
    764                 try 
    765                 { 
    766                     //Reset the file attributes. 
    767                     info.Attributes = FileAttributes.Normal; 
    768                     EraseFileClusterTips(files[i], method); 
    769                 } 
    770                 catch (UnauthorizedAccessException) 
    771                 { 
    772                     task.Log.LastSessionEntries.Add(new LogEntry(S._("{0} did not have its " + 
    773                         "cluster tips erased because you do not have the required permissions to " + 
    774                         "erase the file cluster tips.", files[i]), LogLevel.Error)); 
    775                 } 
    776                 catch (IOException e) 
    777                 { 
    778                     task.Log.LastSessionEntries.Add(new LogEntry(S._("{0} did not have its " + 
    779                         "cluster tips erased. The error returned was: {1}", files[i], 
    780                         e.Message), LogLevel.Error)); 
    781                 } 
    782                 finally 
    783                 { 
    784                     info.Attributes = fileAttr; 
    785                 } 
    786                 eraseCallback(i, files.Count, files[i]); 
    787             } 
    788         } 
    789  
    790         /// <summary> 
    791         /// Erases the cluster tips of the given file. 
    792         /// </summary> 
    793         /// <param name="file">The file to erase.</param> 
    794         /// <param name="method">The erasure method to use.</param> 
    795         private static void EraseFileClusterTips(string file, ErasureMethod method) 
    796         { 
    797             //Get the file access times 
    798             StreamInfo streamInfo = new StreamInfo(file); 
    799             DateTime lastAccess = streamInfo.LastAccessTime; 
    800             DateTime lastWrite = streamInfo.LastWriteTime; 
    801             DateTime created = streamInfo.CreationTime; 
    802  
    803             //And get the file lengths to know how much to overwrite 
    804             long fileArea = GetFileArea(file); 
    805             long fileLength = streamInfo.Length; 
    806  
    807             //If the file length equals the file area there is no cluster tip to overwrite 
    808             if (fileArea == fileLength) 
    809                 return; 
    810  
    811             //Otherwise, create the stream, lengthen the file, then tell the erasure 
    812             //method to erase the cluster tips. 
    813             using (FileStream stream = streamInfo.Open(FileMode.Open, FileAccess.Write, 
    814                 FileShare.None, FileOptions.WriteThrough)) 
    815             { 
    816                 try 
    817                 { 
    818                     stream.SetLength(fileArea); 
    819                     stream.Seek(fileLength, SeekOrigin.Begin); 
    820  
    821                     //Erase the file 
    822                     method.Erase(stream, long.MaxValue, PrngManager.GetInstance( 
    823                         ManagerLibrary.Settings.ActivePrng), null); 
    824                 } 
    825                 finally 
    826                 { 
    827                     //Make sure the file length is restored! 
    828                     stream.SetLength(fileLength); 
    829  
    830                     //Reset the file times 
    831                     streamInfo.LastAccessTime = lastAccess; 
    832                     streamInfo.LastWriteTime = lastWrite; 
    833                     streamInfo.CreationTime = created; 
    834                 } 
    835             } 
    836         } 
    837         #endregion 
    838  
    839         #region Filesystem Object erasure functions 
     665        /// <summary> 
     666        /// Traverses the given folder and deletes it securely only if it is 
     667        /// empty. 
     668        /// </summary> 
     669        /// <param name="info">The folder to check.</param> 
     670        private delegate void FolderEraseDelegate(DirectoryInfo info); 
     671 
    840672        /// <summary> 
    841673        /// Erases a file or folder on the volume. 
     
    894726                    } 
    895727 
    896                     //Create the file stream, and call the erasure method to write to 
    897                     //the stream. 
    898                     long fileArea = GetFileArea(paths[i]); 
    899                     using (FileStream strm = info.Open(FileMode.Open, FileAccess.Write, 
    900                         FileShare.None, FileOptions.WriteThrough)) 
    901                     { 
    902                         //Set the end of the stream after the wrap-round the cluster size 
    903                         strm.SetLength(fileArea); 
    904  
    905                         //If the stream is empty, there's nothing to overwrite. Continue 
    906                         //to the next entry 
    907                         if (strm.Length != 0) 
     728                    long itemWritten = 0; 
     729                    fsManager.EraseFileSystemObject(info, method, 
     730                        delegate(long lastWritten, long totalData, int currentPass) 
    908731                        { 
    909                             //Then erase the file. 
    910                             long itemWritten = 0, 
    911                                  itemTotal = method.CalculateEraseDataSize(null, strm.Length); 
    912                             method.Erase(strm, long.MaxValue, 
    913                                 PrngManager.GetInstance(ManagerLibrary.Settings.ActivePrng), 
    914                                 delegate(long lastWritten, int currentPass) 
    915                                 { 
    916                                     dataTotal -= lastWritten; 
    917                                     progress.Completed += lastWritten; 
    918                                     progress.Event.CurrentItemPass = currentPass; 
    919                                     progress.Event.CurrentItemProgress = (float) 
    920                                         ((itemWritten += lastWritten) / (float)itemTotal); 
    921                                     progress.Event.CurrentTargetProgress = 
    922                                         (i + progress.Event.CurrentItemProgress) / 
    923                                         (float)paths.Count; 
    924                                     progress.Event.TimeLeft = progress.TimeLeft; 
    925                                     task.OnProgressChanged(progress.Event); 
    926  
    927                                     if (currentTask.Canceled) 
    928                                         throw new OperationCanceledException(S._("The task was cancelled.")); 
    929                                 } 
    930                             ); 
    931                         } 
    932  
    933                         //Set the length of the file to 0. 
    934                         strm.Seek(0, SeekOrigin.Begin); 
    935                         strm.SetLength(0); 
    936                     } 
     732                            dataTotal -= lastWritten; 
     733                            progress.Completed += lastWritten; 
     734                            progress.Event.CurrentItemPass = currentPass; 
     735                            progress.Event.CurrentItemProgress = (float) 
     736                                ((itemWritten += lastWritten) / (float)totalData); 
     737                            progress.Event.CurrentTargetProgress = 
     738                                (i + progress.Event.CurrentItemProgress) / 
     739                                (float)paths.Count; 
     740                            progress.Event.TimeLeft = progress.TimeLeft; 
     741                            task.OnProgressChanged(progress.Event); 
     742 
     743                            if (currentTask.Canceled) 
     744                                throw new OperationCanceledException(S._("The task was cancelled.")); 
     745                        }); 
    937746 
    938747                    //Remove the file. 
    939748                    FileInfo fileInfo = info.File; 
    940                     if (fileInfo != null) 
    941                         fsManager.DeleteFile(fileInfo); 
     749                    /*if (fileInfo != null) 
     750                        fsManager.DeleteFile(fileInfo);*/ 
    942751                } 
    943752                catch (UnauthorizedAccessException) 
     
    982791                FolderTarget fldr = (FolderTarget)target; 
    983792                FileSystem fsManager = FileSystem.Get(VolumeInfo.FromMountpoint(fldr.Path)); 
    984                 SubFoldersHandler eraseEmptySubFolders = null; 
     793                FolderEraseDelegate eraseEmptySubFolders = null; 
    985794                eraseEmptySubFolders = delegate(DirectoryInfo info) 
    986795                { 
     
    1029838 
    1030839        /// <summary> 
    1031         /// Retrieves the size of the file on disk, calculated by the amount of 
    1032         /// clusters allocated by it. 
    1033         /// </summary> 
    1034         /// <param name="filePath">The path to the file.</param> 
    1035         /// <returns>The area of the file.</returns> 
    1036         private static long GetFileArea(string filePath) 
    1037         { 
    1038             StreamInfo info = new StreamInfo(filePath); 
    1039             VolumeInfo volume = VolumeInfo.FromMountpoint(info.Directory.FullName); 
    1040             long clusterSize = volume.ClusterSize; 
    1041             return (info.Length + (clusterSize - 1)) & ~(clusterSize - 1); 
    1042         } 
    1043         #endregion 
    1044  
    1045         /// <summary> 
    1046840        /// The thread object. 
    1047841        /// </summary> 
  • trunk/eraser6/Eraser.Manager/FileSystem.cs

    r1145 r1193  
    201201        /// </summary> 
    202202        /// <param name="info">The folder to delete</param> 
    203         public abstract void DeleteFolder(DirectoryInfo info); 
     203        /// <param name="recursive">True if the folder and all its subfolders and 
     204        /// files to be securely deleted.</param> 
     205        public abstract void DeleteFolder(DirectoryInfo info, bool recursive); 
     206 
     207        /// <seealso cref="DeleteFolder"/> 
     208        /// <param name="info">The folder to delete.</param> 
     209        public void DeleteFolder(DirectoryInfo info) 
     210        { 
     211            DeleteFolder(info, true); 
     212        } 
     213 
     214        /// <summary> 
     215        /// The function prototype for cluster tip search progress callbacks. This is 
     216        /// called when the cluster tips are being searched. 
     217        /// </summary> 
     218        /// <param name="currentPath">The directory being searched</param> 
     219        public delegate void ClusterTipsSearchProgress(string currentPath); 
     220 
     221        /// <summary> 
     222        /// The function prototype for cluster tip erasure callbacks. This is called when 
     223        /// the cluster tips are being erased. 
     224        /// </summary> 
     225        /// <param name="currentFile">The current file index being erased.</param> 
     226        /// <param name="totalFiles">The total number of files to be erased.</param> 
     227        /// <param name="currentFilePath">The path to the current file being erased.</param> 
     228        public delegate void ClusterTipsEraseProgress(int currentFile, int totalFiles, 
     229            string currentFilePath); 
     230 
     231        /// <summary> 
     232        /// Erases all file cluster tips in the given volume. 
     233        /// </summary> 
     234        /// <param name="info">The volume to search for file cluster tips and erase them.</param> 
     235        /// <param name="method">The erasure method being employed.</param> 
     236        /// <param name="logger">The log manager instance that tracks log messages.</param> 
     237        /// <param name="searchCallback">The callback function for search progress.</param> 
     238        /// <param name="eraseCallback">The callback function for erasure progress.</param> 
     239        public abstract void EraseClusterTips(VolumeInfo info, ErasureMethod method, 
     240            Logger logger, ClusterTipsSearchProgress searchCallback, 
     241            ClusterTipsEraseProgress eraseCallback); 
    204242 
    205243        /// <summary> 
     
    233271 
    234272        /// <summary> 
     273        /// Erases the file system object from the drive. 
     274        /// </summary> 
     275        /// <param name="info"></param> 
     276        public abstract void EraseFileSystemObject(StreamInfo info, ErasureMethod method, 
     277            EraserMethodProgressFunction callback); 
     278 
     279        /// <summary> 
     280        /// Retrieves the size of the file on disk, calculated by the amount of 
     281        /// clusters allocated by it. 
     282        /// </summary> 
     283        /// <param name="filePath">The path to the file.</param> 
     284        /// <returns>The area of the file.</returns> 
     285        public abstract long GetFileArea(string filePath); 
     286 
     287        /// <summary> 
    235288        /// The number of times file names are renamed to erase the file name from 
    236289        /// the file system table. 
     
    313366        } 
    314367 
    315         public override void DeleteFolder(DirectoryInfo info) 
    316         { 
     368        public override void DeleteFolder(DirectoryInfo info, bool recursive) 
     369        { 
     370            if (!recursive && info.GetFileSystemInfos().Length != 0) 
     371                throw new InvalidOperationException(S._("The folder {0} cannot be deleted as it is " + 
     372                    "not empty.")); 
     373 
    317374            //TODO: check for reparse points 
    318375            foreach (DirectoryInfo dir in info.GetDirectories()) 
     
    342399            //Remove the folder 
    343400            info.Delete(true); 
     401        } 
     402         
     403        public override void EraseClusterTips(VolumeInfo info, ErasureMethod method, 
     404            Logger log, ClusterTipsSearchProgress searchCallback, 
     405            ClusterTipsEraseProgress eraseCallback) 
     406        { 
     407            //List all the files which can be erased. 
     408            List<string> files = new List<string>(); 
     409            if (!info.IsMounted) 
     410                throw new InvalidOperationException(S._("Could not erase cluster tips in {0} " + 
     411                    "as the volume is not mounted.", info.VolumeId)); 
     412            ListFiles(new DirectoryInfo(info.MountPoints[0]), files, log, searchCallback); 
     413 
     414            //For every file, erase the cluster tips. 
     415            for (int i = 0, j = files.Count; i != j; ++i) 
     416            { 
     417                //Get the file attributes for restoring later 
     418                StreamInfo streamInfo = new StreamInfo(files[i]); 
     419                FileAttributes fileAttr = streamInfo.Attributes; 
     420 
     421                try 
     422                { 
     423                    //Reset the file attributes. 
     424                    streamInfo.Attributes = FileAttributes.Normal; 
     425                    EraseFileClusterTips(files[i], method); 
     426                } 
     427                catch (UnauthorizedAccessException) 
     428                { 
     429                    log.LastSessionEntries.Add(new LogEntry(S._("{0} did not have its " + 
     430                        "cluster tips erased because you do not have the required permissions to " + 
     431                        "erase the file cluster tips.", files[i]), LogLevel.Error)); 
     432                } 
     433                catch (IOException e) 
     434                { 
     435                    log.LastSessionEntries.Add(new LogEntry(S._("{0} did not have its " + 
     436                        "cluster tips erased. The error returned was: {1}", files[i], 
     437                        e.Message), LogLevel.Error)); 
     438                } 
     439                finally 
     440                { 
     441                    streamInfo.Attributes = fileAttr; 
     442                } 
     443                eraseCallback(i, files.Count, files[i]); 
     444            } 
     445        } 
     446 
     447        private void ListFiles(DirectoryInfo info, List<string> files, Logger log, 
     448            ClusterTipsSearchProgress searchCallback) 
     449        { 
     450            try 
     451            { 
     452                //Skip this directory if it is a reparse point 
     453                if ((info.Attributes & FileAttributes.ReparsePoint) != 0) 
     454                { 
     455                    log.LastSessionEntries.Add(new LogEntry(S._("Files in {0} did " + 
     456                        "not have their cluster tips erased because it is a hard link or " + 
     457                        "a symbolic link.", info.FullName), LogLevel.Information)); 
     458                    return; 
     459                } 
     460 
     461                foreach (FileInfo file in info.GetFiles()) 
     462                    if (Util.File.IsProtectedSystemFile(file.FullName)) 
     463                        log.LastSessionEntries.Add(new LogEntry(S._("{0} did not have " + 
     464                            "its cluster tips erased, because it is a system file", 
     465                            file.FullName), LogLevel.Information)); 
     466                    else if ((file.Attributes & FileAttributes.ReparsePoint) != 0) 
     467                        log.LastSessionEntries.Add(new LogEntry(S._("{0} did not have " + 
     468                            "its cluster tips erased because it is a hard link or a " + 
     469                            "symbolic link.", file.FullName), LogLevel.Information)); 
     470                    else if ((file.Attributes & FileAttributes.Compressed) != 0 || 
     471                        (file.Attributes & FileAttributes.Encrypted) != 0 || 
     472                        (file.Attributes & FileAttributes.SparseFile) != 0) 
     473                    { 
     474                        log.LastSessionEntries.Add(new LogEntry(S._("{0} did not have " + 
     475                            "its cluster tips erased because it is compressed, encrypted " + 
     476                            "or a sparse file.", file.FullName), LogLevel.Information)); 
     477                    } 
     478                    else 
     479                    { 
     480                        try 
     481                        { 
     482                            foreach (string i in Util.File.GetADSes(file)) 
     483                                files.Add(file.FullName + ':' + i); 
     484 
     485                            files.Add(file.FullName); 
     486                        } 
     487                        catch (UnauthorizedAccessException e) 
     488                        { 
     489                            log.LastSessionEntries.Add(new LogEntry(S._("{0} did not " + 
     490                                "have its cluster tips erased because of the following " + 
     491                                "error: {1}", info.FullName, e.Message), LogLevel.Error)); 
     492                        } 
     493                        catch (IOException e) 
     494                        { 
     495                            log.LastSessionEntries.Add(new LogEntry(S._("{0} did not " + 
     496                                "have its cluster tips erased because of the following " + 
     497                                "error: {1}", info.FullName, e.Message), LogLevel.Error)); 
     498                        } 
     499                    } 
     500 
     501                foreach (DirectoryInfo subDirInfo in info.GetDirectories()) 
     502                { 
     503                    searchCallback(subDirInfo.FullName); 
     504                    ListFiles(subDirInfo, files, log, searchCallback); 
     505                } 
     506            } 
     507            catch (UnauthorizedAccessException e) 
     508            { 
     509                log.LastSessionEntries.Add(new LogEntry(S._("{0} did not have its " + 
     510                    "cluster tips erased because of the following error: {1}", 
     511                    info.FullName, e.Message), LogLevel.Error)); 
     512            } 
     513            catch (IOException e) 
     514            { 
     515                log.LastSessionEntries.Add(new LogEntry(S._("{0} did not have its " + 
     516                    "cluster tips erased because of the following error: {1}", 
     517                    info.FullName, e.Message), LogLevel.Error)); 
     518            } 
     519        } 
     520 
     521        /// <summary> 
     522        /// Erases the cluster tips of the given file. 
     523        /// </summary> 
     524        /// <param name="file">The file to erase.</param> 
     525        /// <param name="method">The erasure method to use.</param> 
     526        private void EraseFileClusterTips(string file, ErasureMethod method) 
     527        { 
     528            //Get the file access times 
     529            StreamInfo streamInfo = new StreamInfo(file); 
     530            DateTime lastAccess = streamInfo.LastAccessTime; 
     531            DateTime lastWrite = streamInfo.LastWriteTime; 
     532            DateTime created = streamInfo.CreationTime; 
     533 
     534            //And get the file lengths to know how much to overwrite 
     535            long fileArea = GetFileArea(file); 
     536            long fileLength = streamInfo.Length; 
     537 
     538            //If the file length equals the file area there is no cluster tip to overwrite 
     539            if (fileArea == fileLength) 
     540                return; 
     541 
     542            //Otherwise, create the stream, lengthen the file, then tell the erasure 
     543            //method to erase the cluster tips. 
     544            using (FileStream stream = streamInfo.Open(FileMode.Open, FileAccess.Write, 
     545                FileShare.None, FileOptions.WriteThrough)) 
     546            { 
     547                try 
     548                { 
     549                    stream.SetLength(fileArea); 
     550                    stream.Seek(fileLength, SeekOrigin.Begin); 
     551 
     552                    //Erase the file 
     553                    method.Erase(stream, long.MaxValue, PrngManager.GetInstance( 
     554                        ManagerLibrary.Settings.ActivePrng), null); 
     555                } 
     556                finally 
     557                { 
     558                    //Make sure the file length is restored! 
     559                    stream.SetLength(fileLength); 
     560 
     561                    //Reset the file times 
     562                    streamInfo.LastAccessTime = lastAccess; 
     563                    streamInfo.LastWriteTime = lastWrite; 
     564                    streamInfo.CreationTime = created; 
     565                } 
     566            } 
     567        } 
     568 
     569        public override long GetFileArea(string filePath) 
     570        { 
     571            StreamInfo info = new StreamInfo(filePath); 
     572            VolumeInfo volume = VolumeInfo.FromMountpoint(info.Directory.FullName); 
     573            long clusterSize = volume.ClusterSize; 
     574            return (info.Length + (clusterSize - 1)) & ~(clusterSize - 1); 
    344575        } 
    345576 
     
    372603                        FileAccess.Write, FileShare.None, 8, FileOptions.WriteThrough)) 
    373604                    { 
    374                         //Stretch the file size to use up some of the resident space. 
    375                         strm.SetLength(1); 
    376  
    377                         //Then run the erase task 
    378                         method.Erase(strm, long.MaxValue, 
    379                             PrngManager.GetInstance(ManagerLibrary.Settings.ActivePrng), 
    380                             null); 
     605                        long streamSize = 0; 
     606                        try 
     607                        { 
     608                            while (true) 
     609                            { 
     610                                //Stretch the file size to use up some of the resident space. 
     611                                strm.SetLength(++streamSize); 
     612 
     613                                //Then run the erase task 
     614                                method.Erase(strm, long.MaxValue, 
     615                                    PrngManager.GetInstance(ManagerLibrary.Settings.ActivePrng), 
     616                                    null); 
     617                            } 
     618                        } 
     619                        catch (IOException) 
     620                        { 
     621                            if (streamSize == 1) 
     622                                return; 
     623                        } 
    381624                    } 
    382625 
     
    445688 
    446689                DeleteFolder(tempDir); 
     690            } 
     691        } 
     692 
     693        public override void EraseFileSystemObject(StreamInfo info, ErasureMethod method, 
     694            EraserMethodProgressFunction callback) 
     695        { 
     696            //Check if the file fits in one MFT record 
     697            long mftRecordSize = NtfsApi.GetMftRecordSegmentSize(VolumeInfo.FromMountpoint(info.DirectoryName)); 
     698            while (info.Length < mftRecordSize) 
     699            { 
     700                //Yes it does, erase exactly to the file length 
     701                using (FileStream strm = info.Open(FileMode.Open, FileAccess.Write, 
     702                    FileShare.None)) 
     703                { 
     704                    strm.SetLength(strm.Length + 1); 
     705                    method.Erase(strm, long.MaxValue, 
     706                        PrngManager.GetInstance(ManagerLibrary.Settings.ActivePrng), null); 
     707                } 
     708            } 
     709 
     710            //Create the file stream, and call the erasure method to write to 
     711            //the stream. 
     712            long fileArea = GetFileArea(info.FullName); 
     713 
     714            //If the stream is empty, there's nothing to overwrite. Continue 
     715            //to the next entry 
     716            if (fileArea == 0) 
     717                return; 
     718 
     719            using (FileStream strm = info.Open(FileMode.Open, FileAccess.Write, 
     720                FileShare.None, FileOptions.WriteThrough)) 
     721            { 
     722                //Set the end of the stream after the wrap-round the cluster size 
     723                strm.SetLength(fileArea);    
     724                 
     725                //Then erase the file. 
     726                method.Erase(strm, long.MaxValue, 
     727                    PrngManager.GetInstance(ManagerLibrary.Settings.ActivePrng), 
     728                    callback 
     729                ); 
     730 
     731                //Set the length of the file to 0. 
     732                strm.Seek(0, SeekOrigin.Begin); 
     733                strm.SetLength(0); 
    447734            } 
    448735        } 
     
    475762        } 
    476763 
     764        public override void EraseFileSystemObject(StreamInfo info, ErasureMethod method, 
     765            EraserMethodProgressFunction callback) 
     766        { 
     767            //Create the file stream, and call the erasure method to write to 
     768            //the stream. 
     769            long fileArea = GetFileArea(info.FullName); 
     770            using (FileStream strm = info.Open(FileMode.Open, FileAccess.Write, 
     771                FileShare.None, FileOptions.WriteThrough)) 
     772            { 
     773                //Set the end of the stream after the wrap-round the cluster size 
     774                strm.SetLength(fileArea); 
     775 
     776                //If the stream is empty, there's nothing to overwrite. Continue 
     777                //to the next entry 
     778                if (strm.Length != 0) 
     779                { 
     780                    //Then erase the file. 
     781                    method.Erase(strm, long.MaxValue, 
     782                        PrngManager.GetInstance(ManagerLibrary.Settings.ActivePrng), 
     783                        callback 
     784                    ); 
     785                } 
     786 
     787                //Set the length of the file to 0. 
     788                strm.Seek(0, SeekOrigin.Begin); 
     789                strm.SetLength(0); 
     790            } 
     791        } 
     792 
     793 
    477794        protected override DateTime MinTimestamp 
    478795        { 
  • trunk/eraser6/Eraser.Manager/Method.cs

    r1176 r1193  
    170170    /// <param name="lastWritten">The amount of data written to the stream since 
    171171    /// the last call to the delegate.</param> 
     172    /// <param name="totalData">The total amount of data that must be written to 
     173    /// complete the erasure.</param> 
    172174    /// <param name="currentPass">The current pass number. The total number 
    173175    /// of passes can be found from the Passes property.</param> 
    174     public delegate void EraserMethodProgressFunction(long lastWritten, int currentPass); 
     176    public delegate void EraserMethodProgressFunction(long lastWritten, long totalData, 
     177        int currentPass); 
    175178 
    176179    /// <summary> 
     
    299302            long strmStart = stream.Position; 
    300303            long strmLength = Math.Min(stream.Length - strmStart, erasureLength); 
     304            long totalData = CalculateEraseDataSize(null, strmLength); 
    301305 
    302306            //Allocate memory for a buffer holding data for the pass. 
     
    308312                //Do a progress callback first. 
    309313                if (callback != null) 
    310                     callback(0, pass + 1); 
     314                    callback(0, totalData, pass + 1); 
    311315 
    312316                //Start from the beginning again 
     
    336340                    //Do a progress callback. 
    337341                    if (callback != null) 
    338                         callback(amount, pass + 1); 
     342                        callback(amount, totalData, pass + 1); 
    339343                } 
    340344            } 
  • trunk/eraser6/Eraser.Manager/Strings.en.resx

    r1178 r1193  
    151151    <value>Erasing unused directory structures...</value> 
    152152  </data> 
     153  <data name="Erasing files..." xml:space="preserve"> 
     154    <value>Erasing files...</value> 
     155  </data> 
     156  <data name="The file {0} could not be erased because the file was either compressed, encrypted or a sparse file." xml:space="preserve"> 
     157    <value>The file {0} could not be erased because the file was either compressed, encrypted or a sparse file.</value> 
     158  </data> 
     159  <data name="The file {0} could not be erased because the file's permissions prevent access to the file." xml:space="preserve"> 
     160    <value>The file {0} could not be erased because the file's permissions prevent access to the file.</value> 
     161  </data> 
     162  <data name="Could not force closure of file \&quot;{0}\&quot; (locked by {1})" xml:space="preserve"> 
     163    <value>Could not force closure of file \"{0}\" (locked by {1})</value> 
     164  </data> 
     165  <data name="Removing folders..." xml:space="preserve"> 
     166    <value>Removing folders...</value> 
     167  </data> 
     168  <data name="Emptying recycle bin..." xml:space="preserve"> 
     169    <value>Emptying recycle bin...</value> 
     170  </data> 
     171  <data name="EntropySource GUID not found: {0}" xml:space="preserve"> 
     172    <value>EntropySource GUID not found: {0}</value> 
     173  </data> 
     174  <data name="Erasure method not found: {0}" xml:space="preserve"> 
     175    <value>Erasure method not found: {0}</value> 
     176  </data> 
     177  <data name="PRNG not found: {0}" xml:space="preserve"> 
     178    <value>PRNG not found: {0}</value> 
     179  </data> 
     180  <data name="The file system on the drive {0} is not supported." xml:space="preserve"> 
     181    <value>The file system on the drive {0} is not supported.</value> 
     182  </data> 
     183  <data name="Plausible deniability was selected, but no decoy files were found. The current file has been only replaced with random data." xml:space="preserve"> 
     184    <value>Plausible deniability was selected, but no decoy files were found. The current file has been only replaced with random data.</value> 
     185  </data> 
     186  <data name="The file {0} is currently in use and cannot be removed." xml:space="preserve"> 
     187    <value>The file {0} is currently in use and cannot be removed.</value> 
     188  </data> 
     189  <data name="The folder {0} cannot be deleted as it is not empty." xml:space="preserve"> 
     190    <value>(Untranslated)</value> 
     191  </data> 
     192  <data name="Could not erase cluster tips in {0} as the volume is not mounted." xml:space="preserve"> 
     193    <value>(Untranslated)</value> 
     194  </data> 
     195  <data name="{0} did not have its cluster tips erased because you do not have the required permissions to erase the file cluster tips." xml:space="preserve"> 
     196    <value>{0} did not have its cluster tips erased because you do not have the required permissions to erase the file cluster tips.</value> 
     197  </data> 
     198  <data name="{0} did not have its cluster tips erased. The error returned was: {1}" xml:space="preserve"> 
     199    <value>{0} did not have its cluster tips erased. The error returned was: {1}</value> 
     200  </data> 
    153201  <data name="Files in {0} did not have their cluster tips erased because it is a hard link or a symbolic link." xml:space="preserve"> 
    154202    <value>Files in {0} did not have their cluster tips erased because it is a hard link or a symbolic link.</value> 
     
    166214    <value>{0} did not have its cluster tips erased because of the following error: {1}</value> 
    167215  </data> 
    168   <data name="{0} did not have its cluster tips erased because you do not have the required permissions to erase the file cluster tips." xml:space="preserve"> 
    169     <value>{0} did not have its cluster tips erased because you do not have the required permissions to erase the file cluster tips.</value> 
    170   </data> 
    171   <data name="{0} did not have its cluster tips erased. The error returned was: {1}" xml:space="preserve"> 
    172     <value>{0} did not have its cluster tips erased. The error returned was: {1}</value> 
    173   </data> 
    174   <data name="Erasing files..." xml:space="preserve"> 
    175     <value>Erasing files...</value> 
    176   </data> 
    177   <data name="The file {0} could not be erased because the file was either compressed, encrypted or a sparse file." xml:space="preserve"> 
    178     <value>The file {0} could not be erased because the file was either compressed, encrypted or a sparse file.</value> 
    179   </data> 
    180   <data name="The file {0} could not be erased because the file's permissions prevent access to the file." xml:space="preserve"> 
    181     <value>The file {0} could not be erased because the file's permissions prevent access to the file.</value> 
    182   </data> 
    183   <data name="Could not force closure of file \&quot;{0}\&quot; (locked by {1})" xml:space="preserve"> 
    184     <value>Could not force closure of file \"{0}\" (locked by {1})</value> 
    185   </data> 
    186   <data name="Removing folders..." xml:space="preserve"> 
    187     <value>Removing folders...</value> 
    188   </data> 
    189   <data name="Emptying recycle bin..." xml:space="preserve"> 
    190     <value>Emptying recycle bin...</value> 
    191   </data> 
    192   <data name="EntropySource GUID not found: {0}" xml:space="preserve"> 
    193     <value>EntropySource GUID not found: {0}</value> 
    194   </data> 
    195   <data name="Erasure method not found: {0}" xml:space="preserve"> 
    196     <value>Erasure method not found: {0}</value> 
    197   </data> 
    198   <data name="PRNG not found: {0}" xml:space="preserve"> 
    199     <value>PRNG not found: {0}</value> 
    200   </data> 
    201   <data name="The file system on the drive {0} is not supported." xml:space="preserve"> 
    202     <value>The file system on the drive {0} is not supported.</value> 
    203   </data> 
    204   <data name="Plausible deniability was selected, but no decoy files were found. The current file has been only replaced with random data." xml:space="preserve"> 
    205     <value>Plausible deniability was selected, but no decoy files were found. The current file has been only replaced with random data.</value> 
    206   </data> 
    207   <data name="The file {0} is currently in use and cannot be removed." xml:space="preserve"> 
    208     <value>The file {0} is currently in use and cannot be removed.</value> 
    209   </data> 
    210216  <data name="{0} (1 pass)" xml:space="preserve"> 
    211217    <value>{0} (1 pass)</value> 
  • trunk/eraser6/Eraser.Manager/Strings.nl.resx

    r1178 r1193  
    151151    <value>(Untranslated)</value> 
    152152  </data> 
     153  <data name="Erasing files..." xml:space="preserve"> 
     154    <value>(Untranslated)</value> 
     155  </data> 
     156  <data name="The file {0} could not be erased because the file was either compressed, encrypted or a sparse file." xml:space="preserve"> 
     157    <value>(Untranslated)</value> 
     158  </data> 
     159  <data name="The file {0} could not be erased because the file's permissions prevent access to the file." xml:space="preserve"> 
     160    <value>(Untranslated)</value> 
     161  </data> 
     162  <data name="Could not force closure of file \&quot;{0}\&quot; (locked by {1})" xml:space="preserve"> 
     163    <value>(Untranslated)</value> 
     164  </data> 
     165  <data name="Removing folders..." xml:space="preserve"> 
     166    <value>(Untranslated)</value> 
     167  </data> 
     168  <data name="Emptying recycle bin..." xml:space="preserve"> 
     169    <value>(Untranslated)</value> 
     170  </data> 
     171  <data name="EntropySource GUID not found: {0}" xml:space="preserve"> 
     172    <value>(Untranslated)</value> 
     173  </data> 
     174  <data name="Erasure method not found: {0}" xml:space="preserve"> 
     175    <value>(Untranslated)</value> 
     176  </data> 
     177  <data name="PRNG not found: {0}" xml:space="preserve"> 
     178    <value>(Untranslated)</value> 
     179  </data> 
     180  <data name="The file system on the drive {0} is not supported." xml:space="preserve"> 
     181    <value>(Untranslated)</value> 
     182  </data> 
     183  <data name="Plausible deniability was selected, but no decoy files were found. The current file has been only replaced with random data." xml:space="preserve"> 
     184    <value>(Untranslated)</value> 
     185  </data> 
     186  <data name="The file {0} is currently in use and cannot be removed." xml:space="preserve"> 
     187    <value>(Untranslated)</value> 
     188  </data> 
     189  <data name="The folder {0} cannot be deleted as it is not empty." xml:space="preserve"> 
     190    <value>(Untranslated)</value> 
     191  </data> 
     192  <data name="Could not erase cluster tips in {0} as the volume is not mounted." xml:space="preserve"> 
     193    <value>(Untranslated)</value> 
     194  </data> 
     195  <data name="{0} did not have its cluster tips erased because you do not have the required permissions to erase the file cluster tips." xml:space="preserve"> 
     196    <value>(Untranslated)</value> 
     197  </data> 
     198  <data name="{0} did not have its cluster tips erased. The error returned was: {1}" xml:space="preserve"> 
     199    <value>(Untranslated)</value> 
     200  </data> 
    153201  <data name="Files in {0} did not have their cluster tips erased because it is a hard link or a symbolic link." xml:space="preserve"> 
    154202    <value>(Untranslated)</value> 
     
    166214    <value>(Untranslated)</value> 
    167215  </data> 
    168   <data name="{0} did not have its cluster tips erased because you do not have the required permissions to erase the file cluster tips." xml:space="preserve"> 
    169     <value>(Untranslated)</value> 
    170   </data> 
    171   <data name="{0} did not have its cluster tips erased. The error returned was: {1}" xml:space="preserve"> 
    172     <value>(Untranslated)</value> 
    173   </data> 
    174   <data name="Erasing files..." xml:space="preserve"> 
    175     <value>(Untranslated)</value> 
    176   </data> 
    177   <data name="The file {0} could not be erased because the file was either compressed, encrypted or a sparse file." xml:space="preserve"> 
    178     <value>(Untranslated)</value> 
    179   </data> 
    180   <data name="The file {0} could not be erased because the file's permissions prevent access to the file." xml:space="preserve"> 
    181     <value>(Untranslated)</value> 
    182   </data> 
    183   <data name="Could not force closure of file \&quot;{0}\&quot; (locked by {1})" xml:space="preserve"> 
    184     <value>(Untranslated)</value> 
    185   </data> 
    186   <data name="Removing folders..." xml:space="preserve"> 
    187     <value>(Untranslated)</value> 
    188   </data> 
    189   <data name="Emptying recycle bin..." xml:space="preserve"> 
    190     <value>(Untranslated)</value> 
    191   </data> 
    192   <data name="EntropySource GUID not found: {0}" xml:space="preserve"> 
    193     <value>(Untranslated)</value> 
    194   </data> 
    195   <data name="Erasure method not found: {0}" xml:space="preserve"> 
    196     <value>(Untranslated)</value> 
    197   </data> 
    198   <data name="PRNG not found: {0}" xml:space="preserve"> 
    199     <value>(Untranslated)</value> 
    200   </data> 
    201   <data name="The file system on the drive {0} is not supported." xml:space="preserve"> 
    202     <value>(Untranslated)</value> 
    203   </data> 
    204   <data name="Plausible deniability was selected, but no decoy files were found. The current file has been only replaced with random data." xml:space="preserve"> 
    205     <value>(Untranslated)</value> 
    206   </data> 
    207   <data name="The file {0} is currently in use and cannot be removed." xml:space="preserve"> 
    208     <value>(Untranslated)</value> 
    209   </data> 
    210216  <data name="{0} (1 pass)" xml:space="preserve"> 
    211217    <value>(Untranslated)</value> 
  • trunk/eraser6/Eraser.Manager/Strings.resx

    r1178 r1193  
    151151    <value>Erasing unused directory structures...</value> 
    152152  </data> 
     153  <data name="Erasing files..." xml:space="preserve"> 
     154    <value>Erasing files...</value> 
     155  </data> 
     156  <data name="The file {0} could not be erased because the file was either compressed, encrypted or a sparse file." xml:space="preserve"> 
     157    <value>The file {0} could not be erased because the file was either compressed, encrypted or a sparse file.</value> 
     158  </data> 
     159  <data name="The file {0} could not be erased because the file's permissions prevent access to the file." xml:space="preserve"> 
     160    <value>The file {0} could not be erased because the file's permissions prevent access to the file.</value> 
     161  </data> 
     162  <data name="Could not force closure of file \&quot;{0}\&quot; (locked by {1})" xml:space="preserve"> 
     163    <value>Could not force closure of file \"{0}\" (locked by {1})</value> 
     164  </data> 
     165  <data name="Removing folders..." xml:space="preserve"> 
     166    <value>Removing folders...</value> 
     167  </data> 
     168  <data name="Emptying recycle bin..." xml:space="preserve"> 
     169    <value>Emptying recycle bin...</value> 
     170  </data> 
     171  <data name="EntropySource GUID not found: {0}" xml:space="preserve"> 
     172    <value>EntropySource GUID not found: {0}</value> 
     173  </data> 
     174  <data name="Erasure method not found: {0}" xml:space="preserve"> 
     175    <value>Erasure method not found: {0}</value> 
     176  </data> 
     177  <data name="PRNG not found: {0}" xml:space="preserve"> 
     178    <value>PRNG not found: {0}</value> 
     179  </data> 
     180  <data name="The file system on the drive {0} is not supported." xml:space="preserve"> 
     181    <value>The file system on the drive {0} is not supported.</value> 
     182  </data> 
     183  <data name="Plausible deniability was selected, but no decoy files were found. The current file has been only replaced with random data." xml:space="preserve"> 
     184    <value>Plausible deniability was selected, but no decoy files were found. The current file has been only replaced with random data.</value> 
     185  </data> 
     186  <data name="The file {0} is currently in use and cannot be removed." xml:space="preserve"> 
     187    <value>The file {0} is currently in use and cannot be removed.</value> 
     188  </data> 
     189  <data name="The folder {0} cannot be deleted as it is not empty." xml:space="preserve"> 
     190    <value>The folder {0} cannot be deleted as it is not empty.</value> 
     191  </data> 
     192  <data name="Could not erase cluster tips in {0} as the volume is not mounted." xml:space="preserve"> 
     193    <value>Could not erase cluster tips in {0} as the volume is not mounted.</value> 
     194  </data> 
     195  <data name="{0} did not have its cluster tips erased because you do not have the required permissions to erase the file cluster tips." xml:space="preserve"> 
     196    <value>{0} did not have its cluster tips erased because you do not have the required permissions to erase the file cluster tips.</value> 
     197  </data> 
     198  <data name="{0} did not have its cluster tips erased. The error returned was: {1}" xml:space="preserve"> 
     199    <value>{0} did not have its cluster tips erased. The error returned was: {1}</value> 
     200  </data> 
    153201  <data name="Files in {0} did not have their cluster tips erased because it is a hard link or a symbolic link." xml:space="preserve"> 
    154202    <value>Files in {0} did not have their cluster tips erased because it is a hard link or a symbolic link.</value> 
     
    166214    <value>{0} did not have its cluster tips erased because of the following error: {1}</value> 
    167215  </data> 
    168   <data name="{0} did not have its cluster tips erased because you do not have the required permissions to erase the file cluster tips." xml:space="preserve"> 
    169     <value>{0} did not have its cluster tips erased because you do not have the required permissions to erase the file cluster tips.</value> 
    170   </data> 
    171   <data name="{0} did not have its cluster tips erased. The error returned was: {1}" xml:space="preserve"> 
    172     <value>{0} did not have its cluster tips erased. The error returned was: {1}</value> 
    173   </data> 
    174   <data name="Erasing files..." xml:space="preserve"> 
    175     <value>Erasing files...</value> 
    176   </data> 
    177   <data name="The file {0} could not be erased because the file was either compressed, encrypted or a sparse file." xml:space="preserve"> 
    178     <value>The file {0} could not be erased because the file was either compressed, encrypted or a sparse file.</value> 
    179   </data> 
    180   <data name="The file {0} could not be erased because the file's permissions prevent access to the file." xml:space="preserve"> 
    181     <value>The file {0} could not be erased because the file's permissions prevent access to the file.</value> 
    182   </data> 
    183   <data name="Could not force closure of file \&quot;{0}\&quot; (locked by {1})" xml:space="preserve"> 
    184     <value>Could not force closure of file \"{0}\" (locked by {1})</value> 
    185   </data> 
    186   <data name="Removing folders..." xml:space="preserve"> 
    187     <value>Removing folders...</value> 
    188   </data> 
    189   <data name="Emptying recycle bin..." xml:space="preserve"> 
    190     <value>Emptying recycle bin...</value> 
    191   </data> 
    192   <data name="EntropySource GUID not found: {0}" xml:space="preserve"> 
    193     <value>EntropySource GUID not found: {0}</value> 
    194   </data> 
    195   <data name="Erasure method not found: {0}" xml:space="preserve"> 
    196     <value>Erasure method not found: {0}</value> 
    197   </data> 
    198   <data name="PRNG not found: {0}" xml:space="preserve"> 
    199     <value>PRNG not found: {0}</value> 
    200   </data> 
    201   <data name="The file system on the drive {0} is not supported." xml:space="preserve"> 
    202     <value>The file system on the drive {0} is not supported.</value> 
    203   </data> 
    204   <data name="Plausible deniability was selected, but no decoy files were found. The current file has been only replaced with random data." xml:space="preserve"> 
    205     <value>Plausible deniability was selected, but no decoy files were found. The current file has been only replaced with random data.</value> 
    206   </data> 
    207   <data name="The file {0} is currently in use and cannot be removed." xml:space="preserve"> 
    208     <value>The file {0} is currently in use and cannot be removed.</value> 
    209   </data> 
    210216  <data name="{0} (1 pass)" xml:space="preserve"> 
    211217    <value>{0} (1 pass)</value> 
Note: See TracChangeset for help on using the changeset viewer.