Changeset 2038
- Timestamp:
- 5/4/2010 1:28:39 AM (3 years ago)
- Location:
- trunk/eraser/Eraser.DefaultPlugins
- Files:
-
- 4 added
- 2 edited
-
Eraser.DefaultPlugins.csproj (modified) (3 diffs)
-
ErasureTargets/File.cs (modified) (2 diffs)
-
ErasureTargets/FileSystemObject.cs (added)
-
ErasureTargets/Folder.cs (added)
-
ErasureTargets/RecycleBin.cs (added)
-
ErasureTargets/UnusedSpace.cs (added)
Legend:
- Unmodified
- Added
- Removed
-
trunk/eraser/Eraser.DefaultPlugins/Eraser.DefaultPlugins.csproj
r2036 r2038 84 84 <Compile Include="ErasureMethods\RCMP_TSSIT_OPS_II.cs" /> 85 85 <Compile Include="ErasureTargets\File.cs" /> 86 <Compile Include="ErasureTargets\FileSystemObject.cs" /> 86 87 <Compile Include="ErasureTargets\FileErasureTargetSettings.cs"> 87 88 <SubType>UserControl</SubType> … … 90 91 <DependentUpon>FileErasureTargetSettings.cs</DependentUpon> 91 92 </Compile> 93 <Compile Include="ErasureTargets\Folder.cs" /> 92 94 <Compile Include="ErasureTargets\FolderErasureTargetSettings.cs"> 93 95 <SubType>UserControl</SubType> … … 96 98 <DependentUpon>FolderErasureTargetSettings.cs</DependentUpon> 97 99 </Compile> 100 <Compile Include="ErasureTargets\RecycleBin.cs" /> 101 <Compile Include="ErasureTargets\UnusedSpace.cs" /> 98 102 <Compile Include="ErasureTargets\UnusedSpaceErasureTargetSettings.cs"> 99 103 <SubType>UserControl</SubType> -
trunk/eraser/Eraser.DefaultPlugins/ErasureTargets/File.cs
r2037 r2038 25 25 using System.Text; 26 26 27 using System.Text.RegularExpressions;28 27 using System.Runtime.Serialization; 29 28 using System.Runtime.InteropServices; 30 using System.Security.Permissions;31 29 using System.IO; 32 33 using Eraser.Manager;34 using Eraser.Util;35 using Eraser.Util.ExtensionMethods;36 30 37 31 namespace Eraser.DefaultPlugins 38 32 { 39 /// <summary>40 /// Class representing a tangible object (file/folder) to be erased.41 /// </summary>42 [Serializable]43 public abstract class FileSystemObjectTarget : ErasureTarget44 {45 #region Serialization code46 protected FileSystemObjectTarget(SerializationInfo info, StreamingContext context)47 : base(info, context)48 {49 Path = (string)info.GetValue("Path", typeof(string));50 }51 52 [SecurityPermission(SecurityAction.Demand, SerializationFormatter = true)]53 public override void GetObjectData(SerializationInfo info, StreamingContext context)54 {55 base.GetObjectData(info, context);56 info.AddValue("Path", Path);57 }58 #endregion59 60 /// <summary>61 /// Constructor.62 /// </summary>63 protected FileSystemObjectTarget()64 : base()65 {66 }67 68 protected new SteppedProgressManager Progress69 {70 get71 {72 return (SteppedProgressManager)base.Progress;73 }74 set75 {76 base.Progress = value;77 }78 }79 80 /// <summary>81 /// Retrieves the list of files/folders to erase as a list.82 /// </summary>83 /// <param name="totalSize">Returns the total size in bytes of the84 /// items.</param>85 /// <returns>A list containing the paths to all the files to be erased.</returns>86 internal abstract List<string> GetPaths(out long totalSize);87 88 /// <summary>89 /// Adds ADSes of the given file to the list.90 /// </summary>91 /// <param name="list">The list to add the ADS paths to.</param>92 /// <param name="file">The file to look for ADSes</param>93 protected void GetPathADSes(ICollection<string> list, out long totalSize, string file)94 {95 totalSize = 0;96 97 try98 {99 //Get the ADS names100 IList<string> adses = new FileInfo(file).GetADSes();101 102 //Then prepend the path.103 foreach (string adsName in adses)104 {105 string adsPath = file + ':' + adsName;106 list.Add(adsPath);107 StreamInfo info = new StreamInfo(adsPath);108 totalSize += info.Length;109 }110 }111 catch (FileNotFoundException)112 {113 }114 catch (SharingViolationException)115 {116 //The system cannot open the file, try to force the file handle to close.117 if (!ManagerLibrary.Settings.ForceUnlockLockedFiles)118 throw;119 120 StringBuilder processStr = new StringBuilder();121 foreach (OpenHandle handle in OpenHandle.Close(file))122 {123 try124 {125 processStr.AppendFormat(126 System.Globalization.CultureInfo.InvariantCulture,127 "{0}, ", (System.Diagnostics.Process.GetProcessById(handle.ProcessId)).MainModule.FileName);128 }129 catch (System.ComponentModel.Win32Exception)130 {131 processStr.AppendFormat(132 System.Globalization.CultureInfo.InvariantCulture,133 "Process ID {0}, ", handle.ProcessId);134 }135 }136 137 if (processStr.Length == 0)138 {139 GetPathADSes(list, out totalSize, file);140 return;141 }142 else143 throw;144 }145 catch (UnauthorizedAccessException e)146 {147 //The system cannot read the file, assume no ADSes for lack of148 //more information.149 Logger.Log(e.Message, LogLevel.Error);150 }151 }152 153 /// <summary>154 /// The path to the file or folder referred to by this object.155 /// </summary>156 public string Path { get; set; }157 158 public sealed override ErasureMethod EffectiveMethod159 {160 get161 {162 if (Method != ErasureMethodRegistrar.Default)163 return base.EffectiveMethod;164 165 return ManagerLibrary.Instance.ErasureMethodRegistrar[166 ManagerLibrary.Settings.DefaultFileErasureMethod];167 }168 }169 170 public override string UIText171 {172 get173 {174 string fileName = System.IO.Path.GetFileName(Path);175 string directoryName = System.IO.Path.GetDirectoryName(Path);176 return string.IsNullOrEmpty(fileName) ?177 (string.IsNullOrEmpty(directoryName) ? Path : directoryName)178 : fileName;179 }180 }181 182 public override void Execute()183 {184 //Retrieve the list of files to erase.185 long dataTotal = 0;186 List<string> paths = GetPaths(out dataTotal);187 188 //Get the erasure method if the user specified he wants the default.189 ErasureMethod method = EffectiveMethod;190 dataTotal = method.CalculateEraseDataSize(paths, dataTotal);191 192 //Set the event's current target status.193 SteppedProgressManager progress = new SteppedProgressManager();194 Progress = progress;195 Task.Progress.Steps.Add(new SteppedProgressManagerStep(progress, 1.0f / Task.Targets.Count));196 197 //Iterate over every path, and erase the path.198 for (int i = 0; i < paths.Count; ++i)199 {200 //Check that the file exists - we do not want to bother erasing nonexistant files201 StreamInfo info = new StreamInfo(paths[i]);202 if (!info.Exists)203 {204 Logger.Log(S._("The file {0} was not erased as the file does not exist.",205 paths[i]), LogLevel.Notice);206 continue;207 }208 209 //Get the filesystem provider to handle the secure file erasures210 FileSystem fsManager = ManagerLibrary.Instance.FileSystemRegistrar[211 VolumeInfo.FromMountPoint(info.DirectoryName)];212 213 bool isReadOnly = false;214 215 try216 {217 //Update the task progress218 ProgressManager step = new ProgressManager();219 progress.Steps.Add(new SteppedProgressManagerStep(step,220 info.Length / (float)dataTotal, S._("Erasing files...")));221 OnProgressChanged(this, new ProgressChangedEventArgs(step,222 new TaskProgressChangedEventArgs(paths[i], 0, method.Passes)));223 224 //Remove the read-only flag, if it is set.225 if (isReadOnly = info.IsReadOnly)226 info.IsReadOnly = false;227 228 //Make sure the file does not have any attributes which may affect229 //the erasure process230 if ((info.Attributes & FileAttributes.Compressed) != 0 ||231 (info.Attributes & FileAttributes.Encrypted) != 0 ||232 (info.Attributes & FileAttributes.SparseFile) != 0)233 {234 //Log the error235 Logger.Log(S._("The file {0} could not be erased because the file was " +236 "either compressed, encrypted or a sparse file.", info.FullName),237 LogLevel.Error);238 continue;239 }240 241 fsManager.EraseFileSystemObject(info, method,242 delegate(long lastWritten, long totalData, int currentPass)243 {244 if (Task.Canceled)245 throw new OperationCanceledException(S._("The task was cancelled."));246 247 step.Total = totalData;248 step.Completed += lastWritten;249 OnProgressChanged(this, new ProgressChangedEventArgs(step,250 new TaskProgressChangedEventArgs(info.FullName, currentPass, method.Passes)));251 });252 253 //Remove the file.254 FileInfo fileInfo = info.File;255 if (fileInfo != null)256 fsManager.DeleteFile(fileInfo);257 step.MarkComplete();258 }259 catch (UnauthorizedAccessException)260 {261 Logger.Log(S._("The file {0} could not be erased because the file's " +262 "permissions prevent access to the file.", info.FullName), LogLevel.Error);263 }264 catch (SharingViolationException)265 {266 if (!ManagerLibrary.Settings.ForceUnlockLockedFiles)267 throw;268 269 StringBuilder processStr = new StringBuilder();270 foreach (OpenHandle handle in OpenHandle.Close(info.FullName))271 {272 try273 {274 processStr.AppendFormat(275 System.Globalization.CultureInfo.InvariantCulture,276 "{0}, ", System.Diagnostics.Process.GetProcessById(handle.ProcessId).MainModule.FileName);277 }278 catch (System.ComponentModel.Win32Exception)279 {280 processStr.AppendFormat(281 System.Globalization.CultureInfo.InvariantCulture,282 "Process ID {0}, ", handle.ProcessId);283 }284 }285 286 if (processStr.Length != 0)287 Logger.Log(S._("Could not force closure of file \"{0}\" {1}",288 paths[i], S._("(locked by {0})",289 processStr.ToString().Remove(processStr.Length - 2)).Trim()),290 LogLevel.Error);291 }292 finally293 {294 //Re-set the read-only flag if the file exists (i.e. there was an error)295 if (isReadOnly && info.Exists && !info.IsReadOnly)296 info.IsReadOnly = isReadOnly;297 }298 }299 300 Progress = null;301 }302 }303 304 /// <summary>305 /// Class representing a unused space erase.306 /// </summary>307 [Serializable]308 [Guid("A627BEC4-CAFC-46ce-92AD-209157C3177A")]309 public class UnusedSpaceTarget : ErasureTarget310 {311 #region Serialization code312 protected UnusedSpaceTarget(SerializationInfo info, StreamingContext context)313 : base(info, context)314 {315 Drive = (string)info.GetValue("Drive", typeof(string));316 EraseClusterTips = (bool)info.GetValue("EraseClusterTips", typeof(bool));317 }318 319 [SecurityPermission(SecurityAction.Demand, SerializationFormatter = true)]320 public override void GetObjectData(SerializationInfo info, StreamingContext context)321 {322 base.GetObjectData(info, context);323 info.AddValue("Drive", Drive);324 info.AddValue("EraseClusterTips", EraseClusterTips);325 }326 #endregion327 328 /// <summary>329 /// Constructor.330 /// </summary>331 public UnusedSpaceTarget()332 : base()333 {334 }335 336 public override Guid Guid337 {338 get { return GetType().GUID; }339 }340 341 public sealed override ErasureMethod EffectiveMethod342 {343 get344 {345 if (Method == ErasureMethodRegistrar.Default)346 return base.EffectiveMethod;347 348 return ManagerLibrary.Instance.ErasureMethodRegistrar[349 ManagerLibrary.Settings.DefaultUnusedSpaceErasureMethod];350 }351 }352 353 public override bool SupportsMethod(ErasureMethod method)354 {355 return method == ErasureMethodRegistrar.Default ||356 method is UnusedSpaceErasureMethod;357 }358 359 /// <summary>360 /// Override the base class property so that we won't need to keep casting361 /// </summary>362 protected new SteppedProgressManager Progress363 {364 get365 {366 return (SteppedProgressManager)base.Progress;367 }368 set369 {370 base.Progress = value;371 }372 }373 374 public override string UIText375 {376 get { return S._("Unused disk space ({0})", Drive); }377 }378 379 public override IErasureTargetConfigurer Configurer380 {381 get { return new UnusedSpaceErasureTargetSettings(); }382 }383 384 /// <summary>385 /// The drive to erase386 /// </summary>387 public string Drive { get; set; }388 389 /// <summary>390 /// Whether cluster tips should be erased.391 /// </summary>392 public bool EraseClusterTips { get; set; }393 394 public override void Execute()395 {396 //Check for sufficient privileges to run the unused space erasure.397 if (!Security.IsAdministrator())398 {399 if (Environment.OSVersion.Platform == PlatformID.Win32NT &&400 Environment.OSVersion.Version >= new Version(6, 0))401 {402 Logger.Log(S._("The program does not have the required permissions to erase " +403 "the unused space on disk. Run the program as an administrator and retry " +404 "the operation."), LogLevel.Error);405 }406 else407 {408 Logger.Log(S._("The program does not have the required permissions to erase " +409 "the unused space on disk."), LogLevel.Error);410 }411 412 return;413 }414 415 //Check whether System Restore has any available checkpoints.416 if (SystemRestore.GetInstances().Count != 0)417 {418 Logger.Log(S._("This computer has had System Restore or Volume Shadow Copies " +419 "enabled. This may allow copies of files stored on the disk to be recovered " +420 "and pose a security concern.", Drive), LogLevel.Warning);421 }422 423 //If the user is under disk quotas, log a warning message424 if (VolumeInfo.FromMountPoint(Drive).HasQuota)425 Logger.Log(S._("The drive {0} has disk quotas active. This will prevent the " +426 "complete erasure of unused space and may pose a security concern.",427 Drive), LogLevel.Warning);428 429 //Get the erasure method if the user specified he wants the default.430 ErasureMethod method = EffectiveMethod;431 432 //Make a folder to dump our temporary files in433 DirectoryInfo info = new DirectoryInfo(Drive);434 VolumeInfo volInfo = VolumeInfo.FromMountPoint(Drive);435 FileSystem fsManager = ManagerLibrary.Instance.FileSystemRegistrar[volInfo];436 437 //Start sampling the speed of the task.438 Progress = new SteppedProgressManager();439 Task.Progress.Steps.Add(new SteppedProgressManagerStep(440 Progress, 1.0f / Task.Targets.Count));441 442 //Erase the cluster tips of every file on the drive.443 if (EraseClusterTips)444 {445 //Define the callback handlers446 ProgressManager tipSearch = new ProgressManager();447 Progress.Steps.Add(new SteppedProgressManagerStep(tipSearch,448 0.0f, S._("Searching for files' cluster tips...")));449 tipSearch.Total = 1;450 ClusterTipsSearchProgress searchProgress = delegate(string path)451 {452 if (Task.Canceled)453 throw new OperationCanceledException(S._("The task was cancelled."));454 455 OnProgressChanged(this, new ProgressChangedEventArgs(tipSearch,456 new TaskProgressChangedEventArgs(path, 0, 0)));457 };458 459 ProgressManager tipProgress = new ProgressManager();460 Progress.Steps.Add(new SteppedProgressManagerStep(tipProgress, 0.1f,461 S._("Erasing cluster tips...")));462 ClusterTipsEraseProgress eraseProgress =463 delegate(int currentFile, int totalFiles, string currentFilePath)464 {465 tipSearch.MarkComplete();466 tipProgress.Total = totalFiles;467 tipProgress.Completed = currentFile;468 OnProgressChanged(this, new ProgressChangedEventArgs(tipProgress,469 new TaskProgressChangedEventArgs(currentFilePath, 0, 0)));470 471 if (Task.Canceled)472 throw new OperationCanceledException(S._("The task was cancelled."));473 };474 475 //Start counting statistics476 fsManager.EraseClusterTips(VolumeInfo.FromMountPoint(Drive),477 method, searchProgress, eraseProgress);478 tipProgress.MarkComplete();479 }480 481 bool lowDiskSpaceNotifications = Shell.LowDiskSpaceNotificationsEnabled;482 info = info.CreateSubdirectory(Path.GetFileName(483 FileSystem.GenerateRandomFileName(info, 18)));484 try485 {486 //Set the folder's compression flag off since we want to use as much487 //space as possible488 if (info.IsCompressed())489 info.Uncompress();490 491 //Disable the low disk space notifications492 Shell.LowDiskSpaceNotificationsEnabled = false;493 494 ProgressManager mainProgress = new ProgressManager();495 Progress.Steps.Add(new SteppedProgressManagerStep(mainProgress,496 EraseClusterTips ? 0.8f : 0.9f, S._("Erasing unused space...")));497 498 //Continue creating files while there is free space.499 while (volInfo.AvailableFreeSpace > 0)500 {501 //Generate a non-existant file name502 string currFile = FileSystem.GenerateRandomFileName(info, 18);503 504 //Create the stream505 using (FileStream stream = new FileStream(currFile, FileMode.CreateNew,506 FileAccess.Write, FileShare.None, 8, FileOptions.WriteThrough))507 {508 //Set the length of the file to be the amount of free space left509 //or the maximum size of one of these dumps.510 mainProgress.Total = mainProgress.Completed +511 method.CalculateEraseDataSize(null, volInfo.AvailableFreeSpace);512 long streamLength = Math.Min(ErasureMethod.FreeSpaceFileUnit,513 volInfo.AvailableFreeSpace);514 515 //Handle IO exceptions gracefully, because the filesystem516 //may require more space than demanded by us for file allocation.517 while (true)518 try519 {520 stream.SetLength(streamLength);521 break;522 }523 catch (IOException)524 {525 if (streamLength > volInfo.ClusterSize)526 streamLength -= volInfo.ClusterSize;527 else528 throw;529 }530 531 //Then run the erase task532 method.Erase(stream, long.MaxValue,533 ManagerLibrary.Instance.PrngRegistrar[ManagerLibrary.Settings.ActivePrng],534 delegate(long lastWritten, long totalData, int currentPass)535 {536 mainProgress.Completed += lastWritten;537 OnProgressChanged(this, new ProgressChangedEventArgs(mainProgress,538 new TaskProgressChangedEventArgs(Drive, currentPass, method.Passes)));539 540 if (Task.Canceled)541 throw new OperationCanceledException(S._("The task was cancelled."));542 }543 );544 }545 }546 547 //Mark the main bulk of the progress as complete548 mainProgress.MarkComplete();549 550 //Erase old resident file system table files551 ProgressManager residentProgress = new ProgressManager();552 Progress.Steps.Add(new SteppedProgressManagerStep(residentProgress,553 0.05f, S._("Old resident file system table files")));554 fsManager.EraseOldFileSystemResidentFiles(volInfo, info, method,555 delegate(int currentFile, int totalFiles)556 {557 residentProgress.Completed = currentFile;558 residentProgress.Total = totalFiles;559 OnProgressChanged(this, new ProgressChangedEventArgs(residentProgress,560 new TaskProgressChangedEventArgs(string.Empty, 0, 0)));561 562 if (Task.Canceled)563 throw new OperationCanceledException(S._("The task was cancelled."));564 }565 );566 567 residentProgress.MarkComplete();568 }569 finally570 {571 //Remove the folder holding all our temporary files.572 ProgressManager tempFiles = new ProgressManager();573 Progress.Steps.Add(new SteppedProgressManagerStep(tempFiles,574 0.0f, S._("Removing temporary files...")));575 OnProgressChanged(this, new ProgressChangedEventArgs(tempFiles,576 new TaskProgressChangedEventArgs(string.Empty, 0, 0)));577 info.Delete(true);578 tempFiles.Completed = tempFiles.Total;579 580 //Reset the low disk space notifications581 Shell.LowDiskSpaceNotificationsEnabled = lowDiskSpaceNotifications;582 }583 584 //Then clean the old file system entries585 ProgressManager structureProgress = new ProgressManager();586 Progress.Steps.Add(new SteppedProgressManagerStep(structureProgress,587 0.05f, S._("Erasing unused directory structures...")));588 fsManager.EraseDirectoryStructures(volInfo,589 delegate(int currentFile, int totalFiles)590 {591 if (Task.Canceled)592 throw new OperationCanceledException(S._("The task was cancelled."));593 594 //Compute the progress595 structureProgress.Total = totalFiles;596 structureProgress.Completed = currentFile;597 598 //Set the event parameters, then broadcast the progress event.599 OnProgressChanged(this, new ProgressChangedEventArgs(structureProgress,600 new TaskProgressChangedEventArgs(string.Empty, 0, 0)));601 }602 );603 604 structureProgress.MarkComplete();605 Progress = null;606 }607 }608 609 33 /// <summary> 610 34 /// Class representing a file to be erased. … … 654 78 } 655 79 } 656 657 /// <summary>658 /// Represents a folder and its files which are to be erased.659 /// </summary>660 [Serializable]661 [Guid("F50B0A44-3AB1-4cab-B81E-1713AC3D28C9")]662 public class FolderTarget : FileSystemObjectTarget663 {664 #region Serialization code665 protected FolderTarget(SerializationInfo info, StreamingContext context)666 : base(info, context)667 {668 IncludeMask = (string)info.GetValue("IncludeMask", typeof(string));669 ExcludeMask = (string)info.GetValue("ExcludeMask", typeof(string));670 DeleteIfEmpty = (bool)info.GetValue("DeleteIfEmpty", typeof(bool));671 }672 673 [SecurityPermission(SecurityAction.Demand, SerializationFormatter = true)]674 public override void GetObjectData(SerializationInfo info, StreamingContext context)675 {676 base.GetObjectData(info, context);677 info.AddValue("IncludeMask", IncludeMask);678 info.AddValue("ExcludeMask", ExcludeMask);679 info.AddValue("DeleteIfEmpty", DeleteIfEmpty);680 }681 #endregion682 683 /// <summary>684 /// Constructor.685 /// </summary>686 public FolderTarget()687 {688 IncludeMask = string.Empty;689 ExcludeMask = string.Empty;690 DeleteIfEmpty = true;691 }692 693 public override Guid Guid694 {695 get { return GetType().GUID; }696 }697 698 public override IErasureTargetConfigurer Configurer699 {700 get { return new FolderErasureTargetSettings(); }701 }702 703 internal override List<string> GetPaths(out long totalSize)704 {705 //Get a list to hold all the resulting paths.706 List<string> result = new List<string>();707 708 //Open the root of the search, including every file matching the pattern709 DirectoryInfo dir = new DirectoryInfo(Path);710 711 //List recursively all the files which match the include pattern.712 FileInfo[] files = GetFiles(dir);713 714 //Then exclude each file and finalize the list and total file size715 totalSize = 0;716 if (ExcludeMask.Length != 0)717 {718 string regex = Regex.Escape(ExcludeMask).Replace("\\*", ".*").719 Replace("\\?", ".");720 Regex excludePattern = new Regex(regex, RegexOptions.IgnoreCase);721 foreach (FileInfo file in files)722 if (file.Exists &&723 (file.Attributes & FileAttributes.ReparsePoint) == 0 &&724 excludePattern.Matches(file.FullName).Count == 0)725 {726 totalSize += file.Length;727 GetPathADSes(result, out totalSize, file.FullName);728 result.Add(file.FullName);729 }730 }731 else732 foreach (FileInfo file in files)733 {734 if (!file.Exists || (file.Attributes & FileAttributes.ReparsePoint) != 0)735 continue;736 737 //Get the size of the file and its ADSes738 totalSize += file.Length;739 long adsesSize = 0;740 GetPathADSes(result, out adsesSize, file.FullName);741 totalSize += adsesSize;742 743 //Append this file to the list of files to erase.744 result.Add(file.FullName);745 }746 747 //Return the filtered list.748 return result;749 }750 751 /// <summary>752 /// Gets all files in the provided directory.753 /// </summary>754 /// <param name="info">The directory to look files in.</param>755 /// <returns>A list of files found in the directory matching the IncludeMask756 /// property.</returns>757 private FileInfo[] GetFiles(DirectoryInfo info)758 {759 List<FileInfo> result = new List<FileInfo>();760 if (info.Exists)761 {762 try763 {764 foreach (DirectoryInfo dir in info.GetDirectories())765 result.AddRange(GetFiles(dir));766 767 if (IncludeMask.Length == 0)768 result.AddRange(info.GetFiles());769 else770 result.AddRange(info.GetFiles(IncludeMask, SearchOption.TopDirectoryOnly));771 }772 catch (UnauthorizedAccessException e)773 {774 Logger.Log(S._("Could not erase files and subfolders in {0} because {1}",775 info.FullName, e.Message), LogLevel.Error);776 }777 }778 779 return result.ToArray();780 }781 782 /// <summary>783 /// A wildcard expression stating the condition for the set of files to include.784 /// The include mask is applied before the exclude mask is applied. If this value785 /// is empty, all files and folders within the folder specified is included.786 /// </summary>787 public string IncludeMask { get; set; }788 789 /// <summary>790 /// A wildcard expression stating the condition for removing files from the set791 /// of included files. If this value is omitted, all files and folders extracted792 /// by the inclusion mask is erased.793 /// </summary>794 public string ExcludeMask { get; set; }795 796 /// <summary>797 /// Determines if Eraser should delete the folder after the erase process.798 /// </summary>799 public bool DeleteIfEmpty { get; set; }800 801 public override void Execute()802 {803 base.Execute();804 805 //If the user requested a folder removal, do it.806 if (Directory.Exists(Path))807 {808 ProgressManager step = new ProgressManager();809 Progress.Steps.Add(new SteppedProgressManagerStep(step,810 0.0f, S._("Removing folders...")));811 812 //Remove all subfolders which are empty.813 FileSystem fsManager = ManagerLibrary.Instance.FileSystemRegistrar[814 VolumeInfo.FromMountPoint(Path)];815 Action<DirectoryInfo> eraseEmptySubFolders = null;816 eraseEmptySubFolders = delegate(DirectoryInfo info)817 {818 foreach (DirectoryInfo subDir in info.GetDirectories())819 eraseEmptySubFolders(subDir);820 OnProgressChanged(this, new ProgressChangedEventArgs(step,821 new TaskProgressChangedEventArgs(info.FullName, 0, 0)));822 823 FileSystemInfo[] files = info.GetFileSystemInfos();824 if (files.Length == 0)825 fsManager.DeleteFolder(info);826 };827 828 DirectoryInfo directory = new DirectoryInfo(Path);829 foreach (DirectoryInfo subDir in directory.GetDirectories())830 eraseEmptySubFolders(subDir);831 832 if (DeleteIfEmpty)833 {834 //See if this is the root of a volume.835 bool isVolumeRoot = directory.Parent == null;836 foreach (VolumeInfo volume in VolumeInfo.Volumes)837 foreach (string mountPoint in volume.MountPoints)838 if (directory.FullName == mountPoint)839 isVolumeRoot = true;840 841 //If the folder is a mount point, then don't delete it. If it isn't,842 //search for files under the folder to see if it is empty.843 if (!isVolumeRoot && directory.Exists &&844 directory.GetFiles("*", SearchOption.AllDirectories).Length == 0)845 {846 fsManager.DeleteFolder(directory);847 }848 }849 }850 }851 }852 853 [Serializable]854 [Guid("A1FA7354-0258-4903-88E9-0D31FC5F8D51")]855 public class RecycleBinTarget : FileSystemObjectTarget856 {857 #region Serialization code858 protected RecycleBinTarget(SerializationInfo info, StreamingContext context)859 : base(info, context)860 {861 }862 #endregion863 864 public RecycleBinTarget()865 {866 }867 868 public override Guid Guid869 {870 get { return GetType().GUID; }871 }872 873 public override IErasureTargetConfigurer Configurer874 {875 get { return null; }876 }877 878 internal override List<string> GetPaths(out long totalSize)879 {880 totalSize = 0;881 List<string> result = new List<string>();882 string[] rootDirectory = new string[] {883 "$RECYCLE.BIN",884 "RECYCLER"885 };886 887 foreach (DriveInfo drive in DriveInfo.GetDrives())888 {889 foreach (string rootDir in rootDirectory)890 {891 DirectoryInfo dir = new DirectoryInfo(892 System.IO.Path.Combine(893 System.IO.Path.Combine(drive.Name, rootDir),894 System.Security.Principal.WindowsIdentity.GetCurrent().895 User.ToString()));896 if (!dir.Exists)897 continue;898 899 GetRecyclerFiles(dir, result, ref totalSize);900 }901 }902 903 return result;904 }905 906 /// <summary>907 /// Retrieves all files within this folder, without exclusions.908 /// </summary>909 /// <param name="info">The DirectoryInfo object representing the folder to traverse.</param>910 /// <param name="paths">The list of files to store path information in.</param>911 /// <param name="totalSize">Receives the total size of the files.</param>912 private void GetRecyclerFiles(DirectoryInfo info, List<string> paths,913 ref long totalSize)914 {915 try916 {917 foreach (FileInfo fileInfo in info.GetFiles())918 {919 if (!fileInfo.Exists || (fileInfo.Attributes & FileAttributes.ReparsePoint) != 0)920 continue;921 922 long adsSize = 0;923 GetPathADSes(paths, out adsSize, fileInfo.FullName);924 totalSize += adsSize;925 totalSize += fileInfo.Length;926 paths.Add(fileInfo.FullName);927 }928 929 foreach (DirectoryInfo directoryInfo in info.GetDirectories())930 if ((directoryInfo.Attributes & FileAttributes.ReparsePoint) == 0)931 GetRecyclerFiles(directoryInfo, paths, ref totalSize);932 }933 catch (UnauthorizedAccessException e)934 {935 Logger.Log(e.Message, LogLevel.Error);936 }937 }938 939 /// <summary>940 /// Retrieves the text to display representing this task.941 /// </summary>942 public override string UIText943 {944 get945 {946 return S._("Recycle Bin");947 }948 }949 950 public override void Execute()951 {952 base.Execute();953 954 ProgressManager step = new ProgressManager();955 Progress.Steps.Add(new SteppedProgressManagerStep(step,956 0.0f, S._("Emptying recycle bin...")));957 OnProgressChanged(this, new ProgressChangedEventArgs(step,958 new TaskProgressChangedEventArgs(string.Empty, 0, 0)));959 960 RecycleBin.Empty(EmptyRecycleBinOptions.NoConfirmation |961 EmptyRecycleBinOptions.NoProgressUI | EmptyRecycleBinOptions.NoSound);962 }963 }964 80 }
Note: See TracChangeset
for help on using the changeset viewer.
