* Mono.Posix_test.dll.sources: Move StdlibTest into the Mono.Unix.Native
[mono.git] / mcs / class / Mono.Posix / Mono.Unix / UnixFileSystemInfo.cs
1 //
2 // Mono.Unix/UnixFileSystemInfo.cs
3 //
4 // Authors:
5 //   Jonathan Pryor (jonpryor@vt.edu)
6 //
7 // (C) 2004-2005 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.IO;
31 using System.Text;
32 using Mono.Unix;
33
34 namespace Mono.Unix {
35
36         public abstract class UnixFileSystemInfo
37         {
38                 private Native.Stat stat;
39                 private string fullPath;
40                 private string originalPath;
41                 private bool valid = false;
42
43                 protected UnixFileSystemInfo (string path)
44                 {
45                         UnixPath.CheckPath (path);
46                         this.originalPath = path;
47                         this.fullPath = UnixPath.GetFullPath (path);
48                         Refresh (true);
49                 }
50
51                 internal UnixFileSystemInfo (String path, Native.Stat stat)
52                 {
53                         this.originalPath = path;
54                         this.fullPath = UnixPath.GetFullPath (path);
55                         this.stat = stat;
56                         this.valid = true;
57                 }
58
59                 protected string FullPath {
60                         get {return fullPath;}
61                         set {fullPath = value;}
62                 }
63
64                 protected string OriginalPath {
65                         get {return originalPath;}
66                         set {originalPath = value;}
67                 }
68
69                 private void AssertValid ()
70                 {
71                         Refresh (false);
72                         if (!valid)
73                                 throw new InvalidOperationException ("Path doesn't exist!");
74                 }
75
76                 public virtual string FullName {
77                         get {return FullPath;}
78                 }
79
80                 public abstract string Name {get;}
81
82                 public bool Exists {
83                         get {
84                                 Refresh (true);
85                                 return valid;
86                         }
87                 }
88
89                 public long Device {
90                         get {AssertValid (); return Convert.ToInt64 (stat.st_dev);}
91                 }
92
93                 public long Inode {
94                         get {AssertValid (); return Convert.ToInt64 (stat.st_ino);}
95                 }
96
97                 [CLSCompliant (false)]
98                 [Obsolete ("Use Protection.")]
99                 public FilePermissions Mode {
100                         get {AssertValid (); return (FilePermissions) stat.st_mode;}
101                 }
102
103                 [CLSCompliant (false)]
104                 [Obsolete ("Use FileAccessPermissions.")]
105                 public FilePermissions Permissions {
106                         get {AssertValid (); return (FilePermissions) stat.st_mode & ~FilePermissions.S_IFMT;}
107                 }
108
109                 [CLSCompliant (false)]
110                 public Native.FilePermissions Protection {
111                         get {AssertValid (); return (Native.FilePermissions) stat.st_mode;}
112                         set {
113                                 int r = Native.Syscall.chmod (FullPath, value);
114                                 UnixMarshal.ThrowExceptionForLastErrorIf (r);
115                         }
116                 }
117
118                 public FileTypes FileType {
119                         get {
120                                 AssertValid ();
121                                 int type = (int) stat.st_mode;
122                                 return (FileTypes) (type & (int) FileTypes.AllTypes);
123                         }
124                         // no set as chmod(2) won't accept changing the file type.
125                 }
126
127                 public FileAccessPermissions FileAccessPermissions {
128                         get {
129                                 AssertValid (); 
130                                 int perms = (int) stat.st_mode;
131                                 return (FileAccessPermissions) (perms & (int) FileAccessPermissions.AllPermissions);
132                         }
133                         set {
134                                 AssertValid ();
135                                 int perms = (int) stat.st_mode;
136                                 perms &= (int) ~FileAccessPermissions.AllPermissions;
137                                 perms |= (int) value;
138                                 Protection = (Native.FilePermissions) perms;
139                         }
140                 }
141
142                 public FileSpecialAttributes FileSpecialAttributes {
143                         get {
144                                 AssertValid ();
145                                 int attrs = (int) stat.st_mode;
146                                 return (FileSpecialAttributes) (attrs & (int) FileSpecialAttributes.AllAttributes);
147                         }
148                         set {
149                                 AssertValid ();
150                                 int perms = (int) stat.st_mode;
151                                 perms &= (int) ~FileSpecialAttributes.AllAttributes;
152                                 perms |= (int) value;
153                                 Protection = (Native.FilePermissions) perms;
154                         }
155                 }
156
157                 public long LinkCount {
158                         get {AssertValid (); return Convert.ToInt64 (stat.st_nlink);}
159                 }
160
161                 public UnixUserInfo OwnerUser {
162                         get {AssertValid (); return new UnixUserInfo (stat.st_uid);}
163                 }
164
165                 public long OwnerUserId {
166                         get {AssertValid (); return stat.st_uid;}
167                 }
168
169                 public UnixGroupInfo OwnerGroup {
170                         get {AssertValid (); return new UnixGroupInfo (stat.st_gid);}
171                 }
172
173                 public long OwnerGroupId {
174                         get {AssertValid (); return stat.st_gid;}
175                 }
176
177                 public long DeviceType {
178                         get {AssertValid (); return Convert.ToInt64 (stat.st_rdev);}
179                 }
180
181                 public long Length {
182                         get {AssertValid (); return (long) stat.st_size;}
183                 }
184
185                 public long BlockSize {
186                         get {AssertValid (); return (long) stat.st_blksize;}
187                 }
188
189                 public long BlocksAllocated {
190                         get {AssertValid (); return (long) stat.st_blocks;}
191                 }
192
193                 public DateTime LastAccessTime {
194                         get {AssertValid (); return UnixConvert.ToDateTime (stat.st_atime);}
195                 }
196
197                 public DateTime LastAccessTimeUtc {
198                         get {return LastAccessTime.ToUniversalTime ();}
199                 }
200
201                 public DateTime LastWriteTime {
202                         get {AssertValid (); return UnixConvert.ToDateTime (stat.st_mtime);}
203                 }
204
205                 public DateTime LastWriteTimeUtc {
206                         get {return LastWriteTime.ToUniversalTime ();}
207                 }
208
209                 public DateTime LastStatusChangeTime {
210                         get {AssertValid (); return UnixConvert.ToDateTime (stat.st_ctime);}
211                 }
212
213                 public DateTime LastStatusChangeTimeUtc {
214                         get {return LastStatusChangeTime.ToUniversalTime ();}
215                 }
216
217                 public bool IsDirectory {
218                         get {AssertValid (); return IsType (stat.st_mode, Native.FilePermissions.S_IFDIR);}
219                 }
220
221                 public bool IsCharacterDevice {
222                         get {AssertValid (); return IsType (stat.st_mode, Native.FilePermissions.S_IFCHR);}
223                 }
224
225                 public bool IsBlockDevice {
226                         get {AssertValid (); return IsType (stat.st_mode, Native.FilePermissions.S_IFBLK);}
227                 }
228
229                 [Obsolete ("Use IsRegularFile")]
230                 public bool IsFile {
231                         get {AssertValid (); return IsType (stat.st_mode, Native.FilePermissions.S_IFREG);}
232                 }
233
234                 public bool IsRegularFile {
235                         get {AssertValid (); return IsType (stat.st_mode, Native.FilePermissions.S_IFREG);}
236                 }
237
238                 [Obsolete ("Use IsFifo")]
239                 [CLSCompliant (false)]
240                 public bool IsFIFO {
241                         get {AssertValid (); return IsType (stat.st_mode, Native.FilePermissions.S_IFIFO);}
242                 }
243
244                 public bool IsFifo {
245                         get {AssertValid (); return IsType (stat.st_mode, Native.FilePermissions.S_IFIFO);}
246                 }
247
248                 public bool IsSymbolicLink {
249                         get {AssertValid (); return IsType (stat.st_mode, Native.FilePermissions.S_IFLNK);}
250                 }
251
252                 public bool IsSocket {
253                         get {AssertValid (); return IsType (stat.st_mode, Native.FilePermissions.S_IFSOCK);}
254                 }
255
256                 public bool IsSetUser {
257                         get {AssertValid (); return IsType (stat.st_mode, Native.FilePermissions.S_ISUID);}
258                 }
259
260                 public bool IsSetGroup {
261                         get {AssertValid (); return IsType (stat.st_mode, Native.FilePermissions.S_ISGID);}
262                 }
263
264                 public bool IsSticky {
265                         get {AssertValid (); return IsType (stat.st_mode, Native.FilePermissions.S_ISVTX);}
266                 }
267
268                 internal static bool IsType (FilePermissions mode, FilePermissions type)
269                 {
270                         return (mode & type) == type;
271                 }
272
273                 internal static bool IsType (Native.FilePermissions mode, Native.FilePermissions type)
274                 {
275                         return (mode & type) == type;
276                 }
277
278                 [CLSCompliant (false)]
279                 [Obsolete ("Use CanAccess (Mono.Unix.Native.AccessModes)")]
280                 public bool CanAccess (AccessMode mode)
281                 {
282                         int r = Syscall.access (FullPath, mode);
283                         return r == 0;
284                 }
285
286                 [CLSCompliant (false)]
287                 public bool CanAccess (Native.AccessModes mode)
288                 {
289                         int r = Native.Syscall.access (FullPath, mode);
290                         return r == 0;
291                 }
292
293                 public UnixFileSystemInfo CreateLink (string path)
294                 {
295                         int r = Syscall.link (FullName, path);
296                         UnixMarshal.ThrowExceptionForLastErrorIf (r);
297                         return Create (path);
298                 }
299
300                 public UnixSymbolicLinkInfo CreateSymbolicLink (string path)
301                 {
302                         int r = Syscall.symlink (FullName, path);
303                         UnixMarshal.ThrowExceptionForLastErrorIf (r);
304                         return new UnixSymbolicLinkInfo (path);
305                 }
306
307                 public abstract void Delete ();
308
309                 [CLSCompliant (false)]
310                 [Obsolete ("Use GetConfigurationValue (Mono.Unix.Native.PathconfName)")]
311                 public long GetConfigurationValue (PathConf name)
312                 {
313                         long r = Syscall.pathconf (FullPath, name);
314                         if (r == -1 && Syscall.GetLastError() != (Error) 0)
315                                 UnixMarshal.ThrowExceptionForLastError ();
316                         return r;
317                 }
318
319                 [CLSCompliant (false)]
320                 public long GetConfigurationValue (Native.PathconfName name)
321                 {
322                         long r = Native.Syscall.pathconf (FullPath, name);
323                         if (r == -1 && Syscall.GetLastError() != (Error) 0)
324                                 UnixMarshal.ThrowExceptionForLastError ();
325                         return r;
326                 }
327
328                 public void Refresh ()
329                 {
330                         Refresh (true);
331                 }
332
333                 internal void Refresh (bool force)
334                 {
335                         if (valid && !force)
336                                 return;
337                         int r = GetFileStatus (FullPath, out this.stat);
338                         valid = r == 0;
339                 }
340
341                 protected virtual int GetFileStatus (string path, out Native.Stat stat)
342                 {
343                         return Native.Syscall.stat (path, out stat);
344                 }
345
346                 public void SetLength (long length)
347                 {
348                         int r;
349                         do {
350                                 r = Syscall.truncate (FullPath, length);
351                         }       while (UnixMarshal.ShouldRetrySyscall (r));
352                         UnixMarshal.ThrowExceptionForLastErrorIf (r);
353                 }
354
355                 [CLSCompliant (false)]
356                 [Obsolete ("Use Protection setter")]
357                 public void SetPermissions (FilePermissions perms)
358                 {
359                         int r = Syscall.chmod (FullPath, perms);
360                         UnixMarshal.ThrowExceptionForLastErrorIf (r);
361                 }
362
363                 [CLSCompliant (false)]
364                 [Obsolete ("Use SetOwner (long, long)")]
365                 public virtual void SetOwner (uint owner, uint group)
366                 {
367                         int r = Syscall.chown (FullPath, owner, group);
368                         UnixMarshal.ThrowExceptionForLastErrorIf (r);
369                 }
370
371                 public virtual void SetOwner (long owner, long group)
372                 {
373                         uint _owner = Convert.ToUInt32 (owner);
374                         uint _group = Convert.ToUInt32 (group);
375                         int r = Syscall.chown (FullPath, _owner, _group);
376                         UnixMarshal.ThrowExceptionForLastErrorIf (r);
377                 }
378
379                 public void SetOwner (string owner)
380                 {
381                         Passwd pw = Syscall.getpwnam (owner);
382                         if (pw == null)
383                                 throw new ArgumentException (Locale.GetText ("invalid username"), "owner");
384                         uint uid = pw.pw_uid;
385                         uint gid = pw.pw_gid;
386                         SetOwner (uid, gid);
387                 }
388
389                 public void SetOwner (string owner, string group)
390                 {
391                         uint uid = UnixUser.GetUserId (owner);
392                         uint gid = UnixGroup.GetGroupId (group);
393
394                         SetOwner (uid, gid);
395                 }
396
397                 public override string ToString ()
398                 {
399                         return FullPath;
400                 }
401
402                 public Native.Stat ToStat ()
403                 {
404                         return stat;
405                 }
406
407                 internal static UnixFileSystemInfo Create (string path)
408                 {
409                         Native.Stat stat;
410                         int r = Native.Syscall.lstat (path, out stat);
411                         UnixMarshal.ThrowExceptionForLastErrorIf (r);
412
413                         if (IsType (stat.st_mode, Native.FilePermissions.S_IFDIR))
414                                 return new UnixDirectoryInfo (path, stat);
415                         else if (IsType (stat.st_mode, Native.FilePermissions.S_IFLNK))
416                                 return new UnixSymbolicLinkInfo (path, stat);
417                         return new UnixFileInfo (path, stat);
418                 }
419         }
420 }
421
422 // vim: noexpandtab