cannam@135: // Copyright (c) 2013-2014 Sandstorm Development Group, Inc. and contributors cannam@135: // Licensed under the MIT License: cannam@135: // cannam@135: // Permission is hereby granted, free of charge, to any person obtaining a copy cannam@135: // of this software and associated documentation files (the "Software"), to deal cannam@135: // in the Software without restriction, including without limitation the rights cannam@135: // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell cannam@135: // copies of the Software, and to permit persons to whom the Software is cannam@135: // furnished to do so, subject to the following conditions: cannam@135: // cannam@135: // The above copyright notice and this permission notice shall be included in cannam@135: // all copies or substantial portions of the Software. cannam@135: // cannam@135: // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR cannam@135: // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, cannam@135: // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE cannam@135: // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER cannam@135: // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, cannam@135: // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN cannam@135: // THE SOFTWARE. cannam@135: cannam@135: #ifndef KJ_MINIPOSIX_H_ cannam@135: #define KJ_MINIPOSIX_H_ cannam@135: cannam@135: // This header provides a small subset of the POSIX API which also happens to be available on cannam@135: // Windows under slightly-different names. cannam@135: cannam@135: #if defined(__GNUC__) && !KJ_HEADER_WARNINGS cannam@135: #pragma GCC system_header cannam@135: #endif cannam@135: cannam@135: #if _WIN32 cannam@135: #include cannam@135: #include cannam@135: #include // _O_BINARY cannam@135: #else cannam@135: #include cannam@135: #include cannam@135: #endif cannam@135: cannam@135: #if !_WIN32 || __MINGW32__ cannam@135: #include cannam@135: #include cannam@135: #include cannam@135: #endif cannam@135: cannam@135: #if !_WIN32 cannam@135: #include cannam@135: #endif cannam@135: cannam@135: namespace kj { cannam@135: namespace miniposix { cannam@135: cannam@135: #if _WIN32 && !__MINGW32__ cannam@135: // We're on Windows and not MinGW. So, we need to define wrappers for the POSIX API. cannam@135: cannam@135: typedef int ssize_t; cannam@135: cannam@135: inline ssize_t read(int fd, void* buffer, size_t size) { cannam@135: return ::_read(fd, buffer, size); cannam@135: } cannam@135: inline ssize_t write(int fd, const void* buffer, size_t size) { cannam@135: return ::_write(fd, buffer, size); cannam@135: } cannam@135: inline int close(int fd) { cannam@135: return ::_close(fd); cannam@135: } cannam@135: cannam@135: #ifndef F_OK cannam@135: #define F_OK 0 // access() existence test cannam@135: #endif cannam@135: cannam@135: #ifndef S_ISREG cannam@135: #define S_ISREG(mode) (((mode) & S_IFMT) == S_IFREG) // stat() regular file test cannam@135: #endif cannam@135: #ifndef S_ISDIR cannam@135: #define S_ISDIR(mode) (((mode) & S_IFMT) == S_IFDIR) // stat() directory test cannam@135: #endif cannam@135: cannam@135: #ifndef STDIN_FILENO cannam@135: #define STDIN_FILENO 0 cannam@135: #endif cannam@135: #ifndef STDOUT_FILENO cannam@135: #define STDOUT_FILENO 1 cannam@135: #endif cannam@135: #ifndef STDERR_FILENO cannam@135: #define STDERR_FILENO 2 cannam@135: #endif cannam@135: cannam@135: #else cannam@135: // We're on a POSIX system or MinGW which already defines the wrappers for us. cannam@135: cannam@135: using ::ssize_t; cannam@135: using ::read; cannam@135: using ::write; cannam@135: using ::close; cannam@135: cannam@135: #endif cannam@135: cannam@135: #if _WIN32 cannam@135: // We're on Windows, including MinGW. pipe() and mkdir() are non-standard even on MinGW. cannam@135: cannam@135: inline int pipe(int fds[2]) { cannam@135: return ::_pipe(fds, 8192, _O_BINARY); cannam@135: } cannam@135: inline int mkdir(const char* path, int mode) { cannam@135: return ::_mkdir(path); cannam@135: } cannam@135: cannam@135: #else cannam@135: // We're on real POSIX. cannam@135: cannam@135: using ::pipe; cannam@135: using ::mkdir; cannam@135: cannam@135: inline size_t iovMax(size_t count) { cannam@135: // Apparently, there is a maximum number of iovecs allowed per call. I don't understand why. cannam@135: // Most platforms define IOV_MAX but Linux defines only UIO_MAXIOV and others, like Hurd, cannam@135: // define neither. cannam@135: // cannam@135: // On platforms where both IOV_MAX and UIO_MAXIOV are undefined, we poke sysconf(_SC_IOV_MAX), cannam@135: // then try to fall back to the POSIX-mandated minimum of _XOPEN_IOV_MAX if that fails. cannam@135: // cannam@135: // http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/limits.h.html#tag_13_23_03_01 cannam@135: cannam@135: #if defined(IOV_MAX) cannam@135: // Solaris (and others?) cannam@135: return IOV_MAX; cannam@135: #elif defined(UIO_MAXIOV) cannam@135: // Linux cannam@135: return UIO_MAXIOV; cannam@135: #else cannam@135: // POSIX mystery meat cannam@135: cannam@135: long iovmax; cannam@135: cannam@135: errno = 0; cannam@135: if ((iovmax = sysconf(_SC_IOV_MAX)) == -1) { cannam@135: // assume iovmax == -1 && errno == 0 means "unbounded" cannam@135: return errno ? _XOPEN_IOV_MAX : count; cannam@135: } else { cannam@135: return (size_t) iovmax; cannam@135: } cannam@135: #endif cannam@135: } cannam@135: cannam@135: #endif cannam@135: cannam@135: } // namespace miniposix cannam@135: } // namespace kj cannam@135: cannam@135: #endif // KJ_MINIPOSIX_H_