Unistd.cpp 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339
  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. // We need to prevent winnt.h from defining the core STATUS codes,
  17. // otherwise they will conflict with what we're getting from ntstatus.h
  18. #define UMDF_USING_NTSTATUS
  19. #include <folly/portability/Unistd.h>
  20. #ifdef _WIN32
  21. #include <cstdio>
  22. #include <fcntl.h>
  23. #include <folly/portability/Sockets.h>
  24. #include <folly/portability/Windows.h>
  25. // Including ntdef.h requires building as a driver, but all we want
  26. // is a status code, but we need NTSTATUS defined for that. Luckily
  27. // bcrypt.h also defines NTSTATUS, so we'll use that one instead.
  28. #include <bcrypt.h> // @manual
  29. #include <ntstatus.h> // @manual
  30. // Generic wrapper for the p* family of functions.
  31. template <class F, class... Args>
  32. static int wrapPositional(F f, int fd, off_t offset, Args... args) {
  33. off_t origLoc = lseek(fd, 0, SEEK_CUR);
  34. if (origLoc == (off_t)-1) {
  35. return -1;
  36. }
  37. if (lseek(fd, offset, SEEK_SET) == (off_t)-1) {
  38. return -1;
  39. }
  40. int res = (int)f(fd, args...);
  41. int curErrNo = errno;
  42. if (lseek(fd, origLoc, SEEK_SET) == (off_t)-1) {
  43. if (res == -1) {
  44. errno = curErrNo;
  45. }
  46. return -1;
  47. }
  48. errno = curErrNo;
  49. return res;
  50. }
  51. namespace folly {
  52. namespace portability {
  53. namespace unistd {
  54. int access(char const* fn, int am) {
  55. return _access(fn, am);
  56. }
  57. int chdir(const char* path) {
  58. return _chdir(path);
  59. }
  60. int close(int fh) {
  61. if (folly::portability::sockets::is_fh_socket(fh)) {
  62. SOCKET h = (SOCKET)_get_osfhandle(fh);
  63. // If we were to just call _close on the descriptor, it would
  64. // close the HANDLE, but it wouldn't free any of the resources
  65. // associated to the SOCKET, and we can't call _close after
  66. // calling closesocket, because closesocket has already closed
  67. // the HANDLE, and _close would attempt to close the HANDLE
  68. // again, resulting in a double free.
  69. // We can however protect the HANDLE from actually being closed
  70. // long enough to close the file descriptor, then close the
  71. // socket itself.
  72. constexpr DWORD protectFlag = HANDLE_FLAG_PROTECT_FROM_CLOSE;
  73. DWORD handleFlags = 0;
  74. if (!GetHandleInformation((HANDLE)h, &handleFlags)) {
  75. return -1;
  76. }
  77. if (!SetHandleInformation((HANDLE)h, protectFlag, protectFlag)) {
  78. return -1;
  79. }
  80. int c = 0;
  81. __try {
  82. // We expect this to fail. It still closes the file descriptor though.
  83. c = _close(fh);
  84. // We just have to catch the SEH exception that gets thrown when we do
  85. // this with a debugger attached -_-....
  86. } __except (
  87. GetExceptionCode() == STATUS_HANDLE_NOT_CLOSABLE
  88. ? EXCEPTION_CONTINUE_EXECUTION
  89. : EXCEPTION_CONTINUE_SEARCH) {
  90. // We told it to continue execution, so there's nothing here would
  91. // be run anyways.
  92. }
  93. // We're at the core, we don't get the luxery of SCOPE_EXIT because
  94. // of circular dependencies.
  95. if (!SetHandleInformation((HANDLE)h, protectFlag, handleFlags)) {
  96. return -1;
  97. }
  98. if (c != -1) {
  99. return -1;
  100. }
  101. return closesocket(h);
  102. }
  103. return _close(fh);
  104. }
  105. int dup(int fh) {
  106. return _dup(fh);
  107. }
  108. int dup2(int fhs, int fhd) {
  109. return _dup2(fhs, fhd);
  110. }
  111. int fsync(int fd) {
  112. HANDLE h = (HANDLE)_get_osfhandle(fd);
  113. if (h == INVALID_HANDLE_VALUE) {
  114. return -1;
  115. }
  116. if (!FlushFileBuffers(h)) {
  117. return -1;
  118. }
  119. return 0;
  120. }
  121. int ftruncate(int fd, off_t len) {
  122. if (_lseek(fd, len, SEEK_SET) == -1) {
  123. return -1;
  124. }
  125. HANDLE h = (HANDLE)_get_osfhandle(fd);
  126. if (h == INVALID_HANDLE_VALUE) {
  127. return -1;
  128. }
  129. if (!SetEndOfFile(h)) {
  130. return -1;
  131. }
  132. return 0;
  133. }
  134. char* getcwd(char* buf, int sz) {
  135. return _getcwd(buf, sz);
  136. }
  137. int getdtablesize() {
  138. return _getmaxstdio();
  139. }
  140. int getgid() {
  141. return 1;
  142. }
  143. pid_t getpid() {
  144. return (pid_t)uint64_t(GetCurrentProcessId());
  145. }
  146. // No major need to implement this, and getting a non-potentially
  147. // stale ID on windows is a bit involved.
  148. pid_t getppid() {
  149. return (pid_t)1;
  150. }
  151. int getuid() {
  152. return 1;
  153. }
  154. int isatty(int fh) {
  155. return _isatty(fh);
  156. }
  157. int lockf(int fd, int cmd, off_t len) {
  158. return _locking(fd, cmd, len);
  159. }
  160. off_t lseek(int fh, off_t off, int orig) {
  161. return _lseek(fh, off, orig);
  162. }
  163. int rmdir(const char* path) {
  164. return _rmdir(path);
  165. }
  166. int pipe(int pth[2]) {
  167. // We need to be able to listen to pipes with
  168. // libevent, so they need to be actual sockets.
  169. return socketpair(PF_UNIX, SOCK_STREAM, 0, pth);
  170. }
  171. ssize_t pread(int fd, void* buf, size_t count, off_t offset) {
  172. return wrapPositional(_read, fd, offset, buf, (unsigned int)count);
  173. }
  174. ssize_t pwrite(int fd, const void* buf, size_t count, off_t offset) {
  175. return wrapPositional(_write, fd, offset, buf, (unsigned int)count);
  176. }
  177. ssize_t read(int fh, void* buf, size_t count) {
  178. if (folly::portability::sockets::is_fh_socket(fh)) {
  179. SOCKET s = (SOCKET)_get_osfhandle(fh);
  180. if (s != INVALID_SOCKET) {
  181. auto r = folly::portability::sockets::recv(fh, buf, count, 0);
  182. if (r == -1 && WSAGetLastError() == WSAEWOULDBLOCK) {
  183. errno = EAGAIN;
  184. }
  185. return r;
  186. }
  187. }
  188. auto r = _read(fh, buf, static_cast<unsigned int>(count));
  189. if (r == -1 && GetLastError() == ERROR_NO_DATA) {
  190. // This only happens if the file was non-blocking and
  191. // no data was present. We have to translate the error
  192. // to a form that the rest of the world is expecting.
  193. errno = EAGAIN;
  194. }
  195. return r;
  196. }
  197. ssize_t readlink(const char* path, char* buf, size_t buflen) {
  198. if (!buflen) {
  199. return -1;
  200. }
  201. HANDLE h = CreateFileA(
  202. path,
  203. GENERIC_READ,
  204. FILE_SHARE_READ,
  205. nullptr,
  206. OPEN_EXISTING,
  207. FILE_FLAG_BACKUP_SEMANTICS,
  208. nullptr);
  209. if (h == INVALID_HANDLE_VALUE) {
  210. return -1;
  211. }
  212. DWORD ret =
  213. GetFinalPathNameByHandleA(h, buf, DWORD(buflen - 1), VOLUME_NAME_DOS);
  214. if (ret >= buflen || ret >= MAX_PATH || !ret) {
  215. CloseHandle(h);
  216. return -1;
  217. }
  218. CloseHandle(h);
  219. buf[ret] = '\0';
  220. return ret;
  221. }
  222. void* sbrk(intptr_t /* i */) {
  223. return (void*)-1;
  224. }
  225. unsigned int sleep(unsigned int seconds) {
  226. Sleep((DWORD)(seconds * 1000));
  227. return 0;
  228. }
  229. long sysconf(int tp) {
  230. switch (tp) {
  231. case _SC_PAGESIZE: {
  232. SYSTEM_INFO inf;
  233. GetSystemInfo(&inf);
  234. return (long)inf.dwPageSize;
  235. }
  236. case _SC_NPROCESSORS_ONLN: {
  237. SYSTEM_INFO inf;
  238. GetSystemInfo(&inf);
  239. return (long)inf.dwNumberOfProcessors;
  240. }
  241. default:
  242. return -1L;
  243. }
  244. }
  245. int truncate(const char* path, off_t len) {
  246. int fd = _open(path, O_WRONLY);
  247. if (!fd) {
  248. return -1;
  249. }
  250. if (ftruncate(fd, len)) {
  251. _close(fd);
  252. return -1;
  253. }
  254. return _close(fd) ? -1 : 0;
  255. }
  256. int usleep(unsigned int ms) {
  257. Sleep((DWORD)(ms / 1000));
  258. return 0;
  259. }
  260. ssize_t write(int fh, void const* buf, size_t count) {
  261. if (folly::portability::sockets::is_fh_socket(fh)) {
  262. SOCKET s = (SOCKET)_get_osfhandle(fh);
  263. if (s != INVALID_SOCKET) {
  264. auto r = folly::portability::sockets::send(fh, buf, (size_t)count, 0);
  265. if (r == -1 && WSAGetLastError() == WSAEWOULDBLOCK) {
  266. errno = EAGAIN;
  267. }
  268. return r;
  269. }
  270. }
  271. auto r = _write(fh, buf, static_cast<unsigned int>(count));
  272. if ((r > 0 && size_t(r) != count) || (r == -1 && errno == ENOSPC)) {
  273. // Writing to a pipe with a full buffer doesn't generate
  274. // any error type, unless it caused us to write exactly 0
  275. // bytes, so we have to see if we have a pipe first. We
  276. // don't touch the errno for anything else.
  277. HANDLE h = (HANDLE)_get_osfhandle(fh);
  278. if (GetFileType(h) == FILE_TYPE_PIPE) {
  279. DWORD state = 0;
  280. if (GetNamedPipeHandleState(
  281. h, &state, nullptr, nullptr, nullptr, nullptr, 0)) {
  282. if ((state & PIPE_NOWAIT) == PIPE_NOWAIT) {
  283. errno = EAGAIN;
  284. return -1;
  285. }
  286. }
  287. }
  288. }
  289. return r;
  290. }
  291. } // namespace unistd
  292. } // namespace portability
  293. } // namespace folly
  294. #endif