diff options
author | Alex Ghiondea <ghiondea.alexandru@microsoft.com> | 2015-10-29 02:44:24 +0300 |
---|---|---|
committer | Alex Ghiondea <ghiondea.alexandru@microsoft.com> | 2015-11-01 22:59:41 +0300 |
commit | 0759d98122c95050c5bf8c7d682d9750525751b8 (patch) | |
tree | 8260d6e82b8780bb1a2ae94c1616fb94aae338ba | |
parent | c9325e9b9fee0232b4768d4eb9cd1f458e4cfdac (diff) |
Implement GetEnvironmentVariable and ExpandEnvironmentVariables on Linux.
Create the Native PAL layer that uses the native getenv method to retrieve
the environemnt variable.
Create the right Interop function in managed code to allow us to call the native PAL
Implement the managed side of the GetEnvironmentVariable and
ExpandEnvironmentVariable to leverage the PAL
9 files changed, 130 insertions, 20 deletions
diff --git a/src/Common/src/Interop/Unix/System.Private.CoreLib.Native/Interop.Environment.cs b/src/Common/src/Interop/Unix/System.Private.CoreLib.Native/Interop.Environment.cs new file mode 100644 index 000000000..040d1ba90 --- /dev/null +++ b/src/Common/src/Interop/Unix/System.Private.CoreLib.Native/Interop.Environment.cs @@ -0,0 +1,20 @@ +// Copyright (c) Microsoft. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +internal static partial class Interop +{ + private static class Libraries + { + internal const string SystemPrivateCoreLibNative = "System.Private.CoreLib.Native"; + } + + internal unsafe partial class Sys + { + [DllImport(Libraries.SystemPrivateCoreLibNative)] + internal static unsafe extern int GetEnvironmentVariable(byte* name, out IntPtr result); + } +} diff --git a/src/Common/src/Interop/Unix/System.Private.CoreLib.Native/Interop.StringHelper.cs b/src/Common/src/Interop/Unix/System.Private.CoreLib.Native/Interop.StringHelper.cs new file mode 100644 index 000000000..ddc637e3d --- /dev/null +++ b/src/Common/src/Interop/Unix/System.Private.CoreLib.Native/Interop.StringHelper.cs @@ -0,0 +1,26 @@ +// Copyright (c) Microsoft. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +using System; +using System.Text; + +internal static partial class Interop +{ + internal unsafe partial class StringHelper + { + public static unsafe byte[] GetBytesFromUTF8string(string value) + { + int bytecount = Encoding.UTF8.GetByteCount(value); + + // GetByteCount does not account for the trailing zero that is needed + // Add one to allocate the trailing zero for the string. + // Note: The runtime will zero-initialize the buffer + byte[] result = new byte[bytecount + 1]; + fixed (char* pValue = value) + fixed (byte* pResult = result) + Encoding.UTF8.GetBytes(pValue, value.Length, pResult, bytecount); + + return result; + } + } +}
\ No newline at end of file diff --git a/src/Common/src/Interop/Unix/libc/Interop.Environment.cs b/src/Common/src/Interop/Unix/libc/Interop.Environment.cs deleted file mode 100644 index f425906dc..000000000 --- a/src/Common/src/Interop/Unix/libc/Interop.Environment.cs +++ /dev/null @@ -1,14 +0,0 @@ -// Copyright (c) Microsoft. All rights reserved. -// Licensed under the MIT license. See LICENSE file in the project root for full license information. - -using System; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; - -internal static partial class Interop -{ - internal unsafe partial class libc - { - - } -} diff --git a/src/Native/CMakeLists.txt b/src/Native/CMakeLists.txt index e2fcacc2f..d04a381a4 100644 --- a/src/Native/CMakeLists.txt +++ b/src/Native/CMakeLists.txt @@ -129,3 +129,8 @@ if(WIN32) endif() add_subdirectory(Runtime) add_subdirectory(Bootstrap) + +# We don't need the PAL on Windows. +if(CMAKE_SYSTEM_NAME STREQUAL Linux) + add_subdirectory(System.Private.CoreLib.Native) +endif() diff --git a/src/Native/System.Private.CoreLib.Native/CMakeLists.txt b/src/Native/System.Private.CoreLib.Native/CMakeLists.txt new file mode 100644 index 000000000..f7976c28a --- /dev/null +++ b/src/Native/System.Private.CoreLib.Native/CMakeLists.txt @@ -0,0 +1,17 @@ +project(System.Private.CoreLib.Native) + +set(NATIVE_SOURCES + pal_environment.cpp +) + +add_library(System.Private.CoreLib.Native + SHARED + ${NATIVE_SOURCES} +) + +if (CMAKE_SYSTEM_NAME STREQUAL Linux) + target_link_libraries(System.Private.CoreLib.Native rt) +endif () + + +install (TARGETS System.Private.CoreLib.Native DESTINATION lib) diff --git a/src/Native/System.Private.CoreLib.Native/pal_environment.cpp b/src/Native/System.Private.CoreLib.Native/pal_environment.cpp new file mode 100644 index 000000000..07ef6fdc9 --- /dev/null +++ b/src/Native/System.Private.CoreLib.Native/pal_environment.cpp @@ -0,0 +1,18 @@ +#include <stdlib.h> +#include <string.h> +#include <assert.h> + +extern "C" int32_t GetEnvironmentVariable(const char* variable, char** result) +{ + assert(result != NULL); + + // Read the environment variable + *result = getenv(variable); + + if (*result == NULL) + { + return 0; + } + + return (int32_t)strlen(*result); +} diff --git a/src/System.Private.CoreLib/src/System.Private.CoreLib.csproj b/src/System.Private.CoreLib/src/System.Private.CoreLib.csproj index 42f13430f..ee88f55e7 100644 --- a/src/System.Private.CoreLib/src/System.Private.CoreLib.csproj +++ b/src/System.Private.CoreLib/src/System.Private.CoreLib.csproj @@ -492,7 +492,8 @@ <Compile Include="System\Globalization\CalendarData.Dummy.cs" /> <!-- For CoreRT we have a different implementation --> <Compile Include="System\Environment.EnvironmentVariables.Unix.cs" /> - <Compile Include="..\..\Common\src\Interop\Unix\libc\Interop.Environment.cs" /> + <Compile Include="..\..\Common\src\Interop\Unix\System.Private.CoreLib.Native\Interop.Environment.cs" /> + <Compile Include="..\..\Common\src\Interop\Unix\System.Private.CoreLib.Native\Interop.StringHelper.cs" /> </ItemGroup> <ItemGroup> diff --git a/src/System.Private.CoreLib/src/System/Environment.EnvironmentVariables.Unix.cs b/src/System.Private.CoreLib/src/System/Environment.EnvironmentVariables.Unix.cs index 19bb70320..744935e53 100644 --- a/src/System.Private.CoreLib/src/System/Environment.EnvironmentVariables.Unix.cs +++ b/src/System.Private.CoreLib/src/System/Environment.EnvironmentVariables.Unix.cs @@ -22,8 +22,34 @@ namespace System if (name == null) throw new ArgumentNullException("name"); - //TODO: Unix implementations - return name; + if (name.Length == 0) + { + return name; + } + + int currentSize = 100; + StringBuilder blob = new StringBuilder(currentSize); // A somewhat reasonable default size + + int lastPos = 0, pos; + while (lastPos < name.Length && (pos = name.IndexOf('%', lastPos + 1)) >= 0) + { + if (name[lastPos] == '%') + { + string key = name.Substring(lastPos + 1, pos - lastPos - 1); + string value = Environment.GetEnvironmentVariable(key); + if (value != null) + { + blob.Append(value); + lastPos = pos + 1; + continue; + } + } + blob.Append(name.Substring(lastPos, pos - lastPos)); + lastPos = pos; + } + blob.Append(name.Substring(lastPos)); + + return blob.ToString(); } public unsafe static String GetEnvironmentVariable(String variable) @@ -31,8 +57,19 @@ namespace System if (variable == null) throw new ArgumentNullException("variable"); - //TODO: Unix implementations - return null; + byte[] variableAsBytes = Interop.StringHelper.GetBytesFromUTF8string(variable); + fixed (byte* pVar = variableAsBytes) + { + IntPtr result; + int size = Interop.Sys.GetEnvironmentVariable(pVar, out result); + + if (size > 0) + { + return Encoding.UTF8.GetString((byte*)result, size); + } + + return null; + } } } } diff --git a/src/System.Private.CoreLib/src/System/Environment.EnvironmentVariables.Win32.cs b/src/System.Private.CoreLib/src/System/Environment.EnvironmentVariables.Win32.cs index c713f912a..f2b8d6689 100644 --- a/src/System.Private.CoreLib/src/System/Environment.EnvironmentVariables.Win32.cs +++ b/src/System.Private.CoreLib/src/System/Environment.EnvironmentVariables.Win32.cs @@ -123,4 +123,4 @@ namespace System return new string(newblob); } } -} +}
\ No newline at end of file |