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

Commit 1b4080c

Browse files
author
Jonathan Miller
committed
Refactoring DriveInfo to work with BSD systems
1 parent 1e9abf4 commit 1b4080c

File tree

8 files changed

+160
-54
lines changed

8 files changed

+160
-54
lines changed
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
// Copyright (c) Microsoft. All rights reserved.
2+
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
3+
4+
using System;
5+
using System.Runtime.InteropServices;
6+
7+
using uid_t = System.UInt32;
8+
9+
internal static partial class Interop
10+
{
11+
internal static partial class libc
12+
{
13+
/// <summary>
14+
/// Gets all the current mount points on the system
15+
/// </summary>
16+
/// <param name="ppBuffer">A pointer to an array of mount points</param>
17+
/// <param name="flags">Flags that are passed to the getfsstat call for each statfs struct</param>
18+
/// <returns>Returns the number of retrieved statfs structs</returns>
19+
/// <remarks
20+
/// Do NOT free this memory...this memory is allocated by the OS, which is responsible for it.
21+
/// This call could also block for a bit to wait for slow network drives.
22+
/// </remarks>
23+
[DllImport(Interop.Libraries.libc, EntryPoint = "getmntinfo" + Interop.Libraries.INODE64SUFFIX)]
24+
internal static unsafe extern int getmntinfo(statfs** ppBuffer, int flags);
25+
26+
/// <summary>
27+
/// Gets a statfs struct for the given path that describes that mount point
28+
/// </summary>
29+
/// <param name="path">The path to retrieve the statfs for</param>
30+
/// <param name="buffer">The output statfs struct describing the mount point</param>
31+
/// <returns>Returns 0 on success, -1 on failure</returns>
32+
[DllImport(Interop.Libraries.libc, EntryPoint = "statfs" + Interop.Libraries.INODE64SUFFIX)]
33+
private static unsafe extern int get_statfs(string path, statfs* buffer);
34+
35+
/// <summary>
36+
/// Gets a statfs struct for a given mount point
37+
/// </summary>
38+
/// <param name="name">The drive name to retrieve the statfs data for</param>
39+
/// <returns>Returns </returns>
40+
internal static unsafe statfs GetStatFsForDriveName(string name)
41+
{
42+
statfs data = default(statfs);
43+
int result = get_statfs(name, &data);
44+
if (result < 0)
45+
throw Interop.GetExceptionForIoErrno(Marshal.GetLastWin32Error());
46+
else
47+
return data;
48+
}
49+
50+
internal static unsafe String GetMountPointName(statfs data)
51+
{
52+
return Marshal.PtrToStringAnsi((IntPtr)data.f_mntonname);
53+
}
54+
55+
internal static unsafe String GetMountPointFsType(statfs data)
56+
{
57+
return Marshal.PtrToStringAnsi((IntPtr)data.f_fstypename);
58+
}
59+
}
60+
}

src/Common/src/Interop/FreeBSD/Interop.Libraries.cs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,12 @@ internal static partial class Interop
55
{
66
private static partial class Libraries
77
{
8-
internal const string LibRt = "librt"; // POSIX Realtime Extensions library
8+
/// <summary>
9+
/// We aren't OS X so don't have an INODE64 suffix to entry points
10+
/// </summary>
11+
internal const string INODE64SUFFIX = "";
12+
13+
internal const string LibRt = "librt"; // POSIX Realtime Extensions library
14+
internal const string libc = "libc"; // C runtime
915
}
1016
}
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
// Copyright (c) Microsoft. All rights reserved.
2+
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
3+
4+
using System;
5+
using System.Runtime.InteropServices;
6+
7+
using uid_t = System.UInt32;
8+
9+
internal static partial class Interop
10+
{
11+
internal static partial class libc
12+
{
13+
internal const int MFSNAMELEN = 16; /* length of type name including null */
14+
internal const int MNAMELEN = 88; /* size of on/from name bufs */
15+
16+
[StructLayout(LayoutKind.Sequential)]
17+
internal unsafe struct fsid_t
18+
{
19+
internal fixed int val[2];
20+
}
21+
22+
[StructLayout(LayoutKind.Sequential)]
23+
internal unsafe struct statfs
24+
{
25+
internal uint f_version; /* structure version number */
26+
internal uint f_type; /* type of filesystem */
27+
internal ulong f_flags; /* copy of mount exported flags */
28+
internal ulong f_bsize; /* filesystem fragment size */
29+
internal ulong f_iosize; /* optimal transfer block size */
30+
internal ulong f_blocks; /* total data blocks in filesystem */
31+
internal ulong f_bfree; /* free blocks in filesystem */
32+
internal long f_bavail; /* free blocks avail to non-superuser */
33+
internal ulong f_files; /* total file nodes in filesystem */
34+
internal long f_ffree; /* free nodes avail to non-superuser */
35+
internal ulong f_syncwrites; /* count of sync writes since mount */
36+
internal ulong f_asyncwrites; /* count of async writes since mount */
37+
internal ulong f_syncreads; /* count of sync reads since mount */
38+
internal ulong f_asyncreads; /* count of async reads since mount */
39+
internal fixed ulong f_spare[10]; /* unused spare */
40+
internal uint f_namemax; /* maximum filename length */
41+
internal uid_t f_owner; /* user that mounted the filesystem */
42+
internal fsid_t f_fsid; /* filesystem id */
43+
internal fixed byte f_charspare[80]; /* spare string space */
44+
internal fixed byte f_fstypename[MFSNAMELEN]; /* filesystem type name */
45+
internal fixed byte f_mntfromname[MNAMELEN]; /* mounted filesystem */
46+
internal fixed byte f_mntonname[MNAMELEN]; /* directory on which mounted */
47+
}
48+
}
49+
}

src/Common/src/Interop/OSX/Interop.Libraries.cs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,15 @@ internal static partial class Interop
55
{
66
private static partial class Libraries
77
{
8+
/// <summary>
9+
/// Some functions in OS X have the __DARWIN_INODE64(<function_name>) decoration, which means
10+
/// that the function has the prefix $INODE64 natively, so we need to apply that decoration
11+
/// onto the end of the entry point name to PInvoke into the right function. We use this const
12+
/// so that other *nix systems that have the same function prototype but don't have the INODE64, since
13+
/// they aren't OS X, can use the same declaration and not redeclare it.
14+
/// </summary>
815
internal const string INODE64SUFFIX = "$INODE64";
16+
917
internal const string CoreFoundationLibrary = "/System/Library/Frameworks/CoreFoundation.framework/CoreFoundation";
1018
internal const string CoreServicesLibrary = "/System/Library/Frameworks/CoreServices.framework/CoreServices";
1119
internal const string libc = "libc";

src/Common/src/Interop/OSX/libc/Interop.statfs.cs

Lines changed: 0 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -39,52 +39,5 @@ internal unsafe struct statfs
3939
internal fixed byte f_mntfromname[MAXPATHLEN]; /* mounted filesystem */
4040
internal fixed uint f_reserved[8]; /* For future use */
4141
}
42-
43-
/// <summary>
44-
/// Gets all the current mount points on the system
45-
/// </summary>
46-
/// <param name="ppBuffer">A pointer to an array of mount points</param>
47-
/// <param name="flags">Flags that are passed to the getfsstat call for each statfs struct</param>
48-
/// <returns>Returns the number of retrieved statfs structs</returns>
49-
/// <remarks
50-
/// Do NOT free this memory...this memory is allocated by the OS, which is responsible for it.
51-
/// This call could also block for a bit to wait for slow network drives.
52-
/// </remarks>
53-
[DllImport(Interop.Libraries.libc, EntryPoint = "getmntinfo" + Interop.Libraries.INODE64SUFFIX)]
54-
internal static unsafe extern int getmntinfo(statfs** ppBuffer, int flags);
55-
56-
/// <summary>
57-
/// Gets a statfs struct for the given path that describes that mount point
58-
/// </summary>
59-
/// <param name="path">The path to retrieve the statfs for</param>
60-
/// <param name="buffer">The output statfs struct describing the mount point</param>
61-
/// <returns>Returns 0 on success, -1 on failure</returns>
62-
[DllImport(Interop.Libraries.libc, EntryPoint = "statfs" + Interop.Libraries.INODE64SUFFIX)]
63-
private static unsafe extern int get_statfs(string path, statfs* buffer);
64-
65-
/// <summary>
66-
/// Gets a statfs struct for a given mount point
67-
/// </summary>
68-
/// <param name="name">The drive name to retrieve the statfs data for</param>
69-
/// <returns>Returns </returns>
70-
internal static unsafe statfs GetStatFsForDriveName(string name)
71-
{
72-
statfs data = default(statfs);
73-
int result = get_statfs(name, &data);
74-
if (result < 0)
75-
throw Interop.GetExceptionForIoErrno(Marshal.GetLastWin32Error());
76-
else
77-
return data;
78-
}
79-
80-
internal static unsafe String GetMountPointName(statfs data)
81-
{
82-
return Marshal.PtrToStringAnsi((IntPtr)data.f_mntonname);
83-
}
84-
85-
internal static unsafe String GetMountPointFsType(statfs data)
86-
{
87-
return Marshal.PtrToStringAnsi((IntPtr)data.f_fstypename);
88-
}
8942
}
9043
}

src/System.IO.FileSystem.DriveInfo/System.IO.FileSystem.DriveInfo.sln

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11

22
Microsoft Visual Studio Solution File, Format Version 12.00
3-
# Visual Studio 2013
4-
VisualStudioVersion = 12.0.30723.0
3+
# Visual Studio 14
4+
VisualStudioVersion = 14.0.22823.1
55
MinimumVisualStudioVersion = 10.0.40219.1
66
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "System.IO.FileSystem.DriveInfo", "src\System.IO.FileSystem.DriveInfo.csproj", "{29C14AD7-DC03-45DC-897D-8DACC762707E}"
77
EndProject
@@ -14,6 +14,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "System.IO.FileSystem.DriveI
1414
EndProject
1515
Global
1616
GlobalSection(SolutionConfigurationPlatforms) = preSolution
17+
FreeBSD_Debug|Any CPU = FreeBSD_Debug|Any CPU
18+
FreeBSD_Release|Any CPU = FreeBSD_Release|Any CPU
1719
Linux_Debug|Any CPU = Linux_Debug|Any CPU
1820
Linux_Release|Any CPU = Linux_Release|Any CPU
1921
OSX_Debug|Any CPU = OSX_Debug|Any CPU
@@ -22,6 +24,10 @@ Global
2224
Windows_Release|Any CPU = Windows_Release|Any CPU
2325
EndGlobalSection
2426
GlobalSection(ProjectConfigurationPlatforms) = postSolution
27+
{29C14AD7-DC03-45DC-897D-8DACC762707E}.FreeBSD_Debug|Any CPU.ActiveCfg = FreeBSD_Debug|Any CPU
28+
{29C14AD7-DC03-45DC-897D-8DACC762707E}.FreeBSD_Debug|Any CPU.Build.0 = FreeBSD_Debug|Any CPU
29+
{29C14AD7-DC03-45DC-897D-8DACC762707E}.FreeBSD_Release|Any CPU.ActiveCfg = FreeBSD_Release|Any CPU
30+
{29C14AD7-DC03-45DC-897D-8DACC762707E}.FreeBSD_Release|Any CPU.Build.0 = FreeBSD_Release|Any CPU
2531
{29C14AD7-DC03-45DC-897D-8DACC762707E}.Linux_Debug|Any CPU.ActiveCfg = Linux_Debug|Any CPU
2632
{29C14AD7-DC03-45DC-897D-8DACC762707E}.Linux_Debug|Any CPU.Build.0 = Linux_Debug|Any CPU
2733
{29C14AD7-DC03-45DC-897D-8DACC762707E}.Linux_Release|Any CPU.ActiveCfg = Linux_Release|Any CPU
@@ -34,6 +40,8 @@ Global
3440
{29C14AD7-DC03-45DC-897D-8DACC762707E}.Windows_Debug|Any CPU.Build.0 = Windows_Debug|Any CPU
3541
{29C14AD7-DC03-45DC-897D-8DACC762707E}.Windows_Release|Any CPU.ActiveCfg = Windows_Release|Any CPU
3642
{29C14AD7-DC03-45DC-897D-8DACC762707E}.Windows_Release|Any CPU.Build.0 = Windows_Release|Any CPU
43+
{7D9E5F2F-5677-40FC-AD04-FA7D603E4806}.FreeBSD_Debug|Any CPU.ActiveCfg = Debug|Any CPU
44+
{7D9E5F2F-5677-40FC-AD04-FA7D603E4806}.FreeBSD_Release|Any CPU.ActiveCfg = Release|Any CPU
3745
{7D9E5F2F-5677-40FC-AD04-FA7D603E4806}.Linux_Debug|Any CPU.ActiveCfg = Debug|Any CPU
3846
{7D9E5F2F-5677-40FC-AD04-FA7D603E4806}.Linux_Release|Any CPU.ActiveCfg = Release|Any CPU
3947
{7D9E5F2F-5677-40FC-AD04-FA7D603E4806}.OSX_Debug|Any CPU.ActiveCfg = Debug|Any CPU

src/System.IO.FileSystem.DriveInfo/src/System.IO.FileSystem.DriveInfo.csproj

Lines changed: 25 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,12 @@
1919
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Linux_Release|AnyCPU' " />
2020
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'OSX_Debug|AnyCPU' " />
2121
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'OSX_Release|AnyCPU' " />
22+
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'FreeBSD_Debug|AnyCPU' "/>
23+
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'FreeBSD_Release|AnyCPU' "/>
24+
<PropertyGroup>
25+
<TargetsBSD Condition="'$(TargetsOSX)' == 'true' or '$(TargetsFreeBSD)' == 'true'">true</TargetsBSD>
26+
</PropertyGroup>
27+
2228
<ItemGroup>
2329
<Compile Include="System\IO\DriveInfo.cs" />
2430
<Compile Include="System\IO\DriveNotFoundException.cs" />
@@ -114,8 +120,13 @@
114120
<Link>Common\System\IO\PathInternal.CaseSensitive.cs</Link>
115121
</Compile>
116122
</ItemGroup>
123+
<ItemGroup Condition=" '$(TargetsBSD)' == 'true' ">
124+
<Compile Include="System\IO\DriveInfo.BSD.cs" />
125+
<Compile Include="$(CommonPath)\Interop\BSD\libc\Interop.mountpoints.cs">
126+
<Link>Common\Interop\BSD\Interop.mountpoints.cs</Link>
127+
</Compile>
128+
</ItemGroup>
117129
<ItemGroup Condition=" '$(TargetsOSX)' == 'true' ">
118-
<Compile Include="System\IO\DriveInfo.OSX.cs" />
119130
<Compile Include="$(CommonPath)\Interop\OSX\Interop.Errors.cs">
120131
<Link>Common\Interop\OSX\Interop.Errors.cs</Link>
121132
</Compile>
@@ -125,8 +136,19 @@
125136
<Compile Include="$(CommonPath)\Interop\OSX\Interop.Libraries.cs">
126137
<Link>Common\Interop\OSX\Interop.Libraries.cs</Link>
127138
</Compile>
128-
<Compile Include="$(CommonPath)\Interop\OSX\libc\Interop.Mount.cs">
129-
<Link>Common\Interop\OSX\Interop.Mount.cs</Link>
139+
<Compile Include="$(CommonPath)\Interop\OSX\libc\Interop.statfs.cs">
140+
<Link>Common\Interop\OSX\Interop.statfs.cs</Link>
141+
</Compile>
142+
</ItemGroup>
143+
<ItemGroup Condition=" '$(TargetsFreeBSD)' == 'true'">
144+
<Compile Include="$(CommonPath)\Interop\FreeBSD\libc\Interop.statfs.cs">
145+
<Link>Common\Interop\FreeBSD\Interop.statfs.cs</Link>
146+
</Compile>
147+
<Compile Include="$(CommonPath)\Interop\FreeBSD\Interop.Libraries.cs">
148+
<Link>Common\Interop\FreeBSD\Interop.Libraries.cs</Link>
149+
</Compile>
150+
<Compile Include="$(CommonPath)\Interop\FreeBSD\Interop.Errors.cs">
151+
<Link>Common\Interop\OSX\Interop.Errors.cs</Link>
130152
</Compile>
131153
</ItemGroup>
132154
<ItemGroup>

src/System.IO.FileSystem.DriveInfo/src/System/IO/DriveInfo.OSX.cs renamed to src/System.IO.FileSystem.DriveInfo/src/System/IO/DriveInfo.BSD.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ public long AvailableFreeSpace
4747
get
4848
{
4949
Interop.libc.statfs data = Interop.libc.GetStatFsForDriveName(Name);
50-
return (long)(data.f_bsize * data.f_bavail);
50+
return (long)data.f_bsize * (long)data.f_bavail;
5151
}
5252
}
5353

0 commit comments

Comments
 (0)