source: trunk/eraser/Eraser.DefaultPlugins/ErasureTargets/FolderErasureTarget.cs @ 2045

Revision 2045, 7.2 KB checked in by lowjoel, 4 years ago (diff)

Fixed the null Progress property upon the completion of the FileSystemObjectErasureTarget?.Execute function. The Progress property is now managed by the derived class itself.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
Line 
1/*
2 * $Id$
3 * Copyright 2008-2010 The Eraser Project
4 * Original Author: Joel Low <lowjoel@users.sourceforge.net>
5 * Modified By:
6 *
7 * This file is part of Eraser.
8 *
9 * Eraser is free software: you can redistribute it and/or modify it under the
10 * terms of the GNU General Public License as published by the Free Software
11 * Foundation, either version 3 of the License, or (at your option) any later
12 * version.
13 *
14 * Eraser is distributed in the hope that it will be useful, but WITHOUT ANY
15 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
16 * A PARTICULAR PURPOSE. See the GNU General Public License for more details.
17 *
18 * A copy of the GNU General Public License can be found at
19 * <http://www.gnu.org/licenses/>.
20 */
21
22using System;
23using System.Collections.Generic;
24using System.Linq;
25using System.Text;
26
27using System.Text.RegularExpressions;
28using System.Runtime.Serialization;
29using System.Runtime.InteropServices;
30using System.Security.Permissions;
31using System.IO;
32
33using Eraser.Manager;
34using Eraser.Util;
35
36namespace Eraser.DefaultPlugins
37{
38    /// <summary>
39    /// Represents a folder and its files which are to be erased.
40    /// </summary>
41    [Serializable]
42    [Guid("F50B0A44-3AB1-4cab-B81E-1713AC3D28C9")]
43    public class FolderErasureTarget : FileSystemObjectErasureTarget
44    {
45        #region Serialization code
46        protected FolderErasureTarget(SerializationInfo info, StreamingContext context)
47            : base(info, context)
48        {
49            IncludeMask = (string)info.GetValue("IncludeMask", typeof(string));
50            ExcludeMask = (string)info.GetValue("ExcludeMask", typeof(string));
51            DeleteIfEmpty = (bool)info.GetValue("DeleteIfEmpty", typeof(bool));
52        }
53
54        [SecurityPermission(SecurityAction.Demand, SerializationFormatter = true)]
55        public override void GetObjectData(SerializationInfo info, StreamingContext context)
56        {
57            base.GetObjectData(info, context);
58            info.AddValue("IncludeMask", IncludeMask);
59            info.AddValue("ExcludeMask", ExcludeMask);
60            info.AddValue("DeleteIfEmpty", DeleteIfEmpty);
61        }
62        #endregion
63
64        /// <summary>
65        /// Constructor.
66        /// </summary>
67        public FolderErasureTarget()
68        {
69            IncludeMask = string.Empty;
70            ExcludeMask = string.Empty;
71            DeleteIfEmpty = true;
72        }
73
74        public override Guid Guid
75        {
76            get { return GetType().GUID; }
77        }
78
79        public override IErasureTargetConfigurer Configurer
80        {
81            get { return new FolderErasureTargetConfigurer(); }
82        }
83
84        internal override List<string> GetPaths(out long totalSize)
85        {
86            //Get a list to hold all the resulting paths.
87            List<string> result = new List<string>();
88
89            //Open the root of the search, including every file matching the pattern
90            DirectoryInfo dir = new DirectoryInfo(Path);
91
92            //List recursively all the files which match the include pattern.
93            FileInfo[] files = GetFiles(dir);
94
95            //Then exclude each file and finalize the list and total file size
96            totalSize = 0;
97            if (ExcludeMask.Length != 0)
98            {
99                string regex = Regex.Escape(ExcludeMask).Replace("\\*", ".*").
100                    Replace("\\?", ".");
101                Regex excludePattern = new Regex(regex, RegexOptions.IgnoreCase);
102                foreach (FileInfo file in files)
103                    if (file.Exists &&
104                        (file.Attributes & FileAttributes.ReparsePoint) == 0 &&
105                        excludePattern.Matches(file.FullName).Count == 0)
106                    {
107                        totalSize += file.Length;
108                        GetPathADSes(result, out totalSize, file.FullName);
109                        result.Add(file.FullName);
110                    }
111            }
112            else
113                foreach (FileInfo file in files)
114                {
115                    if (!file.Exists || (file.Attributes & FileAttributes.ReparsePoint) != 0)
116                        continue;
117
118                    //Get the size of the file and its ADSes
119                    totalSize += file.Length;
120                    long adsesSize = 0;
121                    GetPathADSes(result, out adsesSize, file.FullName);
122                    totalSize += adsesSize;
123
124                    //Append this file to the list of files to erase.
125                    result.Add(file.FullName);
126                }
127
128            //Return the filtered list.
129            return result;
130        }
131
132        /// <summary>
133        /// Gets all files in the provided directory.
134        /// </summary>
135        /// <param name="info">The directory to look files in.</param>
136        /// <returns>A list of files found in the directory matching the IncludeMask
137        /// property.</returns>
138        private FileInfo[] GetFiles(DirectoryInfo info)
139        {
140            List<FileInfo> result = new List<FileInfo>();
141            if (info.Exists)
142            {
143                try
144                {
145                    foreach (DirectoryInfo dir in info.GetDirectories())
146                        result.AddRange(GetFiles(dir));
147
148                    if (IncludeMask.Length == 0)
149                        result.AddRange(info.GetFiles());
150                    else
151                        result.AddRange(info.GetFiles(IncludeMask, SearchOption.TopDirectoryOnly));
152                }
153                catch (UnauthorizedAccessException e)
154                {
155                    Logger.Log(S._("Could not erase files and subfolders in {0} because {1}",
156                        info.FullName, e.Message), LogLevel.Error);
157                }
158            }
159
160            return result.ToArray();
161        }
162
163        /// <summary>
164        /// A wildcard expression stating the condition for the set of files to include.
165        /// The include mask is applied before the exclude mask is applied. If this value
166        /// is empty, all files and folders within the folder specified is included.
167        /// </summary>
168        public string IncludeMask { get; set; }
169
170        /// <summary>
171        /// A wildcard expression stating the condition for removing files from the set
172        /// of included files. If this value is omitted, all files and folders extracted
173        /// by the inclusion mask is erased.
174        /// </summary>
175        public string ExcludeMask { get; set; }
176
177        /// <summary>
178        /// Determines if Eraser should delete the folder after the erase process.
179        /// </summary>
180        public bool DeleteIfEmpty { get; set; }
181
182        public override void Execute()
183        {
184            Progress = new SteppedProgressManager();
185            try
186            {
187                base.Execute();
188
189                //If the user requested a folder removal, do it.
190                if (Directory.Exists(Path))
191                {
192                    ProgressManager step = new ProgressManager();
193                    Progress.Steps.Add(new SteppedProgressManagerStep(step,
194                        0.0f, S._("Removing folders...")));
195
196                    //Remove all subfolders which are empty.
197                    FileSystem fsManager = ManagerLibrary.Instance.FileSystemRegistrar[
198                        VolumeInfo.FromMountPoint(Path)];
199                    Action<DirectoryInfo> eraseEmptySubFolders = null;
200                    eraseEmptySubFolders = delegate(DirectoryInfo info)
201                    {
202                        foreach (DirectoryInfo subDir in info.GetDirectories())
203                            eraseEmptySubFolders(subDir);
204                        OnProgressChanged(this, new ProgressChangedEventArgs(step,
205                            new TaskProgressChangedEventArgs(info.FullName, 0, 0)));
206
207                        FileSystemInfo[] files = info.GetFileSystemInfos();
208                        if (files.Length == 0)
209                            fsManager.DeleteFolder(info);
210                    };
211
212                    DirectoryInfo directory = new DirectoryInfo(Path);
213                    foreach (DirectoryInfo subDir in directory.GetDirectories())
214                        eraseEmptySubFolders(subDir);
215
216                    if (DeleteIfEmpty)
217                    {
218                        //See if this is the root of a volume.
219                        bool isVolumeRoot = directory.Parent == null;
220                        foreach (VolumeInfo volume in VolumeInfo.Volumes)
221                            foreach (string mountPoint in volume.MountPoints)
222                                if (directory.FullName == mountPoint)
223                                    isVolumeRoot = true;
224
225                        //If the folder is a mount point, then don't delete it. If it isn't,
226                        //search for files under the folder to see if it is empty.
227                        if (!isVolumeRoot && directory.Exists &&
228                            directory.GetFiles("*", SearchOption.AllDirectories).Length == 0)
229                        {
230                            fsManager.DeleteFolder(directory);
231                        }
232                    }
233                }
234            }
235            finally
236            {
237                Progress = null;
238            }
239        }
240    }
241}
Note: See TracBrowser for help on using the repository browser.