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