e02a767c12f76336232dfe5ed44c7386c5d4d07f
[folly.git] / folly / portability / Fcntl.cpp
1 /*
2  * Copyright 2016 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 #include <folly/portability/Fcntl.h>
18
19 #ifdef _WIN32
20 #include <folly/portability/Sockets.h>
21 #include <folly/portability/SysStat.h>
22 #include <folly/portability/Windows.h>
23
24 namespace folly {
25 namespace portability {
26 namespace fcntl {
27 int creat(char const* fn, int pm) { return _creat(fn, pm); }
28
29 int fcntl(int fd, int cmd, ...) {
30   va_list args;
31   int res = -1;
32   va_start(args, cmd);
33   switch (cmd) {
34     case F_GETFD: {
35       HANDLE h = (HANDLE)_get_osfhandle(fd);
36       if (h != INVALID_HANDLE_VALUE) {
37         DWORD flags;
38         if (GetHandleInformation(h, &flags)) {
39           res = flags & HANDLE_FLAG_INHERIT;
40         }
41       }
42       break;
43     }
44     case F_SETFD: {
45       int flags = va_arg(args, int);
46       HANDLE h = (HANDLE)_get_osfhandle(fd);
47       if (h != INVALID_HANDLE_VALUE) {
48         if (SetHandleInformation(
49                 h, HANDLE_FLAG_INHERIT, (DWORD)(flags & FD_CLOEXEC))) {
50           res = 0;
51         }
52       }
53       break;
54     }
55     case F_GETFL: {
56       // No idea how to get the IO blocking mode, so return 0.
57       res = 0;
58       break;
59     }
60     case F_SETFL: {
61       int flags = va_arg(args, int);
62       if (flags & O_NONBLOCK) {
63         // If it's not a socket, it's probably a pipe, and
64         // those are non-blocking by default with Windows.
65         if (folly::portability::sockets::is_fh_socket(fd)) {
66           SOCKET s = (SOCKET)_get_osfhandle(fd);
67           if (s != INVALID_SOCKET) {
68             u_long nonBlockingEnabled = 1;
69             res = ioctlsocket(s, FIONBIO, &nonBlockingEnabled);
70           }
71         } else {
72           res = 0;
73         }
74       }
75       break;
76     }
77   }
78   va_end(args);
79   return res;
80 }
81
82 int open(char const* fn, int of, int pm) {
83   int fh;
84   int realMode = _S_IREAD;
85   if ((of & _O_RDWR) == _O_RDWR) {
86     realMode = _S_IREAD | _S_IWRITE;
87   } else if ((of & _O_WRONLY) == _O_WRONLY) {
88     realMode = _S_IWRITE;
89   } else if ((of & _O_RDONLY) != _O_RDONLY) {
90     // One of these needs to be present, just fail if
91     // none are.
92     return -1;
93   }
94   errno_t res = _sopen_s(&fh, fn, of, _SH_DENYNO, realMode);
95   return res ? -1 : fh;
96 }
97
98 int posix_fallocate(int fd, off_t offset, off_t len) {
99   // We'll pretend we always have enough space. We
100   // can't exactly pre-allocate on windows anyways.
101   return 0;
102 }
103 }
104 }
105 }
106 #endif