Changeset 292
- Timestamp:
- 3/20/2008 1:51:49 PM (5 years ago)
- Location:
- branches/eraser6
- Files:
-
- 1 added
- 4 edited
-
Manager/DirectExecutor.cs (modified) (7 diffs)
-
Manager/Task.cs (modified) (5 diffs)
-
Util/File.cs (modified) (2 diffs)
-
Util/StreamInfo.cs (added)
-
Util/Util.csproj (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
-
branches/eraser6/Manager/DirectExecutor.cs
r283 r292 506 506 "erased, because it is a system file", file.FullName), LogLevel.INFORMATION)); 507 507 else 508 { 509 foreach (string i in Util.File.GetADSes(file)) 510 files.Add(file.FullName + ':' + i); 508 511 files.Add(file.FullName); 512 } 509 513 510 514 foreach (DirectoryInfo subDir in info.GetDirectories()) … … 537 541 { 538 542 //Get the file access times 539 DateTime lastAccess, lastWrite, created; 540 { 541 FileInfo info = new FileInfo(file); 542 lastAccess = info.LastAccessTime; 543 lastWrite = info.LastWriteTime; 544 created = info.CreationTime; 543 StreamInfo streamInfo = new StreamInfo(file); 544 DateTime lastAccess = DateTime.MinValue, lastWrite = DateTime.MinValue, 545 created = DateTime.MinValue; 546 { 547 FileInfo info = streamInfo.File; 548 if (info != null) 549 { 550 lastAccess = info.LastAccessTime; 551 lastWrite = info.LastWriteTime; 552 created = info.CreationTime; 553 } 545 554 } 546 555 547 556 //Create the stream, lengthen the file, then tell the erasure method 548 557 //to erase the tips. 549 using (FileStream stream = new FileStream(file, FileMode.Open, 550 FileAccess.Write, FileShare.ReadWrite)) 558 using (FileStream stream = streamInfo.Open(FileMode.Open, FileAccess.Write)) 551 559 { 552 560 long fileLength = stream.Length; … … 570 578 571 579 //Set the file times 572 { 573 FileInfo info = new FileInfo(file); 574 info.LastAccessTime = lastAccess; 575 info.LastWriteTime = lastWrite; 576 info.CreationTime = created; 580 FileInfo fileInfo = streamInfo.File; 581 if (fileInfo != null) 582 { 583 fileInfo.LastAccessTime = lastAccess; 584 fileInfo.LastWriteTime = lastWrite; 585 fileInfo.CreationTime = created; 577 586 } 578 587 } … … 594 603 method = ErasureMethodManager.GetInstance(ManagerLibrary.Instance.Settings.DefaultFileErasureMethod); 595 604 596 //Calculate the total amount of data required to finish the wipe. This 597 //value is just the total about of data to be erased multiplied by 598 //number of passes 605 //Calculate the total amount of data required to finish the wipe. 599 606 dataTotal = method.CalculateEraseDataSize(paths, dataTotal); 600 607 … … 613 620 task.OnProgressChanged(eventArgs); 614 621 615 //Make sure the file does not have any attributes which may 616 //affect the erasure process 617 FileInfo info = new FileInfo(paths[i]); 622 //Make sure the file does not have any attributes which may affect 623 //the erasure process 624 bool isReadOnly = false; 625 StreamInfo info = new StreamInfo(paths[i]); 618 626 if ((info.Attributes & FileAttributes.Compressed) != 0 || 619 627 (info.Attributes & FileAttributes.Encrypted) != 0 || … … 627 635 628 636 //Remove the read-only flag, if it is set. 629 if ((info.Attributes & FileAttributes.ReadOnly) != 0) 630 info.Attributes &= ~FileAttributes.ReadOnly; 631 632 //Create the file stream, and call the erasure method 633 //to write to the stream. 634 using (FileStream strm = new FileStream(info.FullName, 635 FileMode.Open, FileAccess.Write, FileShare.None, 636 8, FileOptions.WriteThrough)) 637 { 638 //Set the end of the stream after the wrap-round the cluster size 639 strm.SetLength(GetFileArea(info.FullName)); 640 641 //Then erase the file. 642 long itemWritten = 0, 643 itemTotal = method.CalculateEraseDataSize(null, strm.Length); 644 method.Erase(strm, long.MaxValue, 645 PRNGManager.GetInstance(ManagerLibrary.Instance.Settings.ActivePRNG), 646 delegate(long lastWritten, int currentPass) 637 if (isReadOnly = info.IsReadOnly) 638 info.IsReadOnly = false; 639 640 try 641 { 642 //Create the file stream, and call the erasure method to write to 643 //the stream. 644 using (FileStream strm = info.Open(FileMode.Open, FileAccess.Write, 645 FileShare.None, FileOptions.WriteThrough)) 646 { 647 //Set the end of the stream after the wrap-round the cluster size 648 strm.SetLength(GetFileArea(paths[i])); 649 650 //If the stream is empty, there's nothing to overwrite. Continue 651 //to the next entry 652 if (strm.Length != 0) 647 653 { 648 statistics.DataWritten += lastWritten; 649 eventArgs.currentPass = currentPass; 650 eventArgs.currentItemProgress = (int)((itemWritten += lastWritten) * 100 / itemTotal); 651 eventArgs.overallProgress = (int)(statistics.DataWritten * 100 / dataTotal); 652 653 if (statistics.Speed != 0) 654 eventArgs.timeLeft = (int)(dataTotal - statistics.DataWritten) / statistics.Speed; 655 else 656 eventArgs.timeLeft = -1; 657 task.OnProgressChanged(eventArgs); 658 659 lock (currentTask) 660 if (currentTask.cancelled) 661 throw new FatalException("The task was cancelled."); 654 //Then erase the file. 655 long itemWritten = 0, 656 itemTotal = method.CalculateEraseDataSize(null, strm.Length); 657 method.Erase(strm, long.MaxValue, 658 PRNGManager.GetInstance(ManagerLibrary.Instance.Settings.ActivePRNG), 659 delegate(long lastWritten, int currentPass) 660 { 661 statistics.DataWritten += lastWritten; 662 eventArgs.currentPass = currentPass; 663 eventArgs.currentItemProgress = (int) 664 ((itemWritten += lastWritten) * 100 / itemTotal); 665 eventArgs.overallProgress = (int) 666 (statistics.DataWritten * 100 / dataTotal); 667 668 if (statistics.Speed != 0) 669 eventArgs.timeLeft = (int) 670 (dataTotal - statistics.DataWritten) / statistics.Speed; 671 else 672 eventArgs.timeLeft = -1; 673 task.OnProgressChanged(eventArgs); 674 675 lock (currentTask) 676 if (currentTask.cancelled) 677 throw new FatalException("The task was cancelled."); 678 } 679 ); 662 680 } 663 ); 664 665 //Set the length of the file to 0. 666 strm.Seek(0, SeekOrigin.Begin); 667 strm.SetLength(0); 668 } 669 670 //Remove the file. 671 RemoveFile(info); 681 682 //Set the length of the file to 0. 683 strm.Seek(0, SeekOrigin.Begin); 684 strm.SetLength(0); 685 } 686 687 //Remove the file. 688 FileInfo fileInfo = info.File; 689 if (fileInfo != null) 690 RemoveFile(fileInfo); 691 } 692 finally 693 { 694 //Re-set the read-only flag 695 info.IsReadOnly = isReadOnly; 696 } 672 697 } 673 698 … … 689 714 private static long GetFileArea(string filePath) 690 715 { 691 FileInfo info = new FileInfo(filePath);716 StreamInfo info = new StreamInfo(filePath); 692 717 uint clusterSize = Drive.GetClusterSize(info.Directory.Root.FullName); 693 718 return (info.Length + (clusterSize - 1)) & ~(clusterSize - 1); -
branches/eraser6/Manager/Task.cs
r283 r292 6 6 using System.Runtime.Serialization; 7 7 using System.ComponentModel; 8 using Eraser.Util; 8 9 9 10 namespace Eraser.Manager … … 104 105 105 106 /// <summary> 107 /// Adds ADSes of the given file to the list. 108 /// </summary> 109 /// <param name="list">The list to add the ADS paths to.</param> 110 /// <param name="file">The file to look for ADSes</param> 111 protected void GetPathADSes(ref List<string> list, ref long totalSize, string file) 112 { 113 //Get the ADS names 114 List<string> adses = Util.File.GetADSes(new FileInfo(file)); 115 116 //Then prepend the path. 117 foreach (string adsName in adses) 118 { 119 string adsPath = file + ':' + adsName; 120 list.Add(adsPath); 121 Util.StreamInfo info = new Util.StreamInfo(adsPath); 122 totalSize += info.Length; 123 } 124 } 125 126 /// <summary> 106 127 /// The path to the file or folder referred to by this object. 107 128 /// </summary> … … 189 210 { 190 211 List<string> result = new List<string>(); 212 totalSize = 0; 213 GetPathADSes(ref result, ref totalSize, Path); 214 215 totalSize += new FileInfo(Path).Length; 191 216 result.Add(Path); 192 193 totalSize = new FileInfo(Path).Length;194 217 return result; 195 218 } … … 253 276 { 254 277 totalSize += file.Length; 278 GetPathADSes(ref result, ref totalSize, file.FullName); 255 279 result.Add(file.FullName); 256 280 } … … 260 284 { 261 285 totalSize += file.Length; 286 GetPathADSes(ref result, ref totalSize, file.FullName); 262 287 result.Add(file.FullName); 263 288 } -
branches/eraser6/Util/File.cs
r291 r292 16 16 public static class File 17 17 { 18 /// <summary> 19 /// Gets the list of ADSes of the given file. 20 /// </summary> 21 /// <param name="info">The FileInfo object with the file path etc.</param> 22 /// <returns>A list containing the names of the ADSes of each file. The 23 /// list will be empty if no ADSes exist.</returns> 24 public static List<string> GetADSes(FileInfo info) 25 { 26 List<string> result = new List<string>(); 27 using (FileStream stream = info.OpenRead()) 28 { 29 SafeFileHandle streamHandle = stream.SafeFileHandle; 30 31 //Allocate the structures 32 WIN32_STREAM_ID streamID = new WIN32_STREAM_ID(); 33 IntPtr context = IntPtr.Zero; 34 uint bytesRead = 0; 35 36 //Read the header of the WIN32_STREAM_ID 37 BackupRead(streamHandle, ref streamID, (uint)Marshal.SizeOf(streamID), 38 ref bytesRead, false, false, ref context); 39 40 while (bytesRead == Marshal.SizeOf(streamID)) 41 { 42 if (streamID.dwStreamId == BACKUP_ALTERNATE_DATA) 43 { 44 //Allocate memory to copy the stream name into, then copy the name 45 IntPtr pName = Marshal.AllocHGlobal((IntPtr)streamID.dwStreamNameSize); 46 uint nameLength = streamID.dwStreamNameSize / sizeof(char); 47 char[] name = new char[nameLength]; 48 BackupRead(streamHandle, pName, streamID.dwStreamNameSize, ref bytesRead, 49 false, false, ref context); 50 Marshal.Copy(pName, name, 0, (int)nameLength); 51 52 //Get the name of the stream. The raw value is :NAME:$DATA 53 string streamName = new string(name); 54 result.Add(streamName.Substring(1, streamName.LastIndexOf(':') - 1)); 55 } 56 57 //Skip the file contents. Jump to the next header. 58 uint seekLow = 0, seekHigh = 0; 59 BackupSeek(streamHandle, (uint)(streamID.Size & uint.MaxValue), 60 (uint)(streamID.Size >> (sizeof(uint) * 8)), out seekLow, 61 out seekHigh, ref context); 62 63 //And try to read the header 64 BackupRead(streamHandle, ref streamID, (uint)Marshal.SizeOf(streamID), 65 ref bytesRead, false, false, ref context); 66 } 67 68 //Free the context 69 BackupRead(streamHandle, IntPtr.Zero, 0, ref bytesRead, true, false, ref context); 70 } 71 72 return result; 73 } 74 18 75 /// <summary> 19 76 /// Uses SHGetFileInfo to retrieve the description for the given file, … … 411 468 private static extern bool SfcIsFileProtected(IntPtr RpcHandle, 412 469 [MarshalAs(UnmanagedType.LPWStr)]string ProtFileName); 470 471 /// <summary> 472 /// The BackupRead function can be used to back up a file or directory, 473 /// including the security information. The function reads data associated 474 /// with a specified file or directory into a buffer, which can then be 475 /// written to the backup medium using the WriteFile function. 476 /// </summary> 477 /// <param name="hFile">Handle to the file or directory to be backed up. 478 /// To obtain the handle, call the CreateFile function. The SACLs are not 479 /// read unless the file handle was created with the ACCESS_SYSTEM_SECURITY 480 /// access right. For more information, see File Security and Access Rights. 481 /// 482 /// The BackupRead function may fail if CreateFile was called with the flag 483 /// FILE_FLAG_NO_BUFFERING. In this case, the GetLastError function 484 /// returns the value ERROR_INVALID_PARAMETER.</param> 485 /// <param name="lpBuffer">Pointer to a buffer that receives the data.</param> 486 /// <param name="nNumberOfBytesToRead">Length of the buffer, in bytes. The 487 /// buffer size must be greater than the size of a WIN32_STREAM_ID structure.</param> 488 /// <param name="lpNumberOfBytesRead">Pointer to a variable that receives 489 /// the number of bytes read. 490 /// 491 /// If the function returns a nonzero value, and the variable pointed to 492 /// by lpNumberOfBytesRead is zero, then all the data associated with the 493 /// file handle has been read.</param> 494 /// <param name="bAbort">Indicates whether you have finished using BackupRead 495 /// on the handle. While you are backing up the file, specify this parameter 496 /// as FALSE. Once you are done using BackupRead, you must call BackupRead 497 /// one more time specifying TRUE for this parameter and passing the appropriate 498 /// lpContext. lpContext must be passed when bAbort is TRUE; all other 499 /// parameters are ignored.</param> 500 /// <param name="bProcessSecurity">Indicates whether the function will 501 /// restore the access-control list (ACL) data for the file or directory. 502 /// 503 /// If bProcessSecurity is TRUE, the ACL data will be backed up.</param> 504 /// <param name="lpContext">Pointer to a variable that receives a pointer 505 /// to an internal data structure used by BackupRead to maintain context 506 /// information during a backup operation. 507 /// 508 /// You must set the variable pointed to by lpContext to NULL before the 509 /// first call to BackupRead for the specified file or directory. The 510 /// function allocates memory for the data structure, and then sets the 511 /// variable to point to that structure. You must not change lpContext or 512 /// the variable that it points to between calls to BackupRead. 513 /// 514 /// To release the memory used by the data structure, call BackupRead with 515 /// the bAbort parameter set to TRUE when the backup operation is complete.</param> 516 /// <returns>If the function succeeds, the return value is nonzero. 517 /// 518 /// If the function fails, the return value is zero, indicating that an 519 /// I/O error occurred. To get extended error information, call 520 /// Marshal.GetLastWin32Error.</returns> 521 [DllImport("Kernel32.dll", SetLastError = true)] 522 [return: MarshalAs(UnmanagedType.Bool)] 523 private static extern bool BackupRead(SafeFileHandle hFile, 524 IntPtr lpBuffer, uint nNumberOfBytesToRead, ref uint lpNumberOfBytesRead, 525 [MarshalAs(UnmanagedType.Bool)] bool bAbort, 526 [MarshalAs(UnmanagedType.Bool)] bool bProcessSecurity, 527 ref IntPtr lpContext); 528 529 530 [DllImport("Kernel32.dll", SetLastError = true)] 531 [return: MarshalAs(UnmanagedType.Bool)] 532 private static extern bool BackupRead(SafeFileHandle hFile, 533 ref WIN32_STREAM_ID lpBuffer, uint nNumberOfBytesToRead, 534 ref uint lpNumberOfBytesRead, [MarshalAs(UnmanagedType.Bool)] bool bAbort, 535 [MarshalAs(UnmanagedType.Bool)] bool bProcessSecurity, 536 ref IntPtr lpContext); 537 538 /// <summary> 539 /// The BackupSeek function seeks forward in a data stream initially 540 /// accessed by using the BackupRead or BackupWrite function. 541 /// </summary> 542 /// <param name="hFile">Handle to the file or directory. This handle is 543 /// created by using the CreateFile function.</param> 544 /// <param name="dwLowBytesToSeek">Low-order part of the number of bytes 545 /// to seek.</param> 546 /// <param name="dwHighBytesToSeek">High-order part of the number of bytes 547 /// to seek.</param> 548 /// <param name="lpdwLowByteSeeked">Pointer to a variable that receives 549 /// the low-order bits of the number of bytes the function actually seeks.</param> 550 /// <param name="lpdwHighByteSeeked">Pointer to a variable that receives 551 /// the high-order bits of the number of bytes the function actually seeks.</param> 552 /// <param name="lpContext">Pointer to an internal data structure used by 553 /// the function. This structure must be the same structure that was 554 /// initialized by the BackupRead function. An application must not touch 555 /// the contents of this structure.</param> 556 /// <returns>If the function could seek the requested amount, the function 557 /// returns a nonzero value. 558 /// 559 /// If the function could not seek the requested amount, the function 560 /// returns zero. To get extended error information, call 561 /// Marshal.GetLastWin32Error.</returns> 562 [DllImport("Kernel32.dll", SetLastError = true)] 563 [return: MarshalAs(UnmanagedType.Bool)] 564 private static extern bool BackupSeek(SafeFileHandle hFile, uint dwLowBytesToSeek, 565 uint dwHighBytesToSeek, out uint lpdwLowByteSeeked, out uint lpdwHighByteSeeked, 566 ref IntPtr lpContext); 567 568 /// <summary> 569 /// The WIN32_STREAM_ID structure contains stream data. 570 /// </summary> 571 [StructLayout(LayoutKind.Sequential, Pack = 4)] 572 private struct WIN32_STREAM_ID 573 { 574 /// <summary> 575 /// Type of data. This member can be one of the BACKUP_* values. 576 /// </summary> 577 public uint dwStreamId; 578 579 /// <summary> 580 /// Attributes of data to facilitate cross-operating system transfer. 581 /// This member can be one or more of the following values. 582 /// Value Meaning 583 /// STREAM_MODIFIED_WHEN_READ Attribute set if the stream contains 584 /// data that is modified when read. Allows 585 /// the backup application to know that 586 /// verification of data will fail. 587 /// STREAM_CONTAINS_SECURITY Stream contains security data 588 /// (general attributes). Allows the stream 589 /// to be ignored on cross-operations restore. 590 /// </summary> 591 public uint dwStreamAttributes; 592 593 /// <summary> 594 /// Size of data, in bytes. 595 /// </summary> 596 public long Size; 597 598 /// <summary> 599 /// Length of the name of the alternative data stream, in bytes. 600 /// </summary> 601 public uint dwStreamNameSize; 602 } 603 604 /// <summary> 605 /// Alternative data streams. 606 /// </summary> 607 public const uint BACKUP_ALTERNATE_DATA = 0x00000004; 608 609 /// <summary> 610 /// Standard data. 611 /// </summary> 612 public const uint BACKUP_DATA = 0x00000001; 613 614 /// <summary> 615 /// Extended attribute data. 616 /// </summary> 617 public const uint BACKUP_EA_DATA = 0x00000002; 618 619 /// <summary> 620 /// Hard link information. 621 /// </summary> 622 public const uint BACKUP_LINK = 0x00000005; 623 624 /// <summary> 625 /// Objects identifiers. 626 /// </summary> 627 public const uint BACKUP_OBJECT_ID = 0x00000007; 628 629 /// <summary> 630 /// Property data. 631 /// </summary> 632 public const uint BACKUP_PROPERTY_DATA = 0x00000006; 633 634 /// <summary> 635 /// Reparse points. 636 /// </summary> 637 public const uint BACKUP_REPARSE_DATA = 0x00000008; 638 639 /// <summary> 640 /// Security descriptor data. 641 /// </summary> 642 public const uint BACKUP_SECURITY_DATA = 0x00000003; 643 644 /// <summary> 645 /// Sparse file. 646 /// </summary> 647 public const uint BACKUP_SPARSE_BLOCK = 0x00000009; 413 648 414 649 /// <summary> -
branches/eraser6/Util/Util.csproj
r291 r292 39 39 <ItemGroup> 40 40 <Compile Include="CryptAPI.cs" /> 41 <Compile Include="StreamInfo.cs" /> 41 42 <Compile Include="KernelAPI.cs" /> 42 43 <Compile Include="File.cs" />
Note: See TracChangeset
for help on using the changeset viewer.
