2 // Mono.Unix/UnixDriveInfo.cs
5 // Jonathan Pryor (jonpryor@vt.edu)
7 // (C) 2004-2006 Jonathan Pryor
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:
17 // The above copyright notice and this permission notice shall be
18 // included in all copies or substantial portions of the Software.
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.
30 using System
.Collections
;
36 public enum UnixDriveType
{
46 // All methods & properties can throw IOException
47 public sealed class UnixDriveInfo
49 private Native
.Statvfs stat
;
50 private string fstype
, mount_point
, block_device
;
52 public UnixDriveInfo (string mountPoint
)
54 if (mountPoint
== null)
55 throw new ArgumentNullException ("mountPoint");
56 Native
.Fstab fstab
= Native
.Syscall
.getfsfile (mountPoint
);
61 this.mount_point
= mountPoint
;
62 this.block_device
= "";
63 this.fstype
= "Unknown";
67 private void FromFstab (Native
.Fstab fstab
)
69 this.fstype
= fstab
.fs_vfstype
;
70 this.mount_point
= fstab
.fs_file
;
71 this.block_device
= fstab
.fs_spec
;
74 public static UnixDriveInfo
GetForSpecialFile (string specialFile
)
76 if (specialFile
== null)
77 throw new ArgumentNullException ("specialFile");
78 Native
.Fstab f
= Native
.Syscall
.getfsspec (specialFile
);
80 throw new ArgumentException ("specialFile isn't valid: " + specialFile
);
81 return new UnixDriveInfo (f
);
84 private UnixDriveInfo (Native
.Fstab fstab
)
89 public long AvailableFreeSpace
{
90 get {Refresh (); return Convert.ToInt64 (stat.f_bavail * stat.f_frsize);}
93 public string DriveFormat
{
97 public UnixDriveType DriveType
{
98 get {return UnixDriveType.Unknown;}
101 // this throws no exceptions
102 public bool IsReady
{
104 bool ready
= Refresh (false);
105 if (mount_point
== "/" || !ready
)
107 Native
.Statvfs parent
;
108 int r
= Native
.Syscall
.statvfs (RootDirectory
.Parent
.FullName
,
112 return parent
.f_fsid
!= stat
.f_fsid
;
117 get {return mount_point;}
120 public UnixDirectoryInfo RootDirectory
{
121 get {return new UnixDirectoryInfo (mount_point);}
124 public long TotalFreeSpace
{
125 get {Refresh (); return (long) (stat.f_bfree * stat.f_frsize);}
128 public long TotalSize
{
129 get {Refresh (); return (long) (stat.f_frsize * stat.f_blocks);}
132 // also throws SecurityException if caller lacks perms
133 public string VolumeLabel
{
134 get {return block_device;}
138 public long MaximumFilenameLength
{
139 get {Refresh (); return Convert.ToInt64 (stat.f_namemax);}
142 public static UnixDriveInfo
[] GetDrives ()
144 // TODO: Return any drives mentioned by getmntent(3) once getmntent(3)
145 // is exported by Syscall.
147 // throws IOException, UnauthorizedAccessException (no permission)
148 ArrayList entries
= new ArrayList ();
150 lock (Native
.Syscall
.fstab_lock
) {
151 int r
= Native
.Syscall
.setfsent ();
153 throw new IOException ("Error calling setfsent(3)", new UnixIOException ());
156 while ((fs
= Native
.Syscall
.getfsent()) != null) {
157 // avoid virtual entries, such as "swap"
158 if (fs
.fs_file
.StartsWith ("/"))
159 entries
.Add (new UnixDriveInfo (fs
));
163 Native
.Syscall
.endfsent ();
166 return (UnixDriveInfo
[]) entries
.ToArray (typeof(UnixDriveInfo
));
169 public override string ToString ()
174 private void Refresh ()
179 private bool Refresh (bool throwException
)
181 int r
= Native
.Syscall
.statvfs (mount_point
, out stat
);
182 if (r
== -1 && throwException
) {
183 Native
.Errno e
= Native
.Syscall
.GetLastError ();
184 throw new InvalidOperationException (
185 UnixMarshal
.GetErrorDescription (e
),
186 new UnixIOException (e
));