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 afs = 0x5346414F, 27 anoninode = 0x09041934, 28 aufs = 0x61756673, 29 autofs = 0x0187, 30 befs = 0x42465331, 31 bdevfs = 0x62646576, 32 bfs = 0x1BADFACE, 33 binfmt_misc = 0x42494E4D, 34 btrfs = 0x9123683E, 35 ceph = 0x00C36400, 36 cgroupfs = 0x0027E0EB, 37 cifs = 0xFF534D42, 38 coda = 0x73757245, 39 coherent = 0x012FF7B7, 40 cramfs = 0x28CD3D45, 41 debugfs = 0x64626720, 42 devfs = 0x1373, 43 devpts = 0x1CD1, 44 ecryptfs = 0xF15F, 45 efs = 0x00414A53, 46 ext = 0x137D, 47 ext2_old = 0xEF51, 48 ext2 = 0xEF53, 49 ext3 = 0xEF53, 50 ext4 = 0xEF53, 51 fat = 0x4006, 52 fhgfs = 0x19830326, 53 fuseblk = 0x65735546, 54 fusectl = 0x65735543, 55 futexfs = 0x0BAD1DEA, 56 gfsgfs2 = 0x1161970, 57 gpfs = 0x47504653, 58 hfs = 0x4244, 59 hpfs = 0xF995E849, 60 hugetlbfs = 0x958458F6, 61 inodefs = 0x11307854, 62 inotifyfs = 0x2BAD1DEA, 63 isofs = 0x9660, 64 // isofs = 0x4004, // R_WIN 65 // isofs = 0x4000, // WIN 66 jffs = 0x07C0, 67 jffs2 = 0x72B6, 68 jfs = 0x3153464A, 69 kafs = 0x6B414653, 70 lustre = 0x0BD00BD0, 71 minix_old = 0x137F, /* orig. minix */ 72 minix = 0x138F, /* 30 char minix */ 73 minix2 = 0x2468, /* minix V2 */ 74 minix2v2 = 0x2478, /* MINIX V2, 30 char names */ 75 minix3 = 0x4D5A, 76 mqueue = 0x19800202, 77 msdos = 0x4D44, 78 nfs = 0x6969, 79 nfsd = 0x6E667364, 80 nilfs = 0x3434, 81 novell = 0x564C, 82 ntfs = 0x5346544E, 83 openprom = 0x9FA1, 84 ocfs2 = 0x7461636F, 85 overlay = 0x794C7630, 86 overlayfs = 0x794C764F, 87 panfs = 0xAAD7AAEA, 88 pipefs = 0x50495045, 89 proc = 0x9FA0, 90 pstorefs = 0x6165676C, 91 qnx4 = 0x002F, 92 qnx6 = 0x68191122, 93 ramfs = 0x858458F6, 94 reiserfs = 0x52654973, 95 romfs = 0x7275, 96 rpc_pipefs = 0x67596969, 97 securityfs = 0x73636673, 98 selinux = 0xF97CFF8C, 99 smb = 0x517B, 100 sockfs = 0x534F434B, 101 squashfs = 0x73717368, 102 sysfs = 0x62656572, 103 sysv2 = 0x012FF7B6, 104 sysv4 = 0x012FF7B5, 105 tmpfs = 0x01021994, 106 udf = 0x15013346, 107 ufs = 0x00011954, 108 // ufs = 0x54190100, // byteswapped 109 usbdevice = 0x9FA2, 110 v9fs = 0x01021997, 111 vmhgfs = 0xBACBACBC, 112 vxfs = 0xA501FCF5, 113 vzfs = 0x565A4653, 114 xenfs = 0xABBA1974, 115 xenix = 0x012FF7B4, 116 xfs = 0x58465342, 117 xia = 0x012FD16D, 118 zfs = 0x2FC12FC1, 119 } 120 121 [StructLayout(LayoutKind.Sequential)] 122 internal struct MountPointInformation 123 { 124 internal ulong AvailableFreeSpace; 125 internal ulong TotalFreeSpace; 126 internal ulong TotalSize; 127 } 128 129 [DllImport(Libraries.SystemNative, EntryPoint = "SystemNative_GetSpaceInfoForMountPoint", SetLastError = true)] GetSpaceInfoForMountPoint([MarshalAs(UnmanagedType.LPStr)]string name, out MountPointInformation mpi)130 internal static extern int GetSpaceInfoForMountPoint([MarshalAs(UnmanagedType.LPStr)]string name, out MountPointInformation mpi); 131 132 [DllImport(Libraries.SystemNative, EntryPoint = "SystemNative_GetFormatInfoForMountPoint", SetLastError = true)] GetFormatInfoForMountPoint( [MarshalAs(UnmanagedType.LPStr)]string name, byte* formatNameBuffer, int bufferLength, long* formatType)133 private static extern unsafe int GetFormatInfoForMountPoint( 134 [MarshalAs(UnmanagedType.LPStr)]string name, 135 byte* formatNameBuffer, 136 int bufferLength, 137 long* formatType); 138 GetFormatInfoForMountPoint(string name, out string format)139 internal static int GetFormatInfoForMountPoint(string name, out string format) 140 { 141 DriveType temp; 142 return GetFormatInfoForMountPoint(name, out format, out temp); 143 } 144 GetFormatInfoForMountPoint(string name, out DriveType type)145 internal static int GetFormatInfoForMountPoint(string name, out DriveType type) 146 { 147 string temp; 148 return GetFormatInfoForMountPoint(name, out temp, out type); 149 } 150 GetFormatInfoForMountPoint(string name, out string format, out DriveType type)151 private static int GetFormatInfoForMountPoint(string name, out string format, out DriveType type) 152 { 153 unsafe 154 { 155 byte* formatBuffer = stackalloc byte[MountPointFormatBufferSizeInBytes]; // format names should be small 156 long numericFormat; 157 int result = GetFormatInfoForMountPoint(name, formatBuffer, MountPointFormatBufferSizeInBytes, &numericFormat); 158 if (result == 0) 159 { 160 // Check if we have a numeric answer or string 161 format = numericFormat != -1 ? 162 Enum.GetName(typeof(UnixFileSystemTypes), numericFormat) : 163 Marshal.PtrToStringAnsi((IntPtr)formatBuffer); 164 type = GetDriveType(format); 165 } 166 else 167 { 168 format = string.Empty; 169 type = DriveType.Unknown; 170 } 171 172 return result; 173 } 174 } 175 176 /// <summary>Categorizes a file system name into a drive type.</summary> 177 /// <param name="fileSystemName">The name to categorize.</param> 178 /// <returns>The recognized drive type.</returns> GetDriveType(string fileSystemName)179 private static DriveType GetDriveType(string fileSystemName) 180 { 181 // This list is based primarily on "man fs", "man mount", "mntent.h", "/proc/filesystems", coreutils "stat.c", 182 // and "wiki.debian.org/FileSystem". It can be extended over time as we 183 // find additional file systems that should be recognized as a particular drive type. 184 switch (fileSystemName) 185 { 186 case "iso": 187 case "isofs": 188 case "iso9660": 189 case "fuseiso": 190 case "fuseiso9660": 191 case "umview-mod-umfuseiso9660": 192 return DriveType.CDRom; 193 194 case "aafs": 195 case "adfs": 196 case "affs": 197 case "anoninode": 198 case "anon-inode FS": 199 case "apfs": 200 case "autofs": 201 case "balloon-kvm-fs": 202 case "bdevfs": 203 case "befs": 204 case "bfs": 205 case "bpf_fs": 206 case "btrfs": 207 case "btrfs_test": 208 case "cgroup2fs": 209 case "cgroupfs": 210 case "coh": 211 case "cramfs": 212 case "cramfs-wend": 213 case "daxfs": 214 case "drvfs": 215 case "ecryptfs": 216 case "efivarfs": 217 case "efs": 218 case "exofs": 219 case "ext": 220 case "ext2": 221 case "ext2_old": 222 case "ext3": 223 case "ext2/ext3": 224 case "ext4": 225 case "ext4dev": 226 case "f2fs": 227 case "fat": 228 case "fuseext2": 229 case "fusefat": 230 case "futexfs": 231 case "hfs": 232 case "hfs+": 233 case "hfsplus": 234 case "hfsx": 235 case "hostfs": 236 case "hpfs": 237 case "inodefs": 238 case "inotifyfs": 239 case "jbd": 240 case "jbd2": 241 case "jffs": 242 case "jffs2": 243 case "jfs": 244 case "logfs": 245 case "lxfs": 246 case "minix (30 char.)": 247 case "minix v2 (30 char.)": 248 case "minix v2": 249 case "minix": 250 case "minix_old": 251 case "minix2": 252 case "minix2v2": 253 case "minix3": 254 case "mlfs": 255 case "msdos": 256 case "nilfs": 257 case "nsfs": 258 case "ntfs": 259 case "ocfs2": 260 case "omfs": 261 case "openprom": 262 case "overlay": 263 case "overlayfs": 264 case "pstorefs": 265 case "qnx4": 266 case "qnx6": 267 case "reiserfs": 268 case "rpc_pipefs": 269 case "selinux": 270 case "smackfs": 271 case "squashfs": 272 case "swap": 273 case "sysfs": 274 case "sysv": 275 case "sysv2": 276 case "sysv4": 277 case "tracefs": 278 case "ubifs": 279 case "udf": 280 case "ufs": 281 case "umsdos": 282 case "umview-mod-umfuseext2": 283 case "usbdevfs": 284 case "v9fs": 285 case "vzfs": 286 case "wslfs": 287 case "xenfs": 288 case "xenix": 289 case "xfs": 290 case "xia": 291 case "xiafs": 292 case "xmount": 293 case "zfs": 294 case "zfs-fuse": 295 case "zsmallocfs": 296 return DriveType.Fixed; 297 298 case "9p": 299 case "acfs": 300 case "afs": 301 case "aufs": 302 case "autofs4": 303 case "beaglefs": 304 case "ceph": 305 case "cifs": 306 case "coda": 307 case "coherent": 308 case "curlftpfs": 309 case "davfs2": 310 case "dlm": 311 case "fhgfs": 312 case "flickrfs": 313 case "fuseblk": 314 case "fusedav": 315 case "fusesmb": 316 case "gfsgfs2": 317 case "gfs/gfs2": 318 case "gfs2": 319 case "glusterfs-client": 320 case "gmailfs": 321 case "gpfs": 322 case "ibrix": 323 case "k-afs": 324 case "kafs": 325 case "ltspfs": 326 case "lustre": 327 case "ncpfs": 328 case "nfs": 329 case "nfs4": 330 case "nfsd": 331 case "novell": 332 case "obexfs": 333 case "panfs": 334 case "prl_fs": 335 case "s3ql": 336 case "smb": 337 case "smb2": 338 case "smbfs": 339 case "snfs": 340 case "sshfs": 341 case "vmhgfs": 342 case "vxfs": 343 case "wikipediafs": 344 return DriveType.Network; 345 346 case "anon_inodefs": 347 case "aptfs": 348 case "avfs": 349 case "bdev": 350 case "binfmt_misc": 351 case "cgroup": 352 case "configfs": 353 case "cryptkeeper": 354 case "cpuset": 355 case "debugfs": 356 case "devfs": 357 case "devpts": 358 case "devtmpfs": 359 case "encfs": 360 case "fuse": 361 case "fuse.gvfsd-fuse": 362 case "fusectl": 363 case "hugetlbfs": 364 case "libpam-encfs": 365 case "ibpam-mount": 366 case "mtpfs": 367 case "mythtvfs": 368 case "mqueue": 369 case "pipefs": 370 case "plptools": 371 case "proc": 372 case "pstore": 373 case "pytagsfs": 374 case "ramfs": 375 case "rofs": 376 case "romfs": 377 case "rootfs": 378 case "securityfs": 379 case "sockfs": 380 case "tmpfs": 381 return DriveType.Ram; 382 383 case "gphotofs": 384 case "usbfs": 385 case "usbdevice": 386 case "vfat": 387 return DriveType.Removable; 388 389 // Categorize as "Unknown" everything else not explicitly 390 // recognized as a particular drive type. 391 default: 392 return DriveType.Unknown; 393 } 394 } 395 } 396 } 397