From 196a37b1186d5d4901c515c02bc09bee9520cf59 Mon Sep 17 00:00:00 2001 From: Andrew Schwartzmeyer Date: Mon, 3 Oct 2016 15:41:38 -0700 Subject: [PATCH] Add native errno to ErrorCategory mapper --- .../CoreCLR/CorePsPlatform.cs | 9 +++ .../namespaces/FileSystemProvider.cs | 4 ++ src/libpsl-native/src/CMakeLists.txt | 1 + src/libpsl-native/src/geterrorcategory.cpp | 63 +++++++++++++++++++ src/libpsl-native/src/geterrorcategory.h | 9 +++ 5 files changed, 86 insertions(+) create mode 100644 src/libpsl-native/src/geterrorcategory.cpp create mode 100644 src/libpsl-native/src/geterrorcategory.h diff --git a/src/System.Management.Automation/CoreCLR/CorePsPlatform.cs b/src/System.Management.Automation/CoreCLR/CorePsPlatform.cs index 2e209daf82..34cb42a93c 100644 --- a/src/System.Management.Automation/CoreCLR/CorePsPlatform.cs +++ b/src/System.Management.Automation/CoreCLR/CorePsPlatform.cs @@ -461,6 +461,12 @@ namespace System.Management.Automation // to a PAL value and calls strerror_r underneath to generate the message. internal static class Unix { + // This is a helper that attempts to map errno into a PowerShell ErrorCategory + internal static ErrorCategory GetErrorCategory(int errno) + { + return (ErrorCategory)Unix.NativeMethods.GetErrorCategory(errno); + } + private static string s_userName; public static string UserName { @@ -574,6 +580,9 @@ namespace System.Management.Automation // C bools are 1 byte and so must be marshaled as I1 + [DllImport(psLib, CharSet = CharSet.Ansi)] + internal static extern int GetErrorCategory(int errno); + [DllImport(psLib, CharSet = CharSet.Ansi, SetLastError = true)] [return: MarshalAs(UnmanagedType.LPStr)] internal static extern string GetUserName(); diff --git a/src/System.Management.Automation/namespaces/FileSystemProvider.cs b/src/System.Management.Automation/namespaces/FileSystemProvider.cs index 8ea6f317e4..f04a76d5f7 100644 --- a/src/System.Management.Automation/namespaces/FileSystemProvider.cs +++ b/src/System.Management.Automation/namespaces/FileSystemProvider.cs @@ -2236,7 +2236,11 @@ namespace Microsoft.PowerShell.Commands Win32Exception w32Exception = new Win32Exception((int)errorCode); +#if UNIX + if (Platform.Unix.GetErrorCategory(errorCode) == ErrorCategory.PermissionDenied) +#else if (errorCode == 1314) //ERROR_PRIVILEGE_NOT_HELD +#endif { string message = FileSystemProviderStrings.ElevationRequired; WriteError(new ErrorRecord(new UnauthorizedAccessException(message, w32Exception), "NewItemSymbolicLinkElevationRequired", ErrorCategory.PermissionDenied, value.ToString())); diff --git a/src/libpsl-native/src/CMakeLists.txt b/src/libpsl-native/src/CMakeLists.txt index 5d4c432b40..1552ce3eec 100644 --- a/src/libpsl-native/src/CMakeLists.txt +++ b/src/libpsl-native/src/CMakeLists.txt @@ -9,6 +9,7 @@ add_library(psl-native SHARED getcomputername.cpp getlinkcount.cpp getfullyqualifiedname.cpp + geterrorcategory.cpp isfile.cpp isdirectory.cpp issymlink.cpp diff --git a/src/libpsl-native/src/geterrorcategory.cpp b/src/libpsl-native/src/geterrorcategory.cpp new file mode 100644 index 0000000000..52abf3e5dc --- /dev/null +++ b/src/libpsl-native/src/geterrorcategory.cpp @@ -0,0 +1,63 @@ +#include "geterrorcategory.h" + +#include +#include +#include +#include +#include + +// Copy of PowerShell ErrorCategory enum from ErrorPackage.cs +enum ErrorCategory { + NotSpecified = 0, + OpenError = 1, + CloseError = 2, + DeviceError = 3, + DeadlockDetected = 4, + InvalidArgument = 5, + InvalidData = 6, + InvalidOperation = 7, + InvalidResult = 8, + InvalidType = 9, + MetadataError = 10, + NotImplemented = 11, + NotInstalled = 12, + ObjectNotFound = 13, + OperationStopped = 14, + OperationTimeout = 15, + SyntaxError = 16, + ParserError = 17, + PermissionDenied = 18, + ResourceBusy = 19, + ResourceExists = 20, + ResourceUnavailable = 21, + ReadError = 22, + WriteError = 23, + FromStdErr = 24, + SecurityError = 25, + ProtocolError = 26, + ConnectionError = 27, + AuthenticationError = 28, + LimitsExceeded = 29, + QuotaExceeded = 30, + NotEnabled = 31, +}; + +//! @brief Maps Linux errno to PowerShell ErrorCategory +int32_t GetErrorCategory(int32_t errnum) +{ + switch (errnum) + { + case EINVAL: + return InvalidArgument; + case ENOENT: + case ESRCH: + return ObjectNotFound; + case EINTR: + return OperationStopped; + case EACCES: + case EPERM: + return PermissionDenied; + default: + return NotSpecified; + } +} diff --git a/src/libpsl-native/src/geterrorcategory.h b/src/libpsl-native/src/geterrorcategory.h new file mode 100644 index 0000000000..fe7a9437f4 --- /dev/null +++ b/src/libpsl-native/src/geterrorcategory.h @@ -0,0 +1,9 @@ +#pragma once + +#include "pal.h" + +PAL_BEGIN_EXTERNC + +int32_t GetErrorCategory(int32_t); + +PAL_END_EXTERNC