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