Replace System.Native call in Interop.Errors.cs
authorKrzysztof Wicher <kwicher@microsoft.com>
Thu, 14 May 2020 21:00:32 +0000 (14:00 -0700)
committerKrzysztof Wicher <kwicher@microsoft.com>
Thu, 14 May 2020 21:00:32 +0000 (14:00 -0700)
src/libraries/Common/src/Interop/Unix/Interop.Errors.cs
src/libraries/Native/Unix/Common/pal_error_common.h
src/libraries/Native/Unix/System.IO.Ports.Native/pal_serial.c
src/libraries/Native/Unix/System.IO.Ports.Native/pal_serial.h
src/libraries/Native/Unix/System.Native/pal_errno.c
src/libraries/System.IO.Ports/src/System.IO.Ports.csproj

index dad7962..e6de6c9 100644 (file)
@@ -182,6 +182,16 @@ internal static partial class Interop
             return Marshal.PtrToStringAnsi((IntPtr)message)!;
         }
 
+#if SERIAL_PORTS
+        [DllImport(Libraries.IOPortsNative, EntryPoint = "SystemIoPortsNative_ConvertErrorPlatformToPal")]
+        internal static extern Error ConvertErrorPlatformToPal(int platformErrno);
+
+        [DllImport(Libraries.IOPortsNative, EntryPoint = "SystemIoPortsNative_ConvertErrorPalToPlatform")]
+        internal static extern int ConvertErrorPalToPlatform(Error error);
+
+        [DllImport(Libraries.IOPortsNative, EntryPoint = "SystemIoPortsNative_StrErrorR")]
+        private static extern unsafe byte* StrErrorR(int platformErrno, byte* buffer, int bufferSize);
+#else
         [DllImport(Libraries.SystemNative, EntryPoint = "SystemNative_ConvertErrorPlatformToPal")]
         internal static extern Error ConvertErrorPlatformToPal(int platformErrno);
 
@@ -190,6 +200,7 @@ internal static partial class Interop
 
         [DllImport(Libraries.SystemNative, EntryPoint = "SystemNative_StrErrorR")]
         private static extern unsafe byte* StrErrorR(int platformErrno, byte* buffer, int bufferSize);
+#endif
     }
 }
 
index d45bc21..f185811 100644 (file)
@@ -6,7 +6,12 @@
 
 #include "pal_compiler.h"
 #include "pal_types.h"
+#include "pal_config.h"
+#include "pal_utilities.h"
+#include <string.h>
+#include <assert.h>
 #include <errno.h>
+#include <netdb.h>
 
 // ENODATA is not defined in FreeBSD 10.3 but is defined in 11.0
 #if defined(__FreeBSD__) & !defined(ENODATA)
@@ -321,3 +326,255 @@ inline static int32_t ConvertErrorPlatformToPal(int32_t platformErrno)
 
     return Error_ENONSTANDARD;
 }
+
+inline static int32_t ConvertErrorPalToPlatform(int32_t error)
+{
+    switch (error)
+    {
+        case Error_SUCCESS:
+            return 0;
+        case Error_E2BIG:
+            return E2BIG;
+        case Error_EACCES:
+            return EACCES;
+        case Error_EADDRINUSE:
+            return EADDRINUSE;
+        case Error_EADDRNOTAVAIL:
+            return EADDRNOTAVAIL;
+        case Error_EAFNOSUPPORT:
+            return EAFNOSUPPORT;
+        case Error_EAGAIN:
+            return EAGAIN;
+        case Error_EALREADY:
+            return EALREADY;
+        case Error_EBADF:
+            return EBADF;
+        case Error_EBADMSG:
+            return EBADMSG;
+        case Error_EBUSY:
+            return EBUSY;
+        case Error_ECANCELED:
+            return ECANCELED;
+        case Error_ECHILD:
+            return ECHILD;
+        case Error_ECONNABORTED:
+            return ECONNABORTED;
+        case Error_ECONNREFUSED:
+            return ECONNREFUSED;
+        case Error_ECONNRESET:
+            return ECONNRESET;
+        case Error_EDEADLK:
+            return EDEADLK;
+        case Error_EDESTADDRREQ:
+            return EDESTADDRREQ;
+        case Error_EDOM:
+            return EDOM;
+        case Error_EDQUOT:
+            return EDQUOT;
+        case Error_EEXIST:
+            return EEXIST;
+        case Error_EFAULT:
+            return EFAULT;
+        case Error_EFBIG:
+            return EFBIG;
+        case Error_EHOSTUNREACH:
+            return EHOSTUNREACH;
+        case Error_EIDRM:
+            return EIDRM;
+        case Error_EILSEQ:
+            return EILSEQ;
+        case Error_EINPROGRESS:
+            return EINPROGRESS;
+        case Error_EINTR:
+            return EINTR;
+        case Error_EINVAL:
+            return EINVAL;
+        case Error_EIO:
+            return EIO;
+        case Error_EISCONN:
+            return EISCONN;
+        case Error_EISDIR:
+            return EISDIR;
+        case Error_ELOOP:
+            return ELOOP;
+        case Error_EMFILE:
+            return EMFILE;
+        case Error_EMLINK:
+            return EMLINK;
+        case Error_EMSGSIZE:
+            return EMSGSIZE;
+        case Error_EMULTIHOP:
+            return EMULTIHOP;
+        case Error_ENAMETOOLONG:
+            return ENAMETOOLONG;
+        case Error_ENETDOWN:
+            return ENETDOWN;
+        case Error_ENETRESET:
+            return ENETRESET;
+        case Error_ENETUNREACH:
+            return ENETUNREACH;
+        case Error_ENFILE:
+            return ENFILE;
+        case Error_ENOBUFS:
+            return ENOBUFS;
+        case Error_ENODEV:
+            return ENODEV;
+        case Error_ENOENT:
+            return ENOENT;
+        case Error_ENOEXEC:
+            return ENOEXEC;
+        case Error_ENOLCK:
+            return ENOLCK;
+        case Error_ENOLINK:
+            return ENOLINK;
+        case Error_ENOMEM:
+            return ENOMEM;
+        case Error_ENOMSG:
+            return ENOMSG;
+        case Error_ENOPROTOOPT:
+            return ENOPROTOOPT;
+        case Error_ENOSPC:
+            return ENOSPC;
+        case Error_ENOSYS:
+            return ENOSYS;
+        case Error_ENOTCONN:
+            return ENOTCONN;
+        case Error_ENOTDIR:
+            return ENOTDIR;
+        case Error_ENOTEMPTY:
+            return ENOTEMPTY;
+#ifdef ENOTRECOVERABLE // not available in NetBSD
+        case Error_ENOTRECOVERABLE:
+            return ENOTRECOVERABLE;
+#endif
+        case Error_ENOTSOCK:
+            return ENOTSOCK;
+        case Error_ENOTSUP:
+            return ENOTSUP;
+        case Error_ENOTTY:
+            return ENOTTY;
+        case Error_ENXIO:
+            return ENXIO;
+        case Error_EOVERFLOW:
+            return EOVERFLOW;
+#ifdef EOWNERDEAD // not available in NetBSD
+        case Error_EOWNERDEAD:
+            return EOWNERDEAD;
+#endif
+        case Error_EPERM:
+            return EPERM;
+        case Error_EPIPE:
+            return EPIPE;
+        case Error_EPROTO:
+            return EPROTO;
+        case Error_EPROTONOSUPPORT:
+            return EPROTONOSUPPORT;
+        case Error_EPROTOTYPE:
+            return EPROTOTYPE;
+        case Error_ERANGE:
+            return ERANGE;
+        case Error_EROFS:
+            return EROFS;
+        case Error_ESPIPE:
+            return ESPIPE;
+        case Error_ESRCH:
+            return ESRCH;
+        case Error_ESTALE:
+            return ESTALE;
+        case Error_ETIMEDOUT:
+            return ETIMEDOUT;
+        case Error_ETXTBSY:
+            return ETXTBSY;
+        case Error_EXDEV:
+            return EXDEV;
+        case Error_EPFNOSUPPORT:
+            return EPFNOSUPPORT;
+#ifdef ESOCKTNOSUPPORT
+        case Error_ESOCKTNOSUPPORT:
+            return ESOCKTNOSUPPORT;
+#endif
+        case Error_ESHUTDOWN:
+            return ESHUTDOWN;
+        case Error_EHOSTDOWN:
+            return EHOSTDOWN;
+        case Error_ENODATA:
+            return ENODATA;
+        case Error_EHOSTNOTFOUND:
+            return -(Error_EHOSTNOTFOUND);
+        case Error_ENONSTANDARD:
+            break; // fall through to assert
+    }
+
+    // We should not use this function to round-trip platform -> pal
+    // -> platform. It's here only to synthesize a platform number
+    // from the fixed set above. Note that the assert is outside the
+    // switch rather than in a default case block because not
+    // having a default will trigger a warning (as error) if there's
+    // an enum value we haven't handled. Should that trigger, make
+    // note that there is probably a corresponding missing case in the
+    // other direction above, but the compiler can't warn in that case
+    // because the platform values are not part of an enum.
+    assert_err(false, "Unknown error code", (int) error);
+    return -1;
+}
+
+static int32_t ConvertErrorPalToGai(int32_t error)
+{
+    switch (error)
+    {
+        case -(Error_EHOSTNOTFOUND):
+            return EAI_NONAME;
+    }
+    // Fall-through for unknown codes. gai_strerror() will handle that.
+
+    return error;
+}
+
+
+
+inline static const char* StrErrorR(int32_t platformErrno, char* buffer, int32_t bufferSize)
+{
+    assert(buffer != NULL);
+    assert(bufferSize > 0);
+
+    if (bufferSize < 0)
+        return NULL;
+
+    if (platformErrno < 0)
+    {
+        // Not a system error
+        SafeStringCopy(buffer, (size_t)bufferSize, gai_strerror(ConvertErrorPalToGai(platformErrno)));
+        return buffer;
+    }
+
+// 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* message = strerror_r(platformErrno, buffer, (uint32_t) bufferSize);
+    assert(message != NULL);
+    return message;
+#else
+    int error = strerror_r(platformErrno, buffer, (uint32_t) bufferSize);
+    if (error == ERANGE)
+    {
+        // Buffer is too small to hold the entire message, but has
+        // still been filled to the extent possible and null-terminated.
+        return NULL;
+    }
+
+    // The only other valid error codes are 0 for success or EINVAL for
+    // an unknown error, but in the latter case a reasonable string (e.g
+    // "Unknown error: 0x123") is returned.
+    assert_err(error == 0 || error == EINVAL, "invalid error", error);
+    return buffer;
+#endif
+}
index 9eceb7e..4a4babd 100644 (file)
@@ -72,3 +72,18 @@ int32_t SystemIoPortsNative_Shutdown(intptr_t socket, int32_t socketShutdown)
 {
     return Common_Shutdown(socket, socketShutdown);
 }
+
+int32_t SystemIoPortsNative_ConvertErrorPlatformToPal(int32_t platformErrno)
+{
+    return ConvertErrorPlatformToPal(platformErrno);
+}
+
+int32_t SystemIoPortsNative_ConvertErrorPalToPlatform(int32_t error)
+{
+    return ConvertErrorPalToPlatform(error);
+}
+
+const char* SystemIoPortsNative_StrErrorR(int32_t platformErrno, char* buffer, int32_t bufferSize)
+{
+    return StrErrorR(platformErrno, buffer, bufferSize);
+}
index 30a2d24..371ceba 100644 (file)
@@ -4,10 +4,12 @@
 
 #include <pal_io_common.h>
 
-
 PALEXPORT intptr_t SystemIoPortsNative_SerialPortOpen(const char * name);
 PALEXPORT int SystemIoPortsNative_SerialPortClose(intptr_t fd);
 PALEXPORT int32_t SystemIoPortsNative_Read(intptr_t fd, void* buffer, int32_t bufferSize);
 PALEXPORT int32_t SystemIoPortsNative_Write(intptr_t fd, const void* buffer, int32_t bufferSize);
 PALEXPORT int32_t SystemIoPortsNative_Poll(PollEvent* pollEvents, uint32_t eventCount, int32_t milliseconds, uint32_t* triggered);
 PALEXPORT int32_t SystemIoPortsNative_Shutdown(intptr_t socket, int32_t socketShutdown);
+PALEXPORT int32_t SystemIoPortsNative_ConvertErrorPlatformToPal(int32_t platformErrno);
+PALEXPORT int32_t SystemIoPortsNative_ConvertErrorPalToPlatform(int32_t error);
+PALEXPORT const char* SystemIoPortsNative_StrErrorR(int32_t platformErrno, char* buffer, int32_t bufferSize);
index 9ee754b..b0da1ec 100644 (file)
@@ -2,13 +2,7 @@
 // The .NET Foundation licenses this file to you under the MIT license.
 // See the LICENSE file in the project root for more information.
 
-#include "pal_config.h"
 #include "pal_errno.h"
-#include "pal_utilities.h"
-
-#include <netdb.h>
-#include <string.h>
-#include <assert.h>
 
 int32_t SystemNative_ConvertErrorPlatformToPal(int32_t platformErrno)
 {
@@ -17,252 +11,10 @@ int32_t SystemNative_ConvertErrorPlatformToPal(int32_t platformErrno)
 
 int32_t SystemNative_ConvertErrorPalToPlatform(int32_t error)
 {
-    switch (error)
-    {
-        case Error_SUCCESS:
-            return 0;
-        case Error_E2BIG:
-            return E2BIG;
-        case Error_EACCES:
-            return EACCES;
-        case Error_EADDRINUSE:
-            return EADDRINUSE;
-        case Error_EADDRNOTAVAIL:
-            return EADDRNOTAVAIL;
-        case Error_EAFNOSUPPORT:
-            return EAFNOSUPPORT;
-        case Error_EAGAIN:
-            return EAGAIN;
-        case Error_EALREADY:
-            return EALREADY;
-        case Error_EBADF:
-            return EBADF;
-        case Error_EBADMSG:
-            return EBADMSG;
-        case Error_EBUSY:
-            return EBUSY;
-        case Error_ECANCELED:
-            return ECANCELED;
-        case Error_ECHILD:
-            return ECHILD;
-        case Error_ECONNABORTED:
-            return ECONNABORTED;
-        case Error_ECONNREFUSED:
-            return ECONNREFUSED;
-        case Error_ECONNRESET:
-            return ECONNRESET;
-        case Error_EDEADLK:
-            return EDEADLK;
-        case Error_EDESTADDRREQ:
-            return EDESTADDRREQ;
-        case Error_EDOM:
-            return EDOM;
-        case Error_EDQUOT:
-            return EDQUOT;
-        case Error_EEXIST:
-            return EEXIST;
-        case Error_EFAULT:
-            return EFAULT;
-        case Error_EFBIG:
-            return EFBIG;
-        case Error_EHOSTUNREACH:
-            return EHOSTUNREACH;
-        case Error_EIDRM:
-            return EIDRM;
-        case Error_EILSEQ:
-            return EILSEQ;
-        case Error_EINPROGRESS:
-            return EINPROGRESS;
-        case Error_EINTR:
-            return EINTR;
-        case Error_EINVAL:
-            return EINVAL;
-        case Error_EIO:
-            return EIO;
-        case Error_EISCONN:
-            return EISCONN;
-        case Error_EISDIR:
-            return EISDIR;
-        case Error_ELOOP:
-            return ELOOP;
-        case Error_EMFILE:
-            return EMFILE;
-        case Error_EMLINK:
-            return EMLINK;
-        case Error_EMSGSIZE:
-            return EMSGSIZE;
-        case Error_EMULTIHOP:
-            return EMULTIHOP;
-        case Error_ENAMETOOLONG:
-            return ENAMETOOLONG;
-        case Error_ENETDOWN:
-            return ENETDOWN;
-        case Error_ENETRESET:
-            return ENETRESET;
-        case Error_ENETUNREACH:
-            return ENETUNREACH;
-        case Error_ENFILE:
-            return ENFILE;
-        case Error_ENOBUFS:
-            return ENOBUFS;
-        case Error_ENODEV:
-            return ENODEV;
-        case Error_ENOENT:
-            return ENOENT;
-        case Error_ENOEXEC:
-            return ENOEXEC;
-        case Error_ENOLCK:
-            return ENOLCK;
-        case Error_ENOLINK:
-            return ENOLINK;
-        case Error_ENOMEM:
-            return ENOMEM;
-        case Error_ENOMSG:
-            return ENOMSG;
-        case Error_ENOPROTOOPT:
-            return ENOPROTOOPT;
-        case Error_ENOSPC:
-            return ENOSPC;
-        case Error_ENOSYS:
-            return ENOSYS;
-        case Error_ENOTCONN:
-            return ENOTCONN;
-        case Error_ENOTDIR:
-            return ENOTDIR;
-        case Error_ENOTEMPTY:
-            return ENOTEMPTY;
-#ifdef ENOTRECOVERABLE // not available in NetBSD
-        case Error_ENOTRECOVERABLE:
-            return ENOTRECOVERABLE;
-#endif
-        case Error_ENOTSOCK:
-            return ENOTSOCK;
-        case Error_ENOTSUP:
-            return ENOTSUP;
-        case Error_ENOTTY:
-            return ENOTTY;
-        case Error_ENXIO:
-            return ENXIO;
-        case Error_EOVERFLOW:
-            return EOVERFLOW;
-#ifdef EOWNERDEAD // not available in NetBSD
-        case Error_EOWNERDEAD:
-            return EOWNERDEAD;
-#endif
-        case Error_EPERM:
-            return EPERM;
-        case Error_EPIPE:
-            return EPIPE;
-        case Error_EPROTO:
-            return EPROTO;
-        case Error_EPROTONOSUPPORT:
-            return EPROTONOSUPPORT;
-        case Error_EPROTOTYPE:
-            return EPROTOTYPE;
-        case Error_ERANGE:
-            return ERANGE;
-        case Error_EROFS:
-            return EROFS;
-        case Error_ESPIPE:
-            return ESPIPE;
-        case Error_ESRCH:
-            return ESRCH;
-        case Error_ESTALE:
-            return ESTALE;
-        case Error_ETIMEDOUT:
-            return ETIMEDOUT;
-        case Error_ETXTBSY:
-            return ETXTBSY;
-        case Error_EXDEV:
-            return EXDEV;
-        case Error_EPFNOSUPPORT:
-            return EPFNOSUPPORT;
-#ifdef ESOCKTNOSUPPORT
-        case Error_ESOCKTNOSUPPORT:
-            return ESOCKTNOSUPPORT;
-#endif
-        case Error_ESHUTDOWN:
-            return ESHUTDOWN;
-        case Error_EHOSTDOWN:
-            return EHOSTDOWN;
-        case Error_ENODATA:
-            return ENODATA;
-        case Error_EHOSTNOTFOUND:
-            return -(Error_EHOSTNOTFOUND);
-        case Error_ENONSTANDARD:
-            break; // fall through to assert
-    }
-
-    // We should not use this function to round-trip platform -> pal
-    // -> platform. It's here only to synthesize a platform number
-    // from the fixed set above. Note that the assert is outside the
-    // switch rather than in a default case block because not
-    // having a default will trigger a warning (as error) if there's
-    // an enum value we haven't handled. Should that trigger, make
-    // note that there is probably a corresponding missing case in the
-    // other direction above, but the compiler can't warn in that case
-    // because the platform values are not part of an enum.
-    assert_err(false, "Unknown error code", (int) error);
-    return -1;
+    return ConvertErrorPalToPlatform(error);
 }
 
-static int32_t SystemNative_ConvertErrorPalToGai(int32_t error)
-{
-    switch (error)
-    {
-        case -(Error_EHOSTNOTFOUND):
-            return EAI_NONAME;
-    }
-    // Fall-through for unknown codes. gai_strerror() will handle that.
-
-    return error;
-}
-
-
-
 const char* SystemNative_StrErrorR(int32_t platformErrno, char* buffer, int32_t bufferSize)
 {
-    assert(buffer != NULL);
-    assert(bufferSize > 0);
-
-    if (bufferSize < 0)
-        return NULL;
-
-    if (platformErrno < 0)
-    {
-        // Not a system error
-        SafeStringCopy(buffer, (size_t)bufferSize, gai_strerror(SystemNative_ConvertErrorPalToGai(platformErrno)));
-        return buffer;
-    }
-
-// 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* message = strerror_r(platformErrno, buffer, (uint32_t) bufferSize);
-    assert(message != NULL);
-    return message;
-#else
-    int error = strerror_r(platformErrno, buffer, (uint32_t) bufferSize);
-    if (error == ERANGE)
-    {
-        // Buffer is too small to hold the entire message, but has
-        // still been filled to the extent possible and null-terminated.
-        return NULL;
-    }
-
-    // The only other valid error codes are 0 for success or EINVAL for
-    // an unknown error, but in the latter case a reasonable string (e.g
-    // "Unknown error: 0x123") is returned.
-    assert_err(error == 0 || error == EINVAL, "invalid error", error);
-    return buffer;
-#endif
+    return StrErrorR(platformErrno, buffer, bufferSize);
 }
index abd8646..d29ea8f 100644 (file)
@@ -1,7 +1,7 @@
 <Project Sdk="Microsoft.NET.Sdk">
   <PropertyGroup>
     <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
-    <DefineConstants>$(DefineConstants);NOSPAN</DefineConstants>
+    <DefineConstants>$(DefineConstants);NOSPAN;SERIAL_PORTS</DefineConstants>
     <IncludeDllSafeSearchPathAttribute>true</IncludeDllSafeSearchPathAttribute>
     <Nullable>annotations</Nullable>
     <TargetFrameworks>netstandard2.0-Windows_NT;netstandard2.0-Linux;netstandard2.0-OSX;netstandard2.0;net461-Windows_NT;netstandard2.0-FreeBSD;$(NetFrameworkCurrent)-Windows_NT</TargetFrameworks>