From: Christopher Dykes Date: Fri, 6 May 2016 00:24:55 +0000 (-0700) Subject: Create the unistd.h portability header X-Git-Tag: 2016.07.26~272 X-Git-Url: http://demsky.eecs.uci.edu/git/?a=commitdiff_plain;h=af77aab7ea371176605245b4056d0a46efbfcaba;p=folly.git Create the unistd.h portability header Summary: Windows doesn't have it, and it's used in a lot of places. Reviewed By: yfeldblum Differential Revision: D2997499 fb-gh-sync-id: fbf8f5f087b8f39197d5bf2177e4d34efd74631f fbshipit-source-id: fbf8f5f087b8f39197d5bf2177e4d34efd74631f --- diff --git a/folly/Makefile.am b/folly/Makefile.am index 912e117b..70c2d31d 100644 --- a/folly/Makefile.am +++ b/folly/Makefile.am @@ -299,6 +299,7 @@ nobase_follyinclude_HEADERS = \ portability/SysUio.h \ portability/Time.h \ portability/Windows.h \ + portability/Unistd.h \ Preprocessor.h \ ProducerConsumerQueue.h \ Random.h \ @@ -441,6 +442,7 @@ libfolly_la_SOURCES = \ portability/SysStat.cpp \ portability/SysTime.cpp \ portability/Time.cpp \ + portability/Unistd.cpp \ Random.cpp \ SafeAssert.cpp \ SharedMutex.cpp \ diff --git a/folly/portability/Unistd.cpp b/folly/portability/Unistd.cpp new file mode 100755 index 00000000..33a8f7a4 --- /dev/null +++ b/folly/portability/Unistd.cpp @@ -0,0 +1,207 @@ +/* + * Copyright 2016 Facebook, Inc. + * + * 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. + */ + +#include + +#ifdef _WIN32 +#include +#include +#include +#include + +// Generic wrapper for the p* family of functions. +template +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)) { + SOCKET h = (SOCKET)_get_osfhandle(fh); + return closesocket(h); + } + 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)) { + 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(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); } + +long lseek(int fh, long off, int orig) { return _lseek(fh, off, orig); } + +int rmdir(const char* path) { return _rmdir(path); } + +int pipe(int* pth) { return _pipe(pth, 0, _O_BINARY); } + +int pread(int fd, void* buf, size_t count, off_t offset) { + return wrapPositional(_read, fd, offset, buf, (unsigned int)count); +} + +int pwrite(int fd, const void* buf, size_t count, off_t offset) { + return wrapPositional(_write, fd, offset, buf, (unsigned int)count); +} + +int read(int fh, void* buf, unsigned int mcc) { return _read(fh, buf, mcc); } + +ssize_t readlink(const char* path, char* buf, size_t buflen) { + if (!buflen) { + return -1; + } + + HANDLE h = CreateFile(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, 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; } + +int setmode(int fh, int md) { return _setmode(fh, md); } + +unsigned int sleep(unsigned int seconds) { + Sleep((DWORD)(seconds * 1000)); + return 0; +} + +size_t sysconf(int tp) { + switch (tp) { + case _SC_PAGESIZE: { + SYSTEM_INFO inf; + GetSystemInfo(&inf); + return (size_t)inf.dwPageSize; + } + case _SC_NPROCESSORS_ONLN: { + SYSTEM_INFO inf; + GetSystemInfo(&inf); + return (size_t)inf.dwNumberOfProcessors; + } + default: + return (size_t)-1; + } +} + +long tell(int fh) { return _tell(fh); } + +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; +} + +int write(int fh, void const* buf, unsigned int mcc) { + return _write(fh, buf, mcc); +} +} +} +} +#endif diff --git a/folly/portability/Unistd.h b/folly/portability/Unistd.h new file mode 100755 index 00000000..717fe03d --- /dev/null +++ b/folly/portability/Unistd.h @@ -0,0 +1,91 @@ +/* + * Copyright 2016 Facebook, Inc. + * + * 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. + */ + +#pragma once + +#ifndef _WIN32 +#include +#else +#include +#include +#include + +// This is different from the normal headers because there are a few cases, +// such as close(), where we need to override the definition of an existing +// function. To avoid conflicts at link time, everything here is in a namespace +// which is then used globally. + +#define _SC_PAGESIZE 1 +#define _SC_PAGE_SIZE _SC_PAGESIZE +#define _SC_NPROCESSORS_ONLN 2 +#define _SC_NPROCESSORS_CONF 2 + +// Windows doesn't define these, but these are the correct values +// for Windows. +#define STDIN_FILENO 0 +#define STDOUT_FILENO 1 +#define STDERR_FILENO 2 + +// Windows is weird and doesn't actually defined these +// for the parameters to access, so we have to do it ourselves -_-... +#define F_OK 0 +#define X_OK F_OK +#define W_OK 2 +#define R_OK 4 +#define RW_OK 6 + +#define F_LOCK _LK_LOCK +#define F_ULOCK _LK_UNLCK + +namespace folly { +namespace portability { +namespace unistd { +int access(char const* fn, int am); +int chdir(const char* path); +int close(int fh); +int dup(int fh); +int dup2(int fhs, int fhd); +int fsync(int fd); +int ftruncate(int fd, off_t len); +char* getcwd(char* buf, int sz); +int getdtablesize(); +int getgid(); +pid_t getpid(); +pid_t getppid(); +int getuid(); +int isatty(int fh); +int lockf(int fd, int cmd, off_t len); +long lseek(int fh, long off, int orig); +int read(int fh, void* buf, unsigned int mcc); +int rmdir(const char* path); +int pipe(int* pth); +int pread(int fd, void* buf, size_t count, off_t offset); +int pwrite(int fd, const void* buf, size_t count, off_t offset); +ssize_t readlink(const char* path, char* buf, size_t buflen); +int setmode(int fh, int md); +void* sbrk(intptr_t i); +unsigned int sleep(unsigned int seconds); +size_t sysconf(int tp); +long tell(int fh); +int truncate(const char* path, off_t len); +int usleep(unsigned int ms); +int write(int fh, void const* buf, unsigned int mcc); +} +} +} + +/* using override */ using namespace folly::portability::unistd; +#endif