Example #1
0
extern "C" Error SystemNative_CreateNetworkChangeListenerSocket(int32_t* retSocket)
{
    sockaddr_nl sa = {};
    sa.nl_family = AF_NETLINK;
    sa.nl_groups = RTMGRP_LINK | RTMGRP_IPV4_IFADDR;
    int32_t sock = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
    if (sock == -1)
    {
        *retSocket = -1;
        return SystemNative_ConvertErrorPlatformToPal(errno);
    }
    if (bind(sock, reinterpret_cast<sockaddr*>(&sa), sizeof(sa)) != 0)
    {
        *retSocket = -1;
        return SystemNative_ConvertErrorPlatformToPal(errno);
    }

    *retSocket = sock;
    return PAL_SUCCESS;
}
Example #2
0
extern "C" Error SystemNative_Poll(PollEvent* pollEvents, uint32_t eventCount, int32_t milliseconds, uint32_t* triggered)
{
    if (pollEvents == nullptr || triggered == nullptr)
    {
        return PAL_EFAULT;
    }

    if (milliseconds < -1)
    {
        return PAL_EINVAL;
    }

    size_t bufferSize = sizeof(pollfd) * static_cast<size_t>(eventCount);
    bool useStackBuffer = bufferSize <= 2048;
    pollfd* pollfds = reinterpret_cast<pollfd*>(useStackBuffer ? alloca(bufferSize) : malloc(bufferSize));

    for (uint32_t i = 0; i < eventCount; i++)
    {
        const PollEvent& event = pollEvents[i];
        pollfds[i] = { .fd = event.FileDescriptor, .events = event.Events, .revents = 0 };
    }

    int rv;
    while (CheckInterrupted(rv = poll(pollfds, static_cast<nfds_t>(eventCount), milliseconds)));

    if (rv < 0)
    {
        if (!useStackBuffer)
        {
            free(pollfds);
        }

        *triggered = 0;
        return SystemNative_ConvertErrorPlatformToPal(errno);
    }

    for (uint32_t i = 0; i < eventCount; i++)
    {
        const pollfd& pfd = pollfds[i];
        assert(pfd.fd == pollEvents[i].FileDescriptor);
        assert(pfd.events == pollEvents[i].Events);

        pollEvents[i].TriggeredEvents = static_cast<PollEvents>(pfd.revents);
    }

    *triggered = static_cast<uint32_t>(rv);

    if (!useStackBuffer)
    {
        free(pollfds);
    }

    return PAL_SUCCESS;
}

extern "C" int32_t SystemNative_PosixFAdvise(intptr_t fd, int64_t offset, int64_t length, FileAdvice advice)
{
#if HAVE_POSIX_ADVISE
    int32_t result;
    while (CheckInterrupted(result = posix_fadvise(ToFileDescriptor(fd), offset, length, advice)));
    return result;
#else
    // Not supported on this platform. Caller can ignore this failure since it's just a hint.
    (void)fd, (void)offset, (void)length, (void)advice;
    return ENOTSUP;
#endif
}
Example #3
0
int32_t SystemNative_Poll(PollEvent* pollEvents, uint32_t eventCount, int32_t milliseconds, uint32_t* triggered)
{
    if (pollEvents == NULL || triggered == NULL)
    {
        return Error_EFAULT;
    }

    if (milliseconds < -1)
    {
        return Error_EINVAL;
    }

    size_t bufferSize;
    if (!multiply_s(sizeof(struct pollfd), (size_t)eventCount, &bufferSize))
    {
        return SystemNative_ConvertErrorPlatformToPal(EOVERFLOW);
    }


    int useStackBuffer = bufferSize <= 2048;
    struct pollfd* pollfds = (struct pollfd*)(useStackBuffer ? alloca(bufferSize) : malloc(bufferSize));
    if (pollfds == NULL)
    {
        return Error_ENOMEM;
    }

    for (uint32_t i = 0; i < eventCount; i++)
    {
        const PollEvent* event = &pollEvents[i];
        pollfds[i].fd = event->FileDescriptor;
        // 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;
    }

    int rv;
    while ((rv = poll(pollfds, (nfds_t)eventCount, milliseconds)) < 0 && errno == EINTR);

    if (rv < 0)
    {
        if (!useStackBuffer)
        {
            free(pollfds);
        }

        *triggered = 0;
        return SystemNative_ConvertErrorPlatformToPal(errno);
    }

    for (uint32_t i = 0; i < eventCount; i++)
    {
        const struct pollfd* pfd = &pollfds[i];
        assert(pfd->fd == pollEvents[i].FileDescriptor);
        assert(pfd->events == pollEvents[i].Events);

        // 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;

    if (!useStackBuffer)
    {
        free(pollfds);
    }

    return Error_SUCCESS;
}
Example #4
0
extern "C" Error SystemNative_CloseNetworkChangeListenerSocket(int32_t socket)
{
    int err = close(socket);
    return err == 0 || CheckInterrupted(err) ? PAL_SUCCESS : SystemNative_ConvertErrorPlatformToPal(errno);
}