public override void EraseClusterTips(VolumeInfo info, ErasureMethod method, ClusterTipsSearchProgress searchCallback, ClusterTipsEraseProgress eraseCallback) { List<string> files = new List<string>(); if (!info.IsMounted) throw new InvalidOperationException(S._("Could not erase cluster tips in {0} " + "as the volume is not mounted.", info.VolumeId)); ListFiles(new DirectoryInfo(info.MountPoints[0]), files, searchCallback); for (int i = 0, j = files.Count; i != j; ++i) { StreamInfo streamInfo = new StreamInfo(files[i]); FileAttributes fileAttr = streamInfo.Attributes; try { streamInfo.Attributes = FileAttributes.Normal; EraseFileClusterTips(files[i], method); } catch (UnauthorizedAccessException) { Logger.Log(S._("{0} did not have its cluster tips erased because you do not " + "have the required permissions to erase the file cluster tips.", files[i]), LogLevel.Information); } catch (IOException e) { Logger.Log(S._("{0} did not have its cluster tips erased. The error returned " + "was: {1}", files[i], e.Message), LogLevel.Error); } finally { streamInfo.Attributes = fileAttr; } eraseCallback(i, files.Count, files[i]); } }
public override void EraseDirectoryStructures(VolumeInfo info, FileSystemEntriesEraseProgress callback) { DirectoryInfo tempDir = new DirectoryInfo(FileSystem.GenerateRandomFileName( new DirectoryInfo(info.MountPoints[0]), 32)); tempDir.Create(); try { long mftSize = NtfsApi.GetMftValidSize(info); long mftRecordSegmentSize = NtfsApi.GetMftRecordSegmentSize(info); int pollingInterval = (int)Math.Min(Math.Max(1, mftSize / info.ClusterSize / 20), 128); int totalFiles = (int)Math.Max(1L, mftSize / mftRecordSegmentSize); int filesCreated = 0; while (true) { ++filesCreated; using (FileStream strm = new FileStream(FileSystem.GenerateRandomFileName( tempDir, 220), FileMode.CreateNew, FileAccess.Write)) { } if (filesCreated % pollingInterval == 0) { if (callback != null) { int halfFilesCreated = filesCreated / 2; callback(halfFilesCreated, Math.Max(halfFilesCreated, totalFiles)); } if (mftSize < NtfsApi.GetMftValidSize(info)) break; } } } catch (IOException) { } finally { FileInfo[] files = tempDir.GetFiles("*", SearchOption.AllDirectories); for (int i = 0; i < files.Length; ++i) { if (callback != null && i % 50 == 0) callback(files.Length + i, files.Length * 2); DeleteFile(files[i]); } DeleteFolder(tempDir); } }
internal static NativeMethods.NTFS_VOLUME_DATA_BUFFER GetNtfsVolumeData(VolumeInfo volume) { using (SafeFileHandle volumeHandle = NativeMethods.CreateFile( volume.VolumeId.Remove(volume.VolumeId.Length - 1), NativeMethods.GENERIC_READ, NativeMethods.FILE_SHARE_READ | NativeMethods.FILE_SHARE_WRITE, IntPtr.Zero, NativeMethods.OPEN_EXISTING, 0, IntPtr.Zero)) { uint resultSize = 0; NativeMethods.NTFS_VOLUME_DATA_BUFFER volumeData = new NativeMethods.NTFS_VOLUME_DATA_BUFFER(); if (NativeMethods.DeviceIoControl(volumeHandle, NativeMethods.FSCTL_GET_NTFS_VOLUME_DATA, IntPtr.Zero, 0, out volumeData, (uint)Marshal.SizeOf(volumeData), out resultSize, IntPtr.Zero)) { return volumeData; } throw Win32ErrorCode.GetExceptionForWin32Error(Marshal.GetLastWin32Error()); } }
public override void EraseDirectoryStructures(VolumeInfo info, FileSystemEntriesEraseProgress callback) { using (FileStream stream = info.Open(FileAccess.ReadWrite, FileShare.ReadWrite)) { int directoriesCleaned = 0; FatApi api = GetFatApi(info, stream); HashSet<uint> eraseQueueClusters = new HashSet<uint>(); List<FatDirectoryEntry> eraseQueue = new List<FatDirectoryEntry>(); { FatDirectoryEntry entry = api.LoadDirectory(string.Empty); eraseQueue.Add(entry); eraseQueueClusters.Add(entry.Cluster); } using (VolumeLock volumeLock = info.LockVolume(stream)) { while (eraseQueue.Count != 0) { if (callback != null) callback(directoriesCleaned, directoriesCleaned + eraseQueue.Count); FatDirectoryBase currentDir = api.LoadDirectory(eraseQueue[0].FullName); eraseQueue.RemoveAt(0); foreach (KeyValuePair<string, FatDirectoryEntry> entry in currentDir.Items) if (entry.Value.EntryType == FatDirectoryEntryType.Directory) { if (eraseQueueClusters.Contains(entry.Value.Cluster)) continue; eraseQueueClusters.Add(entry.Value.Cluster); eraseQueue.Add(entry.Value); } currentDir.ClearDeletedEntries(); ++directoriesCleaned; } } } }
public override void EraseOldFileSystemResidentFiles(VolumeInfo volume, DirectoryInfo tempDirectory, ErasureMethod method, FileSystemEntriesEraseProgress callback) { try { long oldMFTSize = NtfsApi.GetMftValidSize(volume); for (; ; ) { using (FileStream strm = new FileStream( GenerateRandomFileName(tempDirectory, 18), FileMode.CreateNew, FileAccess.Write, FileShare.None, 8, FileOptions.WriteThrough)) { long streamSize = 0; try { while (true) { strm.SetLength(++streamSize); method.Erase(strm, long.MaxValue, PrngManager.GetInstance(ManagerLibrary.Settings.ActivePrng), null); } } catch (IOException) { if (streamSize == 1) return; } } if (NtfsApi.GetMftValidSize(volume) > oldMFTSize) break; } } catch (IOException) { } }
public abstract void EraseOldFileSystemResidentFiles(VolumeInfo volume, DirectoryInfo tempDirectory, ErasureMethod method, FileSystemEntriesEraseProgress callback);
public abstract void EraseDirectoryStructures(VolumeInfo info, FileSystemEntriesEraseProgress callback);
public abstract void EraseClusterTips(VolumeInfo info, ErasureMethod method, Logger log, ClusterTipsSearchProgress searchCallback, ClusterTipsEraseProgress eraseCallback);
public static FileSystem Get(VolumeInfo volume) { lock (ManagerLibrary.Instance.FileSystemManager.FileSystems) foreach (FileSystem filesystem in ManagerLibrary.Instance.FileSystemManager.FileSystems) if (filesystem.Supports(volume.VolumeFormat)) return filesystem; throw new NotSupportedException(S._("The file system on the drive {0} is not " + "supported.", volume)); }
protected override FatApi GetFatApi(VolumeInfo info, FileStream stream) { return new Fat32Api(info, stream); }
protected abstract FatApi GetFatApi(VolumeInfo info, FileStream stream);
public static long GetMftValidSize(VolumeInfo volume) { return GetNtfsVolumeData(volume).MftValidDataLength; }
public static long GetMftRecordSegmentSize(VolumeInfo volume) { return GetNtfsVolumeData(volume).BytesPerFileRecordSegment; }
public static long GetMftValidSize(VolumeInfo volume) { NTApi.NativeMethods.NTFS_VOLUME_DATA_BUFFER data = NTApi.NativeMethods.GetNtfsVolumeData(volume); return data.MftValidDataLength; }
public static long GetMftRecordSegmentSize(VolumeInfo volume) { NTApi.NativeMethods.NTFS_VOLUME_DATA_BUFFER data = NTApi.NativeMethods.GetNtfsVolumeData(volume); return data.BytesPerFileRecordSegment; }