verdnatura-chat/ios/Pods/Flipper-Folly/folly/portability/Unistd.cpp

295 lines
6.5 KiB
C++
Raw Normal View History

/*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
// We need to prevent winnt.h from defining the core STATUS codes,
// otherwise they will conflict with what we're getting from ntstatus.h
#define UMDF_USING_NTSTATUS
#include <folly/portability/Unistd.h>
#ifdef _WIN32
#include <cstdio>
#include <fcntl.h>
#include <folly/net/detail/SocketFileDescriptorMap.h>
#include <folly/portability/Sockets.h>
#include <folly/portability/Windows.h>
// Generic wrapper for the p* family of functions.
template <class F, class... Args>
static int wrapPositional(F f, int fd, off_t offset, Args... args) {
off_t origLoc = lseek(fd, 0, SEEK_CUR);
if (origLoc == (off_t)-1) {
return -1;
}
if (lseek(fd, offset, SEEK_SET) == (off_t)-1) {
return -1;
}
int res = (int)f(fd, args...);
int curErrNo = errno;
if (lseek(fd, origLoc, SEEK_SET) == (off_t)-1) {
if (res == -1) {
errno = curErrNo;
}
return -1;
}
errno = curErrNo;
return res;
}
namespace folly {
namespace portability {
namespace unistd {
int access(char const* fn, int am) {
return _access(fn, am);
}
int chdir(const char* path) {
return _chdir(path);
}
int close(int fh) {
if (folly::portability::sockets::is_fh_socket(fh)) {
return netops::detail::SocketFileDescriptorMap::close(fh);
}
return _close(fh);
}
int dup(int fh) {
return _dup(fh);
}
int dup2(int fhs, int fhd) {
return _dup2(fhs, fhd);
}
int fsync(int fd) {
HANDLE h = (HANDLE)_get_osfhandle(fd);
if (h == INVALID_HANDLE_VALUE) {
return -1;
}
if (!FlushFileBuffers(h)) {
return -1;
}
return 0;
}
int ftruncate(int fd, off_t len) {
if (_lseek(fd, len, SEEK_SET) == -1) {
return -1;
}
HANDLE h = (HANDLE)_get_osfhandle(fd);
if (h == INVALID_HANDLE_VALUE) {
return -1;
}
if (!SetEndOfFile(h)) {
return -1;
}
return 0;
}
char* getcwd(char* buf, int sz) {
return _getcwd(buf, sz);
}
int getdtablesize() {
return _getmaxstdio();
}
int getgid() {
return 1;
}
pid_t getpid() {
return (pid_t)uint64_t(GetCurrentProcessId());
}
// No major need to implement this, and getting a non-potentially
// stale ID on windows is a bit involved.
pid_t getppid() {
return (pid_t)1;
}
int getuid() {
return 1;
}
int isatty(int fh) {
return _isatty(fh);
}
int lockf(int fd, int cmd, off_t len) {
return _locking(fd, cmd, len);
}
off_t lseek(int fh, off_t off, int orig) {
return _lseek(fh, off, orig);
}
int rmdir(const char* path) {
return _rmdir(path);
}
int pipe(int pth[2]) {
// We need to be able to listen to pipes with
// libevent, so they need to be actual sockets.
return socketpair(PF_UNIX, SOCK_STREAM, 0, pth);
}
ssize_t pread(int fd, void* buf, size_t count, off_t offset) {
return wrapPositional(_read, fd, offset, buf, (unsigned int)count);
}
ssize_t pwrite(int fd, const void* buf, size_t count, off_t offset) {
return wrapPositional(_write, fd, offset, buf, (unsigned int)count);
}
ssize_t read(int fh, void* buf, size_t count) {
if (folly::portability::sockets::is_fh_socket(fh)) {
SOCKET s = (SOCKET)_get_osfhandle(fh);
if (s != INVALID_SOCKET) {
auto r = folly::portability::sockets::recv(fh, buf, count, 0);
if (r == -1 && WSAGetLastError() == WSAEWOULDBLOCK) {
errno = EAGAIN;
}
return r;
}
}
auto r = _read(fh, buf, static_cast<unsigned int>(count));
if (r == -1 && GetLastError() == ERROR_NO_DATA) {
// This only happens if the file was non-blocking and
// no data was present. We have to translate the error
// to a form that the rest of the world is expecting.
errno = EAGAIN;
}
return r;
}
ssize_t readlink(const char* path, char* buf, size_t buflen) {
if (!buflen) {
return -1;
}
HANDLE h = CreateFileA(
path,
GENERIC_READ,
FILE_SHARE_READ,
nullptr,
OPEN_EXISTING,
FILE_FLAG_BACKUP_SEMANTICS,
nullptr);
if (h == INVALID_HANDLE_VALUE) {
return -1;
}
DWORD ret =
GetFinalPathNameByHandleA(h, buf, DWORD(buflen - 1), VOLUME_NAME_DOS);
if (ret >= buflen || ret >= MAX_PATH || !ret) {
CloseHandle(h);
return -1;
}
CloseHandle(h);
buf[ret] = '\0';
return ret;
}
void* sbrk(intptr_t /* i */) {
return (void*)-1;
}
unsigned int sleep(unsigned int seconds) {
Sleep((DWORD)(seconds * 1000));
return 0;
}
long sysconf(int tp) {
switch (tp) {
case _SC_PAGESIZE: {
SYSTEM_INFO inf;
GetSystemInfo(&inf);
return (long)inf.dwPageSize;
}
case _SC_NPROCESSORS_ONLN: {
SYSTEM_INFO inf;
GetSystemInfo(&inf);
return (long)inf.dwNumberOfProcessors;
}
default:
return -1L;
}
}
int truncate(const char* path, off_t len) {
int fd = _open(path, O_WRONLY);
if (!fd) {
return -1;
}
if (ftruncate(fd, len)) {
_close(fd);
return -1;
}
return _close(fd) ? -1 : 0;
}
int usleep(unsigned int ms) {
Sleep((DWORD)(ms / 1000));
return 0;
}
ssize_t write(int fh, void const* buf, size_t count) {
if (folly::portability::sockets::is_fh_socket(fh)) {
SOCKET s = (SOCKET)_get_osfhandle(fh);
if (s != INVALID_SOCKET) {
auto r = folly::portability::sockets::send(fh, buf, (size_t)count, 0);
if (r == -1 && WSAGetLastError() == WSAEWOULDBLOCK) {
errno = EAGAIN;
}
return r;
}
}
auto r = _write(fh, buf, static_cast<unsigned int>(count));
if ((r > 0 && size_t(r) != count) || (r == -1 && errno == ENOSPC)) {
// Writing to a pipe with a full buffer doesn't generate
// any error type, unless it caused us to write exactly 0
// bytes, so we have to see if we have a pipe first. We
// don't touch the errno for anything else.
HANDLE h = (HANDLE)_get_osfhandle(fh);
if (GetFileType(h) == FILE_TYPE_PIPE) {
DWORD state = 0;
if (GetNamedPipeHandleState(
h, &state, nullptr, nullptr, nullptr, nullptr, 0)) {
if ((state & PIPE_NOWAIT) == PIPE_NOWAIT) {
errno = EAGAIN;
return -1;
}
}
}
}
return r;
}
} // namespace unistd
} // namespace portability
} // namespace folly
#endif