diff --git a/src/Common/src/Interop/Unix/System.Native/Interop.MountPoints.FormatInfo.cs b/src/Common/src/Interop/Unix/System.Native/Interop.MountPoints.FormatInfo.cs new file mode 100644 index 000000000000..3a0a829a897b --- /dev/null +++ b/src/Common/src/Interop/Unix/System.Native/Interop.MountPoints.FormatInfo.cs @@ -0,0 +1,281 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using System.IO; +using System.Collections.Generic; +using System.Runtime.InteropServices; + +internal static partial class Interop +{ + internal static partial class Sys + { + private const int MountPointFormatBufferSizeInBytes = 32; + + /// + /// Internal FileSystem names and magic numbers taken from man(2) statfs + /// + /// + /// These value names MUST be kept in sync with those in GetDriveType below + /// + internal enum UnixFileSystemTypes : long + { + adfs = 0xadf5, + affs = 0xADFF, + befs = 0x42465331, + bfs = 0x1BADFACE, + cifs = 0xFF534D42, + coda = 0x73757245, + coherent = 0x012FF7B7, + cramfs = 0x28cd3d45, + devfs = 0x1373, + efs = 0x00414A53, + ext = 0x137D, + ext2_old = 0xEF51, + ext2 = 0xEF53, + ext3 = 0xEF53, + ext4 = 0xEF53, + hfs = 0x4244, + hpfs = 0xF995E849, + hugetlbfs = 0x958458f6, + isofs = 0x9660, + jffs2 = 0x72b6, + jfs = 0x3153464a, + minix_old = 0x137F, /* orig. minix */ + minix = 0x138F, /* 30 char minix */ + minix2 = 0x2468, /* minix V2 */ + minix2v2 = 0x2478, /* minix V2, 30 char names */ + msdos = 0x4d44, + ncpfs = 0x564c, + nfs = 0x6969, + ntfs = 0x5346544e, + openprom = 0x9fa1, + proc = 0x9fa0, + qnx4 = 0x002f, + reiserfs = 0x52654973, + romfs = 0x7275, + smb = 0x517B, + sysv2 = 0x012FF7B6, + sysv4 = 0x012FF7B5, + tmpfs = 0x01021994, + udf = 0x15013346, + ufs = 0x00011954, + usbdevice = 0x9fa2, + vxfs = 0xa501FCF5, + xenix = 0x012FF7B4, + xfs = 0x58465342, + xiafs = 0x012FD16D, + } + + [StructLayout(LayoutKind.Sequential)] + internal struct MountPointInformation + { + internal ulong AvailableFreeSpace; + internal ulong TotalFreeSpace; + internal ulong TotalSize; + } + + [DllImport(Libraries.SystemNative, EntryPoint = "SystemNative_GetSpaceInfoForMountPoint", SetLastError = true)] + internal static extern int GetSpaceInfoForMountPoint([MarshalAs(UnmanagedType.LPStr)]string name, out MountPointInformation mpi); + + [DllImport(Libraries.SystemNative, EntryPoint = "SystemNative_GetFormatInfoForMountPoint", SetLastError = true)] + private unsafe static extern int GetFormatInfoForMountPoint( + [MarshalAs(UnmanagedType.LPStr)]string name, + byte* formatNameBuffer, + int bufferLength, + long* formatType); + + internal static int GetFormatInfoForMountPoint(string name, out string format) + { + DriveType temp; + return GetFormatInfoForMountPoint(name, out format, out temp); + } + + internal static int GetFormatInfoForMountPoint(string name, out DriveType type) + { + string temp; + return GetFormatInfoForMountPoint(name, out temp, out type); + } + + private static int GetFormatInfoForMountPoint(string name, out string format, out DriveType type) + { + unsafe + { + byte* formatBuffer = stackalloc byte[MountPointFormatBufferSizeInBytes]; // format names should be small + long numericFormat; + int result = GetFormatInfoForMountPoint(name, formatBuffer, MountPointFormatBufferSizeInBytes, &numericFormat); + if (result == 0) + { + // Check if we have a numeric answer or string + format = numericFormat != -1 ? + Enum.GetName(typeof(UnixFileSystemTypes), numericFormat) : + Marshal.PtrToStringAnsi((IntPtr)formatBuffer); + type = GetDriveType(format); + } + else + { + format = string.Empty; + type = DriveType.Unknown; + } + + return result; + } + } + + /// Categorizes a file system name into a drive type. + /// The name to categorize. + /// The recognized drive type. + private static DriveType GetDriveType(string fileSystemName) + { + // This list is based primarily on "man fs", "man mount", "mntent.h", "/proc/filesystems", + // and "wiki.debian.org/FileSystem". It can be extended over time as we + // find additional file systems that should be recognized as a particular drive type. + switch (fileSystemName) + { + case "iso": + case "isofs": + case "iso9660": + case "fuseiso": + case "fuseiso9660": + case "umview-mod-umfuseiso9660": + return DriveType.CDRom; + + case "adfs": + case "affs": + case "befs": + case "bfs": + case "btrfs": + case "ecryptfs": + case "efs": + case "ext": + case "ext2": + case "ext2_old": + case "ext3": + case "ext4": + case "ext4dev": + case "fat": + case "fuseblk": + case "fuseext2": + case "fusefat": + case "hfs": + case "hfsplus": + case "hpfs": + case "jbd": + case "jbd2": + case "jfs": + case "jffs": + case "jffs2": + case "minix": + case "minix_old": + case "minix2": + case "minix2v2": + case "msdos": + case "ocfs2": + case "omfs": + case "openprom": + case "ntfs": + case "qnx4": + case "reiserfs": + case "squashfs": + case "swap": + case "sysv": + case "ubifs": + case "udf": + case "ufs": + case "umsdos": + case "umview-mod-umfuseext2": + case "xenix": + case "xfs": + case "xiafs": + case "xmount": + case "zfs-fuse": + return DriveType.Fixed; + + case "9p": + case "autofs": + case "autofs4": + case "beaglefs": + case "cifs": + case "coda": + case "coherent": + case "curlftpfs": + case "davfs2": + case "dlm": + case "flickrfs": + case "fusedav": + case "fusesmb": + case "gfs2": + case "glusterfs-client": + case "gmailfs": + case "kafs": + case "ltspfs": + case "ncpfs": + case "nfs": + case "nfs4": + case "obexfs": + case "s3ql": + case "smb": + case "smbfs": + case "sshfs": + case "sysfs": + case "sysv2": + case "sysv4": + case "vxfs": + case "wikipediafs": + return DriveType.Network; + + case "anon_inodefs": + case "aptfs": + case "avfs": + case "bdev": + case "binfmt_misc": + case "cgroup": + case "configfs": + case "cramfs": + case "cryptkeeper": + case "cpuset": + case "debugfs": + case "devfs": + case "devpts": + case "devtmpfs": + case "encfs": + case "fuse": + case "fuse.gvfsd-fuse": + case "fusectl": + case "hugetlbfs": + case "libpam-encfs": + case "ibpam-mount": + case "mtpfs": + case "mythtvfs": + case "mqueue": + case "pipefs": + case "plptools": + case "proc": + case "pstore": + case "pytagsfs": + case "ramfs": + case "rofs": + case "romfs": + case "rootfs": + case "securityfs": + case "sockfs": + case "tmpfs": + return DriveType.Ram; + + case "gphotofs": + case "usbfs": + case "usbdevice": + case "vfat": + return DriveType.Removable; + + case "aufs": // marking all unions as unknown + case "funionfs": + case "unionfs-fuse": + case "mhddfs": + default: + return DriveType.Unknown; + } + } + } +} diff --git a/src/Common/src/Interop/Unix/System.Native/Interop.MountPoints.cs b/src/Common/src/Interop/Unix/System.Native/Interop.MountPoints.cs index 448250f2b758..4e6552c5dfff 100644 --- a/src/Common/src/Interop/Unix/System.Native/Interop.MountPoints.cs +++ b/src/Common/src/Interop/Unix/System.Native/Interop.MountPoints.cs @@ -3,7 +3,6 @@ // See the LICENSE file in the project root for more information. using System; -using System.IO; using System.Collections.Generic; using System.Runtime.InteropServices; @@ -11,124 +10,12 @@ internal static partial class Interop { internal static partial class Sys { - private const int MountPointFormatBufferSizeInBytes = 32; - - /// - /// Internal FileSystem names and magic numbers taken from man(2) statfs - /// - /// - /// These value names MUST be kept in sync with those in GetDriveType below - /// - internal enum UnixFileSystemTypes : long - { - adfs = 0xadf5, - affs = 0xADFF, - befs = 0x42465331, - bfs = 0x1BADFACE, - cifs = 0xFF534D42, - coda = 0x73757245, - coherent = 0x012FF7B7, - cramfs = 0x28cd3d45, - devfs = 0x1373, - efs = 0x00414A53, - ext = 0x137D, - ext2_old = 0xEF51, - ext2 = 0xEF53, - ext3 = 0xEF53, - ext4 = 0xEF53, - hfs = 0x4244, - hpfs = 0xF995E849, - hugetlbfs = 0x958458f6, - isofs = 0x9660, - jffs2 = 0x72b6, - jfs = 0x3153464a, - minix_old = 0x137F, /* orig. minix */ - minix = 0x138F, /* 30 char minix */ - minix2 = 0x2468, /* minix V2 */ - minix2v2 = 0x2478, /* minix V2, 30 char names */ - msdos = 0x4d44, - ncpfs = 0x564c, - nfs = 0x6969, - ntfs = 0x5346544e, - openprom = 0x9fa1, - proc = 0x9fa0, - qnx4 = 0x002f, - reiserfs = 0x52654973, - romfs = 0x7275, - smb = 0x517B, - sysv2 = 0x012FF7B6, - sysv4 = 0x012FF7B5, - tmpfs = 0x01021994, - udf = 0x15013346, - ufs = 0x00011954, - usbdevice = 0x9fa2, - vxfs = 0xa501FCF5, - xenix = 0x012FF7B4, - xfs = 0x58465342, - xiafs = 0x012FD16D, - } - - [StructLayout(LayoutKind.Sequential)] - internal struct MountPointInformation - { - internal ulong AvailableFreeSpace; - internal ulong TotalFreeSpace; - internal ulong TotalSize; - } - [UnmanagedFunctionPointer(CallingConvention.Cdecl)] private unsafe delegate void MountPointFound(byte* name); [DllImport(Libraries.SystemNative, EntryPoint = "SystemNative_GetAllMountPoints", SetLastError = true)] private static extern int GetAllMountPoints(MountPointFound mpf); - [DllImport(Libraries.SystemNative, EntryPoint = "SystemNative_GetSpaceInfoForMountPoint", SetLastError = true)] - internal static extern int GetSpaceInfoForMountPoint([MarshalAs(UnmanagedType.LPStr)]string name, out MountPointInformation mpi); - - [DllImport(Libraries.SystemNative, EntryPoint = "SystemNative_GetFormatInfoForMountPoint", SetLastError = true)] - private unsafe static extern int GetFormatInfoForMountPoint( - [MarshalAs(UnmanagedType.LPStr)]string name, - byte* formatNameBuffer, - int bufferLength, - long* formatType); - - internal static int GetFormatInfoForMountPoint(string name, out string format) - { - DriveType temp; - return GetFormatInfoForMountPoint(name, out format, out temp); - } - - internal static int GetFormatInfoForMountPoint(string name, out DriveType type) - { - string temp; - return GetFormatInfoForMountPoint(name, out temp, out type); - } - - private static int GetFormatInfoForMountPoint(string name, out string format, out DriveType type) - { - unsafe - { - byte* formatBuffer = stackalloc byte[MountPointFormatBufferSizeInBytes]; // format names should be small - long numericFormat; - int result = GetFormatInfoForMountPoint(name, formatBuffer, MountPointFormatBufferSizeInBytes, &numericFormat); - if (result == 0) - { - // Check if we have a numeric answer or string - format = numericFormat != -1 ? - Enum.GetName(typeof(UnixFileSystemTypes), numericFormat) : - Marshal.PtrToStringAnsi((IntPtr)formatBuffer); - type = GetDriveType(format); - } - else - { - format = string.Empty; - type = DriveType.Unknown; - } - - return result; - } - } - internal static List GetAllMountPoints() { List lst = new List(); @@ -142,160 +29,5 @@ internal static List GetAllMountPoints() return lst; } - - /// Categorizes a file system name into a drive type. - /// The name to categorize. - /// The recognized drive type. - private static DriveType GetDriveType(string fileSystemName) - { - // This list is based primarily on "man fs", "man mount", "mntent.h", "/proc/filesystems", - // and "wiki.debian.org/FileSystem". It can be extended over time as we - // find additional file systems that should be recognized as a particular drive type. - switch (fileSystemName) - { - case "iso": - case "isofs": - case "iso9660": - case "fuseiso": - case "fuseiso9660": - case "umview-mod-umfuseiso9660": - return DriveType.CDRom; - - case "adfs": - case "affs": - case "befs": - case "bfs": - case "btrfs": - case "ecryptfs": - case "efs": - case "ext": - case "ext2": - case "ext2_old": - case "ext3": - case "ext4": - case "ext4dev": - case "fat": - case "fuseblk": - case "fuseext2": - case "fusefat": - case "hfs": - case "hfsplus": - case "hpfs": - case "jbd": - case "jbd2": - case "jfs": - case "jffs": - case "jffs2": - case "minix": - case "minix_old": - case "minix2": - case "minix2v2": - case "msdos": - case "ocfs2": - case "omfs": - case "openprom": - case "ntfs": - case "qnx4": - case "reiserfs": - case "squashfs": - case "swap": - case "sysv": - case "ubifs": - case "udf": - case "ufs": - case "umsdos": - case "umview-mod-umfuseext2": - case "xenix": - case "xfs": - case "xiafs": - case "xmount": - case "zfs-fuse": - return DriveType.Fixed; - - case "9p": - case "autofs": - case "autofs4": - case "beaglefs": - case "cifs": - case "coda": - case "coherent": - case "curlftpfs": - case "davfs2": - case "dlm": - case "flickrfs": - case "fusedav": - case "fusesmb": - case "gfs2": - case "glusterfs-client": - case "gmailfs": - case "kafs": - case "ltspfs": - case "ncpfs": - case "nfs": - case "nfs4": - case "obexfs": - case "s3ql": - case "smb": - case "smbfs": - case "sshfs": - case "sysfs": - case "sysv2": - case "sysv4": - case "vxfs": - case "wikipediafs": - return DriveType.Network; - - case "anon_inodefs": - case "aptfs": - case "avfs": - case "bdev": - case "binfmt_misc": - case "cgroup": - case "configfs": - case "cramfs": - case "cryptkeeper": - case "cpuset": - case "debugfs": - case "devfs": - case "devpts": - case "devtmpfs": - case "encfs": - case "fuse": - case "fuse.gvfsd-fuse": - case "fusectl": - case "hugetlbfs": - case "libpam-encfs": - case "ibpam-mount": - case "mtpfs": - case "mythtvfs": - case "mqueue": - case "pipefs": - case "plptools": - case "proc": - case "pstore": - case "pytagsfs": - case "ramfs": - case "rofs": - case "romfs": - case "rootfs": - case "securityfs": - case "sockfs": - case "tmpfs": - return DriveType.Ram; - - case "gphotofs": - case "usbfs": - case "usbdevice": - case "vfat": - return DriveType.Removable; - - case "aufs": // marking all unions as unknown - case "funionfs": - case "unionfs-fuse": - case "mhddfs": - default: - return DriveType.Unknown; - } - } } } diff --git a/src/Common/src/System/IO/DriveInfoInternal.Unix.cs b/src/Common/src/System/IO/DriveInfoInternal.Unix.cs new file mode 100644 index 000000000000..cdeb762787df --- /dev/null +++ b/src/Common/src/System/IO/DriveInfoInternal.Unix.cs @@ -0,0 +1,18 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Diagnostics; +using System.Text; + +namespace System.IO +{ + /// Contains internal volume helpers that are shared between many projects. + internal static partial class DriveInfoInternal + { + internal static string[] GetLogicalDrives() + { + return Interop.Sys.GetAllMountPoints().ToArray(); + } + } +} diff --git a/src/System.IO.FileSystem/src/System/IO/Directory.Win32.cs b/src/Common/src/System/IO/DriveInfoInternal.Win32.cs similarity index 67% rename from src/System.IO.FileSystem/src/System/IO/Directory.Win32.cs rename to src/Common/src/System/IO/DriveInfoInternal.Win32.cs index 0cbede0919e5..09f46bf064bd 100644 --- a/src/System.IO.FileSystem/src/System/IO/Directory.Win32.cs +++ b/src/Common/src/System/IO/DriveInfoInternal.Win32.cs @@ -1,10 +1,14 @@ -// Licensed to the .NET Foundation under one or more agreements. +// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +using System.Diagnostics; +using System.Text; + namespace System.IO { - public static partial class Directory + /// Contains internal volume helpers that are shared between many projects. + internal static partial class DriveInfoInternal { public static string[] GetLogicalDrives() { @@ -12,6 +16,11 @@ public static string[] GetLogicalDrives() if (drives == 0) throw Win32Marshal.GetExceptionForLastWin32Error(); + // GetLogicalDrives returns a bitmask starting from + // position 0 "A" indicating whether a drive is present. + // Loop over each bit, creating a string for each one + // that is set. + uint d = (uint)drives; int count = 0; while (d != 0) @@ -19,6 +28,7 @@ public static string[] GetLogicalDrives() if (((int)d & 1) != 0) count++; d >>= 1; } + string[] result = new string[count]; char[] root = new char[] { 'A', ':', '\\' }; d = (uint)drives; diff --git a/src/Common/src/System/IO/DriveInfoInternal.WinRT.cs b/src/Common/src/System/IO/DriveInfoInternal.WinRT.cs new file mode 100644 index 000000000000..93460b844aa4 --- /dev/null +++ b/src/Common/src/System/IO/DriveInfoInternal.WinRT.cs @@ -0,0 +1,19 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Diagnostics; +using System.Text; + +namespace System.IO +{ + /// Contains internal volume helpers that are shared between many projects. + internal static partial class DriveInfoInternal + { + internal static string[] GetLogicalDrives() + { + // Getting volume information isn't supported on WinRT + throw new PlatformNotSupportedException(); + } + } +} diff --git a/src/System.IO.FileSystem.DriveInfo/src/System.IO.FileSystem.DriveInfo.csproj b/src/System.IO.FileSystem.DriveInfo/src/System.IO.FileSystem.DriveInfo.csproj index c1110baca2cb..aafb9dee9fc7 100644 --- a/src/System.IO.FileSystem.DriveInfo/src/System.IO.FileSystem.DriveInfo.csproj +++ b/src/System.IO.FileSystem.DriveInfo/src/System.IO.FileSystem.DriveInfo.csproj @@ -74,6 +74,9 @@ Common\System\IO\Win32Marshal.cs + + Common\System\IO\DriveInfoInternal.Win32.cs + Common\System\IO\PathInternal.Windows.cs @@ -98,6 +101,9 @@ Common\Interop\Unix\Interop.MountPoints.cs + + Common\Interop\Unix\Interop.MountPoints.FormatInfo.cs + diff --git a/src/System.IO.FileSystem.DriveInfo/src/System/IO/DriveInfo.Windows.cs b/src/System.IO.FileSystem.DriveInfo/src/System/IO/DriveInfo.Windows.cs index 84aa4ba31c82..d77317a43804 100644 --- a/src/System.IO.FileSystem.DriveInfo/src/System/IO/DriveInfo.Windows.cs +++ b/src/System.IO.FileSystem.DriveInfo/src/System/IO/DriveInfo.Windows.cs @@ -152,35 +152,11 @@ public long TotalSize public static DriveInfo[] GetDrives() { - int drives = Interop.mincore.GetLogicalDrives(); - if (drives == 0) - throw Win32Marshal.GetExceptionForLastWin32Error(); - - // GetLogicalDrives returns a bitmask starting from - // position 0 "A" indicating whether a drive is present. - // Loop over each bit, creating a DriveInfo for each one - // that is set. - - uint d = (uint)drives; - int count = 0; - while (d != 0) + string[] drives = DriveInfoInternal.GetLogicalDrives(); + DriveInfo[] result = new DriveInfo[drives.Length]; + for (int i = 0; i < drives.Length; i++) { - if (((int)d & 1) != 0) count++; - d >>= 1; - } - - DriveInfo[] result = new DriveInfo[count]; - char[] root = new char[] { 'A', ':', '\\' }; - d = (uint)drives; - count = 0; - while (d != 0) - { - if (((int)d & 1) != 0) - { - result[count++] = new DriveInfo(new String(root)); - } - d >>= 1; - root[0]++; + result[i] = new DriveInfo(drives[i]); } return result; } diff --git a/src/System.IO.FileSystem/src/System.IO.FileSystem.csproj b/src/System.IO.FileSystem/src/System.IO.FileSystem.csproj index 5d2bed6076b3..fedf64bf73cd 100644 --- a/src/System.IO.FileSystem/src/System.IO.FileSystem.csproj +++ b/src/System.IO.FileSystem/src/System.IO.FileSystem.csproj @@ -208,7 +208,9 @@ Common\Interop\Windows\Interop.GetLogicalDrive.cs - + + Common\System\IO\DriveInfoInternal.Win32.cs + @@ -238,7 +240,9 @@ Common\Interop\Windows\WinRT\Interop.SetErrorMode.cs - + + Common\System\IO\DriveInfoInternal.WinRT.cs + @@ -256,16 +260,12 @@ - - - Common\Microsoft\Win32\SafeHandles\SafeFileHandle.Unix.cs - Common\Interop\Unix\Interop.Libraries.cs @@ -317,9 +317,6 @@ Common\Interop\Unix\Interop.Stat.cs - - Common\System\IO\PathInternal.Unix.cs - Common\Interop\Unix\Interop.ReadDir.cs @@ -344,6 +341,9 @@ Common\Interop\Unix\Interop.Link.cs + + Common\Interop\Unix\Interop.MountPoints.cs + Common\Interop\Unix\Interop.PosixFAdvise.cs @@ -365,6 +365,15 @@ Common\Microsoft\Win32\SafeHandles\SafeDirectoryHandle.Unix.cs + + Common\Microsoft\Win32\SafeHandles\SafeFileHandle.Unix.cs + + + Common\System\IO\PathInternal.Unix.cs + + + Common\System\IO\DriveInfoInternal.Unix.cs + diff --git a/src/System.IO.FileSystem/src/System/IO/Directory.Unix.cs b/src/System.IO.FileSystem/src/System/IO/Directory.Unix.cs deleted file mode 100644 index f387838e3eb8..000000000000 --- a/src/System.IO.FileSystem/src/System/IO/Directory.Unix.cs +++ /dev/null @@ -1,14 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. - -namespace System.IO -{ - public static partial class Directory - { - public static string[] GetLogicalDrives() - { - throw new PlatformNotSupportedException(); - } - } -} diff --git a/src/System.IO.FileSystem/src/System/IO/Directory.WinRT.cs b/src/System.IO.FileSystem/src/System/IO/Directory.WinRT.cs deleted file mode 100644 index f387838e3eb8..000000000000 --- a/src/System.IO.FileSystem/src/System/IO/Directory.WinRT.cs +++ /dev/null @@ -1,14 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. - -namespace System.IO -{ - public static partial class Directory - { - public static string[] GetLogicalDrives() - { - throw new PlatformNotSupportedException(); - } - } -} diff --git a/src/System.IO.FileSystem/src/System/IO/Directory.cs b/src/System.IO.FileSystem/src/System/IO/Directory.cs index 2eac0f1e15f7..7cbcc4c9790b 100644 --- a/src/System.IO.FileSystem/src/System/IO/Directory.cs +++ b/src/System.IO.FileSystem/src/System/IO/Directory.cs @@ -579,6 +579,11 @@ public static void Delete(String path, bool recursive) String fullPath = Path.GetFullPath(path); FileSystem.Current.RemoveDirectory(fullPath, recursive); } + + public static string[] GetLogicalDrives() + { + return FileSystem.Current.GetLogicalDrives(); + } } } diff --git a/src/System.IO.FileSystem/src/System/IO/FileSystem.cs b/src/System.IO.FileSystem/src/System/IO/FileSystem.cs index 8724811fa0cb..8a651bd7ee73 100644 --- a/src/System.IO.FileSystem/src/System/IO/FileSystem.cs +++ b/src/System.IO.FileSystem/src/System/IO/FileSystem.cs @@ -43,5 +43,8 @@ internal abstract partial class FileSystem public abstract void SetCurrentDirectory(string fullPath); public abstract int MaxPath { get; } public abstract int MaxDirectoryPath { get; } + + // Volume + public abstract string[] GetLogicalDrives(); } } diff --git a/src/System.IO.FileSystem/src/System/IO/MultiplexingWin32WinRTFileSystem.cs b/src/System.IO.FileSystem/src/System/IO/MultiplexingWin32WinRTFileSystem.cs index 48dacc043340..526338eb582b 100644 --- a/src/System.IO.FileSystem/src/System/IO/MultiplexingWin32WinRTFileSystem.cs +++ b/src/System.IO.FileSystem/src/System/IO/MultiplexingWin32WinRTFileSystem.cs @@ -149,6 +149,12 @@ private FileSystem Select(string sourceFullPath, string destFullPath) return (ShouldUseWinRT(sourceFullPath, isCreate: false) || ShouldUseWinRT(destFullPath, isCreate: true)) ? _winRTFileSystem : _win32FileSystem; } + public override string[] GetLogicalDrives() + { + // This API is always blocked on WinRT, don't use Win32 + return _winRTFileSystem.GetLogicalDrives(); + } + private static bool ShouldUseWinRT(string fullPath, bool isCreate) { // The purpose of this method is to determine if we can access a path diff --git a/src/System.IO.FileSystem/src/System/IO/UnixFileSystem.cs b/src/System.IO.FileSystem/src/System/IO/UnixFileSystem.cs index f404f4cc2fd5..8e55d3be1e22 100644 --- a/src/System.IO.FileSystem/src/System/IO/UnixFileSystem.cs +++ b/src/System.IO.FileSystem/src/System/IO/UnixFileSystem.cs @@ -653,5 +653,10 @@ public override IFileSystemObject GetFileSystemInfo(string fullPath, bool asDire (IFileSystemObject)new DirectoryInfo(fullPath, null) : (IFileSystemObject)new FileInfo(fullPath, null); } + + public override string[] GetLogicalDrives() + { + return DriveInfoInternal.GetLogicalDrives(); + } } } diff --git a/src/System.IO.FileSystem/src/System/IO/Win32FileSystem.cs b/src/System.IO.FileSystem/src/System/IO/Win32FileSystem.cs index b2004b0600da..595420257255 100644 --- a/src/System.IO.FileSystem/src/System/IO/Win32FileSystem.cs +++ b/src/System.IO.FileSystem/src/System/IO/Win32FileSystem.cs @@ -729,5 +729,10 @@ private static void SetLastWriteTimeInternal(string fullPath, DateTimeOffset tim } } } + + public override string[] GetLogicalDrives() + { + return DriveInfoInternal.GetLogicalDrives(); + } } } diff --git a/src/System.IO.FileSystem/src/System/IO/WinRTFileSystem.cs b/src/System.IO.FileSystem/src/System/IO/WinRTFileSystem.cs index 076f5a9973f1..c12361df21c9 100644 --- a/src/System.IO.FileSystem/src/System/IO/WinRTFileSystem.cs +++ b/src/System.IO.FileSystem/src/System/IO/WinRTFileSystem.cs @@ -725,6 +725,11 @@ public override void SetLastWriteTime(string fullPath, DateTimeOffset time, bool // "System.DateModified" property is readonly } + public override string[] GetLogicalDrives() + { + return DriveInfoInternal.GetLogicalDrives(); + } + #region Task Utility private static void EnsureBackgroundThread() { diff --git a/src/System.IO.FileSystem/tests/Directory/GetLogicalDrives.cs b/src/System.IO.FileSystem/tests/Directory/GetLogicalDrives.cs index 67eeab60adbb..8e68ccb0509f 100644 --- a/src/System.IO.FileSystem/tests/Directory/GetLogicalDrives.cs +++ b/src/System.IO.FileSystem/tests/Directory/GetLogicalDrives.cs @@ -12,9 +12,12 @@ public class Directory_GetLogicalDrives { [Fact] [PlatformSpecific(PlatformID.AnyUnix)] - public void ThrowsPlatformNotSupported_Unix() + public void GetsValidDriveStrings_Unix() { - Assert.Throws(() => Directory.GetLogicalDrives()); + string[] drives = Directory.GetLogicalDrives(); + Assert.NotEmpty(drives); + Assert.All(drives, d => Assert.NotNull(d)); + Assert.Contains(drives, d => d == "/"); } [Fact]