Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mono/corefx.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCalvin <calvin@cmpct.info>2018-06-10 11:39:25 +0300
committerAlexander Köplinger <alex.koeplinger@outlook.com>2018-06-10 11:39:25 +0300
commit62eb6bea5f339913711571c14018e4e2eb790781 (patch)
treefc5da516c5a4704177213471c98fa363da169818
parent05a53870334c668fa6b6cdec39c3972b5ed0284d (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.in4
-rw-r--r--src/Native/Unix/System.Native/pal_errno.c2
-rw-r--r--src/Native/Unix/System.Native/pal_io.c134
-rw-r--r--src/Native/Unix/System.Native/pal_maphardwaretype.c2
-rw-r--r--src/Native/Unix/System.Native/pal_networking.c36
-rw-r--r--src/Native/Unix/System.Native/pal_random.c5
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));