1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
|
// 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.Runtime.InteropServices;
internal static partial class Interop
{
internal static partial class Sys
{
[DllImport(Libraries.SystemNative, EntryPoint = "SystemNative_GetCwd", SetLastError = true)]
private static unsafe extern byte* GetCwd(byte* buffer, int bufferLength);
internal static unsafe string GetCwd()
{
const int StackLimit = 256;
// First try to get the path into a buffer on the stack
byte* stackBuf = stackalloc byte[StackLimit];
string result = GetCwdHelper(stackBuf, StackLimit);
if (result != null)
{
return result;
}
// If that was too small, try increasing large buffer sizes
// until we get one that works or until we hit MaxPath.
int maxPath = Interop.Sys.MaxPath;
if (StackLimit < maxPath)
{
int bufferSize = StackLimit;
do
{
checked { bufferSize *= 2; }
var buf = new byte[Math.Min(bufferSize, maxPath)];
fixed (byte* ptr = buf)
{
result = GetCwdHelper(ptr, buf.Length);
if (result != null)
{
return result;
}
}
}
while (bufferSize < maxPath);
}
// If we couldn't get the cwd with a MaxPath-sized buffer, something's wrong.
throw Interop.GetExceptionForIoErrno(new ErrorInfo(Interop.Error.ENAMETOOLONG));
}
private static unsafe string GetCwdHelper(byte* ptr, int bufferSize)
{
// Call the real getcwd
byte* result = GetCwd(ptr, bufferSize);
// If it returned non-null, the null-terminated path is in the buffer
if (result != null)
{
return Marshal.PtrToStringAnsi((IntPtr)ptr);
}
// Otherwise, if it failed due to the buffer being too small, return null;
// for anything else, throw.
ErrorInfo errorInfo = Interop.Sys.GetLastErrorInfo();
if (errorInfo.Error == Interop.Error.ERANGE)
{
return null;
}
throw Interop.GetExceptionForIoErrno(errorInfo);
}
}
}
|