示例#1
0
        public override void Erase(Stream stream, long erasureLength, IPrng prng,
                                   ErasureMethodProgressFunction callback)
        {
            //Randomize the order of the passes
            ErasureMethodPass[] randomizedPasses = PassesSet;
            if (RandomizePasses)
            {
                randomizedPasses = ShufflePasses(randomizedPasses);
            }

            //Remember the starting position of the stream.
            long strmStart  = stream.Position;
            long strmLength = Math.Min(stream.Length - strmStart, erasureLength);
            long totalData  = CalculateEraseDataSize(null, strmLength);

            //Allocate memory for a buffer holding data for the pass.
            byte[] buffer = new byte[Math.Min(DiskOperationUnit, strmLength)];

            //Run every pass!
            for (int pass = 0; pass < Passes; ++pass)
            {
                //Do a progress callback first.
                if (callback != null)
                {
                    callback(0, totalData, pass + 1);
                }

                //Start from the beginning again
                stream.Seek(strmStart, SeekOrigin.Begin);

                //Write the buffer to disk.
                long toWrite     = strmLength;
                int  dataStopped = buffer.Length;
                while (toWrite > 0)
                {
                    //Calculate how much of the buffer to write to disk.
                    int amount = (int)Math.Min(toWrite, buffer.Length - dataStopped);

                    //If we have no data left, get more!
                    if (amount == 0)
                    {
                        randomizedPasses[pass].Execute(buffer, prng);
                        dataStopped = 0;
                        continue;
                    }

                    //Write the data.
                    stream.Write(buffer, dataStopped, amount);
                    stream.Flush();
                    dataStopped += amount;
                    toWrite     -= amount;

                    //Do a progress callback.
                    if (callback != null)
                    {
                        callback(amount, totalData, pass + 1);
                    }
                }
            }
        }
示例#2
0
      public override void EraseFileSystemObject(StreamInfo info, ErasureMethod method,
 ErasureMethodProgressFunction callback)
      {
          VolumeInfo volume = VolumeInfo.FromMountpoint(info.DirectoryName);
             if (info.Length < Math.Max(volume.ClusterSize, 1024))
             {
          using (FileStream strm = info.Open(FileMode.Open, FileAccess.Write,
           FileShare.None))
          {
           method.Erase(strm, long.MaxValue,
            PrngManager.GetInstance(ManagerLibrary.Settings.ActivePrng), null);
          }
             }
             long fileArea = GetFileArea(info.FullName);
             if (fileArea == 0)
          return;
             using (FileStream strm = info.Open(FileMode.Open, FileAccess.Write,
          FileShare.None, FileOptions.WriteThrough))
             {
          strm.SetLength(fileArea);
          method.Erase(strm, long.MaxValue,
           PrngManager.GetInstance(ManagerLibrary.Settings.ActivePrng),
           callback
          );
          strm.Seek(0, SeekOrigin.Begin);
          strm.SetLength(0);
             }
      }
示例#3
0
        public override void EraseFileSystemObject(StreamInfo info, IErasureMethod method,
                                                   ErasureMethodProgressFunction callback)
        {
            //Create the file stream, and call the erasure method to write to
            //the stream.
            long fileArea = GetFileArea(info);

            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);

                //If the stream is empty, there's nothing to overwrite. Continue
                //to the next entry
                if (strm.Length != 0)
                {
                    //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);
            }
        }
示例#4
0
        public override void Erase(Stream strm, long erasureLength, IPrng prng,
                                   ErasureMethodProgressFunction callback)
        {
            //If we have no default or we are the default then throw an exception
            if (method == null || method.Guid == Guid)
            {
                throw new InvalidOperationException(S._("The First/last 16KB erasure method " +
                                                        "requires another erasure method to erase the file.\n\nThis must " +
                                                        "be set in the Plugin Settings dialog."));
            }

            //Make sure that the erasureLength passed in here is the maximum value
            //for the size of long, since we don't want to write extra or write
            //less.
            if (erasureLength != long.MaxValue)
            {
                throw new ArgumentException("The amount of data erased should not be " +
                                            "limited, since this is a self-limiting erasure method.");
            }

            //If the target stream is shorter than or equal to 32kb, just forward it to
            //the default function.
            if (strm.Length < DataSize * 2)
            {
                method.Erase(strm, erasureLength, prng, callback);
                return;
            }

            //We need to intercept the callback function as we run the erasure method
            //twice on two parts of the file.
            long dataSize = method.CalculateEraseDataSize(null, DataSize * 2);
            ErasureMethodProgressFunction customCallback =
                delegate(long lastWritten, long totalData, int currentPass)
            {
                callback(lastWritten, dataSize, currentPass);
            };

            //Seek to the beginning and write 16kb.
            strm.Seek(0, SeekOrigin.Begin);
            method.Erase(strm, dataSize, prng, callback == null ? null: customCallback);

            //Seek to the end - 16kb, and write.
            strm.Seek(-dataSize, SeekOrigin.End);
            method.Erase(strm, long.MaxValue, prng, callback == null ? null : customCallback);
        }
示例#5
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);
            }
        }
示例#6
0
 public virtual void EraseDriveSpace(Stream stream, IPrng prng,
                                     ErasureMethodProgressFunction callback)
 {
     Erase(stream, long.MaxValue, prng, callback);
 }
示例#7
0
 public void Erase(Stream strm, long erasureLength, IPrng prng,
                   ErasureMethodProgressFunction callback)
 {
     throw new InvalidOperationException("The DefaultMethod class should never " +
                                         "be used and should instead be replaced before execution!");
 }
示例#8
0
      public abstract void EraseFileSystemObject(StreamInfo info, ErasureMethod method,
 ErasureMethodProgressFunction callback);
示例#9
0
      public override void Erase(Stream stream, long erasureLength, Prng prng,
 ErasureMethodProgressFunction callback)
      {
          ErasureMethodPass[] randomizedPasses = PassesSet;
             if (RandomizePasses)
          randomizedPasses = ShufflePasses(randomizedPasses);
             long strmStart = stream.Position;
             long strmLength = Math.Min(stream.Length - strmStart, erasureLength);
             long totalData = CalculateEraseDataSize(null, strmLength);
             byte[] buffer = new byte[Math.Min(DiskOperationUnit, strmLength)];
             for (int pass = 0; pass < Passes; ++pass)
             {
          if (callback != null)
           callback(0, totalData, pass + 1);
          stream.Seek(strmStart, SeekOrigin.Begin);
          long toWrite = strmLength;
          int dataStopped = buffer.Length;
          while (toWrite > 0)
          {
           int amount = (int)Math.Min(toWrite, buffer.Length - dataStopped);
           if (amount == 0)
           {
            randomizedPasses[pass].Execute(buffer, prng);
            dataStopped = 0;
            continue;
           }
           stream.Write(buffer, dataStopped, amount);
           stream.Flush();
           toWrite -= amount;
           if (callback != null)
            callback(amount, totalData, pass + 1);
          }
             }
      }
示例#10
0
        /// <summary>
        /// Attempts to erase a stream, trying to close all open handles if a process has
        /// a lock on the file.
        /// </summary>
        /// <param name="fsManager">The file system provider used to erase the stream.</param>
        /// <param name="method">The erasure method to use to erase the stream.</param>
        /// <param name="info">The stream to erase.</param>
        /// <param name="callback">The erasure progress callback.</param>
        private void TryEraseStream(IFileSystem fsManager, IErasureMethod method, StreamInfo info,
                                    ErasureMethodProgressFunction callback)
        {
            for (int i = 0; ; ++i)
            {
                try
                {
                    //Make sure the file does not have any attributes which may affect
                    //the erasure process
                    if ((info.Attributes & FileAttributes.Compressed) != 0 ||
                        (info.Attributes & FileAttributes.Encrypted) != 0 ||
                        (info.Attributes & FileAttributes.SparseFile) != 0)
                    {
                        //Log the error
                        Logger.Log(S._("The file {0} could not be erased because the file was " +
                                       "either compressed, encrypted or a sparse file.", info.FullName),
                                   LogLevel.Error);
                        return;
                    }

                    //Do not erase reparse points, as they will cause other references to the file
                    //to be to garbage.
                    if ((info.Attributes & FileAttributes.ReparsePoint) == 0)
                    {
                        fsManager.EraseFileSystemObject(info, method, callback);
                    }
                    else
                    {
                        Logger.Log(S._("The file {0} is a hard link or a symbolic link thus the " +
                                       "contents of the file was not erased.", info.FullName), LogLevel.Notice);
                    }
                    return;
                }
                catch (FileNotFoundException)
                {
                    Logger.Log(S._("The file {0} was not erased because it was " +
                                   "deleted before it could be erased.", info.FullName), LogLevel.Information);
                }
                catch (DirectoryNotFoundException)
                {
                    Logger.Log(S._("The file {0} was not erased because the containing " +
                                   "directory was deleted before it could be erased.", info.FullName),
                               LogLevel.Information);
                }
                catch (SharingViolationException)
                {
                    if (!Host.Instance.Settings.ForceUnlockLockedFiles)
                    {
                        throw;
                    }

                    //Try closing all open handles. If it succeeds, we can run the erase again.
                    //To prevent Eraser from deadlocking, we will only attempt this once. Some
                    //programs may be aggressive and keep a handle open in a tight loop.
                    List <OpenHandle> remainingHandles = OpenHandle.Close(info.FullName);
                    if (i == 0 && remainingHandles.Count == 0)
                    {
                        continue;
                    }

                    //Either we could not close all instances, or we already tried twice. Report
                    //the error.
                    string processes = string.Empty;
                    {
                        StringBuilder processStr = new StringBuilder();
                        foreach (OpenHandle handle in remainingHandles)
                        {
                            try
                            {
                                processStr.AppendFormat(
                                    System.Globalization.CultureInfo.InvariantCulture,
                                    "{0}, ", handle.Process.MainModule.FileName);
                            }
                            catch (System.ComponentModel.Win32Exception)
                            {
                                processStr.AppendFormat(
                                    System.Globalization.CultureInfo.InvariantCulture,
                                    "Process ID {0}, ", handle.Process.Id);
                            }
                        }

                        if (processStr.Length > 2)
                        {
                            processes = processStr.ToString().Remove(processStr.Length - 2).Trim();
                        }
                        else
                        {
                            processes = S._("(unknown)");
                        }
                    }

                    throw new SharingViolationException(S._(
                                                            "Could not force closure of file \"{0}\" {1}", info.FileName,
                                                            S._("(locked by {0})", processes)));
                }
            }
        }
示例#11
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;
                }
            }
        }
示例#12
0
      public override void Erase(Stream strm, long erasureLength, Prng prng,
 ErasureMethodProgressFunction callback)
      {
          if (method == null || method.Guid == Guid)
          throw new InvalidOperationException(S._("The First/last 16KB erasure method " +
           "requires another erasure method to erase the file.\n\nThis must " +
           "be set in the Plugin Settings dialog."));
             if (erasureLength != long.MaxValue)
          throw new ArgumentException(S._("The amount of data erased should not be " +
           "limited, since this is a self-limiting erasure method."));
             if (strm.Length < dataSize)
             {
          method.Erase(strm, erasureLength, prng, callback);
          return;
             }
             strm.Seek(0, SeekOrigin.Begin);
             method.Erase(strm, dataSize, prng, callback);
             strm.Seek(-dataSize, SeekOrigin.End);
             method.Erase(strm, long.MaxValue, prng, callback);
      }
示例#13
0
 public abstract void EraseFileSystemObject(StreamInfo info, IErasureMethod method,
                                            ErasureMethodProgressFunction callback);
示例#14
0
      public abstract void Erase(Stream stream, long erasureLength, Prng prng,
 ErasureMethodProgressFunction callback);
示例#15
0
 public virtual void EraseUnusedSpace(Stream stream, Prng prng, ErasureMethodProgressFunction callback)
 {
     Erase(stream, long.MaxValue, prng, callback);
 }
示例#16
0
      public override void EraseFileSystemObject(StreamInfo info, ErasureMethod method,
 ErasureMethodProgressFunction callback)
      {
          long fileArea = GetFileArea(info.FullName);
             using (FileStream strm = info.Open(FileMode.Open, FileAccess.Write,
          FileShare.None, FileOptions.WriteThrough))
             {
          strm.SetLength(fileArea);
          if (strm.Length != 0)
          {
           method.Erase(strm, long.MaxValue,
            PrngManager.GetInstance(ManagerLibrary.Settings.ActivePrng),
            callback
           );
          }
          strm.Seek(0, SeekOrigin.Begin);
          strm.SetLength(0);
             }
      }
示例#17
0
 public abstract void Erase(Stream stream, long erasureLength, IPrng prng,
                            ErasureMethodProgressFunction callback);
示例#18
0
         public override void Erase(Stream strm, long erasureLength, Prng prng,
 ErasureMethodProgressFunction callback)
         {
             throw new InvalidOperationException(S._("The DefaultMethod class should never " +
              "be used and should instead be replaced before execution!"));
         }