mirror of
https://github.com/PowerShell/PowerShell
synced 2026-06-08 12:12:50 +00:00
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:
@@ -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);
|
||||
|
||||
@@ -9,5 +9,4 @@ Testing/
|
||||
test/psl-native-test
|
||||
src/libpsl-native.so
|
||||
src/libpsl-native.dylib
|
||||
src/config.h
|
||||
test/native-tests.xml
|
||||
|
||||
@@ -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 +0,0 @@
|
||||
#cmakedefine HAVE_GNU_STRERROR_R 1
|
||||
@@ -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;
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include "pal.h"
|
||||
|
||||
PAL_BEGIN_EXTERNC
|
||||
|
||||
char* GetStrError(int);
|
||||
|
||||
PAL_END_EXTERNC
|
||||
@@ -1,7 +1,5 @@
|
||||
#pragma once
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <inttypes.h>
|
||||
|
||||
Reference in New Issue
Block a user