source: branches/eraser6/6.0/Eraser.Manager/FileSystem.cs @ 1878

Revision 1878, 12.7 KB checked in by lowjoel, 5 years ago (diff)

Compilo fix.

  • 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: Kasra Nassiri <cjax@users.sourceforge.net> @17/10/2008
6 * Modified By:
7 *
8 * This file is part of Eraser.
9 *
10 * Eraser is free software: you can redistribute it and/or modify it under the
11 * terms of the GNU General Public License as published by the Free Software
12 * Foundation, either version 3 of the License, or (at your option) any later
13 * version.
14 *
15 * Eraser is distributed in the hope that it will be useful, but WITHOUT ANY
16 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
17 * A PARTICULAR PURPOSE. See the GNU General Public License for more details.
18 *
19 * A copy of the GNU General Public License can be found at
20 * <http://www.gnu.org/licenses/>.
21 */
22
23using System;
24using System.Collections.Generic;
25using System.Text;
26using System.IO;
27using Eraser.Util;
28
29namespace Eraser.Manager
30{
31    /// <summary>
32    /// Provides functions to handle erasures specfic to file systems.
33    /// </summary>
34    public abstract class FileSystem
35    {
36        /// <summary>
37        /// Generates a random file name with the given length.
38        /// </summary>
39        /// <remarks>The generated file name is guaranteed not to exist.</remarks>
40        /// <param name="info">The directory to generate the file name in. This
41        /// parameter can be null to indicate merely a random file name</param>
42        /// <param name="length">The length of the file name to generate.</param>
43        /// <returns>A full path to a file containing random file name.</returns>
44        public static string GenerateRandomFileName(DirectoryInfo info, int length)
45        {
46            //Initialise the base name, if any.
47            Prng prng = PrngManager.GetInstance(ManagerLibrary.Settings.ActivePrng);
48            string resultPrefix = info == null ? string.Empty : info.FullName +
49                Path.DirectorySeparatorChar;
50
51            //Variables to store the intermediates.
52            byte[] resultAry = new byte[length];
53            string result = string.Empty;
54            List<string> prohibitedFileNames = new List<string>(new string[] {
55                "CON", "PRN", "AUX", "NUL", "COM1", "COM2", "COM3", "COM4",
56                "COM5", "COM6", "COM7", "COM8", "COM9", "LPT1", "LPT2", "LPT3",
57                "LPT4", "LPT5", "LPT6", "LPT7", "LPT8", "LPT9"
58            });
59
60            do
61            {
62                prng.NextBytes(resultAry);
63
64                //Validate the name
65                string validFileNameChars = "0123456789abcdefghijklmnopqrstuvwxyz" +
66                    "ABCDEFGHIJKLMNOPQRSTUVWXYZ _+=-()[]{}',`~!";
67                for (int j = 0, k = resultAry.Length; j < k; ++j)
68                    resultAry[j] = (byte)validFileNameChars[
69                        (int)resultAry[j] % validFileNameChars.Length];
70
71                result = Encoding.UTF8.GetString(resultAry);
72            }
73            while (info != null &&
74                prohibitedFileNames.IndexOf(Path.GetFileNameWithoutExtension(result)) != -1 ||
75                (Directory.Exists(resultPrefix + result) ||
76                    System.IO.File.Exists(resultPrefix + result))
77            );
78            return resultPrefix + result;
79        }
80
81        /// <summary>
82        /// Gets a random file from within the provided directory.
83        /// </summary>
84        /// <param name="info">The directory to get a random file name from.</param>
85        /// <returns>A string containing the full path to the file.</returns>
86        public static string GetRandomFile(DirectoryInfo info)
87        {
88            //First retrieve the list of files and folders in the provided directory.
89            FileSystemInfo[] entries = null;
90            try
91            {
92                entries = info.GetFileSystemInfos();
93            }
94            catch (DirectoryNotFoundException)
95            {
96                return string.Empty;
97            }
98            if (entries.Length == 0)
99                return string.Empty;
100
101            //Find a random entry.
102            Prng prng = PrngManager.GetInstance(ManagerLibrary.Settings.ActivePrng);
103            string result = string.Empty;
104            while (result.Length == 0)
105            {
106                int index = prng.Next(entries.Length - 1);
107                if (entries[index] is DirectoryInfo)
108                    result = GetRandomFile((DirectoryInfo)entries[index]);
109                else
110                    result = ((FileInfo)entries[index]).FullName;
111            }
112
113            return result;
114        }
115
116        /// <summary>
117        /// Writes a file for plausible deniability over the current stream.
118        /// </summary>
119        /// <param name="stream">The stream to write the data to.</param>
120        protected static void CopyPlausibleDeniabilityFile(Stream stream)
121        {
122            //Get the template file to copy
123            FileInfo shadowFileInfo;
124            {
125                string shadowFile = null;
126                List<string> entries = new List<string>(
127                    ManagerLibrary.Settings.PlausibleDeniabilityFiles);
128                Prng prng = PrngManager.GetInstance(ManagerLibrary.Settings.ActivePrng);
129                do
130                {
131                    if (entries.Count == 0)
132                        throw new FatalException(S._("Plausible deniability was selected, " +
133                            "but no decoy files were found. The current file has been only " +
134                            "replaced with random data."));
135
136                    int index = prng.Next(entries.Count - 1);
137                    if ((System.IO.File.GetAttributes(entries[index]) & FileAttributes.Directory) != 0)
138                    {
139                        DirectoryInfo dir = new DirectoryInfo(entries[index]);
140                        FileInfo[] files = dir.GetFiles("*", SearchOption.AllDirectories);
141                        foreach (FileInfo f in files)
142                            entries.Add(f.FullName);
143                    }
144                    else
145                        shadowFile = entries[index];
146
147                    entries.RemoveAt(index);
148                }
149                while (shadowFile == null || shadowFile.Length == 0 ||
150                    !System.IO.File.Exists(shadowFile));
151                shadowFileInfo = new FileInfo(shadowFile);
152            }
153
154            //Dump the copy (the first 4MB, or less, depending on the file size and size of
155            //the original file)
156            long amountToCopy = Math.Min(stream.Length,
157                Math.Min(4 * 1024 * 1024, shadowFileInfo.Length));
158            using (FileStream shadowFileStream = shadowFileInfo.OpenRead())
159            {
160                while (stream.Position < amountToCopy)
161                {
162                    byte[] buf = new byte[524288];
163                    int bytesRead = shadowFileStream.Read(buf, 0, buf.Length);
164
165                    //Stop bothering if the input stream is at the end
166                    if (bytesRead == 0)
167                        break;
168
169                    //Dump the read contents onto the file to be deleted
170                    stream.Write(buf, 0,
171                        (int)Math.Min(bytesRead, amountToCopy - stream.Position));
172                }
173            }
174        }
175
176        /// <summary>
177        /// Checks whether the given file system is supported by the current provider.
178        /// </summary>
179        /// <param name="fileSystemName">The file system name to check.</param>
180        /// <returns>True if the current provider supports the file system.</returns>
181        public abstract bool Supports(string fileSystemName);
182
183        /// <summary>
184        /// Securely deletes the file reference from the directory structures
185        /// as well as resetting the Date Created, Date Accessed and Date Modified
186        /// records.
187        /// </summary>
188        /// <param name="info">The file to delete.</param>
189        public abstract void DeleteFile(FileInfo info);
190
191        /// <summary>
192        /// Securely deletes the folder reference from the directory structures
193        /// as well as all subfolders and files, resetting the Date Created, Date
194        /// Accessed and Date Modified records.
195        /// </summary>
196        /// <param name="info">The folder to delete</param>
197        /// <param name="recursive">True if the folder and all its subfolders and
198        /// files to be securely deleted.</param>
199        public abstract void DeleteFolder(DirectoryInfo info, bool recursive);
200
201        /// <seealso cref="DeleteFolder"/>
202        /// <param name="info">The folder to delete.</param>
203        public void DeleteFolder(DirectoryInfo info)
204        {
205            DeleteFolder(info, true);
206        }
207
208        /// <summary>
209        /// Erases all file cluster tips in the given volume.
210        /// </summary>
211        /// <param name="info">The volume to search for file cluster tips and erase them.</param>
212        /// <param name="method">The erasure method being employed.</param>
213        /// <param name="log">The log manager instance that tracks log messages.</param>
214        /// <param name="searchCallback">The callback function for search progress.</param>
215        /// <param name="eraseCallback">The callback function for erasure progress.</param>
216        public abstract void EraseClusterTips(VolumeInfo info, ErasureMethod method,
217            Logger log, ClusterTipsSearchProgress searchCallback,
218            ClusterTipsEraseProgress eraseCallback);
219
220        /// <summary>
221        /// Erases old file system table-resident files. This creates small one-byte
222        /// files until disk is full. This will erase unused space which was used for
223        /// files resident in the file system table.
224        /// </summary>
225        /// <param name="volume">The directory information structure containing
226        /// the path to store the temporary one-byte files. The file system table
227        /// of that drive will be erased.</param>
228        /// <param name="tempDirectory">The directory structure containing the path
229        /// to store temporary files used for resident file cleaning.</param>
230        /// <param name="method">The method used to erase the files.</param>
231        public abstract void EraseOldFileSystemResidentFiles(VolumeInfo volume,
232            DirectoryInfo tempDirectory, ErasureMethod method,
233            FileSystemEntriesEraseProgress callback);
234
235        /// <summary>
236        /// Erases the unused space in the main filesystem structures by creating,
237        /// files until the table grows.
238        ///
239        /// This will overwrite unused portions of the table which were previously
240        /// used to store file entries.
241        /// </summary>
242        /// <param name="info">The directory information structure containing
243        /// the path to store the temporary files.</param>
244        /// <param name="callback">The callback function to handle the progress
245        /// of the file system entry erasure.</param>
246        public abstract void EraseDirectoryStructures(VolumeInfo info,
247            FileSystemEntriesEraseProgress callback);
248
249        /// <summary>
250        /// Erases the file system object from the drive.
251        /// </summary>
252        /// <param name="info"></param>
253        public abstract void EraseFileSystemObject(StreamInfo info, ErasureMethod method,
254            ErasureMethodProgressFunction callback);
255
256        /// <summary>
257        /// Retrieves the size of the file on disk, calculated by the amount of
258        /// clusters allocated by it.
259        /// </summary>
260        /// <param name="filePath">The path to the file.</param>
261        /// <returns>The area of the file.</returns>
262        public abstract long GetFileArea(string filePath);
263
264        /// <summary>
265        /// The number of times file names are renamed to erase the file name from
266        /// the file system table.
267        /// </summary>
268        public const int FileNameErasePasses = 7;
269
270        /// <summary>
271        /// The maximum number of times Eraser tries to erase a file/folder before
272        /// it gives up.
273        /// </summary>
274        public const int FileNameEraseTries = 50;
275    }
276
277    /// <summary>
278    /// The function prototype for cluster tip search progress callbacks. This is
279    /// called when the cluster tips are being searched.
280    /// </summary>
281    /// <param name="currentPath">The directory being searched</param>
282    public delegate void ClusterTipsSearchProgress(string currentPath);
283
284    /// <summary>
285    /// The function prototype for cluster tip erasure callbacks. This is called when
286    /// the cluster tips are being erased.
287    /// </summary>
288    /// <param name="currentFile">The current file index being erased.</param>
289    /// <param name="totalFiles">The total number of files to be erased.</param>
290    /// <param name="currentFilePath">The path to the current file being erased.</param>
291    public delegate void ClusterTipsEraseProgress(int currentFile, int totalFiles,
292        string currentFilePath);
293
294    /// <summary>
295    /// The prototype of callbacks handling the file system table erase progress.
296    /// </summary>
297    /// <param name="currentFile">The current file being erased.</param>
298    /// <param name="totalFiles">The estimated number of files that must be
299    /// erased.</param>
300    public delegate void FileSystemEntriesEraseProgress(int currentFile, int totalFiles);
301
302    public class FileSystemManager
303    {
304        #region Registrar fields
305        /// <summary>
306        /// Gets the FileSystem object that implements the FileSystem interface
307        /// for the given file system.
308        /// </summary>
309        /// <param name="volume">The volume to get the FileSystem provider for.</param>
310        /// <returns>The FileSystem object providing interfaces to handle the
311        /// given volume.</returns>
312        /// <exception cref="NotSupportedException">Thrown when an unimplemented
313        /// file system is requested.</exception>
314        public static FileSystem Get(VolumeInfo volume)
315        {
316            lock (ManagerLibrary.Instance.FileSystemManager.FileSystems)
317                foreach (FileSystem filesystem in ManagerLibrary.Instance.FileSystemManager.FileSystems)
318                    if (filesystem.Supports(volume.VolumeFormat))
319                        return filesystem;
320
321            throw new NotSupportedException(S._("The file system on the drive {0} is not " +
322                "supported.", volume.IsMounted ? volume.MountPoints[0] : volume.VolumeId));
323        }
324
325        /// <summary>
326        /// Allows plug-ins to register file system providers with the main program.
327        /// Thread-safe.
328        /// </summary>
329        /// <param name="method">The filesystem to register.</param>
330        public static void Register(FileSystem filesystem)
331        {
332            //Insert the entry
333            lock (ManagerLibrary.Instance.FileSystemManager.FileSystems)
334            {
335                ManagerLibrary.Instance.FileSystemManager.FileSystems.Add(filesystem);
336            }
337        }
338
339        /// <summary>
340        /// The list of currently registered erasure methods.
341        /// </summary>
342        private List<FileSystem> FileSystems = new List<FileSystem>();
343        #endregion
344    }
345}
Note: See TracBrowser for help on using the repository browser.