OSDN Git Service

一部ツールで復元できてしまう不具合を修正した
[completeeraser/CompleteEraser.git] / CompleteEraser / FileBreaker.cs
1 using System;\r
2 using System.Text;\r
3 using System.Collections.Generic;\r
4 using System.IO;\r
5 using System.Security.AccessControl;\r
6 using System.Security.Principal;\r
7 using System.Linq;\r
8 using Trinet.Core.IO.Ntfs;\r
9 using CompleteEraser.Properties;\r
10 \r
11 namespace CompleteEraser\r
12 {\r
13     class FileBreaker\r
14     {\r
15         const long ShirnkLength = 1;\r
16 \r
17         public static void BreakFileOrFolder(string path)\r
18         {\r
19             if (Directory.Exists(path))\r
20                 BreakFolder(path);\r
21             else if (File.Exists(path))\r
22                 BreakFile(path);\r
23         }\r
24 \r
25         public static void BreakFile(string file)\r
26         {\r
27             FileAttributes attr = File.GetAttributes(file);\r
28             if ((attr & FileAttributes.ReadOnly) == FileAttributes.ReadOnly)\r
29                 File.SetAttributes(file, attr & ~FileAttributes.ReadOnly);\r
30 \r
31             string ext = Path.GetExtension(file);\r
32 \r
33             FileStream fs;\r
34             FileInfo info = new FileInfo(file);\r
35             foreach (AlternateDataStreamInfo alt in info.ListAlternateDataStreams())\r
36             {\r
37                 fs = alt.Open(FileMode.Open);\r
38                 BreakFileSlowSpeed(fs);\r
39                 fs.Close();\r
40             }\r
41 \r
42             fs = new FileStream(file, FileMode.Open);\r
43             if (Settings.Default.AlwaysSlowSpeed || Settings.Default.SlowSpeedExt.IndexOf(ext) != -1)\r
44                 BreakFileSlowSpeed(fs);\r
45             else\r
46                 BreakFileHiSpeed(fs);\r
47             fs.Close();\r
48 \r
49             string newFile = GenerateRandoName(Path.GetDirectoryName(file), Path.GetFileName(file).Length);\r
50             if(File.Exists(newFile) == false)\r
51                 File.Move(file, newFile);\r
52             \r
53             File.Delete(newFile);\r
54         }\r
55 \r
56         private static void BreakFileSlowSpeed(FileStream fs)\r
57         {\r
58             fs.Seek(0, SeekOrigin.Begin);\r
59             byte[] data = new byte[Settings.Default.FillLengthAtHiSpeed];\r
60             for (long i = 0; i < fs.Length; i += data.Length)\r
61                 fs.Write(data,0,data.Length);\r
62             fs.Flush(true);\r
63             fs.SetLength(ShirnkLength);\r
64         }\r
65 \r
66         private static void BreakFileHiSpeed(FileStream fs)\r
67         {\r
68             fs.Seek(0, SeekOrigin.Begin);\r
69             byte[] data = new byte[Settings.Default.FillLengthAtHiSpeed];\r
70             fs.Write(data, 0, data.Length);\r
71             fs.Seek(-data.Length, SeekOrigin.End);\r
72             fs.Write(data, 0, data.Length);\r
73             fs.Flush(true);\r
74             fs.SetLength(ShirnkLength);\r
75         }\r
76 \r
77         public static void BreakFolder(string folder)\r
78         {\r
79             IEnumerable<string> files = Directory.EnumerateFiles(folder, "*.*", SearchOption.TopDirectoryOnly);\r
80             foreach (string file in files)\r
81                 BreakFile(file);\r
82             IEnumerable<string> dirs = Directory.EnumerateDirectories(folder, "*.*", SearchOption.TopDirectoryOnly);\r
83             foreach (string dir in dirs)\r
84                 BreakFolder(dir);\r
85             string newName = RenameFolderName(folder);\r
86             Directory.Delete(newName);\r
87         }\r
88 \r
89         public static string RenameFolderName(string dir)\r
90         {\r
91             string newName = GenerateRandoName(Path.GetDirectoryName(dir), Path.GetFileName(dir).Length);\r
92             if (Directory.Exists(newName))\r
93                 return dir;\r
94             if ((FileAccessPermissionHelper.GetCurrentAccessRule(dir).FileSystemRights & FileSystemRights.Modify) == FileSystemRights.Modify)\r
95                 Directory.Move(dir, newName);\r
96             else\r
97                 throw new UnauthorizedAccessException();\r
98             return newName;\r
99         }\r
100         \r
101         private static string GenerateRandoName(string dirpath, int length)\r
102         {\r
103             string list = "abcdefghijklmnopqrstuvwxyz0123456789";\r
104             Random rnd = new Random();\r
105             StringBuilder output = new StringBuilder();\r
106             for (int i = 0; i < length; i++)\r
107                 output.Append(list[rnd.Next(list.Length - 1)]);\r
108             return dirpath + "\\" + output.ToString();\r
109         }\r
110     }\r
111 \r
112     public static class FileAccessPermissionHelper\r
113     {\r
114         // 書き込み権限持ってる?\r
115         public static bool IsGotPermission(string path)\r
116         {\r
117             var rule = GetCurrentAccessRule(path);\r
118             return ((rule != null) && ((rule.FileSystemRights & FileSystemRights.Write) == FileSystemRights.Write));\r
119         }\r
120 \r
121         // 現在のユーザーが持っている指定パスのFileSystemAccessRuleを得る\r
122         public static FileSystemAccessRule GetCurrentAccessRule(string path)\r
123         {\r
124             var fileSecurity = File.GetAccessControl(path);\r
125             var rules = fileSecurity.GetAccessRules(true, true, typeof(SecurityIdentifier)).OfType<FileSystemAccessRule>();\r
126             var currentIdentity = WindowsIdentity.GetCurrent();\r
127             var sids = new[] { currentIdentity.User }.Concat(currentIdentity.Groups);\r
128 \r
129             // アクセスルール内にユーザーSIDがある?無ければグループSIDも探す\r
130             return rules.FirstOrDefault(rule => sids.Contains(rule.IdentityReference));\r
131         }\r
132     }\r
133 }\r