Exemplo n.º 1
0
        public override long GetFileArea(StreamInfo info)
        {
            VolumeInfo volume      = VolumeInfo.FromMountPoint(info.Directory.FullName);
            long       clusterSize = volume.ClusterSize;

            return((info.Length + (clusterSize - 1)) & ~(clusterSize - 1));
        }
Exemplo n.º 2
0
        /// <summary>
        /// Erases the folder after all files have been deleted. This folder does not
        /// delete folders which have files within it.
        /// </summary>
        private void EraseFolder()
        {
            //Update the progress to show that folders are being removed.
            ProgressManager step = new ProgressManager();

            Progress.Steps.Add(new SteppedProgressManagerStep(step,
                                                              0.0f, S._("Removing folders...")));

            //Erase all subdirectories which are not reparse points.
            DirectoryInfo directory = new DirectoryInfo(Path);

            if ((directory.Attributes & FileAttributes.ReparsePoint) == 0)
            {
                foreach (DirectoryInfo subDir in directory.GetDirectories())
                {
                    EraseFolder(subDir, step);
                }
            }

            //Does the user want this directory to be erased if there are no more
            //entries within it?
            if (DeleteIfEmpty)
            {
                //See if this is the root of a volume.
                bool isVolumeRoot = directory.Parent == null;
                foreach (VolumeInfo volume in VolumeInfo.Volumes)
                {
                    if (volume.IsReady)
                    {
                        foreach (DirectoryInfo mountPoint in volume.MountPoints)
                        {
                            if (directory.FullName == mountPoint.FullName)
                            {
                                isVolumeRoot = true;
                            }
                        }
                    }
                }

                //If the folder is a mount point, then don't delete it. If it isn't,
                //search for files under the folder to see if it is empty.
                if (!isVolumeRoot && directory.Exists)
                {
                    IFileSystem fsManager = Host.Instance.FileSystems[
                        VolumeInfo.FromMountPoint(Path)];
                    if ((directory.Attributes & FileAttributes.ReparsePoint) == 0)
                    {
                        if (directory.GetFiles("*", SearchOption.AllDirectories).Length == 0)
                        {
                            fsManager.DeleteFolder(directory, true);
                        }
                    }
                    else
                    {
                        fsManager.DeleteFolder(directory, false);
                    }
                }
            }
        }
Exemplo n.º 3
0
        public override void EraseFileSystemObject(StreamInfo info, IErasureMethod method,
                                                   ErasureMethodProgressFunction callback)
        {
            //Check if the file fits in one cluster - if it does it may be MFT resident
            //TODO: any more deterministic way of finding out?
            VolumeInfo volume = VolumeInfo.FromMountPoint(info.DirectoryName);

            if (info.Length < NtfsApi.GetMftRecordSegmentSize(volume))
            {
                //Yes it does, erase exactly to the file length
                using (FileStream strm = info.Open(FileMode.Open, FileAccess.Write,
                                                   FileShare.None))
                {
                    method.Erase(strm, long.MaxValue, Host.Instance.Prngs.ActivePrng,
                                 null);
                }
            }

            //Create the file stream, and call the erasure method to write to
            //the stream.
            long fileArea = GetFileArea(info);

            //If the stream is empty, there's nothing to overwrite. Continue
            //to the next entry
            if (fileArea == 0)
            {
                return;
            }

            using (FileStream strm = info.Open(FileMode.Open, FileAccess.Write,
                                               FileShare.None, FileOptions.WriteThrough))
            {
                //Set the end of the stream after the wrap-round the cluster size
                strm.SetLength(fileArea);

                //Then erase the file.
                method.Erase(strm, long.MaxValue, Host.Instance.Prngs.ActivePrng, callback);

                //Set the length of the file to 0.
                strm.Seek(0, SeekOrigin.Begin);
                strm.SetLength(0);
            }
        }
Exemplo n.º 4
0
        private void EraseFolder(DirectoryInfo info, ProgressManager progress)
        {
            //Skip all symbolic links and junctions as we want to retain the
            //contents of those directories.
            if ((info.Attributes & FileAttributes.ReparsePoint) != 0)
            {
                return;
            }

            //Iterate over each directory and erase the subdirectories.
            foreach (DirectoryInfo subDir in info.GetDirectories())
            {
                EraseFolder(subDir, progress);
            }

            //Public progress updates.
            progress.Tag = info.FullName;

            //Ensure that the current directory is empty before deleting.
            FileSystemInfo[] files = info.GetFileSystemInfos();
            if (files.Length == 0)
            {
                try
                {
                    Host.Instance.FileSystems[VolumeInfo.FromMountPoint(Path)].
                    DeleteFolder(info, true);
                }
                catch (DirectoryNotFoundException)
                {
                    Logger.Log(new LogEntry(S._("The folder {0} was not erased because " +
                                                "the containing directory was deleted before it could be erased.",
                                                info.FullName), LogLevel.Information));
                }
                catch (UnauthorizedAccessException)
                {
                    Logger.Log(new LogEntry(S._("The folder {0} could not be deleted because " +
                                                "the folder's permissions prevents the deletion of the folder.",
                                                info.FullName), LogLevel.Error));
                }
            }
        }
        public override void Execute()
        {
            //Check for sufficient privileges to run the unused space erasure.
            if (!Security.IsAdministrator())
            {
                if (Environment.OSVersion.Platform == PlatformID.Win32NT &&
                    Environment.OSVersion.Version >= new Version(6, 0))
                {
                    Logger.Log(S._("The program does not have the required permissions to erase " +
                                   "the unused space on disk. Run the program as an administrator and retry " +
                                   "the operation."), LogLevel.Error);
                }
                else
                {
                    Logger.Log(S._("The program does not have the required permissions to erase " +
                                   "the unused space on disk."), LogLevel.Error);
                }

                return;
            }

            //Check whether System Restore has any available checkpoints.
            if (SystemRestore.GetInstances().Count != 0)
            {
                Logger.Log(S._("This computer has had System Restore or Volume Shadow Copies " +
                               "enabled. This may allow copies of files stored on the disk to be recovered " +
                               "and pose a security concern.", Drive), LogLevel.Warning);
            }

            //If the user is under disk quotas, log a warning message
            if (VolumeInfo.FromMountPoint(Drive).HasQuota)
            {
                Logger.Log(S._("The drive {0} has disk quotas active. This will prevent the " +
                               "complete erasure of unused space and may pose a security concern.",
                               Drive), LogLevel.Warning);
            }

            //Get the erasure method if the user specified he wants the default.
            IErasureMethod method = EffectiveMethod;

            //Make a folder to dump our temporary files in
            DirectoryInfo info      = new DirectoryInfo(Drive);
            VolumeInfo    volInfo   = VolumeInfo.FromMountPoint(Drive);
            IFileSystem   fsManager = Host.Instance.FileSystems[volInfo];

            //Start sampling the speed of the task.
            Progress = new SteppedProgressManager();

            //Erase the cluster tips of every file on the drive.
            if (EraseClusterTips)
            {
                //Define the callback handlers
                ProgressManager tipSearch = new ProgressManager();
                tipSearch.MarkIndeterminate();
                Progress.Steps.Add(new SteppedProgressManagerStep(tipSearch,
                                                                  0.0f, S._("Searching for files' cluster tips...")));
                ClusterTipsSearchProgress searchProgress = delegate(string path)
                {
                    if (Task.Canceled)
                    {
                        throw new OperationCanceledException(S._("The task was cancelled."));
                    }

                    tipSearch.Tag = path;
                };

                ProgressManager tipProgress = new ProgressManager();
                Progress.Steps.Add(new SteppedProgressManagerStep(tipProgress, 0.1f,
                                                                  S._("Erasing cluster tips...")));
                ClusterTipsEraseProgress eraseProgress =
                    delegate(int currentFile, int totalFiles, string currentFilePath)
                {
                    tipSearch.MarkComplete();
                    tipProgress.Total     = totalFiles;
                    tipProgress.Completed = currentFile;
                    tipProgress.Tag       = currentFilePath;

                    if (Task.Canceled)
                    {
                        throw new OperationCanceledException(S._("The task was cancelled."));
                    }
                };

                //Start counting statistics
                fsManager.EraseClusterTips(VolumeInfo.FromMountPoint(Drive),
                                           method, searchProgress, eraseProgress);
                tipProgress.MarkComplete();
            }

            bool lowDiskSpaceNotifications = Shell.LowDiskSpaceNotificationsEnabled;

            info = info.CreateSubdirectory(Path.GetFileName(
                                               FileSystemBase.GenerateRandomFileName(info, 18)));
            try
            {
                //Set the folder's compression flag off since we want to use as much
                //space as possible
                if (info.IsCompressed())
                {
                    info.Uncompress();
                }

                //Disable the low disk space notifications
                Shell.LowDiskSpaceNotificationsEnabled = false;

                //Fill the disk
                EraseUnusedSpace(volInfo, info, fsManager, method);

                //Erase old resident file system table files
                ProgressManager residentProgress = new ProgressManager();
                Progress.Steps.Add(new SteppedProgressManagerStep(residentProgress,
                                                                  0.05f, S._("Old resident file system table files")));
                fsManager.EraseOldFileSystemResidentFiles(volInfo, info, method,
                                                          delegate(int currentFile, int totalFiles)
                {
                    residentProgress.Completed = currentFile;
                    residentProgress.Total     = totalFiles;

                    if (Task.Canceled)
                    {
                        throw new OperationCanceledException(S._("The task was cancelled."));
                    }
                }
                                                          );

                residentProgress.MarkComplete();
            }
            finally
            {
                //Remove the folder holding all our temporary files.
                ProgressManager tempFiles = new ProgressManager();
                Progress.Steps.Add(new SteppedProgressManagerStep(tempFiles,
                                                                  0.0f, S._("Removing temporary files...")));

                fsManager.DeleteFolder(info, true);
                tempFiles.MarkComplete();

                //Reset the low disk space notifications
                Shell.LowDiskSpaceNotificationsEnabled = lowDiskSpaceNotifications;
            }

            //Then clean the old file system entries
            ProgressManager structureProgress = new ProgressManager();

            Progress.Steps.Add(new SteppedProgressManagerStep(structureProgress,
                                                              0.05f, S._("Erasing unused directory structures...")));
            fsManager.EraseDirectoryStructures(volInfo,
                                               delegate(int currentFile, int totalFiles)
            {
                if (Task.Canceled)
                {
                    throw new OperationCanceledException(S._("The task was cancelled."));
                }

                //Compute the progress
                structureProgress.Total     = totalFiles;
                structureProgress.Completed = currentFile;
            }
                                               );

            structureProgress.MarkComplete();
            Progress = null;
        }
Exemplo n.º 6
0
        /// <summary>
        /// Erases the provided stream, and updates progress using the provided
        /// progress manager.
        /// </summary>
        /// <param name="info">The information regarding the stream that needs erasure.</param>
        /// <param name="progress">The progress manager for the erasure of the current
        /// stream.</param>
        protected void EraseStream(StreamInfo info, ProgressManager progress)
        {
            //Check that the file exists - we do not want to bother erasing nonexistant files
            if (!info.Exists)
            {
                Logger.Log(S._("The file {0} was not erased as the file does not exist.",
                               info.FileName), LogLevel.Notice);
                return;
            }

            //Get the filesystem provider to handle the secure file erasures
            IFileSystem fsManager = Host.Instance.FileSystems[
                VolumeInfo.FromMountPoint(info.DirectoryName)];

            bool isReadOnly = false;

            try
            {
                //Update the task progress
                IErasureMethod method = EffectiveMethod;

                //Remove the read-only flag, if it is set.
                if (isReadOnly = info.IsReadOnly)
                {
                    info.IsReadOnly = false;
                }

                //Define the callback function for progress reporting.
                ErasureMethodProgressFunction callback =
                    delegate(long lastWritten, long totalData, int currentPass)
                {
                    if (Task.Canceled)
                    {
                        throw new OperationCanceledException(S._("The task was cancelled."));
                    }

                    progress.Tag        = new int[] { currentPass, method.Passes };
                    progress.Total      = totalData;
                    progress.Completed += lastWritten;
                };

                TryEraseStream(fsManager, method, info, callback);

                //Remove the file.
                FileInfo fileInfo = info.File;
                if (fileInfo != null)
                {
                    fsManager.DeleteFile(fileInfo);
                }
                progress.MarkComplete();
            }
            catch (UnauthorizedAccessException)
            {
                Logger.Log(S._("The file {0} could not be erased because the file's " +
                               "permissions prevent access to the file.", info.FullName), LogLevel.Error);
            }
            catch (SharingViolationException e)
            {
                Logger.Log(S._("The file {0} could not be erased because the file is " +
                               "currently in used by another application.", info.FullName), LogLevel.Error);
            }
            finally
            {
                //Re-set the read-only flag if the file exists (i.e. there was an error)
                if (isReadOnly && info.Exists && !info.IsReadOnly)
                {
                    info.IsReadOnly = isReadOnly;
                }
            }
        }
Exemplo n.º 7
0
        private void CopyDirectory(DirectoryInfo info)
        {
            //Check the the destination is not a subfolder of the source.
            if (PathUtil.IsRootedAt(info, Destination))
            {
                Logger.Log(S._("The destination directory cannot be within the source directory."),
                           LogLevel.Error);
                return;
            }

            //We need to get the files from the list of streams
            List <StreamInfo> streams = GetPaths();
            List <FileInfo>   files   = new List <FileInfo>(
                streams.Distinct(new StreamInfoFileEqualityComparer()).
                Select(x => x.File));
            long totalSize = streams.Sum(x => x.Length);

            foreach (FileInfo file in files)
            {
                //Compute the total size of the file on the disk (including ADSes)
                List <StreamInfo> fileStreams = new List <StreamInfo>(file.GetADSes());
                fileStreams.Add(new StreamInfo(file.FullName));
                long fileSize = fileStreams.Sum(x => x.Length);

                SteppedProgressManager fileProgress = new SteppedProgressManager();
                Progress.Steps.Add(new SteppedProgressManagerStep(fileProgress,
                                                                  fileSize / (float)totalSize, S._("Securely moving files and folders...")));

                //Add the copying step to the file progress.
                ProgressManager copyProgress = new ProgressManager();
                int             totalPasses  = 1 + EffectiveMethod.Passes;
                fileProgress.Steps.Add(new SteppedProgressManagerStep(copyProgress,
                                                                      1f / totalPasses));

                try
                {
                    //Compute the path to the new directory.
                    DirectoryInfo sourceDirectory = file.Directory;
                    DirectoryInfo destDirectory   = new DirectoryInfo(
                        SourceToDestinationPath(file.DirectoryName));

                    //Make sure all necessary folders exist before the copy.
                    if (!destDirectory.Exists)
                    {
                        destDirectory.Create();
                    }

                    //Then copy the file.
                    file.CopyTo(System.IO.Path.Combine(destDirectory.FullName, file.Name),
                                delegate(long TotalFileSize, long TotalBytesTransferred)
                    {
                        return(CopyProgress(copyProgress, file, TotalFileSize,
                                            TotalBytesTransferred));
                    });
                }
                catch (OperationCanceledException)
                {
                    //The copy was cancelled: Complete the copy part.
                    copyProgress.MarkComplete();

                    //We need to erase the partially copied copy of the file.
                    SteppedProgressManager destroyProgress = new SteppedProgressManager();
                    Progress.Steps.Add(new SteppedProgressManagerStep(destroyProgress, 0.5f,
                                                                      S._("Erasing incomplete destination file")));
                    EraseFile(file, destroyProgress);

                    //Rethrow the exception.
                    throw;
                }

                //We copied the file over; erase the source file
                SteppedProgressManager eraseProgress = new SteppedProgressManager();
                fileProgress.Steps.Add(new SteppedProgressManagerStep(eraseProgress,
                                                                      (totalPasses - 1) / (float)totalPasses,
                                                                      S._("Erasing source files...")));
                EraseFile(file, eraseProgress);
            }

            //Then copy the timestamps from the source folders and delete the source.
            ProgressManager folderDeleteProgress = new ProgressManager();

            Progress.Steps.Add(new SteppedProgressManagerStep(folderDeleteProgress, 0.0f,
                                                              S._("Removing folders...")));

            Action <DirectoryInfo> CopyTimesAndDelete = null;

            CopyTimesAndDelete = delegate(DirectoryInfo subDirectory)
            {
                foreach (DirectoryInfo child in subDirectory.GetDirectories())
                {
                    CopyTimesAndDelete(child);
                }

                //Update progress.
                folderDeleteProgress.Tag = subDirectory.FullName;

                //Get the directory which we copied to and copy the file times to the
                //destination directory
                DirectoryInfo destDirectory = new DirectoryInfo(
                    SourceToDestinationPath(subDirectory.FullName));
                if (!destDirectory.Exists)
                {
                    destDirectory.Create();
                }
                destDirectory.CopyTimes(subDirectory);

                //Then delete the source directory.
                IFileSystem fsManager = Host.Instance.FileSystems[
                    VolumeInfo.FromMountPoint(Path)];
                fsManager.DeleteFolder(subDirectory, true);
            };
            CopyTimesAndDelete(info);
        }