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