diff options
author | Calvin <calvin@cmpct.info> | 2018-06-10 11:39:25 +0300 |
---|---|---|
committer | Alexander Köplinger <alex.koeplinger@outlook.com> | 2018-06-10 11:39:25 +0300 |
commit | 62eb6bea5f339913711571c14018e4e2eb790781 (patch) | |
tree | fc5da516c5a4704177213471c98fa363da169818 | |
parent | 05a53870334c668fa6b6cdec39c3972b5ed0284d (diff) |
Attempt at AIX support for CoreFX PAL (#79)
This is a manual cherry pick of the commit due to differences in
cmake files preventing a clean merge of the normal patch. The
commit applied can be found at:
dotnet/corefx@eedd1c2784fd1c597428187985df00567bc00f86
More work will likely need to be done as more is backported and PAL
changes. In addition, the submodule will need to be updated as well.
Hopefully AIX CI should light up after that though!
-rw-r--r-- | src/Native/Unix/Common/pal_config.h.in | 4 | ||||
-rw-r--r-- | src/Native/Unix/System.Native/pal_errno.c | 2 | ||||
-rw-r--r-- | src/Native/Unix/System.Native/pal_io.c | 134 | ||||
-rw-r--r-- | src/Native/Unix/System.Native/pal_maphardwaretype.c | 2 | ||||
-rw-r--r-- | src/Native/Unix/System.Native/pal_networking.c | 36 | ||||
-rw-r--r-- | src/Native/Unix/System.Native/pal_random.c | 5 |
6 files changed, 179 insertions, 4 deletions
diff --git a/src/Native/Unix/Common/pal_config.h.in b/src/Native/Unix/Common/pal_config.h.in index 157cb4bf78..2501a6a31d 100644 --- a/src/Native/Unix/Common/pal_config.h.in +++ b/src/Native/Unix/Common/pal_config.h.in @@ -6,6 +6,9 @@ #cmakedefine01 HAVE_FTRUNCATE64 #cmakedefine01 HAVE_POSIX_FADVISE64 #cmakedefine01 HAVE_FLOCK64 +#cmakedefine01 HAVE_F_DUPFD_CLOEXEC +#cmakedefine01 HAVE_O_CLOEXEC +#cmakedefine01 HAVE_GETIFADDRS #cmakedefine01 HAVE_STAT64 #cmakedefine01 HAVE_PIPE2 #cmakedefine01 HAVE_STAT_BIRTHTIME @@ -33,6 +36,7 @@ #cmakedefine01 HAVE_FDS_BITS #cmakedefine01 HAVE_PRIVATE_FDS_BITS #cmakedefine01 HAVE_STATFS +#cmakedefine01 HAVE_SYS_POLL_H #cmakedefine01 HAVE_EPOLL #cmakedefine01 HAVE_ACCEPT4 #cmakedefine01 HAVE_KQUEUE diff --git a/src/Native/Unix/System.Native/pal_errno.c b/src/Native/Unix/System.Native/pal_errno.c index 3a7972369c..996d777da0 100644 --- a/src/Native/Unix/System.Native/pal_errno.c +++ b/src/Native/Unix/System.Native/pal_errno.c @@ -130,8 +130,10 @@ int32_t SystemNative_ConvertErrorPlatformToPal(int32_t platformErrno) 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; diff --git a/src/Native/Unix/System.Native/pal_io.c b/src/Native/Unix/System.Native/pal_io.c index 320dccd4e8..acb0097347 100644 --- a/src/Native/Unix/System.Native/pal_io.c +++ b/src/Native/Unix/System.Native/pal_io.c @@ -2,6 +2,11 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#ifdef _AIX +// For getline (declare this before stdio) +#define _GETDELIM 1 +#endif + #include "pal_compiler.h" #include "pal_config.h" #include "pal_errno.h" @@ -37,6 +42,13 @@ #include <sys/inotify.h> #endif +#ifdef _AIX +#include <alloca.h> +// Somehow, AIX mangles the definition for this behind a C++ def +// Redeclare it here +extern int getpeereid(int, uid_t *__restrict__, gid_t *__restrict__); +#endif + #if HAVE_STAT64 #define stat_ stat64 #define fstat_ fstat64 @@ -78,6 +90,8 @@ c_static_assert(PAL_S_IFSOCK == S_IFSOCK); // Validate that our enum for inode types is the same as what is // declared by the dirent.h header on the local system. +// (AIX doesn't have dirent d_type, so none of this there) +#if defined(DT_UNKNOWN) c_static_assert(PAL_DT_UNKNOWN == DT_UNKNOWN); c_static_assert(PAL_DT_FIFO == DT_FIFO); c_static_assert(PAL_DT_CHR == DT_CHR); @@ -87,6 +101,7 @@ c_static_assert(PAL_DT_REG == DT_REG); c_static_assert(PAL_DT_LNK == DT_LNK); c_static_assert(PAL_DT_SOCK == DT_SOCK); c_static_assert(PAL_DT_WHT == DT_WHT); +#endif // Validate that our Lock enum value are correct for the platform c_static_assert(PAL_LOCK_SH == LOCK_SH); @@ -106,12 +121,15 @@ c_static_assert(PAL_SEEK_CUR == SEEK_CUR); c_static_assert(PAL_SEEK_END == SEEK_END); // Validate our PollFlags enum values are correct for the platform +// HACK: AIX values are different; we convert them between PAL_POLL and POLL now +#ifndef _AIX c_static_assert(PAL_POLLIN == POLLIN); c_static_assert(PAL_POLLPRI == POLLPRI); c_static_assert(PAL_POLLOUT == POLLOUT); c_static_assert(PAL_POLLERR == POLLERR); c_static_assert(PAL_POLLHUP == POLLHUP); c_static_assert(PAL_POLLNVAL == POLLNVAL); +#endif // Validate our FileAdvice enum values are correct for the platform #if HAVE_POSIX_ADVISE @@ -239,8 +257,10 @@ static int32_t ConvertOpenFlags(int32_t flags) return -1; } +#if HAVE_O_CLOEXEC if (flags & PAL_O_CLOEXEC) ret |= O_CLOEXEC; +#endif if (flags & PAL_O_CREAT) ret |= O_CREAT; if (flags & PAL_O_EXCL) @@ -256,6 +276,11 @@ static int32_t ConvertOpenFlags(int32_t flags) intptr_t SystemNative_Open(const char* path, int32_t flags, int32_t mode) { +// these two ifdefs are for platforms where we dont have the open version of CLOEXEC and thus +// must simulate it by doing a fcntl with the SETFFD version after the open instead +#if !HAVE_O_CLOEXEC + int32_t old_flags = flags; +#endif flags = ConvertOpenFlags(flags); if (flags == -1) { @@ -265,6 +290,12 @@ intptr_t SystemNative_Open(const char* path, int32_t flags, int32_t mode) int result; while ((result = open(path, flags, (mode_t)mode)) < 0 && errno == EINTR); +#if !HAVE_O_CLOEXEC + if (old_flags & PAL_O_CLOEXEC) + { + fcntl(result, F_SETFD, FD_CLOEXEC); + } +#endif return result; } @@ -276,7 +307,13 @@ int32_t SystemNative_Close(intptr_t fd) intptr_t SystemNative_Dup(intptr_t oldfd) { int result; +#if HAVE_F_DUPFD_CLOEXEC while ((result = fcntl(ToFileDescriptor(oldfd), F_DUPFD_CLOEXEC, 0)) < 0 && errno == EINTR); +#else + while ((result = fcntl(ToFileDescriptor(oldfd), F_DUPFD, 0)) < 0 && errno == EINTR); + // do CLOEXEC here too + fcntl(result, F_SETFD, FD_CLOEXEC); +#endif return result; } @@ -325,7 +362,45 @@ static void ConvertDirent(const struct dirent* entry, struct DirectoryEntry* out // the start of the unmanaged string. Give the caller back a pointer to the // location of the start of the string that exists in their own byte buffer. outputEntry->Name = entry->d_name; +#if !defined(DT_UNKNOWN) + /* AIX has no d_type, make a substitute */ + struct stat s; + stat(entry->d_name, &s); + if (S_ISDIR(s.st_mode)) + { + outputEntry->InodeType = PAL_DT_DIR; + } + else if (S_ISFIFO(s.st_mode)) + { + outputEntry->InodeType = PAL_DT_FIFO; + } + else if (S_ISCHR(s.st_mode)) + { + outputEntry->InodeType = PAL_DT_CHR; + } + else if (S_ISBLK(s.st_mode)) + { + outputEntry->InodeType = PAL_DT_BLK; + } + else if (S_ISREG(s.st_mode)) + { + outputEntry->InodeType = PAL_DT_REG; + } + else if (S_ISLNK(s.st_mode)) + { + outputEntry->InodeType = PAL_DT_LNK; + } + else if (S_ISSOCK(s.st_mode)) + { + outputEntry->InodeType = PAL_DT_SOCK; + } + else + { + outputEntry->InodeType = PAL_DT_UNKNOWN; + } +#else outputEntry->InodeType = (int32_t)entry->d_type; +#endif #if HAVE_DIRENT_NAME_LEN outputEntry->NameLength = entry->d_namlen; @@ -435,7 +510,9 @@ int32_t SystemNative_Pipe(int32_t pipeFds[2], int32_t flags) case 0: break; case PAL_O_CLOEXEC: +#if HAVE_O_CLOEXEC flags = O_CLOEXEC; +#endif break; default: assert_msg(false, "Unknown pipe flag", (int)flags); @@ -452,7 +529,11 @@ int32_t SystemNative_Pipe(int32_t pipeFds[2], int32_t flags) while ((result = pipe(pipeFds)) < 0 && errno == EINTR); // Then, if O_CLOEXEC was specified, use fcntl to configure the file descriptors appropriately. +#if HAVE_O_CLOEXEC if ((flags & O_CLOEXEC) != 0 && result == 0) +#else + if ((flags & PAL_O_CLOEXEC) != 0 && result == 0) +#endif { while ((result = fcntl(pipeFds[0], F_SETFD, FD_CLOEXEC)) < 0 && errno == EINTR); if (result == 0) @@ -918,7 +999,32 @@ int32_t SystemNative_Poll(struct PollEvent* pollEvents, uint32_t eventCount, int { const struct PollEvent* event = &pollEvents[i]; pollfds[i].fd = event->FileDescriptor; - pollfds[i].events = event->Events; + // we need to do this for platforms like AIX where PAL_POLL* doesn't + // match up to their reality; this is PollEvent -> system polling + switch (event->Events) + { + case PAL_POLLIN: + pollfds[i].events = POLLIN; + break; + case PAL_POLLPRI: + pollfds[i].events = POLLPRI; + break; + case PAL_POLLOUT: + pollfds[i].events = POLLOUT; + break; + case PAL_POLLERR: + pollfds[i].events = POLLERR; + break; + case PAL_POLLHUP: + pollfds[i].events = POLLHUP; + break; + case PAL_POLLNVAL: + pollfds[i].events = POLLNVAL; + break; + default: + pollfds[i].events = event->Events; + break; + } pollfds[i].revents = 0; } @@ -942,7 +1048,31 @@ int32_t SystemNative_Poll(struct PollEvent* pollEvents, uint32_t eventCount, int assert(pfd->fd == pollEvents[i].FileDescriptor); assert(pfd->events == pollEvents[i].Events); - pollEvents[i].TriggeredEvents = (int16_t)pfd->revents; + // same as the other switch, just system -> PollEvent + switch (pfd->revents) + { + case POLLIN: + pollEvents[i].TriggeredEvents = PAL_POLLIN; + break; + case POLLPRI: + pollEvents[i].TriggeredEvents = PAL_POLLPRI; + break; + case POLLOUT: + pollEvents[i].TriggeredEvents = PAL_POLLOUT; + break; + case POLLERR: + pollEvents[i].TriggeredEvents = PAL_POLLERR; + break; + case POLLHUP: + pollEvents[i].TriggeredEvents = PAL_POLLHUP; + break; + case POLLNVAL: + pollEvents[i].TriggeredEvents = PAL_POLLNVAL; + break; + default: + pollEvents[i].TriggeredEvents = (int16_t)pfd->revents; + break; + } } *triggered = (uint32_t)rv; diff --git a/src/Native/Unix/System.Native/pal_maphardwaretype.c b/src/Native/Unix/System.Native/pal_maphardwaretype.c index d1284cbd36..7f8e825783 100644 --- a/src/Native/Unix/System.Native/pal_maphardwaretype.c +++ b/src/Native/Unix/System.Native/pal_maphardwaretype.c @@ -76,8 +76,10 @@ uint16_t MapHardwareType(uint16_t nativeType) return NetworkInterfaceType_Atm; case IFT_MODEM: return NetworkInterfaceType_GenericModem; +#if defined(IFT_IEEE1394) case IFT_IEEE1394: return NetworkInterfaceType_HighPerformanceSerialBus; +#endif default: return NetworkInterfaceType_Unknown; } diff --git a/src/Native/Unix/System.Native/pal_networking.c b/src/Native/Unix/System.Native/pal_networking.c index daec6bee54..74864b371b 100644 --- a/src/Native/Unix/System.Native/pal_networking.c +++ b/src/Native/Unix/System.Native/pal_networking.c @@ -20,6 +20,8 @@ #include <sys/types.h> #include <sys/event.h> #include <sys/time.h> +#elif HAVE_SYS_POLL_H +#include <sys/poll.h> #endif #include <errno.h> #include <netdb.h> @@ -46,8 +48,10 @@ #endif #if !HAVE_IN_PKTINFO #include <net/if.h> +#if HAVE_GETIFADDRS #include <ifaddrs.h> #endif +#endif #if HAVE_KQUEUE #if KEVENT_HAS_VOID_UDATA @@ -782,7 +786,7 @@ static int32_t GetIPv4PacketInformation(struct cmsghdr* controlMessage, struct I ConvertInAddrToByteArray(&packetInfo->Address.Address[0], NUM_BYTES_IN_IPV4_ADDRESS, &pktinfo->ipi_addr); #if HAVE_IN_PKTINFO packetInfo->InterfaceIndex = (int32_t)pktinfo->ipi_ifindex; -#else +#elif HAVE_GETIFADDRS packetInfo->InterfaceIndex = 0; struct ifaddrs* addrs; @@ -800,6 +804,9 @@ static int32_t GetIPv4PacketInformation(struct cmsghdr* controlMessage, struct I } freeifaddrs(addrs_head); } +#else + // assume the first interface, we have no other methods + packetInfo->InterfaceIndex = 0; #endif return 1; @@ -2254,7 +2261,32 @@ static int32_t WaitForSocketEventsInner(int32_t port, struct SocketEvent* buffer } #else -#error Asynchronous sockets require epoll or kqueue support. +#warning epoll/kqueue not detected; building with stub socket events support +static const size_t SocketEventBufferElementSize = sizeof(struct pollfd); + +static enum SocketEvents GetSocketEvents(int16_t filter, uint16_t flags) +{ + return SocketEvents_SA_NONE; +} +static int32_t CloseSocketEventPortInner(int32_t port) +{ + return Error_ENOSYS; +} +static int32_t CreateSocketEventPortInner(int32_t* port) +{ + return Error_ENOSYS; +} +static int32_t TryChangeSocketEventRegistrationInner( + int32_t port, int32_t socket, enum SocketEvents currentEvents, enum SocketEvents newEvents, +uintptr_t data) +{ + return Error_ENOSYS; +} +static int32_t WaitForSocketEventsInner(int32_t port, struct SocketEvent* buffer, int32_t* count) +{ + return Error_ENOSYS; +} + #endif int32_t SystemNative_CreateSocketEventPort(intptr_t* port) diff --git a/src/Native/Unix/System.Native/pal_random.c b/src/Native/Unix/System.Native/pal_random.c index ddbed43f98..5c216cc88e 100644 --- a/src/Native/Unix/System.Native/pal_random.c +++ b/src/Native/Unix/System.Native/pal_random.c @@ -40,7 +40,12 @@ void SystemNative_GetNonCryptographicallySecureRandomBytes(uint8_t* buffer, int3 do { +#if HAVE_O_CLOEXEC fd = open("/dev/urandom", O_RDONLY, O_CLOEXEC); +#else + fd = open("/dev/urandom", O_RDONLY); + fcntl(fd, F_SETFD, FD_CLOEXEC); +#endif } while ((fd == -1) && (errno == EINTR)); |