123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553 |
- #include "il2cpp-config.h"
- #include "pal_platform.h"
- #if IL2CPP_USES_POSIX_CLASS_LIBRARY_PAL
- #include <errno.h>
- extern "C"
- {
- // Items needed by mscorlib
- IL2CPP_EXPORT int32_t SystemNative_ConvertErrorPlatformToPal(int32_t platformErrno);
- IL2CPP_EXPORT const char* SystemNative_StrErrorR(int32_t platformErrno, char* buffer, int32_t bufferSize);
- IL2CPP_EXPORT int32_t SystemNative_ConvertErrorPalToPlatform(int32_t error);
- }
- /**
- * Error codes returned via ConvertErrno.
- *
- * Only the names (without the PAL_ prefix) are specified by POSIX.
- *
- * The values chosen below are simply assigned arbitrarily (originally
- * in alphabetical order they appear in the spec, but they can't change so
- * add new values to the end!).
- *
- * Also, the values chosen are deliberately outside the range of
- * typical UNIX errnos (small numbers), HRESULTs (negative for errors)
- * and Win32 errors (0x0000 - 0xFFFF). This isn't required for
- * correctness, but may help debug a caller that is interpreting a raw
- * int incorrectly.
- *
- * Wherever the spec says "x may be the same value as y", we do use
- * the same value so that callers cannot not take a dependency on
- * being able to distinguish between them.
- */
- enum Error
- {
- Error_SUCCESS = 0,
- Error_E2BIG = 0x10001, // Argument list too long.
- Error_EACCES = 0x10002, // Permission denied.
- Error_EADDRINUSE = 0x10003, // Address in use.
- Error_EADDRNOTAVAIL = 0x10004, // Address not available.
- Error_EAFNOSUPPORT = 0x10005, // Address family not supported.
- Error_EAGAIN = 0x10006, // Resource unavailable, try again (same value as EWOULDBLOCK),
- Error_EALREADY = 0x10007, // Connection already in progress.
- Error_EBADF = 0x10008, // Bad file descriptor.
- Error_EBADMSG = 0x10009, // Bad message.
- Error_EBUSY = 0x1000A, // Device or resource busy.
- Error_ECANCELED = 0x1000B, // Operation canceled.
- Error_ECHILD = 0x1000C, // No child processes.
- Error_ECONNABORTED = 0x1000D, // Connection aborted.
- Error_ECONNREFUSED = 0x1000E, // Connection refused.
- Error_ECONNRESET = 0x1000F, // Connection reset.
- Error_EDEADLK = 0x10010, // Resource deadlock would occur.
- Error_EDESTADDRREQ = 0x10011, // Destination address required.
- Error_EDOM = 0x10012, // Mathematics argument out of domain of function.
- Error_EDQUOT = 0x10013, // Reserved.
- Error_EEXIST = 0x10014, // File exists.
- Error_EFAULT = 0x10015, // Bad address.
- Error_EFBIG = 0x10016, // File too large.
- Error_EHOSTUNREACH = 0x10017, // Host is unreachable.
- Error_EIDRM = 0x10018, // Identifier removed.
- Error_EILSEQ = 0x10019, // Illegal byte sequence.
- Error_EINPROGRESS = 0x1001A, // Operation in progress.
- Error_EINTR = 0x1001B, // Interrupted function.
- Error_EINVAL = 0x1001C, // Invalid argument.
- Error_EIO = 0x1001D, // I/O error.
- Error_EISCONN = 0x1001E, // Socket is connected.
- Error_EISDIR = 0x1001F, // Is a directory.
- Error_ELOOP = 0x10020, // Too many levels of symbolic links.
- Error_EMFILE = 0x10021, // File descriptor value too large.
- Error_EMLINK = 0x10022, // Too many links.
- Error_EMSGSIZE = 0x10023, // Message too large.
- Error_EMULTIHOP = 0x10024, // Reserved.
- Error_ENAMETOOLONG = 0x10025, // Filename too long.
- Error_ENETDOWN = 0x10026, // Network is down.
- Error_ENETRESET = 0x10027, // Connection aborted by network.
- Error_ENETUNREACH = 0x10028, // Network unreachable.
- Error_ENFILE = 0x10029, // Too many files open in system.
- Error_ENOBUFS = 0x1002A, // No buffer space available.
- Error_ENODEV = 0x1002C, // No such device.
- Error_ENOENT = 0x1002D, // No such file or directory.
- Error_ENOEXEC = 0x1002E, // Executable file format error.
- Error_ENOLCK = 0x1002F, // No locks available.
- Error_ENOLINK = 0x10030, // Reserved.
- Error_ENOMEM = 0x10031, // Not enough space.
- Error_ENOMSG = 0x10032, // No message of the desired type.
- Error_ENOPROTOOPT = 0x10033, // Protocol not available.
- Error_ENOSPC = 0x10034, // No space left on device.
- Error_ENOSYS = 0x10037, // Function not supported.
- Error_ENOTCONN = 0x10038, // The socket is not connected.
- Error_ENOTDIR = 0x10039, // Not a directory or a symbolic link to a directory.
- Error_ENOTEMPTY = 0x1003A, // Directory not empty.
- Error_ENOTRECOVERABLE = 0x1003B, // State not recoverable.
- Error_ENOTSOCK = 0x1003C, // Not a socket.
- Error_ENOTSUP = 0x1003D, // Not supported (same value as EOPNOTSUP).
- Error_ENOTTY = 0x1003E, // Inappropriate I/O control operation.
- Error_ENXIO = 0x1003F, // No such device or address.
- Error_EOVERFLOW = 0x10040, // Value too large to be stored in data type.
- Error_EOWNERDEAD = 0x10041, // Previous owner died.
- Error_EPERM = 0x10042, // Operation not permitted.
- Error_EPIPE = 0x10043, // Broken pipe.
- Error_EPROTO = 0x10044, // Protocol error.
- Error_EPROTONOSUPPORT = 0x10045, // Protocol not supported.
- Error_EPROTOTYPE = 0x10046, // Protocol wrong type for socket.
- Error_ERANGE = 0x10047, // Result too large.
- Error_EROFS = 0x10048, // Read-only file system.
- Error_ESPIPE = 0x10049, // Invalid seek.
- Error_ESRCH = 0x1004A, // No such process.
- Error_ESTALE = 0x1004B, // Reserved.
- Error_ETIMEDOUT = 0x1004D, // Connection timed out.
- Error_ETXTBSY = 0x1004E, // Text file busy.
- Error_EXDEV = 0x1004F, // Cross-device link.
- Error_ESOCKTNOSUPPORT = 0x1005E, // Socket type not supported.
- Error_EPFNOSUPPORT = 0x10060, // Protocol family not supported.
- Error_ESHUTDOWN = 0x1006C, // Socket shutdown.
- Error_EHOSTDOWN = 0x10070, // Host is down.
- Error_ENODATA = 0x10071, // No data available.
- // POSIX permits these to have the same value and we make them
- // always equal so that we cannot introduce a dependency on
- // distinguishing between them that would not work on all
- // platforms.
- Error_EOPNOTSUPP = Error_ENOTSUP, // Operation not supported on socket
- Error_EWOULDBLOCK = Error_EAGAIN, // Operation would block
- // This one is not part of POSIX, but is a catch-all for the case
- // where we cannot convert the raw errno value to something above.
- Error_ENONSTANDARD = 0x1FFFF,
- };
- // Items needed by mscorlib
- int32_t SystemNative_ConvertErrorPlatformToPal(int32_t platformErrno)
- {
- switch (platformErrno)
- {
- case 0:
- return Error_SUCCESS;
- case E2BIG:
- return Error_E2BIG;
- case EACCES:
- return Error_EACCES;
- case EADDRINUSE:
- return Error_EADDRINUSE;
- case EADDRNOTAVAIL:
- return Error_EADDRNOTAVAIL;
- case EAFNOSUPPORT:
- return Error_EAFNOSUPPORT;
- case EAGAIN:
- return Error_EAGAIN;
- case EALREADY:
- return Error_EALREADY;
- case EBADF:
- return Error_EBADF;
- case EBADMSG:
- return Error_EBADMSG;
- case EBUSY:
- return Error_EBUSY;
- case ECANCELED:
- return Error_ECANCELED;
- case ECHILD:
- return Error_ECHILD;
- case ECONNABORTED:
- return Error_ECONNABORTED;
- case ECONNREFUSED:
- return Error_ECONNREFUSED;
- case ECONNRESET:
- return Error_ECONNRESET;
- case EDEADLK:
- return Error_EDEADLK;
- case EDESTADDRREQ:
- return Error_EDESTADDRREQ;
- case EDOM:
- return Error_EDOM;
- case EDQUOT:
- return Error_EDQUOT;
- case EEXIST:
- return Error_EEXIST;
- case EFAULT:
- return Error_EFAULT;
- case EFBIG:
- return Error_EFBIG;
- case EHOSTUNREACH:
- return Error_EHOSTUNREACH;
- case EIDRM:
- return Error_EIDRM;
- case EILSEQ:
- return Error_EILSEQ;
- case EINPROGRESS:
- return Error_EINPROGRESS;
- case EINTR:
- return Error_EINTR;
- case EINVAL:
- return Error_EINVAL;
- case EIO:
- return Error_EIO;
- case EISCONN:
- return Error_EISCONN;
- case EISDIR:
- return Error_EISDIR;
- case ELOOP:
- return Error_ELOOP;
- case EMFILE:
- return Error_EMFILE;
- case EMLINK:
- return Error_EMLINK;
- case EMSGSIZE:
- return Error_EMSGSIZE;
- case EMULTIHOP:
- return Error_EMULTIHOP;
- case ENAMETOOLONG:
- return Error_ENAMETOOLONG;
- case ENETDOWN:
- return Error_ENETDOWN;
- case ENETRESET:
- return Error_ENETRESET;
- case ENETUNREACH:
- return Error_ENETUNREACH;
- case ENFILE:
- return Error_ENFILE;
- case ENOBUFS:
- return Error_ENOBUFS;
- case ENODEV:
- return Error_ENODEV;
- case ENOENT:
- return Error_ENOENT;
- case ENOEXEC:
- return Error_ENOEXEC;
- case ENOLCK:
- return Error_ENOLCK;
- case ENOLINK:
- return Error_ENOLINK;
- case ENOMEM:
- return Error_ENOMEM;
- case ENOMSG:
- return Error_ENOMSG;
- case ENOPROTOOPT:
- return Error_ENOPROTOOPT;
- case ENOSPC:
- return Error_ENOSPC;
- case ENOSYS:
- return Error_ENOSYS;
- case ENOTCONN:
- return Error_ENOTCONN;
- case ENOTDIR:
- return Error_ENOTDIR;
- #if ENOTEMPTY != EEXIST // AIX defines this
- case ENOTEMPTY:
- return Error_ENOTEMPTY;
- #endif
- #ifdef ENOTRECOVERABLE // not available in NetBSD
- case ENOTRECOVERABLE:
- return Error_ENOTRECOVERABLE;
- #endif
- case ENOTSOCK:
- return Error_ENOTSOCK;
- case ENOTSUP:
- return Error_ENOTSUP;
- case ENOTTY:
- return Error_ENOTTY;
- case ENXIO:
- return Error_ENXIO;
- case EOVERFLOW:
- return Error_EOVERFLOW;
- #ifdef EOWNERDEAD // not available in NetBSD
- case EOWNERDEAD:
- return Error_EOWNERDEAD;
- #endif
- case EPERM:
- return Error_EPERM;
- case EPIPE:
- return Error_EPIPE;
- case EPROTO:
- return Error_EPROTO;
- case EPROTONOSUPPORT:
- return Error_EPROTONOSUPPORT;
- case EPROTOTYPE:
- return Error_EPROTOTYPE;
- case ERANGE:
- return Error_ERANGE;
- case EROFS:
- return Error_EROFS;
- case ESPIPE:
- return Error_ESPIPE;
- case ESRCH:
- return Error_ESRCH;
- case ESTALE:
- return Error_ESTALE;
- case ETIMEDOUT:
- return Error_ETIMEDOUT;
- case ETXTBSY:
- return Error_ETXTBSY;
- case EXDEV:
- return Error_EXDEV;
- #ifdef ESOCKTNOSUPPORT
- case ESOCKTNOSUPPORT:
- return Error_ESOCKTNOSUPPORT;
- #endif
- case EPFNOSUPPORT:
- return Error_EPFNOSUPPORT;
- case ESHUTDOWN:
- return Error_ESHUTDOWN;
- case EHOSTDOWN:
- return Error_EHOSTDOWN;
- case ENODATA:
- return Error_ENODATA;
- // #if because these will trigger duplicate case label warnings when
- // they have the same value, which is permitted by POSIX and common.
- #if EOPNOTSUPP != ENOTSUP
- case EOPNOTSUPP:
- return Error_EOPNOTSUPP;
- #endif
- #if EWOULDBLOCK != EAGAIN
- case EWOULDBLOCK:
- return Error_EWOULDBLOCK;
- #endif
- }
- return Error_ENONSTANDARD;
- }
- const char* SystemNative_StrErrorR(int32_t platformErrno, char* buffer, int32_t bufferSize)
- {
- IL2CPP_ASSERT(buffer != NULL);
- IL2CPP_ASSERT(bufferSize > 0);
- if (bufferSize < 0)
- return NULL;
- // 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 IL2CPP_HAVE_GNU_STRERROR_R
- const char* message = strerror_r(platformErrno, buffer, (uint32_t)bufferSize);
- IL2CPP_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.
- IL2CPP_ASSERT((error == 0 || error == EINVAL) && "invalid error");
- return buffer;
- #endif
- }
- 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_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.
- IL2CPP_ASSERT(0 && "Unknown error code");
- return -1;
- }
- #endif
|