OSDN Git Service

fe7f359f6c3dcf87c817ddde5dd1e3f0d1d85375
[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 \r
16         public static void BreakFileOrFolder(string path)\r
17         {\r
18             if (Directory.Exists(path))\r
19                 BreakFolder(path);\r
20             else if (File.Exists(path))\r
21                 BreakFile(path);\r
22         }\r
23 \r
24         public static void BreakFile(string file)\r
25         {\r
26             FileAttributes attr = File.GetAttributes(file);\r
27             if ((attr & FileAttributes.ReadOnly) == FileAttributes.ReadOnly)\r
28                 File.SetAttributes(file, attr & ~FileAttributes.ReadOnly);\r
29 \r
30             string ext = Path.GetExtension(file);\r
31 \r
32             FileStream fs;\r
33             FileInfo info = new FileInfo(file);\r
34             foreach (AlternateDataStreamInfo alt in info.ListAlternateDataStreams())\r
35             {\r
36                 fs = alt.Open(FileMode.Open);\r
37                 BreakFileSlowSpeed(fs);\r
38                 fs.Close();\r
39             }\r
40 \r
41             fs = new FileStream(file, FileMode.Open);\r
42             if (Settings.Default.AlwaysSlowSpeed || Settings.Default.SlowSpeedExt.IndexOf(ext) != -1)\r
43                 BreakFileSlowSpeed(fs);\r
44             else\r
45                 BreakFileHiSpeed(fs);\r
46             fs.Close();\r
47 \r
48             string newFile = GenerateRandoName(Path.GetDirectoryName(file), file.Length);\r
49             File.Move(file, newFile);\r
50             \r
51             File.Delete(newFile);\r
52         }\r
53 \r
54         private static void BreakFileSlowSpeed(FileStream fs)\r
55         {\r
56             if (BreakFileInMFTArea(fs))\r
57                 return;\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         }\r
63 \r
64         private static void BreakFileHiSpeed(FileStream fs)\r
65         {\r
66             if (BreakFileInMFTArea(fs))\r
67                 return;\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         }\r
74 \r
75         private static bool BreakFileInMFTArea(FileStream fs)\r
76         {\r
77             if (fs.Length >= 1024)  //MFTのレコードサイズ以上か\r
78                 return false;\r
79             fs.Seek(0, SeekOrigin.Begin);\r
80             byte[] data = new byte[fs.Length];\r
81             fs.Write(data, 0, data.Length);\r
82             return true;\r
83         }\r
84 \r
85         public static void BreakFolder(string folder)\r
86         {\r
87             IEnumerable<string> files = Directory.GetFiles(folder, "*.*", SearchOption.AllDirectories);\r
88             foreach (string file in files)\r
89                 BreakFile(file);\r
90             string newName = GenerateRandoName(Path.GetDirectoryName(folder), Path.GetFileName(folder).Length);\r
91             if ((FileAccessPermissionHelper.GetCurrentAccessRule(folder).FileSystemRights & FileSystemRights.Modify) == FileSystemRights.Modify)\r
92                 Directory.Move(folder, newName);\r
93             else\r
94                 throw new UnauthorizedAccessException();\r
95             Directory.Delete(newName, true);\r
96         }\r
97 \r
98         private static string GenerateRandoName(string dirpath, int length)\r
99         {\r
100             string list = "abcdefghijklmnopqrstuvwxyz0123456789";\r
101             Random rnd = new Random();\r
102             StringBuilder output = new StringBuilder();\r
103             for (int i = 0; i < length; i++)\r
104                 output.Append(list[rnd.Next(list.Length - 1)]);\r
105             return dirpath + "\\" + output.ToString();\r
106         }\r
107     }\r
108 \r
109     public static class FileAccessPermissionHelper\r
110     {\r
111         // 書き込み権限持ってる?\r
112         public static bool IsGotPermission(string path)\r
113         {\r
114             var rule = GetCurrentAccessRule(path);\r
115             return ((rule != null) && ((rule.FileSystemRights & FileSystemRights.Write) == FileSystemRights.Write));\r
116         }\r
117 \r
118         // 現在のユーザーが持っている指定パスのFileSystemAccessRuleを得る\r
119         public static FileSystemAccessRule GetCurrentAccessRule(string path)\r
120         {\r
121             var fileSecurity = File.GetAccessControl(path);\r
122             var rules = fileSecurity.GetAccessRules(true, true, typeof(SecurityIdentifier)).OfType<FileSystemAccessRule>();\r
123             var currentIdentity = WindowsIdentity.GetCurrent();\r
124             var sids = new[] { currentIdentity.User }.Concat(currentIdentity.Groups);\r
125 \r
126             // アクセスルール内にユーザーSIDがある?無ければグループSIDも探す\r
127             return rules.FirstOrDefault(rule => sids.Contains(rule.IdentityReference));\r
128         }\r
129     }\r
130 }\r