* attribute.cs (GetMarshal): Work even if "DefineCustom" is
[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 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 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, 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                                 int r = Syscall.access (FullPath, AccessMode.F_OK);
85                                 if (r == 0)
86                                         return true;
87                                 return false;
88                         }
89                 }
90
91                 public ulong Device {
92                         get {AssertValid (); return stat.st_dev;}
93                 }
94
95                 public ulong Inode {
96                         get {AssertValid (); return stat.st_ino;}
97                 }
98
99                 public FilePermissions Mode {
100                         get {AssertValid (); return stat.st_mode;}
101                 }
102
103                 public FilePermissions Permissions {
104                         get {AssertValid (); return stat.st_mode & ~FilePermissions.S_IFMT;}
105                 }
106
107                 public FilePermissions FileType {
108                         get {AssertValid (); return stat.st_mode & FilePermissions.S_IFMT;}
109                 }
110
111                 public ulong LinkCount {
112                         get {AssertValid (); return (ulong) stat.st_nlink;}
113                 }
114
115                 public uint OwnerUser {
116                         get {AssertValid (); return stat.st_uid;}
117                 }
118
119                 public uint OwnerGroup {
120                         get {AssertValid (); return stat.st_gid;}
121                 }
122
123                 public ulong DeviceType {
124                         get {AssertValid (); return stat.st_rdev;}
125                 }
126
127                 public long Length {
128                         get {AssertValid (); return (long) stat.st_size;}
129                 }
130
131                 public long BlockSize {
132                         get {AssertValid (); return (long) stat.st_blksize;}
133                 }
134
135                 public long BlocksAllocated {
136                         get {AssertValid (); return (long) stat.st_blocks;}
137                 }
138
139                 public DateTime LastAccessTime {
140                         get {AssertValid (); return UnixConvert.ToDateTime (stat.st_atime);}
141                 }
142
143                 public DateTime LastAccessTimeUtc {
144                         get {return LastAccessTime.ToUniversalTime ();}
145                 }
146
147                 public DateTime LastWriteTime {
148                         get {AssertValid (); return UnixConvert.ToDateTime (stat.st_mtime);}
149                 }
150
151                 public DateTime LastWriteTimeUtc {
152                         get {return LastWriteTime.ToUniversalTime ();}
153                 }
154
155                 public DateTime LastStatusChangeTime {
156                         get {AssertValid (); return UnixConvert.ToDateTime (stat.st_ctime);}
157                 }
158
159                 public DateTime LastStatusChangeTimeUtc {
160                         get {return LastStatusChangeTime.ToUniversalTime ();}
161                 }
162
163                 public bool IsDirectory {
164                         get {AssertValid (); return IsType (stat.st_mode, FilePermissions.S_IFDIR);}
165                 }
166
167                 public bool IsCharacterDevice {
168                         get {AssertValid (); return IsType (stat.st_mode, FilePermissions.S_IFCHR);}
169                 }
170
171                 public bool IsBlockDevice {
172                         get {AssertValid (); return IsType (stat.st_mode, FilePermissions.S_IFBLK);}
173                 }
174
175                 public bool IsFile {
176                         get {AssertValid (); return IsType (stat.st_mode, FilePermissions.S_IFREG);}
177                 }
178
179                 public bool IsFIFO {
180                         get {AssertValid (); return IsType (stat.st_mode, FilePermissions.S_IFIFO);}
181                 }
182
183                 public bool IsSymbolicLink {
184                         get {AssertValid (); return IsType (stat.st_mode, FilePermissions.S_IFLNK);}
185                 }
186
187                 public bool IsSocket {
188                         get {AssertValid (); return IsType (stat.st_mode, FilePermissions.S_IFSOCK);}
189                 }
190
191                 public bool IsSetUser {
192                         get {AssertValid (); return IsType (stat.st_mode, FilePermissions.S_ISUID);}
193                 }
194
195                 public bool IsSetGroup {
196                         get {AssertValid (); return IsType (stat.st_mode, FilePermissions.S_ISGID);}
197                 }
198
199                 public bool IsSticky {
200                         get {AssertValid (); return IsType (stat.st_mode, FilePermissions.S_ISVTX);}
201                 }
202
203                 internal static bool IsType (FilePermissions mode, FilePermissions type)
204                 {
205                         return (mode & type) == type;
206                 }
207
208                 public bool CanAccess (AccessMode mode)
209                 {
210                         int r = Syscall.access (FullPath, mode);
211                         return r == 0;
212                 }
213
214                 public UnixFileSystemInfo CreateLink (string path)
215                 {
216                         int r = Syscall.link (FullName, path);
217                         UnixMarshal.ThrowExceptionForLastErrorIf (r);
218                         return Create (path);
219                 }
220
221                 public UnixSymbolicLinkInfo CreateSymbolicLink (string path)
222                 {
223                         int r = Syscall.symlink (FullName, path);
224                         UnixMarshal.ThrowExceptionForLastErrorIf (r);
225                         return new UnixSymbolicLinkInfo (path);
226                 }
227
228                 public abstract void Delete ();
229
230                 public long GetConfigurationValue (PathConf name)
231                 {
232                         Syscall.SetLastError ((Error) 0);
233                         long r = Syscall.pathconf (FullPath, name);
234                         if (r == -1 && Syscall.GetLastError() != (Error) 0)
235                                 UnixMarshal.ThrowExceptionForLastError ();
236                         return r;
237                 }
238
239                 public void Refresh ()
240                 {
241                         Refresh (true);
242                 }
243
244                 internal void Refresh (bool force)
245                 {
246                         if (valid && !force)
247                                 return;
248                         int r = GetFileStatus (FullPath, out this.stat);
249                         valid = r == 0;
250                 }
251
252                 protected virtual int GetFileStatus (string path, out Stat stat)
253                 {
254                         return Syscall.stat (path, out stat);
255                 }
256
257                 public void SetLength (long length)
258                 {
259                         int r;
260                         do {
261                                 r = Syscall.truncate (FullPath, length);
262                         }       while (UnixMarshal.ShouldRetrySyscall (r));
263                         UnixMarshal.ThrowExceptionForLastErrorIf (r);
264                 }
265
266                 public void SetPermissions (FilePermissions perms)
267                 {
268                         int r = Syscall.chmod (FullPath, perms);
269                         UnixMarshal.ThrowExceptionForLastErrorIf (r);
270                 }
271
272                 public virtual void SetOwner (uint owner, uint group)
273                 {
274                         int r = Syscall.chown (FullPath, owner, group);
275                         UnixMarshal.ThrowExceptionForLastErrorIf (r);
276                 }
277
278                 public void SetOwner (string owner)
279                 {
280                         Passwd pw = Syscall.getpwnam (owner);
281                         if (pw == null)
282                                 throw new ArgumentException (Locale.GetText ("invalid username"), "owner");
283                         uint uid = pw.pw_uid;
284                         uint gid = pw.pw_gid;
285                         SetOwner (uid, gid);
286                 }
287
288                 public void SetOwner (string owner, string group)
289                 {
290                         uint uid = UnixUser.GetUserId (owner);
291                         uint gid = UnixGroup.GetGroupId (group);
292
293                         SetOwner (uid, gid);
294                 }
295
296                 public override string ToString ()
297                 {
298                         return FullPath;
299                 }
300
301                 internal static UnixFileSystemInfo Create (string path)
302                 {
303                         Stat stat;
304                         int r = Syscall.lstat (path, out stat);
305                         UnixMarshal.ThrowExceptionForLastErrorIf (r);
306
307                         if (IsType (stat.st_mode, FilePermissions.S_IFDIR))
308                                 return new UnixDirectoryInfo (path, stat);
309                         else if (IsType (stat.st_mode, FilePermissions.S_IFLNK))
310                                 return new UnixSymbolicLinkInfo (path, stat);
311                         return new UnixFileInfo (path, stat);
312                 }
313         }
314 }
315
316 // vim: noexpandtab