1 // Licensed to the .NET Foundation under one or more agreements.
2 // The .NET Foundation licenses this file to you under the MIT license.
3 // See the LICENSE file in the project root for more information.
4 
5 using System.Collections.Generic;
6 using System.Security;
7 
8 namespace System.IO
9 {
10     public sealed partial class DriveInfo
11     {
GetDrives()12         public static DriveInfo[] GetDrives()
13         {
14             string[] mountPoints = Interop.Sys.GetAllMountPoints();
15             DriveInfo[] info = new DriveInfo[mountPoints.Length];
16             for (int i = 0; i < info.Length; i++)
17             {
18                 info[i] = new DriveInfo(mountPoints[i]);
19             }
20 
21             return info;
22         }
23 
NormalizeDriveName(string driveName)24         private static string NormalizeDriveName(string driveName)
25         {
26             if (driveName.Contains("\0"))
27             {
28                 throw new ArgumentException(SR.Format(SR.Arg_InvalidDriveChars, driveName), nameof(driveName));
29             }
30             if (driveName.Length == 0)
31             {
32                 throw new ArgumentException(SR.Arg_MustBeNonEmptyDriveName, nameof(driveName));
33             }
34             return driveName;
35         }
36 
37         public DriveType DriveType
38         {
39             get
40             {
41                 DriveType type;
42                 int result = Interop.Sys.GetFormatInfoForMountPoint(Name, out type);
43                 if (result == 0)
44                 {
45                     return type;
46                 }
47                 else
48                 {
49                     Interop.ErrorInfo errorInfo = Interop.Sys.GetLastErrorInfo();
50 
51                     // This is one of the few properties that doesn't throw on failure,
52                     // instead returning a value from the enum.
53                     switch (errorInfo.Error)
54                     {
55                         case Interop.Error.ELOOP:
56                         case Interop.Error.ENAMETOOLONG:
57                         case Interop.Error.ENOENT:
58                         case Interop.Error.ENOTDIR:
59                             return DriveType.NoRootDirectory;
60                         default:
61                             return DriveType.Unknown;
62                     }
63                 }
64             }
65         }
66 
67         public string DriveFormat
68         {
69             get
70             {
71                 string format = string.Empty;
72                 CheckStatfsResultAndThrowIfNecessary(Interop.Sys.GetFormatInfoForMountPoint(Name, out format));
73                 return format;
74             }
75         }
76 
77         public long AvailableFreeSpace
78         {
79             get
80             {
81                 Interop.Sys.MountPointInformation mpi = default(Interop.Sys.MountPointInformation);
82                 CheckStatfsResultAndThrowIfNecessary(Interop.Sys.GetSpaceInfoForMountPoint(Name, out mpi));
83                 return checked((long)mpi.AvailableFreeSpace);
84             }
85         }
86 
87         public long TotalFreeSpace
88         {
89             get
90             {
91                 Interop.Sys.MountPointInformation mpi = default(Interop.Sys.MountPointInformation);
92                 CheckStatfsResultAndThrowIfNecessary(Interop.Sys.GetSpaceInfoForMountPoint(Name, out mpi));
93                 return checked((long)mpi.TotalFreeSpace);
94             }
95         }
96 
97         public long TotalSize
98         {
99             get
100             {
101                 Interop.Sys.MountPointInformation mpi = default(Interop.Sys.MountPointInformation);
102                 CheckStatfsResultAndThrowIfNecessary(Interop.Sys.GetSpaceInfoForMountPoint(Name, out mpi));
103                 return checked((long)mpi.TotalSize);
104             }
105         }
106 
107         public string VolumeLabel
108         {
109             get
110             {
111                 return Name;
112             }
113             set
114             {
115                 throw new PlatformNotSupportedException();
116             }
117         }
118 
119         // -----------------------------
120         // ---- PAL layer ends here ----
121         // -----------------------------
122 
CheckStatfsResultAndThrowIfNecessary(int result)123         private void CheckStatfsResultAndThrowIfNecessary(int result)
124         {
125             if (result != 0)
126             {
127                 var errorInfo = Interop.Sys.GetLastErrorInfo();
128                 if (errorInfo.Error == Interop.Error.ENOENT)
129                 {
130                     throw new DriveNotFoundException(SR.Format(SR.IO_DriveNotFound_Drive, Name)); // match Win32
131                 }
132                 else
133                 {
134                     throw Interop.GetExceptionForIoErrno(errorInfo, isDirectory: true);
135                 }
136             }
137         }
138     }
139 }
140