Merge pull request #2040 from esdrubal/monoman
[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-2006 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, Native.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.Length == 0)
54                                         return FullPath;
55                                 return r;
56                         }
57                 }
58
59                 public UnixDirectoryInfo Parent {
60                         get {
61                                 if (FullPath == "/")
62                                         return this;
63                                 string dirname = UnixPath.GetDirectoryName (FullPath);
64                                 if (dirname == "")
65                                         throw new InvalidOperationException ("Do not know parent directory for path `" + FullPath + "'");
66                                 return new UnixDirectoryInfo (dirname);
67                         }
68                 }
69
70                 public UnixDirectoryInfo Root {
71                         get {
72                                 string root = UnixPath.GetPathRoot (FullPath);
73                                 if (root == null)
74                                         return null;
75                                 return new UnixDirectoryInfo (root);
76                         }
77                 }
78
79                 [CLSCompliant (false)]
80                 public void Create (Mono.Unix.Native.FilePermissions mode)
81                 {
82                         int r = Mono.Unix.Native.Syscall.mkdir (FullPath, mode);
83                         UnixMarshal.ThrowExceptionForLastErrorIf (r);
84                         base.Refresh ();
85                 }
86
87                 public void Create (FileAccessPermissions mode)
88                 {
89                         Create ((Native.FilePermissions) mode);
90                 }
91
92                 public void Create ()
93                 {
94                         Mono.Unix.Native.FilePermissions mode = 
95                                 Mono.Unix.Native.FilePermissions.ACCESSPERMS;
96                         Create (mode);
97                 }
98
99                 public override void Delete ()
100                 {
101                         Delete (false);
102                 }
103
104                 public void Delete (bool recursive)
105                 {
106                         if (recursive) {
107                                 foreach (UnixFileSystemInfo e in GetFileSystemEntries ()) {
108                                         UnixDirectoryInfo d = e as UnixDirectoryInfo;
109                                         if (d != null)
110                                                 d.Delete (true);
111                                         else
112                                                 e.Delete ();
113                                 }
114                         }
115                         int r = Native.Syscall.rmdir (FullPath);
116                         UnixMarshal.ThrowExceptionForLastErrorIf (r);
117                         base.Refresh ();
118                 }
119
120                 public Native.Dirent[] GetEntries ()
121                 {
122                         IntPtr dirp = Native.Syscall.opendir (FullPath);
123                         if (dirp == IntPtr.Zero)
124                                 UnixMarshal.ThrowExceptionForLastError ();
125
126                         bool complete = false;
127                         try {
128                                 Native.Dirent[] entries = GetEntries (dirp);
129                                 complete = true;
130                                 return entries;
131                         }
132                         finally {
133                                 int r = Native.Syscall.closedir (dirp);
134                                 // don't throw an exception if an exception is in progress
135                                 if (complete)
136                                         UnixMarshal.ThrowExceptionForLastErrorIf (r);
137                         }
138                 }
139
140                 private static Native.Dirent[] GetEntries (IntPtr dirp)
141                 {
142                         ArrayList entries = new ArrayList ();
143
144                         int r;
145                         IntPtr result;
146                         do {
147                                 Native.Dirent d = new Native.Dirent ();
148                                 r = Native.Syscall.readdir_r (dirp, d, out result);
149                                 if (r == 0 && result != IntPtr.Zero)
150                                         // don't include current & parent dirs
151                                         if (d.d_name != "." && d.d_name != "..")
152                                                 entries.Add (d);
153                         } while  (r == 0 && result != IntPtr.Zero);
154                         if (r != 0)
155                                 UnixMarshal.ThrowExceptionForLastErrorIf (r);
156
157                         return (Native.Dirent[]) entries.ToArray (typeof(Native.Dirent));
158                 }
159
160                 public Native.Dirent[] GetEntries (Regex regex)
161                 {
162                         IntPtr dirp = Native.Syscall.opendir (FullPath);
163                         if (dirp == IntPtr.Zero)
164                                 UnixMarshal.ThrowExceptionForLastError ();
165
166                         try {
167                                 return GetEntries (dirp, regex);
168                         }
169                         finally {
170                                 int r = Native.Syscall.closedir (dirp);
171                                 UnixMarshal.ThrowExceptionForLastErrorIf (r);
172                         }
173                 }
174
175                 private static Native.Dirent[] GetEntries (IntPtr dirp, Regex regex)
176                 {
177                         ArrayList entries = new ArrayList ();
178
179                         int r;
180                         IntPtr result;
181                         do {
182                                 Native.Dirent d = new Native.Dirent ();
183                                 r = Native.Syscall.readdir_r (dirp, d, out result);
184                                 if (r == 0 && result != IntPtr.Zero && regex.Match (d.d_name).Success) {
185                                         // don't include current & parent dirs
186                                         if (d.d_name != "." && d.d_name != "..")
187                                                 entries.Add (d);
188                                 }
189                         } while  (r == 0 && result != IntPtr.Zero);
190                         if (r != 0)
191                                 UnixMarshal.ThrowExceptionForLastError ();
192
193                         return (Native.Dirent[]) entries.ToArray (typeof(Native.Dirent));
194                 }
195
196                 public Native.Dirent[] GetEntries (string regex)
197                 {
198                         Regex re = new Regex (regex);
199                         return GetEntries (re);
200                 }
201
202                 public UnixFileSystemInfo[] GetFileSystemEntries ()
203                 {
204                         Native.Dirent[] dentries = GetEntries ();
205                         return GetFileSystemEntries (dentries);
206                 }
207
208                 private UnixFileSystemInfo[] GetFileSystemEntries (Native.Dirent[] dentries)
209                 {
210                         UnixFileSystemInfo[] entries = new UnixFileSystemInfo[dentries.Length];
211                         for (int i = 0; i != entries.Length; ++i)
212                                 entries [i] = UnixFileSystemInfo.GetFileSystemEntry (
213                                                 UnixPath.Combine (FullPath, dentries[i].d_name));
214                         return entries;
215                 }
216
217                 public UnixFileSystemInfo[] GetFileSystemEntries (Regex regex)
218                 {
219                         Native.Dirent[] dentries = GetEntries (regex);
220                         return GetFileSystemEntries (dentries);
221                 }
222
223                 public UnixFileSystemInfo[] GetFileSystemEntries (string regex)
224                 {
225                         Regex re = new Regex (regex);
226                         return GetFileSystemEntries (re);
227                 }
228
229                 public static string GetCurrentDirectory ()
230                 {
231                         StringBuilder buf = new StringBuilder (16);
232                         IntPtr r = IntPtr.Zero;
233                         do {
234                                 buf.Capacity *= 2;
235                                 r = Native.Syscall.getcwd (buf, (ulong) buf.Capacity);
236                         } while (r == IntPtr.Zero && Native.Syscall.GetLastError() == Native.Errno.ERANGE);
237                         if (r == IntPtr.Zero)
238                                 UnixMarshal.ThrowExceptionForLastError ();
239                         return buf.ToString ();
240                 }
241
242                 public static void SetCurrentDirectory (string path)
243                 {
244                         int r = Native.Syscall.chdir (path);
245                         UnixMarshal.ThrowExceptionForLastErrorIf (r);
246                 }
247         }
248 }
249
250 // vim: noexpandtab