Some more OpenSSL 1.1.0 compat APIs
[folly.git] / folly / portability / Fcntl.cpp
1 /*
2  * Copyright 2017 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) {
28   return _creat(fn, pm);
29 }
30
31 int fcntl(int fd, int cmd, ...) {
32   va_list args;
33   int res = -1;
34   va_start(args, cmd);
35   switch (cmd) {
36     case F_GETFD: {
37       HANDLE h = (HANDLE)_get_osfhandle(fd);
38       if (h != INVALID_HANDLE_VALUE) {
39         DWORD flags;
40         if (GetHandleInformation(h, &flags)) {
41           res = int(flags & HANDLE_FLAG_INHERIT);
42         }
43       }
44       break;
45     }
46     case F_SETFD: {
47       int flags = va_arg(args, int);
48       HANDLE h = (HANDLE)_get_osfhandle(fd);
49       if (h != INVALID_HANDLE_VALUE) {
50         if (SetHandleInformation(
51                 h, HANDLE_FLAG_INHERIT, (DWORD)(flags & FD_CLOEXEC))) {
52           res = 0;
53         }
54       }
55       break;
56     }
57     case F_GETFL: {
58       // No idea how to get the IO blocking mode, so return 0.
59       res = 0;
60       break;
61     }
62     case F_SETFL: {
63       int flags = va_arg(args, int);
64       if (flags & O_NONBLOCK) {
65         // If it's not a socket, it's probably a pipe.
66         if (folly::portability::sockets::is_fh_socket(fd)) {
67           SOCKET s = (SOCKET)_get_osfhandle(fd);
68           if (s != INVALID_SOCKET) {
69             u_long nonBlockingEnabled = 1;
70             res = ioctlsocket(s, FIONBIO, &nonBlockingEnabled);
71           }
72         } else {
73           HANDLE p = (HANDLE)_get_osfhandle(fd);
74           if (GetFileType(p) == FILE_TYPE_PIPE) {
75             DWORD newMode = PIPE_READMODE_BYTE | PIPE_NOWAIT;
76             if (SetNamedPipeHandleState(p, &newMode, nullptr, nullptr)) {
77               res = 0;
78             }
79           }
80         }
81       }
82       break;
83     }
84   }
85   va_end(args);
86   return res;
87 }
88
89 int open(char const* fn, int of, int pm) {
90   int fh;
91   int realMode = _S_IREAD;
92   if ((of & _O_RDWR) == _O_RDWR) {
93     realMode = _S_IREAD | _S_IWRITE;
94   } else if ((of & _O_WRONLY) == _O_WRONLY) {
95     realMode = _S_IWRITE;
96   } else if ((of & _O_RDONLY) != _O_RDONLY) {
97     // One of these needs to be present, just fail if
98     // none are.
99     return -1;
100   }
101   if (!strcmp(fn, "/dev/null")) {
102     // Windows doesn't have a /dev/null, but it does have
103     // NUL, which achieves the same result.
104     fn = "NUL";
105   }
106   errno_t res = _sopen_s(&fh, fn, of, _SH_DENYNO, realMode);
107   return res ? -1 : fh;
108 }
109
110 int posix_fallocate(int fd, off_t offset, off_t len) {
111   // We'll pretend we always have enough space. We
112   // can't exactly pre-allocate on windows anyways.
113   return 0;
114 }
115 }
116 }
117 }
118 #endif