Switch to Win32Exception(GetLastWin32Error)

This is verified to work "correctly" on Linux in that it gets the
`perror` for the last set value of errno in native code.

No extra mapping or handling needs to be done on our part.

Keeping the strerror_r implementation in the history for the valuable
implementation of config.h.in in the library.
This commit is contained in:
Andrew Schwartzmeyer
2016-10-14 15:30:19 -07:00
parent 6c3e536ca8
commit e1aeeaa9c2
8 changed files with 11 additions and 82 deletions
@@ -4,6 +4,7 @@ Copyright (c) Microsoft Corporation. All rights reserved.
using System.Collections.Generic;
using System.Runtime.InteropServices;
using System.ComponentModel;
using Microsoft.Win32;
using Microsoft.Win32.SafeHandles;
using System.IO;
@@ -451,13 +452,15 @@ namespace System.Management.Automation
return 0;
}
// Unix specific implementations of required functionality
//
// Please note that `Win32Exception(Marshal.GetLastWin32Error())`
// works *correctly* on Linux in that it creates an exception with
// the string perror would give you for the last set value of errno.
// No manual mapping is required. .NET Core maps the Linux errno
// to a PAL value and calls strerror_r underneath to generate the message.
internal static class Unix
{
internal static string GetLastPerror()
{
return Unix.NativeMethods.GetStrError(Marshal.GetLastWin32Error());
}
private static string s_userName;
public static string UserName
{
@@ -513,8 +516,7 @@ namespace System.Management.Automation
}
else
{
int lastError = Marshal.GetLastWin32Error();
throw new InvalidOperationException("Unix.IsHardLink error: " + lastError);
throw new Win32Exception(Marshal.GetLastWin32Error());
}
}
@@ -523,8 +525,7 @@ namespace System.Management.Automation
int ret = NativeMethods.SetDate(info);
if (ret == -1)
{
int lastError = Marshal.GetLastWin32Error();
throw new InvalidOperationException("Unix.NonWindowsSetDate error: " + lastError);
throw new Win32Exception(Marshal.GetLastWin32Error());
}
}
@@ -573,10 +574,6 @@ namespace System.Management.Automation
// C bools are 1 byte and so must be marshaled as I1
[DllImport(psLib, CharSet = CharSet.Ansi)]
[return: MarshalAs(UnmanagedType.LPStr)]
internal static extern string GetStrError(int errno);
[DllImport(psLib, CharSet = CharSet.Ansi, SetLastError = true)]
[return: MarshalAs(UnmanagedType.LPStr)]
internal static extern string GetUserName();
@@ -2231,6 +2231,7 @@ namespace Microsoft.PowerShell.Commands
if (!success)
{
// Porting note: The Win32Exception will report the correct error on Linux
int errorCode = Marshal.GetLastWin32Error();
Win32Exception w32Exception = new Win32Exception((int)errorCode);
-1
View File
@@ -9,5 +9,4 @@ Testing/
test/psl-native-test
src/libpsl-native.so
src/libpsl-native.dylib
src/config.h
test/native-tests.xml
-16
View File
@@ -1,18 +1,3 @@
include(CheckCXXSourceCompiles)
check_cxx_source_compiles(
"
#include <string.h>
int main()
{
char buffer[1];
char* c = strerror_r(0, buffer, 0);
(void)c;
}
"
HAVE_GNU_STRERROR_R)
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/config.h.in ${CMAKE_CURRENT_BINARY_DIR}/config.h)
add_library(psl-native SHARED
getstat.cpp
getlstat.cpp
@@ -24,7 +9,6 @@ add_library(psl-native SHARED
getcomputername.cpp
getlinkcount.cpp
getfullyqualifiedname.cpp
getstrerror.cpp
isfile.cpp
isdirectory.cpp
issymlink.cpp
-1
View File
@@ -1 +0,0 @@
#cmakedefine HAVE_GNU_STRERROR_R 1
-40
View File
@@ -1,40 +0,0 @@
#include "getstrerror.h"
#include <assert.h>
#include <sys/types.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
char* GetStrError(int errnum)
{
size_t buflen = 256;
char* buf = (char*)calloc(buflen, sizeof(char));
// Note that we must use strerror_r because plain strerror is not
// thread-safe.
//
// However, there are two versions of strerror_r:
// - GNU: char* strerror_r(int, char*, size_t);
// - POSIX: int strerror_r(int, char*, size_t);
//
// The former may or may not use the supplied buffer, and returns
// the error message string. The latter stores the error message
// string into the supplied buffer and returns an error code.
#if HAVE_GNU_STRERROR_R
const char* ret = strerror_r(errnum, buf, buflen);
assert(ret != NULL);
if (ret != buf)
{
// message was returned but is static, copy for return
strncpy(buf, ret, buflen);
}
#else
int ret = strerror_r(errnum, buf, buflen);
// EINVAL: unknown error but reasonable message returned.
// ERANGE: too small for entire message, but still filled and null-terminated.
assert(ret == 0 || ret == EINVAL || ret == ERANGE);
#endif
return buf;
}
-9
View File
@@ -1,9 +0,0 @@
#pragma once
#include "pal.h"
PAL_BEGIN_EXTERNC
char* GetStrError(int);
PAL_END_EXTERNC
-2
View File
@@ -1,7 +1,5 @@
#pragma once
#include "config.h"
#include <stdlib.h>
#include <string.h>
#include <inttypes.h>