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