* Stdlib.cs: Cache delegates passed to Stdlib.signal() so that they survive
[mono.git] / mcs / class / Mono.Posix / Mono.Unix / UnixDirectoryInfo.cs
1 //
2 // Mono.Unix/UnixDirectoryInfo.cs
3 //
4 // Authors:
5 //   Jonathan Pryor (jonpryor@vt.edu)
6 //
7 // (C) 2004 Jonathan Pryor
8 //
9 // Permission is hereby granted, free of charge, to any person obtaining
10 // a copy of this software and associated documentation files (the
11 // "Software"), to deal in the Software without restriction, including
12 // without limitation the rights to use, copy, modify, merge, publish,
13 // distribute, sublicense, and/or sell copies of the Software, and to
14 // permit persons to whom the Software is furnished to do so, subject to
15 // the following conditions:
16 // 
17 // The above copyright notice and this permission notice shall be
18 // included in all copies or substantial portions of the Software.
19 // 
20 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
23 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
24 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
25 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
26 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
27 //
28
29 using System;
30 using System.Collections;
31 using System.IO;
32 using System.Text;
33 using System.Text.RegularExpressions;
34 using Mono.Unix;
35
36 namespace Mono.Unix {
37
38         public sealed class UnixDirectoryInfo : UnixFileSystemInfo
39         {
40                 public UnixDirectoryInfo (string path)
41                         : base (path)
42                 {
43                 }
44
45                 internal UnixDirectoryInfo (string path, Stat stat)
46                         : base (path, stat)
47                 {
48                 }
49
50                 public override string Name {
51                         get {
52                                 string r = UnixPath.GetFileName (FullPath);
53                                 if (r == null || r == "")
54                                         return FullPath;
55                                 return r;
56                         }
57                 }
58
59                 public UnixDirectoryInfo Parent {
60                         get {
61                                 string dirname = UnixPath.GetDirectoryName (FullPath);
62                                 if (dirname == null)
63                                         return null;
64                                 return new UnixDirectoryInfo (dirname);
65                         }
66                 }
67
68                 public UnixDirectoryInfo Root {
69                         get {
70                                 string root = UnixPath.GetPathRoot (FullPath);
71                                 if (root == null)
72                                         return null;
73                                 return new UnixDirectoryInfo (root);
74                         }
75                 }
76
77                 public void Create (FilePermissions mode)
78                 {
79                         int r = Syscall.mkdir (FullPath, mode);
80                         UnixMarshal.ThrowExceptionForLastErrorIf (r);
81                         base.Refresh ();
82                 }
83
84                 public void Create ()
85                 {
86                         FilePermissions mode = FilePermissions.ACCESSPERMS;
87                         Create (mode);
88                 }
89
90                 public override void Delete ()
91                 {
92                         Delete (false);
93                 }
94
95                 public void Delete (bool recursive)
96                 {
97                         if (recursive) {
98                                 foreach (UnixFileSystemInfo e in GetFileSystemEntries ()) {
99                                         UnixDirectoryInfo d = e as UnixDirectoryInfo;
100                                         if (d != null)
101                                                 d.Delete (true);
102                                         else
103                                                 e.Delete ();
104                                 }
105                         }
106                         int r = Syscall.rmdir (FullPath);
107                         UnixMarshal.ThrowExceptionForLastErrorIf (r);
108                         base.Refresh ();
109                 }
110
111                 public Dirent[] GetEntries ()
112                 {
113                         IntPtr dirp = Syscall.opendir (FullPath);
114                         if (dirp == IntPtr.Zero)
115                                 UnixMarshal.ThrowExceptionForLastError ();
116
117                         bool complete = false;
118                         try {
119                                 Dirent[] entries = GetEntries (dirp);
120                                 complete = true;
121                                 return entries;
122                         }
123                         finally {
124                                 int r = Syscall.closedir (dirp);
125                                 // don't throw an exception if an exception is in progress
126                                 if (complete)
127                                         UnixMarshal.ThrowExceptionForLastErrorIf (r);
128                         }
129                 }
130
131                 private static Dirent[] GetEntries (IntPtr dirp)
132                 {
133                         ArrayList entries = new ArrayList ();
134
135                         int r;
136                         IntPtr result;
137                         do {
138                                 Dirent d = new Dirent ();
139                                 r = Syscall.readdir_r (dirp, d, out result);
140                                 if (r == 0 && result != IntPtr.Zero)
141                                         // don't include current & parent dirs
142                                         if (d.d_name != "." && d.d_name != "..")
143                                                 entries.Add (d);
144                         } while  (r == 0 && result != IntPtr.Zero);
145                         if (r != 0)
146                                 UnixMarshal.ThrowExceptionForLastErrorIf (r);
147
148                         return (Dirent[]) entries.ToArray (typeof(Dirent));
149                 }
150
151                 public Dirent[] GetEntries (Regex regex)
152                 {
153                         IntPtr dirp = Syscall.opendir (FullPath);
154                         if (dirp == IntPtr.Zero)
155                                 UnixMarshal.ThrowExceptionForLastError ();
156
157                         try {
158                                 return GetEntries (dirp, regex);
159                         }
160                         finally {
161                                 int r = Syscall.closedir (dirp);
162                                 UnixMarshal.ThrowExceptionForLastErrorIf (r);
163                         }
164                 }
165
166                 private static Dirent[] GetEntries (IntPtr dirp, Regex regex)
167                 {
168                         ArrayList entries = new ArrayList ();
169
170                         int r;
171                         IntPtr result;
172                         do {
173                                 Dirent d = new Dirent ();
174                                 r = Syscall.readdir_r (dirp, d, out result);
175                                 if (r == 0 && result != IntPtr.Zero && regex.Match (d.d_name).Success) {
176                                         // don't include current & parent dirs
177                                         if (d.d_name != "." && d.d_name != "..")
178                                                 entries.Add (d);
179                                 }
180                         } while  (r == 0 && result != IntPtr.Zero);
181                         if (r != 0)
182                                 UnixMarshal.ThrowExceptionForLastError ();
183
184                         return (Dirent[]) entries.ToArray (typeof(Dirent));
185                 }
186
187                 public Dirent[] GetEntries (string regex)
188                 {
189                         Regex re = new Regex (regex);
190                         return GetEntries (re);
191                 }
192
193                 public UnixFileSystemInfo[] GetFileSystemEntries ()
194                 {
195                         Dirent[] dentries = GetEntries ();
196                         return GetFileSystemEntries (dentries);
197                 }
198
199                 private UnixFileSystemInfo[] GetFileSystemEntries (Dirent[] dentries)
200                 {
201                         UnixFileSystemInfo[] entries = new UnixFileSystemInfo[dentries.Length];
202                         for (int i = 0; i != entries.Length; ++i)
203                                 entries [i] = UnixFileSystemInfo.Create (dentries[i].d_name);
204                         return entries;
205                 }
206
207                 public UnixFileSystemInfo[] GetFileSystemEntries (Regex regex)
208                 {
209                         Dirent[] dentries = GetEntries (regex);
210                         return GetFileSystemEntries (dentries);
211                 }
212
213                 public UnixFileSystemInfo[] GetFileSystemEntries (string regex)
214                 {
215                         Regex re = new Regex (regex);
216                         return GetFileSystemEntries (re);
217                 }
218         }
219 }
220
221 // vim: noexpandtab