dart-sdk/runtime/bin/fdutils_linux.cc
Zach Anderson f407419d0a [vm] Reland: Prefix HOST_OS_* and TARGET_OS_* with DART_
This relands https://dart-review.googlesource.com/c/sdk/+/205633
but without renaming TARGET_OS_IPHONE to DART_TARGET_OS_IPHONE.
It also changes uses of TARGET_OS_IOS to
DART_TARGET_OS_MACOS_IOS to be consistent with the rest of the
VM.

TargetConditionals.h for XCode 13 defines several
TARGET_OS_* preprocessor symbols that confuse the
Dart build. There is probably a more targeted fix
for this, but renaming the symbols that Dart uses
will also prevent this problem if more symbols
are added to the platform headers in the future.

See: https://github.com/dart-lang/sdk/issues/46499

TEST=It builds.

Change-Id: Ie775c19dd23cfdf5f65e5ebc6ee4ec3a561676fa
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/205860
Commit-Queue: Zach Anderson <zra@google.com>
Reviewed-by: Alexander Aprelev <aam@google.com>
2021-07-02 19:06:45 +00:00

142 lines
3.7 KiB
C++

// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
#include "platform/globals.h"
#if defined(DART_HOST_OS_LINUX)
#include "bin/fdutils.h"
#include <errno.h> // NOLINT
#include <fcntl.h> // NOLINT
#include <sys/ioctl.h> // NOLINT
#include <unistd.h> // NOLINT
#include "platform/signal_blocker.h"
namespace dart {
namespace bin {
bool FDUtils::SetCloseOnExec(intptr_t fd) {
intptr_t status;
status = NO_RETRY_EXPECTED(fcntl(fd, F_GETFD));
if (status < 0) {
perror("fcntl(F_GETFD) failed");
return false;
}
status |= FD_CLOEXEC;
if (NO_RETRY_EXPECTED(fcntl(fd, F_SETFD, status)) < 0) {
perror("fcntl(F_SETFD, FD_CLOEXEC) failed");
return false;
}
return true;
}
static bool SetBlockingHelper(intptr_t fd, bool blocking) {
intptr_t status;
status = NO_RETRY_EXPECTED(fcntl(fd, F_GETFL));
if (status < 0) {
perror("fcntl(F_GETFL) failed");
return false;
}
status = blocking ? (status & ~O_NONBLOCK) : (status | O_NONBLOCK);
if (NO_RETRY_EXPECTED(fcntl(fd, F_SETFL, status)) < 0) {
perror("fcntl(F_SETFL, O_NONBLOCK) failed");
return false;
}
return true;
}
bool FDUtils::SetNonBlocking(intptr_t fd) {
return SetBlockingHelper(fd, false);
}
bool FDUtils::SetBlocking(intptr_t fd) {
return SetBlockingHelper(fd, true);
}
bool FDUtils::IsBlocking(intptr_t fd, bool* is_blocking) {
intptr_t status;
status = NO_RETRY_EXPECTED(fcntl(fd, F_GETFL));
if (status < 0) {
return false;
}
*is_blocking = (status & O_NONBLOCK) == 0;
return true;
}
intptr_t FDUtils::AvailableBytes(intptr_t fd) {
int available; // ioctl for FIONREAD expects an 'int*' argument.
int result = NO_RETRY_EXPECTED(ioctl(fd, FIONREAD, &available));
if (result < 0) {
return result;
}
ASSERT(available >= 0);
return static_cast<intptr_t>(available);
}
ssize_t FDUtils::ReadFromBlocking(int fd, void* buffer, size_t count) {
#ifdef DEBUG
bool is_blocking = false;
ASSERT(FDUtils::IsBlocking(fd, &is_blocking));
ASSERT(is_blocking);
#endif
size_t remaining = count;
char* buffer_pos = reinterpret_cast<char*>(buffer);
while (remaining > 0) {
ssize_t bytes_read = TEMP_FAILURE_RETRY(read(fd, buffer_pos, remaining));
if (bytes_read == 0) {
return count - remaining;
} else if (bytes_read == -1) {
ASSERT(EAGAIN == EWOULDBLOCK);
// Error code EWOULDBLOCK should only happen for non blocking
// file descriptors.
ASSERT(errno != EWOULDBLOCK);
return -1;
} else {
ASSERT(bytes_read > 0);
remaining -= bytes_read;
buffer_pos += bytes_read;
}
}
return count;
}
ssize_t FDUtils::WriteToBlocking(int fd, const void* buffer, size_t count) {
#ifdef DEBUG
bool is_blocking = false;
ASSERT(FDUtils::IsBlocking(fd, &is_blocking));
ASSERT(is_blocking);
#endif
size_t remaining = count;
char* buffer_pos = const_cast<char*>(reinterpret_cast<const char*>(buffer));
while (remaining > 0) {
ssize_t bytes_written =
TEMP_FAILURE_RETRY(write(fd, buffer_pos, remaining));
if (bytes_written == 0) {
return count - remaining;
} else if (bytes_written == -1) {
ASSERT(EAGAIN == EWOULDBLOCK);
// Error code EWOULDBLOCK should only happen for non blocking
// file descriptors.
ASSERT(errno != EWOULDBLOCK);
return -1;
} else {
ASSERT(bytes_written > 0);
remaining -= bytes_written;
buffer_pos += bytes_written;
}
}
return count;
}
void FDUtils::SaveErrorAndClose(intptr_t fd) {
int err = errno;
close(fd);
errno = err;
}
} // namespace bin
} // namespace dart
#endif // defined(DART_HOST_OS_LINUX)