Flutter Engine
The Flutter Engine
Loading...
Searching...
No Matches
fdutils_linux.cc
Go to the documentation of this file.
1// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
2// for details. All rights reserved. Use of this source code is governed by a
3// BSD-style license that can be found in the LICENSE file.
4
5#include "platform/globals.h"
6#if defined(DART_HOST_OS_LINUX) || defined(DART_HOST_OS_ANDROID)
7
8#include "bin/fdutils.h"
9
10#include <errno.h> // NOLINT
11#include <fcntl.h> // NOLINT
12#include <sys/ioctl.h> // NOLINT
13#include <unistd.h> // NOLINT
14
16
17namespace dart {
18namespace bin {
19
20bool FDUtils::SetCloseOnExec(intptr_t fd) {
21 intptr_t status;
22 status = NO_RETRY_EXPECTED(fcntl(fd, F_GETFD));
23 if (status < 0) {
24 perror("fcntl(F_GETFD) failed");
25 return false;
26 }
27 status |= FD_CLOEXEC;
28 if (NO_RETRY_EXPECTED(fcntl(fd, F_SETFD, status)) < 0) {
29 perror("fcntl(F_SETFD, FD_CLOEXEC) failed");
30 return false;
31 }
32 return true;
33}
34
35static bool SetBlockingHelper(intptr_t fd, bool blocking) {
36 intptr_t status;
37 status = NO_RETRY_EXPECTED(fcntl(fd, F_GETFL));
38 if (status < 0) {
39 perror("fcntl(F_GETFL) failed");
40 return false;
41 }
42 status = blocking ? (status & ~O_NONBLOCK) : (status | O_NONBLOCK);
43 if (NO_RETRY_EXPECTED(fcntl(fd, F_SETFL, status)) < 0) {
44 perror("fcntl(F_SETFL, O_NONBLOCK) failed");
45 return false;
46 }
47 return true;
48}
49
50bool FDUtils::SetNonBlocking(intptr_t fd) {
51 return SetBlockingHelper(fd, false);
52}
53
54bool FDUtils::SetBlocking(intptr_t fd) {
55 return SetBlockingHelper(fd, true);
56}
57
58bool FDUtils::IsBlocking(intptr_t fd, bool* is_blocking) {
59 intptr_t status;
60 status = NO_RETRY_EXPECTED(fcntl(fd, F_GETFL));
61 if (status < 0) {
62 return false;
63 }
64 *is_blocking = (status & O_NONBLOCK) == 0;
65 return true;
66}
67
68intptr_t FDUtils::AvailableBytes(intptr_t fd) {
69 int available; // ioctl for FIONREAD expects an 'int*' argument.
70 int result = NO_RETRY_EXPECTED(ioctl(fd, FIONREAD, &available));
71 if (result < 0) {
72 return result;
73 }
74 ASSERT(available >= 0);
75 return static_cast<intptr_t>(available);
76}
77
78ssize_t FDUtils::ReadFromBlocking(int fd, void* buffer, size_t count) {
79#ifdef DEBUG
80 bool is_blocking = false;
81 ASSERT(FDUtils::IsBlocking(fd, &is_blocking));
82 ASSERT(is_blocking);
83#endif
84 size_t remaining = count;
85 char* buffer_pos = reinterpret_cast<char*>(buffer);
86 while (remaining > 0) {
87 ssize_t bytes_read = TEMP_FAILURE_RETRY(read(fd, buffer_pos, remaining));
88 if (bytes_read == 0) {
89 return count - remaining;
90 } else if (bytes_read == -1) {
91 ASSERT(EAGAIN == EWOULDBLOCK);
92 // Error code EWOULDBLOCK should only happen for non blocking
93 // file descriptors.
94 ASSERT(errno != EWOULDBLOCK);
95 return -1;
96 } else {
97 ASSERT(bytes_read > 0);
98 remaining -= bytes_read;
99 buffer_pos += bytes_read;
100 }
101 }
102 return count;
103}
104
105ssize_t FDUtils::WriteToBlocking(int fd, const void* buffer, size_t count) {
106#ifdef DEBUG
107 bool is_blocking = false;
108 ASSERT(FDUtils::IsBlocking(fd, &is_blocking));
109 ASSERT(is_blocking);
110#endif
111 size_t remaining = count;
112 char* buffer_pos = const_cast<char*>(reinterpret_cast<const char*>(buffer));
113 while (remaining > 0) {
114 ssize_t bytes_written =
115 TEMP_FAILURE_RETRY(write(fd, buffer_pos, remaining));
116 if (bytes_written == 0) {
117 return count - remaining;
118 } else if (bytes_written == -1) {
119 ASSERT(EAGAIN == EWOULDBLOCK);
120 // Error code EWOULDBLOCK should only happen for non blocking
121 // file descriptors.
122 ASSERT(errno != EWOULDBLOCK);
123 return -1;
124 } else {
125 ASSERT(bytes_written > 0);
126 remaining -= bytes_written;
127 buffer_pos += bytes_written;
128 }
129 }
130 return count;
131}
132
133void FDUtils::SaveErrorAndClose(intptr_t fd) {
134 int err = errno;
135 close(fd);
136 errno = err;
137}
138
139} // namespace bin
140} // namespace dart
141
142#endif // defined(DART_HOST_OS_LINUX) || defined(DART_HOST_OS_ANDROID)
int count
static bool read(SkStream *stream, void *buffer, size_t amount)
static intptr_t AvailableBytes(intptr_t fd)
static bool SetCloseOnExec(intptr_t fd)
static bool SetBlocking(intptr_t fd)
static bool IsBlocking(intptr_t fd, bool *is_blocking)
static bool SetNonBlocking(intptr_t fd)
static void SaveErrorAndClose(intptr_t fd)
static ssize_t ReadFromBlocking(int fd, void *buffer, size_t count)
static ssize_t WriteToBlocking(int fd, const void *buffer, size_t count)
#define ASSERT(E)
static const uint8_t buffer[]
GAsyncResult * result
#define NO_RETRY_EXPECTED(expression)
#define TEMP_FAILURE_RETRY(expression)
void write(SkWStream *wStream, const T &text)
Definition skqp.cpp:188