Skip to content
This repository was archived by the owner on Jan 23, 2023. It is now read-only.

Commit 20ddbef

Browse files
committed
Implement GetLogicalDrives for Unix
Implement and unify code for getting drives/mount points
1 parent 3032cd2 commit 20ddbef

17 files changed

+392
-337
lines changed
Lines changed: 281 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,281 @@
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;
6+
using System.IO;
7+
using System.Collections.Generic;
8+
using System.Runtime.InteropServices;
9+
10+
internal static partial class Interop
11+
{
12+
internal static partial class Sys
13+
{
14+
private const int MountPointFormatBufferSizeInBytes = 32;
15+
16+
/// <summary>
17+
/// Internal FileSystem names and magic numbers taken from man(2) statfs
18+
/// </summary>
19+
/// <remarks>
20+
/// These value names MUST be kept in sync with those in GetDriveType below
21+
/// </remarks>
22+
internal enum UnixFileSystemTypes : long
23+
{
24+
adfs = 0xadf5,
25+
affs = 0xADFF,
26+
befs = 0x42465331,
27+
bfs = 0x1BADFACE,
28+
cifs = 0xFF534D42,
29+
coda = 0x73757245,
30+
coherent = 0x012FF7B7,
31+
cramfs = 0x28cd3d45,
32+
devfs = 0x1373,
33+
efs = 0x00414A53,
34+
ext = 0x137D,
35+
ext2_old = 0xEF51,
36+
ext2 = 0xEF53,
37+
ext3 = 0xEF53,
38+
ext4 = 0xEF53,
39+
hfs = 0x4244,
40+
hpfs = 0xF995E849,
41+
hugetlbfs = 0x958458f6,
42+
isofs = 0x9660,
43+
jffs2 = 0x72b6,
44+
jfs = 0x3153464a,
45+
minix_old = 0x137F, /* orig. minix */
46+
minix = 0x138F, /* 30 char minix */
47+
minix2 = 0x2468, /* minix V2 */
48+
minix2v2 = 0x2478, /* minix V2, 30 char names */
49+
msdos = 0x4d44,
50+
ncpfs = 0x564c,
51+
nfs = 0x6969,
52+
ntfs = 0x5346544e,
53+
openprom = 0x9fa1,
54+
proc = 0x9fa0,
55+
qnx4 = 0x002f,
56+
reiserfs = 0x52654973,
57+
romfs = 0x7275,
58+
smb = 0x517B,
59+
sysv2 = 0x012FF7B6,
60+
sysv4 = 0x012FF7B5,
61+
tmpfs = 0x01021994,
62+
udf = 0x15013346,
63+
ufs = 0x00011954,
64+
usbdevice = 0x9fa2,
65+
vxfs = 0xa501FCF5,
66+
xenix = 0x012FF7B4,
67+
xfs = 0x58465342,
68+
xiafs = 0x012FD16D,
69+
}
70+
71+
[StructLayout(LayoutKind.Sequential)]
72+
internal struct MountPointInformation
73+
{
74+
internal ulong AvailableFreeSpace;
75+
internal ulong TotalFreeSpace;
76+
internal ulong TotalSize;
77+
}
78+
79+
[DllImport(Libraries.SystemNative, EntryPoint = "SystemNative_GetSpaceInfoForMountPoint", SetLastError = true)]
80+
internal static extern int GetSpaceInfoForMountPoint([MarshalAs(UnmanagedType.LPStr)]string name, out MountPointInformation mpi);
81+
82+
[DllImport(Libraries.SystemNative, EntryPoint = "SystemNative_GetFormatInfoForMountPoint", SetLastError = true)]
83+
private unsafe static extern int GetFormatInfoForMountPoint(
84+
[MarshalAs(UnmanagedType.LPStr)]string name,
85+
byte* formatNameBuffer,
86+
int bufferLength,
87+
long* formatType);
88+
89+
internal static int GetFormatInfoForMountPoint(string name, out string format)
90+
{
91+
DriveType temp;
92+
return GetFormatInfoForMountPoint(name, out format, out temp);
93+
}
94+
95+
internal static int GetFormatInfoForMountPoint(string name, out DriveType type)
96+
{
97+
string temp;
98+
return GetFormatInfoForMountPoint(name, out temp, out type);
99+
}
100+
101+
private static int GetFormatInfoForMountPoint(string name, out string format, out DriveType type)
102+
{
103+
unsafe
104+
{
105+
byte* formatBuffer = stackalloc byte[MountPointFormatBufferSizeInBytes]; // format names should be small
106+
long numericFormat;
107+
int result = GetFormatInfoForMountPoint(name, formatBuffer, MountPointFormatBufferSizeInBytes, &numericFormat);
108+
if (result == 0)
109+
{
110+
// Check if we have a numeric answer or string
111+
format = numericFormat != -1 ?
112+
Enum.GetName(typeof(UnixFileSystemTypes), numericFormat) :
113+
Marshal.PtrToStringAnsi((IntPtr)formatBuffer);
114+
type = GetDriveType(format);
115+
}
116+
else
117+
{
118+
format = string.Empty;
119+
type = DriveType.Unknown;
120+
}
121+
122+
return result;
123+
}
124+
}
125+
126+
/// <summary>Categorizes a file system name into a drive type.</summary>
127+
/// <param name="fileSystemName">The name to categorize.</param>
128+
/// <returns>The recognized drive type.</returns>
129+
private static DriveType GetDriveType(string fileSystemName)
130+
{
131+
// This list is based primarily on "man fs", "man mount", "mntent.h", "/proc/filesystems",
132+
// and "wiki.debian.org/FileSystem". It can be extended over time as we
133+
// find additional file systems that should be recognized as a particular drive type.
134+
switch (fileSystemName)
135+
{
136+
case "iso":
137+
case "isofs":
138+
case "iso9660":
139+
case "fuseiso":
140+
case "fuseiso9660":
141+
case "umview-mod-umfuseiso9660":
142+
return DriveType.CDRom;
143+
144+
case "adfs":
145+
case "affs":
146+
case "befs":
147+
case "bfs":
148+
case "btrfs":
149+
case "ecryptfs":
150+
case "efs":
151+
case "ext":
152+
case "ext2":
153+
case "ext2_old":
154+
case "ext3":
155+
case "ext4":
156+
case "ext4dev":
157+
case "fat":
158+
case "fuseblk":
159+
case "fuseext2":
160+
case "fusefat":
161+
case "hfs":
162+
case "hfsplus":
163+
case "hpfs":
164+
case "jbd":
165+
case "jbd2":
166+
case "jfs":
167+
case "jffs":
168+
case "jffs2":
169+
case "minix":
170+
case "minix_old":
171+
case "minix2":
172+
case "minix2v2":
173+
case "msdos":
174+
case "ocfs2":
175+
case "omfs":
176+
case "openprom":
177+
case "ntfs":
178+
case "qnx4":
179+
case "reiserfs":
180+
case "squashfs":
181+
case "swap":
182+
case "sysv":
183+
case "ubifs":
184+
case "udf":
185+
case "ufs":
186+
case "umsdos":
187+
case "umview-mod-umfuseext2":
188+
case "xenix":
189+
case "xfs":
190+
case "xiafs":
191+
case "xmount":
192+
case "zfs-fuse":
193+
return DriveType.Fixed;
194+
195+
case "9p":
196+
case "autofs":
197+
case "autofs4":
198+
case "beaglefs":
199+
case "cifs":
200+
case "coda":
201+
case "coherent":
202+
case "curlftpfs":
203+
case "davfs2":
204+
case "dlm":
205+
case "flickrfs":
206+
case "fusedav":
207+
case "fusesmb":
208+
case "gfs2":
209+
case "glusterfs-client":
210+
case "gmailfs":
211+
case "kafs":
212+
case "ltspfs":
213+
case "ncpfs":
214+
case "nfs":
215+
case "nfs4":
216+
case "obexfs":
217+
case "s3ql":
218+
case "smb":
219+
case "smbfs":
220+
case "sshfs":
221+
case "sysfs":
222+
case "sysv2":
223+
case "sysv4":
224+
case "vxfs":
225+
case "wikipediafs":
226+
return DriveType.Network;
227+
228+
case "anon_inodefs":
229+
case "aptfs":
230+
case "avfs":
231+
case "bdev":
232+
case "binfmt_misc":
233+
case "cgroup":
234+
case "configfs":
235+
case "cramfs":
236+
case "cryptkeeper":
237+
case "cpuset":
238+
case "debugfs":
239+
case "devfs":
240+
case "devpts":
241+
case "devtmpfs":
242+
case "encfs":
243+
case "fuse":
244+
case "fuse.gvfsd-fuse":
245+
case "fusectl":
246+
case "hugetlbfs":
247+
case "libpam-encfs":
248+
case "ibpam-mount":
249+
case "mtpfs":
250+
case "mythtvfs":
251+
case "mqueue":
252+
case "pipefs":
253+
case "plptools":
254+
case "proc":
255+
case "pstore":
256+
case "pytagsfs":
257+
case "ramfs":
258+
case "rofs":
259+
case "romfs":
260+
case "rootfs":
261+
case "securityfs":
262+
case "sockfs":
263+
case "tmpfs":
264+
return DriveType.Ram;
265+
266+
case "gphotofs":
267+
case "usbfs":
268+
case "usbdevice":
269+
case "vfat":
270+
return DriveType.Removable;
271+
272+
case "aufs": // marking all unions as unknown
273+
case "funionfs":
274+
case "unionfs-fuse":
275+
case "mhddfs":
276+
default:
277+
return DriveType.Unknown;
278+
}
279+
}
280+
}
281+
}

0 commit comments

Comments
 (0)