* Mono.Unix/FileAccessPermissions.cs: Remove UserMask, GroupMask, OtherMask values.
[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                 [Obsolete ("Use Protection.")]
113                 public FilePermissions Mode {
114                         get {AssertValid (); return (FilePermissions) stat.st_mode;}
115                 }
116
117                 [CLSCompliant (false)]
118                 [Obsolete ("Use FileAccessPermissions.")]
119                 public FilePermissions Permissions {
120                         get {AssertValid (); return (FilePermissions) stat.st_mode & ~FilePermissions.S_IFMT;}
121                 }
122
123                 [CLSCompliant (false)]
124                 public Native.FilePermissions Protection {
125                         get {AssertValid (); return (Native.FilePermissions) stat.st_mode;}
126                         set {
127                                 int r = Native.Syscall.chmod (FullPath, value);
128                                 UnixMarshal.ThrowExceptionForLastErrorIf (r);
129                         }
130                 }
131
132                 public FileTypes FileType {
133                         get {
134                                 AssertValid ();
135                                 int type = (int) stat.st_mode;
136                                 return (FileTypes) (type & (int) AllFileTypes);
137                         }
138                         // no set as chmod(2) won't accept changing the file type.
139                 }
140
141                 public FileAccessPermissions FileAccessPermissions {
142                         get {
143                                 AssertValid (); 
144                                 int perms = (int) stat.st_mode;
145                                 return (FileAccessPermissions) (perms & (int) FileAccessPermissions.AllPermissions);
146                         }
147                         set {
148                                 AssertValid ();
149                                 int perms = (int) stat.st_mode;
150                                 perms &= (int) ~FileAccessPermissions.AllPermissions;
151                                 perms |= (int) value;
152                                 Protection = (Native.FilePermissions) perms;
153                         }
154                 }
155
156                 public FileSpecialAttributes FileSpecialAttributes {
157                         get {
158                                 AssertValid ();
159                                 int attrs = (int) stat.st_mode;
160                                 return (FileSpecialAttributes) (attrs & (int) AllSpecialAttributes);
161                         }
162                         set {
163                                 AssertValid ();
164                                 int perms = (int) stat.st_mode;
165                                 perms &= (int) ~AllSpecialAttributes;
166                                 perms |= (int) value;
167                                 Protection = (Native.FilePermissions) perms;
168                         }
169                 }
170
171                 public long LinkCount {
172                         get {AssertValid (); return Convert.ToInt64 (stat.st_nlink);}
173                 }
174
175                 public UnixUserInfo OwnerUser {
176                         get {AssertValid (); return new UnixUserInfo (stat.st_uid);}
177                 }
178
179                 public long OwnerUserId {
180                         get {AssertValid (); return stat.st_uid;}
181                 }
182
183                 public UnixGroupInfo OwnerGroup {
184                         get {AssertValid (); return new UnixGroupInfo (stat.st_gid);}
185                 }
186
187                 public long OwnerGroupId {
188                         get {AssertValid (); return stat.st_gid;}
189                 }
190
191                 public long DeviceType {
192                         get {AssertValid (); return Convert.ToInt64 (stat.st_rdev);}
193                 }
194
195                 public long Length {
196                         get {AssertValid (); return (long) stat.st_size;}
197                 }
198
199                 public long BlockSize {
200                         get {AssertValid (); return (long) stat.st_blksize;}
201                 }
202
203                 public long BlocksAllocated {
204                         get {AssertValid (); return (long) stat.st_blocks;}
205                 }
206
207                 public DateTime LastAccessTime {
208                         get {AssertValid (); return Native.NativeConvert.ToDateTime (stat.st_atime);}
209                 }
210
211                 public DateTime LastAccessTimeUtc {
212                         get {return LastAccessTime.ToUniversalTime ();}
213                 }
214
215                 public DateTime LastWriteTime {
216                         get {AssertValid (); return Native.NativeConvert.ToDateTime (stat.st_mtime);}
217                 }
218
219                 public DateTime LastWriteTimeUtc {
220                         get {return LastWriteTime.ToUniversalTime ();}
221                 }
222
223                 public DateTime LastStatusChangeTime {
224                         get {AssertValid (); return Native.NativeConvert.ToDateTime (stat.st_ctime);}
225                 }
226
227                 public DateTime LastStatusChangeTimeUtc {
228                         get {return LastStatusChangeTime.ToUniversalTime ();}
229                 }
230
231                 public bool IsDirectory {
232                         get {AssertValid (); return IsType (stat.st_mode, Native.FilePermissions.S_IFDIR);}
233                 }
234
235                 public bool IsCharacterDevice {
236                         get {AssertValid (); return IsType (stat.st_mode, Native.FilePermissions.S_IFCHR);}
237                 }
238
239                 public bool IsBlockDevice {
240                         get {AssertValid (); return IsType (stat.st_mode, Native.FilePermissions.S_IFBLK);}
241                 }
242
243                 [Obsolete ("Use IsRegularFile")]
244                 public bool IsFile {
245                         get {AssertValid (); return IsType (stat.st_mode, Native.FilePermissions.S_IFREG);}
246                 }
247
248                 public bool IsRegularFile {
249                         get {AssertValid (); return IsType (stat.st_mode, Native.FilePermissions.S_IFREG);}
250                 }
251
252                 [Obsolete ("Use IsFifo")]
253                 [CLSCompliant (false)]
254                 public bool IsFIFO {
255                         get {AssertValid (); return IsType (stat.st_mode, Native.FilePermissions.S_IFIFO);}
256                 }
257
258                 public bool IsFifo {
259                         get {AssertValid (); return IsType (stat.st_mode, Native.FilePermissions.S_IFIFO);}
260                 }
261
262                 public bool IsSymbolicLink {
263                         get {AssertValid (); return IsType (stat.st_mode, Native.FilePermissions.S_IFLNK);}
264                 }
265
266                 public bool IsSocket {
267                         get {AssertValid (); return IsType (stat.st_mode, Native.FilePermissions.S_IFSOCK);}
268                 }
269
270                 public bool IsSetUser {
271                         get {AssertValid (); return IsType (stat.st_mode, Native.FilePermissions.S_ISUID);}
272                 }
273
274                 public bool IsSetGroup {
275                         get {AssertValid (); return IsType (stat.st_mode, Native.FilePermissions.S_ISGID);}
276                 }
277
278                 public bool IsSticky {
279                         get {AssertValid (); return IsType (stat.st_mode, Native.FilePermissions.S_ISVTX);}
280                 }
281
282                 [Obsolete ("Use IsType(Native.FilePermissions, Native.FilePermissions)", true)]
283                 internal static bool IsType (FilePermissions mode, FilePermissions type)
284                 {
285                         return (mode & type) == type;
286                 }
287
288                 internal static bool IsType (Native.FilePermissions mode, Native.FilePermissions type)
289                 {
290                         return (mode & type) == type;
291                 }
292
293                 [CLSCompliant (false)]
294                 [Obsolete ("Use CanAccess (Mono.Unix.Native.AccessModes)", true)]
295                 public bool CanAccess (AccessMode mode)
296                 {
297                         int r = Syscall.access (FullPath, mode);
298                         return r == 0;
299                 }
300
301                 [CLSCompliant (false)]
302                 public bool CanAccess (Native.AccessModes mode)
303                 {
304                         int r = Native.Syscall.access (FullPath, mode);
305                         return r == 0;
306                 }
307
308                 public UnixFileSystemInfo CreateLink (string path)
309                 {
310                         int r = Native.Syscall.link (FullName, path);
311                         UnixMarshal.ThrowExceptionForLastErrorIf (r);
312                         return Create (path);
313                 }
314
315                 public UnixSymbolicLinkInfo CreateSymbolicLink (string path)
316                 {
317                         int r = Native.Syscall.symlink (FullName, path);
318                         UnixMarshal.ThrowExceptionForLastErrorIf (r);
319                         return new UnixSymbolicLinkInfo (path);
320                 }
321
322                 public abstract void Delete ();
323
324                 [CLSCompliant (false)]
325                 [Obsolete ("Use GetConfigurationValue (Mono.Unix.Native.PathconfName)", true)]
326                 public long GetConfigurationValue (PathConf name)
327                 {
328                         long r = Syscall.pathconf (FullPath, name);
329                         if (r == -1 && Syscall.GetLastError() != (Error) 0)
330                                 UnixMarshal.ThrowExceptionForLastError ();
331                         return r;
332                 }
333
334                 [CLSCompliant (false)]
335                 public long GetConfigurationValue (Native.PathconfName name)
336                 {
337                         long r = Native.Syscall.pathconf (FullPath, name);
338                         if (r == -1 && Native.Stdlib.GetLastError() != (Native.Errno) 0)
339                                 UnixMarshal.ThrowExceptionForLastError ();
340                         return r;
341                 }
342
343                 public void Refresh ()
344                 {
345                         Refresh (true);
346                 }
347
348                 internal void Refresh (bool force)
349                 {
350                         if (valid && !force)
351                                 return;
352                         valid = GetFileStatus (FullPath, out this.stat);
353                 }
354
355                 protected virtual bool GetFileStatus (string path, out Native.Stat stat)
356                 {
357                         return Native.Syscall.stat (path, out stat) == 0;
358                 }
359
360                 public void SetLength (long length)
361                 {
362                         int r;
363                         do {
364                                 r = Native.Syscall.truncate (FullPath, length);
365                         }       while (UnixMarshal.ShouldRetrySyscall (r));
366                         UnixMarshal.ThrowExceptionForLastErrorIf (r);
367                 }
368
369                 [CLSCompliant (false)]
370                 [Obsolete ("Use Protection setter", true)]
371                 public void SetPermissions (FilePermissions perms)
372                 {
373                         int r = Syscall.chmod (FullPath, perms);
374                         UnixMarshal.ThrowExceptionForLastErrorIf (r);
375                 }
376
377                 [CLSCompliant (false)]
378                 [Obsolete ("Use SetOwner (long, long)", true)]
379                 public virtual void SetOwner (uint owner, uint group)
380                 {
381                         int r = Syscall.chown (FullPath, owner, group);
382                         UnixMarshal.ThrowExceptionForLastErrorIf (r);
383                 }
384
385                 public virtual void SetOwner (long owner, long group)
386                 {
387                         uint _owner = Convert.ToUInt32 (owner);
388                         uint _group = Convert.ToUInt32 (group);
389                         int r = Native.Syscall.chown (FullPath, _owner, _group);
390                         UnixMarshal.ThrowExceptionForLastErrorIf (r);
391                 }
392
393                 public void SetOwner (string owner)
394                 {
395                         Native.Passwd pw = Native.Syscall.getpwnam (owner);
396                         if (pw == null)
397                                 throw new ArgumentException (Locale.GetText ("invalid username"), "owner");
398                         uint uid = pw.pw_uid;
399                         uint gid = pw.pw_gid;
400                         SetOwner ((long) uid, (long) gid);
401                 }
402
403                 public void SetOwner (string owner, string group)
404                 {
405                         long uid = -1;
406                         if (owner != null)
407                                 uid = new UnixUserInfo (owner).UserId;
408                         long gid = -1;
409                         if (group != null)
410                                 gid = new UnixGroupInfo (group).GroupId;
411
412                         SetOwner (uid, gid);
413                 }
414
415                 public void SetOwner (UnixUserInfo owner)
416                 {
417                         long uid, gid;
418                         uid = gid = -1;
419                         if (owner != null) {
420                                 uid = owner.UserId;
421                                 gid = owner.GroupId;
422                         }
423                         SetOwner (uid, gid);
424                 }
425
426                 public void SetOwner (UnixUserInfo owner, UnixGroupInfo group)
427                 {
428                         long uid, gid;
429                         uid = gid = -1;
430                         if (owner != null)
431                                 uid = owner.UserId;
432                         if (group != null)
433                                 gid = owner.GroupId;
434                         SetOwner (uid, gid);
435                 }
436
437                 public override string ToString ()
438                 {
439                         return FullPath;
440                 }
441
442                 public Native.Stat ToStat ()
443                 {
444                         AssertValid ();
445                         return stat;
446                 }
447
448                 internal static UnixFileSystemInfo Create (string path)
449                 {
450                         Native.Stat stat;
451                         int r = Native.Syscall.lstat (path, out stat);
452                         UnixMarshal.ThrowExceptionForLastErrorIf (r);
453
454                         if (IsType (stat.st_mode, Native.FilePermissions.S_IFDIR))
455                                 return new UnixDirectoryInfo (path, stat);
456                         else if (IsType (stat.st_mode, Native.FilePermissions.S_IFLNK))
457                                 return new UnixSymbolicLinkInfo (path, stat);
458                         return new UnixFileInfo (path, stat);
459                 }
460         }
461 }
462
463 // vim: noexpandtab