2009-12-01 Jb Evain <jbevain@novell.com>
[mcs.git] / class / Mono.Posix / Mono.Unix / UnixFileSystemInfo.cs
blob13909c9794ae03b94abb9f017bdaae1e4039232a
1 //
2 // Mono.Unix/UnixFileSystemInfo.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.
29 using System;
30 using System.IO;
31 using System.Text;
32 using Mono.Unix;
34 namespace Mono.Unix {
36 public abstract class UnixFileSystemInfo
38 private Native.Stat stat;
39 private string fullPath;
40 private string originalPath;
41 private bool valid = false;
43 internal const FileSpecialAttributes AllSpecialAttributes =
44 FileSpecialAttributes.SetUserId | FileSpecialAttributes.SetGroupId |
45 FileSpecialAttributes.Sticky;
46 internal const FileTypes AllFileTypes =
47 FileTypes.Directory | FileTypes.CharacterDevice | FileTypes.BlockDevice |
48 FileTypes.RegularFile | FileTypes.Fifo | FileTypes.SymbolicLink |
49 FileTypes.Socket;
51 protected UnixFileSystemInfo (string path)
53 UnixPath.CheckPath (path);
54 this.originalPath = path;
55 this.fullPath = UnixPath.GetFullPath (path);
56 Refresh (true);
59 internal UnixFileSystemInfo (String path, Native.Stat stat)
61 this.originalPath = path;
62 this.fullPath = UnixPath.GetFullPath (path);
63 this.stat = stat;
64 this.valid = true;
67 protected string FullPath {
68 get {return fullPath;}
69 set {
70 if (fullPath != value) {
71 UnixPath.CheckPath (value);
72 valid = false;
73 fullPath = value;
78 protected string OriginalPath {
79 get {return originalPath;}
80 set {originalPath = value;}
83 private void AssertValid ()
85 Refresh (false);
86 if (!valid)
87 throw new InvalidOperationException ("Path doesn't exist!");
90 public virtual string FullName {
91 get {return FullPath;}
94 public abstract string Name {get;}
96 public bool Exists {
97 get {
98 Refresh (true);
99 return valid;
103 public long Device {
104 get {AssertValid (); return Convert.ToInt64 (stat.st_dev);}
107 public long Inode {
108 get {AssertValid (); return Convert.ToInt64 (stat.st_ino);}
111 [CLSCompliant (false)]
112 public Native.FilePermissions Protection {
113 get {AssertValid (); return (Native.FilePermissions) stat.st_mode;}
114 set {
115 int r = Native.Syscall.chmod (FullPath, value);
116 UnixMarshal.ThrowExceptionForLastErrorIf (r);
120 public FileTypes FileType {
121 get {
122 AssertValid ();
123 return (FileTypes) (stat.st_mode & Native.FilePermissions.S_IFMT);
125 // no set as chmod(2) won't accept changing the file type.
128 public FileAccessPermissions FileAccessPermissions {
129 get {
130 AssertValid ();
131 int perms = (int) stat.st_mode;
132 return (FileAccessPermissions) (perms & (int) FileAccessPermissions.AllPermissions);
134 set {
135 AssertValid ();
136 int perms = (int) stat.st_mode;
137 perms &= (int) ~FileAccessPermissions.AllPermissions;
138 perms |= (int) value;
139 Protection = (Native.FilePermissions) perms;
143 public FileSpecialAttributes FileSpecialAttributes {
144 get {
145 AssertValid ();
146 int attrs = (int) stat.st_mode;
147 return (FileSpecialAttributes) (attrs & (int) AllSpecialAttributes);
149 set {
150 AssertValid ();
151 int perms = (int) stat.st_mode;
152 perms &= (int) ~AllSpecialAttributes;
153 perms |= (int) value;
154 Protection = (Native.FilePermissions) perms;
158 public long LinkCount {
159 get {AssertValid (); return Convert.ToInt64 (stat.st_nlink);}
162 public UnixUserInfo OwnerUser {
163 get {AssertValid (); return new UnixUserInfo (stat.st_uid);}
166 public long OwnerUserId {
167 get {AssertValid (); return stat.st_uid;}
170 public UnixGroupInfo OwnerGroup {
171 get {AssertValid (); return new UnixGroupInfo (stat.st_gid);}
174 public long OwnerGroupId {
175 get {AssertValid (); return stat.st_gid;}
178 public long DeviceType {
179 get {AssertValid (); return Convert.ToInt64 (stat.st_rdev);}
182 public long Length {
183 get {AssertValid (); return (long) stat.st_size;}
186 public long BlockSize {
187 get {AssertValid (); return (long) stat.st_blksize;}
190 public long BlocksAllocated {
191 get {AssertValid (); return (long) stat.st_blocks;}
194 public DateTime LastAccessTime {
195 get {AssertValid (); return Native.NativeConvert.ToDateTime (stat.st_atime);}
198 public DateTime LastAccessTimeUtc {
199 get {return LastAccessTime.ToUniversalTime ();}
202 public DateTime LastWriteTime {
203 get {AssertValid (); return Native.NativeConvert.ToDateTime (stat.st_mtime);}
206 public DateTime LastWriteTimeUtc {
207 get {return LastWriteTime.ToUniversalTime ();}
210 public DateTime LastStatusChangeTime {
211 get {AssertValid (); return Native.NativeConvert.ToDateTime (stat.st_ctime);}
214 public DateTime LastStatusChangeTimeUtc {
215 get {return LastStatusChangeTime.ToUniversalTime ();}
218 public bool IsDirectory {
219 get {AssertValid (); return IsFileType (stat.st_mode, Native.FilePermissions.S_IFDIR);}
222 public bool IsCharacterDevice {
223 get {AssertValid (); return IsFileType (stat.st_mode, Native.FilePermissions.S_IFCHR);}
226 public bool IsBlockDevice {
227 get {AssertValid (); return IsFileType (stat.st_mode, Native.FilePermissions.S_IFBLK);}
230 public bool IsRegularFile {
231 get {AssertValid (); return IsFileType (stat.st_mode, Native.FilePermissions.S_IFREG);}
234 public bool IsFifo {
235 get {AssertValid (); return IsFileType (stat.st_mode, Native.FilePermissions.S_IFIFO);}
238 public bool IsSymbolicLink {
239 get {AssertValid (); return IsFileType (stat.st_mode, Native.FilePermissions.S_IFLNK);}
242 public bool IsSocket {
243 get {AssertValid (); return IsFileType (stat.st_mode, Native.FilePermissions.S_IFSOCK);}
246 public bool IsSetUser {
247 get {AssertValid (); return IsSet (stat.st_mode, Native.FilePermissions.S_ISUID);}
250 public bool IsSetGroup {
251 get {AssertValid (); return IsSet (stat.st_mode, Native.FilePermissions.S_ISGID);}
254 public bool IsSticky {
255 get {AssertValid (); return IsSet (stat.st_mode, Native.FilePermissions.S_ISVTX);}
258 internal static bool IsFileType (Native.FilePermissions mode, Native.FilePermissions type)
260 return (mode & Native.FilePermissions.S_IFMT) == type;
263 internal static bool IsSet (Native.FilePermissions mode, Native.FilePermissions type)
265 return (mode & type) == type;
268 [CLSCompliant (false)]
269 public bool CanAccess (Native.AccessModes mode)
271 int r = Native.Syscall.access (FullPath, mode);
272 return r == 0;
275 public UnixFileSystemInfo CreateLink (string path)
277 int r = Native.Syscall.link (FullName, path);
278 UnixMarshal.ThrowExceptionForLastErrorIf (r);
279 return GetFileSystemEntry (path);
282 public UnixSymbolicLinkInfo CreateSymbolicLink (string path)
284 int r = Native.Syscall.symlink (FullName, path);
285 UnixMarshal.ThrowExceptionForLastErrorIf (r);
286 return new UnixSymbolicLinkInfo (path);
289 public abstract void Delete ();
291 [CLSCompliant (false)]
292 public long GetConfigurationValue (Native.PathconfName name)
294 long r = Native.Syscall.pathconf (FullPath, name);
295 if (r == -1 && Native.Stdlib.GetLastError() != (Native.Errno) 0)
296 UnixMarshal.ThrowExceptionForLastError ();
297 return r;
300 public void Refresh ()
302 Refresh (true);
305 internal void Refresh (bool force)
307 if (valid && !force)
308 return;
309 valid = GetFileStatus (FullPath, out this.stat);
312 protected virtual bool GetFileStatus (string path, out Native.Stat stat)
314 return Native.Syscall.stat (path, out stat) == 0;
317 public void SetLength (long length)
319 int r;
320 do {
321 r = Native.Syscall.truncate (FullPath, length);
322 } while (UnixMarshal.ShouldRetrySyscall (r));
323 UnixMarshal.ThrowExceptionForLastErrorIf (r);
326 public virtual void SetOwner (long owner, long group)
328 uint _owner = Convert.ToUInt32 (owner);
329 uint _group = Convert.ToUInt32 (group);
330 int r = Native.Syscall.chown (FullPath, _owner, _group);
331 UnixMarshal.ThrowExceptionForLastErrorIf (r);
334 public void SetOwner (string owner)
336 Native.Passwd pw = Native.Syscall.getpwnam (owner);
337 if (pw == null)
338 throw new ArgumentException (Locale.GetText ("invalid username"), "owner");
339 uint uid = pw.pw_uid;
340 uint gid = pw.pw_gid;
341 SetOwner ((long) uid, (long) gid);
344 public void SetOwner (string owner, string group)
346 long uid = -1;
347 if (owner != null)
348 uid = new UnixUserInfo (owner).UserId;
349 long gid = -1;
350 if (group != null)
351 gid = new UnixGroupInfo (group).GroupId;
353 SetOwner (uid, gid);
356 public void SetOwner (UnixUserInfo owner)
358 long uid, gid;
359 uid = gid = -1;
360 if (owner != null) {
361 uid = owner.UserId;
362 gid = owner.GroupId;
364 SetOwner (uid, gid);
367 public void SetOwner (UnixUserInfo owner, UnixGroupInfo group)
369 long uid, gid;
370 uid = gid = -1;
371 if (owner != null)
372 uid = owner.UserId;
373 if (group != null)
374 gid = owner.GroupId;
375 SetOwner (uid, gid);
378 public override string ToString ()
380 return FullPath;
383 public Native.Stat ToStat ()
385 AssertValid ();
386 return stat;
389 public static UnixFileSystemInfo GetFileSystemEntry (string path)
391 Native.Stat stat;
392 int r = Native.Syscall.lstat (path, out stat);
393 if (r == -1 && Native.Stdlib.GetLastError() == Native.Errno.ENOENT) {
394 return new UnixFileInfo (path);
396 UnixMarshal.ThrowExceptionForLastErrorIf (r);
398 if (IsFileType (stat.st_mode, Native.FilePermissions.S_IFDIR))
399 return new UnixDirectoryInfo (path, stat);
400 else if (IsFileType (stat.st_mode, Native.FilePermissions.S_IFLNK))
401 return new UnixSymbolicLinkInfo (path, stat);
402 return new UnixFileInfo (path, stat);
407 // vim: noexpandtab