#define UMDF_USING_NTSTATUS
#include <folly/ScopeGuard.h>
#include <folly/portability/Unistd.h>
#if defined(__APPLE__)
off64_t lseek64(int fh, off64_t off, int orig) { … }
ssize_t pread64(int fd, void* buf, size_t count, off64_t offset) { … }
static_assert …;
#endif
#ifdef _WIN32
#include <cstdio>
#include <fcntl.h>
#include <folly/net/detail/SocketFileDescriptorMap.h>
#include <folly/portability/Sockets.h>
#include <folly/portability/Windows.h>
#include <tlhelp32.h>
template <bool is64Bit, class Offset>
static Offset seek(int fd, Offset offset, int whence) {
Offset res;
if (is64Bit) {
res = lseek64(fd, offset, whence);
} else {
res = lseek(fd, offset, whence);
}
return res;
}
template <bool is64Bit, class F, class Offset, class... Args>
static int wrapPositional(F f, int fd, Offset offset, Args... args) {
Offset origLoc = seek<is64Bit>(fd, 0, SEEK_CUR);
if (origLoc == Offset(-1)) {
return -1;
}
Offset moved = seek<is64Bit>(fd, offset, SEEK_SET);
if (moved == Offset(-1)) {
return -1;
}
int res = (int)f(fd, args...);
int curErrNo = errno;
Offset afterOperation = seek<is64Bit>(fd, origLoc, SEEK_SET);
if (afterOperation == Offset(-1)) {
if (res == -1) {
errno = curErrNo;
}
return -1;
}
errno = curErrNo;
return res;
}
namespace folly {
namespace portability {
namespace unistd {
namespace {
struct UniqueHandleWrapper {
UniqueHandleWrapper(HANDLE handle) : handle_(handle) {}
HANDLE get() const { return handle_; }
bool valid() const { return handle_ != INVALID_HANDLE_VALUE; }
UniqueHandleWrapper(UniqueHandleWrapper&& other) {
handle_ = other.handle_;
other.handle_ = INVALID_HANDLE_VALUE;
}
UniqueHandleWrapper& operator=(UniqueHandleWrapper&& other) {
handle_ = other.handle_;
other.handle_ = INVALID_HANDLE_VALUE;
return *this;
}
UniqueHandleWrapper(const UniqueHandleWrapper& other) = delete;
UniqueHandleWrapper& operator=(const UniqueHandleWrapper& other) = delete;
~UniqueHandleWrapper() {
if (valid()) {
CloseHandle(handle_);
}
}
private:
HANDLE handle_;
};
struct ProcessHandleWrapper {
ProcessHandleWrapper(HANDLE handle)
: ProcessHandleWrapper(UniqueHandleWrapper(handle)) {}
ProcessHandleWrapper(UniqueHandleWrapper handle)
: procHandle_(std::move(handle)) {
id_ = procHandle_.valid() ? GetProcessId(procHandle_.get()) : 1;
}
pid_t id() const { return id_; }
private:
UniqueHandleWrapper procHandle_;
pid_t id_;
};
int64_t getProcessStartTime(HANDLE processHandle) {
FILETIME createTime;
FILETIME exitTime;
FILETIME kernelTime;
FILETIME userTime;
if (GetProcessTimes(
processHandle, &createTime, &exitTime, &kernelTime, &userTime) == 0) {
return -1;
}
ULARGE_INTEGER ret;
ret.LowPart = createTime.dwLowDateTime;
ret.HighPart = createTime.dwHighDateTime;
return ret.QuadPart;
}
ProcessHandleWrapper getParentProcessHandle() {
DWORD ppid = 1;
DWORD pid = GetCurrentProcessId();
UniqueHandleWrapper hSnapshot =
CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
if (!hSnapshot.valid()) {
return INVALID_HANDLE_VALUE;
}
PROCESSENTRY32 pe32;
ZeroMemory(&pe32, sizeof(pe32));
pe32.dwSize = sizeof(pe32);
if (!Process32First(hSnapshot.get(), &pe32)) {
return INVALID_HANDLE_VALUE;
}
do {
if (pe32.th32ProcessID == pid) {
ppid = pe32.th32ParentProcessID;
break;
}
} while (Process32Next(hSnapshot.get(), &pe32));
UniqueHandleWrapper parent = OpenProcess(PROCESS_ALL_ACCESS, false, ppid);
if (!parent.valid()) {
return INVALID_HANDLE_VALUE;
}
int64_t currentProcessStartTime = getProcessStartTime(GetCurrentProcess());
int64_t parentProcessStartTime = getProcessStartTime(parent.get());
if (currentProcessStartTime == -1 || parentProcessStartTime == -1 ||
currentProcessStartTime < parentProcessStartTime) {
return INVALID_HANDLE_VALUE;
}
return std::move(parent);
}
}
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) {
off_t origLoc = _lseek(fd, 0, SEEK_CUR);
if (origLoc == -1) {
return -1;
}
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;
}
if (_lseek(fd, origLoc, SEEK_SET) == -1) {
return -1;
}
return 0;
}
char* getcwd(char* buf, int sz) {
return _getcwd(buf, sz);
}
int getdtablesize() {
return _getmaxstdio();
}
gid_t getgid() {
return 1;
}
pid_t getppid() {
static ProcessHandleWrapper wrapper = getParentProcessHandle();
return wrapper.id();
}
uid_t 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);
}
off64_t lseek64(int fh, off64_t off, int orig) {
return _lseeki64(fh, static_cast<int64_t>(off), orig);
}
int rmdir(const char* path) {
return _rmdir(path);
}
int pipe(int pth[2]) {
return socketpair(PF_UNIX, SOCK_STREAM, 0, pth);
}
ssize_t pread(int fd, void* buf, size_t count, off_t offset) {
const bool is64Bit = false;
return wrapPositional<is64Bit>(_read, fd, offset, buf, (unsigned int)count);
}
ssize_t pread64(int fd, void* buf, size_t count, off64_t offset) {
const bool is64Bit = true;
return wrapPositional<is64Bit>(_read, fd, offset, buf, (unsigned int)count);
}
ssize_t pwrite(int fd, const void* buf, size_t count, off_t offset) {
const bool is64Bit = false;
return wrapPositional<is64Bit>(_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) {
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 ) {
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)) {
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;
}
}
}
}
#endif