proxygen
Unistd.cpp
Go to the documentation of this file.
1 /*
2  * Copyright 2016-present Facebook, Inc.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 // We need to prevent winnt.h from defining the core STATUS codes,
18 // otherwise they will conflict with what we're getting from ntstatus.h
19 #define UMDF_USING_NTSTATUS
20 
22 
23 #ifdef _WIN32
24 
25 #include <cstdio>
26 
27 #include <fcntl.h>
28 
32 
33 // Generic wrapper for the p* family of functions.
34 template <class F, class... Args>
35 static int wrapPositional(F f, int fd, off_t offset, Args... args) {
36  off_t origLoc = lseek(fd, 0, SEEK_CUR);
37  if (origLoc == (off_t)-1) {
38  return -1;
39  }
40  if (lseek(fd, offset, SEEK_SET) == (off_t)-1) {
41  return -1;
42  }
43 
44  int res = (int)f(fd, args...);
45 
46  int curErrNo = errno;
47  if (lseek(fd, origLoc, SEEK_SET) == (off_t)-1) {
48  if (res == -1) {
49  errno = curErrNo;
50  }
51  return -1;
52  }
53  errno = curErrNo;
54 
55  return res;
56 }
57 
58 namespace folly {
59 namespace portability {
60 namespace unistd {
61 int access(char const* fn, int am) {
62  return _access(fn, am);
63 }
64 
65 int chdir(const char* path) {
66  return _chdir(path);
67 }
68 
69 int close(int fh) {
70  if (folly::portability::sockets::is_fh_socket(fh)) {
72  }
73  return _close(fh);
74 }
75 
76 int dup(int fh) {
77  return _dup(fh);
78 }
79 
80 int dup2(int fhs, int fhd) {
81  return _dup2(fhs, fhd);
82 }
83 
84 int fsync(int fd) {
85  HANDLE h = (HANDLE)_get_osfhandle(fd);
86  if (h == INVALID_HANDLE_VALUE) {
87  return -1;
88  }
89  if (!FlushFileBuffers(h)) {
90  return -1;
91  }
92  return 0;
93 }
94 
95 int ftruncate(int fd, off_t len) {
96  if (_lseek(fd, len, SEEK_SET) == -1) {
97  return -1;
98  }
99 
100  HANDLE h = (HANDLE)_get_osfhandle(fd);
101  if (h == INVALID_HANDLE_VALUE) {
102  return -1;
103  }
104  if (!SetEndOfFile(h)) {
105  return -1;
106  }
107  return 0;
108 }
109 
110 char* getcwd(char* buf, int sz) {
111  return _getcwd(buf, sz);
112 }
113 
114 int getdtablesize() {
115  return _getmaxstdio();
116 }
117 
118 int getgid() {
119  return 1;
120 }
121 
122 pid_t getpid() {
123  return (pid_t)uint64_t(GetCurrentProcessId());
124 }
125 
126 // No major need to implement this, and getting a non-potentially
127 // stale ID on windows is a bit involved.
128 pid_t getppid() {
129  return (pid_t)1;
130 }
131 
132 int getuid() {
133  return 1;
134 }
135 
136 int isatty(int fh) {
137  return _isatty(fh);
138 }
139 
140 int lockf(int fd, int cmd, off_t len) {
141  return _locking(fd, cmd, len);
142 }
143 
144 off_t lseek(int fh, off_t off, int orig) {
145  return _lseek(fh, off, orig);
146 }
147 
148 int rmdir(const char* path) {
149  return _rmdir(path);
150 }
151 
152 int pipe(int pth[2]) {
153  // We need to be able to listen to pipes with
154  // libevent, so they need to be actual sockets.
155  return socketpair(PF_UNIX, SOCK_STREAM, 0, pth);
156 }
157 
158 ssize_t pread(int fd, void* buf, size_t count, off_t offset) {
159  return wrapPositional(_read, fd, offset, buf, (unsigned int)count);
160 }
161 
162 ssize_t pwrite(int fd, const void* buf, size_t count, off_t offset) {
163  return wrapPositional(_write, fd, offset, buf, (unsigned int)count);
164 }
165 
166 ssize_t read(int fh, void* buf, size_t count) {
167  if (folly::portability::sockets::is_fh_socket(fh)) {
168  SOCKET s = (SOCKET)_get_osfhandle(fh);
169  if (s != INVALID_SOCKET) {
170  auto r = folly::portability::sockets::recv(fh, buf, count, 0);
171  if (r == -1 && WSAGetLastError() == WSAEWOULDBLOCK) {
172  errno = EAGAIN;
173  }
174  return r;
175  }
176  }
177  auto r = _read(fh, buf, static_cast<unsigned int>(count));
178  if (r == -1 && GetLastError() == ERROR_NO_DATA) {
179  // This only happens if the file was non-blocking and
180  // no data was present. We have to translate the error
181  // to a form that the rest of the world is expecting.
182  errno = EAGAIN;
183  }
184  return r;
185 }
186 
187 ssize_t readlink(const char* path, char* buf, size_t buflen) {
188  if (!buflen) {
189  return -1;
190  }
191 
192  HANDLE h = CreateFileA(
193  path,
194  GENERIC_READ,
195  FILE_SHARE_READ,
196  nullptr,
197  OPEN_EXISTING,
198  FILE_FLAG_BACKUP_SEMANTICS,
199  nullptr);
200  if (h == INVALID_HANDLE_VALUE) {
201  return -1;
202  }
203 
204  DWORD ret =
205  GetFinalPathNameByHandleA(h, buf, DWORD(buflen - 1), VOLUME_NAME_DOS);
206  if (ret >= buflen || ret >= MAX_PATH || !ret) {
207  CloseHandle(h);
208  return -1;
209  }
210 
211  CloseHandle(h);
212  buf[ret] = '\0';
213  return ret;
214 }
215 
216 void* sbrk(intptr_t /* i */) {
217  return (void*)-1;
218 }
219 
220 unsigned int sleep(unsigned int seconds) {
221  Sleep((DWORD)(seconds * 1000));
222  return 0;
223 }
224 
225 long sysconf(int tp) {
226  switch (tp) {
227  case _SC_PAGESIZE: {
228  SYSTEM_INFO inf;
229  GetSystemInfo(&inf);
230  return (long)inf.dwPageSize;
231  }
232  case _SC_NPROCESSORS_ONLN: {
233  SYSTEM_INFO inf;
234  GetSystemInfo(&inf);
235  return (long)inf.dwNumberOfProcessors;
236  }
237  default:
238  return -1L;
239  }
240 }
241 
242 int truncate(const char* path, off_t len) {
243  int fd = _open(path, O_WRONLY);
244  if (!fd) {
245  return -1;
246  }
247  if (ftruncate(fd, len)) {
248  _close(fd);
249  return -1;
250  }
251  return _close(fd) ? -1 : 0;
252 }
253 
254 int usleep(unsigned int ms) {
255  Sleep((DWORD)(ms / 1000));
256  return 0;
257 }
258 
259 ssize_t write(int fh, void const* buf, size_t count) {
260  if (folly::portability::sockets::is_fh_socket(fh)) {
261  SOCKET s = (SOCKET)_get_osfhandle(fh);
262  if (s != INVALID_SOCKET) {
263  auto r = folly::portability::sockets::send(fh, buf, (size_t)count, 0);
264  if (r == -1 && WSAGetLastError() == WSAEWOULDBLOCK) {
265  errno = EAGAIN;
266  }
267  return r;
268  }
269  }
270  auto r = _write(fh, buf, static_cast<unsigned int>(count));
271  if ((r > 0 && size_t(r) != count) || (r == -1 && errno == ENOSPC)) {
272  // Writing to a pipe with a full buffer doesn't generate
273  // any error type, unless it caused us to write exactly 0
274  // bytes, so we have to see if we have a pipe first. We
275  // don't touch the errno for anything else.
276  HANDLE h = (HANDLE)_get_osfhandle(fh);
277  if (GetFileType(h) == FILE_TYPE_PIPE) {
278  DWORD state = 0;
279  if (GetNamedPipeHandleState(
280  h, &state, nullptr, nullptr, nullptr, nullptr, 0)) {
281  if ((state & PIPE_NOWAIT) == PIPE_NOWAIT) {
282  errno = EAGAIN;
283  return -1;
284  }
285  }
286  }
287  }
288  return r;
289 }
290 } // namespace unistd
291 } // namespace portability
292 } // namespace folly
293 
294 #endif
*than *hazptr_holder h
Definition: Hazptr.h:116
auto f
void write(const T &in, folly::io::Appender &appender)
Definition: Types-inl.h:112
Future< Unit > sleep(Duration dur, Timekeeper *tk)
Definition: Future.cpp:42
internal::ArgsMatcher< InnerMatcher > Args(const InnerMatcher &matcher)
—— Concurrent Priority Queue Implementation ——
Definition: AtomicBitSet.h:29
size_t read(T &out, folly::io::Cursor &cursor)
Definition: Types-inl.h:258
static int wrapPositional(F f, int fd, off_t offset, Args...args)
Definition: SysUio.cpp:28
ssize_t send(NetworkSocket s, const void *buf, size_t len, int flags)
Definition: NetOps.cpp:319
int * count
cmd
Definition: gtest-cfgcmd.txt:1
static set< string > s
ssize_t recv(NetworkSocket s, void *buf, size_t len, int flags)
Definition: NetOps.cpp:180
int close(NetworkSocket s)
Definition: NetOps.cpp:90
void pipe(CPUExecutor cpu, IOExecutor io)
state
Definition: http_parser.c:272
int socketpair(int domain, int type, int protocol, NetworkSocket sv[2])
Definition: NetOps.cpp:416