Example #1
0
extern "C" int32_t SystemNative_FcntlSetIsNonBlocking(intptr_t fd, int32_t isNonBlocking)
{
    int fileDescriptor = ToFileDescriptor(fd);

    int flags = fcntl(fileDescriptor, F_GETFL);
    if (flags == -1)
    {
        return -1;
    }

    if (isNonBlocking == 0)
    {
        flags &= ~O_NONBLOCK;
    }
    else
    {
        flags |= O_NONBLOCK;
    }

    return fcntl(fileDescriptor, F_SETFL, flags);
}
Example #2
0
extern "C" int32_t SystemNative_GetPeerID(intptr_t socket, uid_t* euid)
{
    int fd = ToFileDescriptor(socket);
#ifdef SO_PEERCRED
    struct ucred creds;
    socklen_t len = sizeof(creds);
    if (getsockopt(fd, SOL_SOCKET, SO_PEERCRED, &creds, &len) == 0)
    {
        *euid = creds.uid;
        return 0;
    }
    return -1;
#elif HAVE_GETPEEREID
    uid_t egid;
    return getpeereid(fd, euid, &egid);
#else
    (void)fd;
    (void)*euid;
    errno = ENOTSUP;
    return -1;
#endif
}
Example #3
0
int32_t SystemNative_PosixFAdvise(intptr_t fd, int64_t offset, int64_t length, int32_t advice)
{
#if HAVE_POSIX_ADVISE
    int32_t result;
    while ((
        result =
#if HAVE_POSIX_FADVISE64
            posix_fadvise64(
#else
            posix_fadvise(
#endif
                ToFileDescriptor(fd),
                (off_t)offset,
                (off_t)length,
                advice)) < 0 && errno == EINTR);
    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 #4
0
int32_t SystemNative_LockFileRegion(intptr_t fd, int64_t offset, int64_t length, int16_t lockType)
{
    if (offset < 0 || length < 0) 
    {
        errno = EINVAL;
        return -1;
    }

#if HAVE_FLOCK64
    struct flock64 lockArgs;
#else
    struct flock lockArgs;
#endif

    lockArgs.l_type = lockType;
    lockArgs.l_whence = SEEK_SET;
    lockArgs.l_start = (off_t)offset;
    lockArgs.l_len = (off_t)length;

    int32_t ret;
    while ((ret = fcntl (ToFileDescriptor(fd), F_SETLK, &lockArgs)) < 0 && errno == EINTR);
    return ret;
}
Example #5
0
extern "C" int64_t SystemNative_LSeek(intptr_t fd, int64_t offset, SeekWhence whence)
{
    int64_t result;
    while (CheckInterrupted(result = lseek(ToFileDescriptor(fd), offset, whence)));
    return result;
}
Example #6
0
extern "C" int32_t SystemNative_FLock(intptr_t fd, LockOperations operation)
{
    int32_t result;
    while (CheckInterrupted(result = flock(ToFileDescriptor(fd), operation)));
    return result;
}
Example #7
0
extern "C" int32_t SystemNative_FSync(intptr_t fd)
{
    int32_t result;
    while (CheckInterrupted(result = fsync(ToFileDescriptor(fd))));
    return result;
}
Example #8
0
extern "C" int32_t SystemNative_FChMod(intptr_t fd, int32_t mode)
{
    int32_t result;
    while (CheckInterrupted(result = fchmod(ToFileDescriptor(fd), static_cast<mode_t>(mode))));
    return result;
}
Example #9
0
extern "C" int32_t SystemNative_FcntlSetCloseOnExec(intptr_t fd)
{
    int result;
    while (CheckInterrupted(result = fcntl(ToFileDescriptor(fd), F_SETFD, FD_CLOEXEC)));
    return result;
}
Example #10
0
extern "C" intptr_t SystemNative_Dup(intptr_t oldfd)
{
    int result;
    while (CheckInterrupted(result = dup(ToFileDescriptor(oldfd))));
    return result;
}
Example #11
0
extern "C" int32_t SystemNative_CopyFile(intptr_t sourceFd, intptr_t destinationFd)
{
    int inFd = ToFileDescriptor(sourceFd);
    int outFd = ToFileDescriptor(destinationFd);

#if HAVE_FCOPYFILE
    // If fcopyfile is available (OS X), try to use it, as the whole copy
    // can be performed in the kernel, without lots of unnecessary copying.
    // Copy data and metadata.
    return fcopyfile(inFd, outFd, nullptr, COPYFILE_ALL) == 0 ? 0 : -1;
#else
    // Get the stats on the source file.
    int ret;
    struct stat_ sourceStat;
    bool copied = false;
#if HAVE_SENDFILE
    // If sendfile is available (Linux), try to use it, as the whole copy
    // can be performed in the kernel, without lots of unnecessary copying.
    while (CheckInterrupted(ret = fstat_(inFd, &sourceStat)));
    if (ret != 0)
    {
        return -1;
    }


    // We use `auto' here to adapt the type of `size' depending on the running platform.
    // On 32-bit, if you use 64-bit offsets, the last argument of `sendfile' will be a
    // `size_t' a 32-bit integer while the `st_size' field of the stat structure will be off64_t.
    // So `size' will have to be `uint64_t'. In all other cases, it will be `size_t'.
    auto size = UnsignedCast(sourceStat.st_size);

    // Note that per man page for large files, you have to iterate until the
    // whole file is copied (Linux has a limit of 0x7ffff000 bytes copied).
    while (size > 0)
    {
        ssize_t sent = sendfile(outFd, inFd, nullptr, (size >= SSIZE_MAX ? SSIZE_MAX : static_cast<size_t>(size)));
        if (sent < 0)
        {
            if (errno != EINVAL && errno != ENOSYS)
            {
                return -1;
            }
            else
            {
                break;
            }
        }
        else
        {
            assert(UnsignedCast(sent) <= size);
            size -= UnsignedCast(sent);
        }
    }
    if (size == 0)
    {
        copied = true;
    }
    // sendfile couldn't be used; fall back to a manual copy below. This could happen
    // if we're on an old kernel, for example, where sendfile could only be used
    // with sockets and not regular files.
#endif // HAVE_SENDFILE

    // Manually read all data from the source and write it to the destination.
    if (!copied && CopyFile_ReadWrite(inFd, outFd) != 0)
    {
        return -1;
    }

    // Now that the data from the file has been copied, copy over metadata
    // from the source file.  First copy the file times.
    while (CheckInterrupted(ret = fstat_(inFd, &sourceStat)));
    if (ret == 0)
    {
        struct timeval origTimes[2];
        origTimes[0].tv_sec = sourceStat.st_atime;
        origTimes[0].tv_usec = 0;
        origTimes[1].tv_sec = sourceStat.st_mtime;
        origTimes[1].tv_usec = 0;
        while (CheckInterrupted(ret = futimes(outFd, origTimes)));
    }
    if (ret != 0)
    {
        return -1;
    }

    // Then copy permissions.
    while (CheckInterrupted(ret = fchmod(outFd, sourceStat.st_mode & (S_IRWXU | S_IRWXG | S_IRWXO))));
    if (ret != 0)
    {
        return -1;
    }

    return 0;
#endif // HAVE_FCOPYFILE
}
Example #12
0
int32_t SystemNative_FLock(intptr_t fd, int32_t operation)
{
    int32_t result;
    while ((result = flock(ToFileDescriptor(fd), operation)) < 0 && errno == EINTR);
    return result;
}
Example #13
0
extern "C" int32_t SystemNative_IsATty(intptr_t fd)
{
    return isatty(ToFileDescriptor(fd));
}
Example #14
0
int32_t SystemNative_FSync(intptr_t fd)
{
    int32_t result;
    while ((result = fsync(ToFileDescriptor(fd))) < 0 && errno == EINTR);
    return result;
}
Example #15
0
int32_t SystemNative_FChMod(intptr_t fd, int32_t mode)
{
    int32_t result;
    while ((result = fchmod(ToFileDescriptor(fd), (mode_t)mode)) < 0 && errno == EINTR);
    return result;
}
Example #16
0
int32_t SystemNative_FcntlSetCloseOnExec(intptr_t fd)
{
    int result;
    while ((result = fcntl(ToFileDescriptor(fd), F_SETFD, FD_CLOEXEC)) < 0 && errno == EINTR);
    return result;
}
Example #17
0
extern "C" int32_t SystemNative_FTruncate(intptr_t fd, int64_t length)
{
    int32_t result;
    while (CheckInterrupted(result = ftruncate(ToFileDescriptor(fd), length)));
    return result;
}
Example #18
0
extern "C" int32_t SystemNative_Close(intptr_t fd)
{
    return close(ToFileDescriptor(fd));
}
Example #19
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 #20
0
int32_t SystemNative_CopyFile(intptr_t sourceFd, intptr_t destinationFd)
{
    int inFd = ToFileDescriptor(sourceFd);
    int outFd = ToFileDescriptor(destinationFd);

#if HAVE_FCOPYFILE
    // If fcopyfile is available (OS X), try to use it, as the whole copy
    // can be performed in the kernel, without lots of unnecessary copying.
    // Copy data and metadata.
    return fcopyfile(inFd, outFd, NULL, COPYFILE_ALL) == 0 ? 0 : -1;
#else
    // Get the stats on the source file.
    int ret;
    struct stat_ sourceStat;
    bool copied = false;
#if HAVE_SENDFILE_4
    // If sendfile is available (Linux), try to use it, as the whole copy
    // can be performed in the kernel, without lots of unnecessary copying.
    while ((ret = fstat_(inFd, &sourceStat)) < 0 && errno == EINTR);
    if (ret != 0)
    {
        return -1;
    }


    // On 32-bit, if you use 64-bit offsets, the last argument of `sendfile' will be a
    // `size_t' a 32-bit integer while the `st_size' field of the stat structure will be off64_t.
    // So `size' will have to be `uint64_t'. In all other cases, it will be `size_t'.
    uint64_t size = (uint64_t)sourceStat.st_size;

    // Note that per man page for large files, you have to iterate until the
    // whole file is copied (Linux has a limit of 0x7ffff000 bytes copied).
    while (size > 0)
    {
        ssize_t sent = sendfile(outFd, inFd, NULL, (size >= SSIZE_MAX ? SSIZE_MAX : (size_t)size));
        if (sent < 0)
        {
            if (errno != EINVAL && errno != ENOSYS)
            {
                return -1;
            }
            else
            {
                break;
            }
        }
        else
        {
            assert((size_t)sent <= size);
            size -= (size_t)sent;
        }
    }
    if (size == 0)
    {
        copied = true;
    }
    // sendfile couldn't be used; fall back to a manual copy below. This could happen
    // if we're on an old kernel, for example, where sendfile could only be used
    // with sockets and not regular files.
#endif // HAVE_SENDFILE_4

    // Manually read all data from the source and write it to the destination.
    if (!copied && CopyFile_ReadWrite(inFd, outFd) != 0)
    {
        return -1;
    }

    // Now that the data from the file has been copied, copy over metadata
    // from the source file.  First copy the file times.
    // If futimes nor futimes are available on this platform, file times will
    // not be copied over.
    while ((ret = fstat_(inFd, &sourceStat)) < 0 && errno == EINTR);
    if (ret == 0)
    {
#if HAVE_FUTIMES
        struct timeval origTimes[2];
        origTimes[0].tv_sec = sourceStat.st_atime;
        origTimes[0].tv_usec = ST_ATIME_NSEC(&sourceStat) / 1000;
        origTimes[1].tv_sec = sourceStat.st_mtime;
        origTimes[1].tv_usec = ST_MTIME_NSEC(&sourceStat) / 1000;
        while ((ret = futimes(outFd, origTimes)) < 0 && errno == EINTR);
#elif HAVE_FUTIMENS
        // futimes is not a POSIX function, and not available on Android,
        // but futimens is
        struct timespec origTimes[2];
        origTimes[0].tv_sec = (time_t)sourceStat.st_atime;
        origTimes[0].tv_nsec = ST_ATIME_NSEC(&sourceStat);
        origTimes[1].tv_sec = (time_t)sourceStat.st_mtime;
        origTimes[1].tv_nsec = ST_MTIME_NSEC(&sourceStat);
        while ((ret = futimens(outFd, origTimes)) < 0 && errno == EINTR);
#endif
    }
    if (ret != 0)
    {
        return -1;
    }

    // Then copy permissions.
    while ((ret = fchmod(outFd, sourceStat.st_mode & (S_IRWXU | S_IRWXG | S_IRWXO))) < 0 && errno == EINTR);
    if (ret != 0)
    {
        return -1;
    }

    return 0;
#endif // HAVE_FCOPYFILE
}