From: Lucian Petrut Date: Fri, 11 Oct 2019 14:21:45 +0000 (+0300) Subject: include,common: Add functions missing on Windows X-Git-Tag: v16.1.0~1760^2~4 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=8cd92783da9482d91ccdce90c3f43fad12588c75;p=ceph.git include,common: Add functions missing on Windows The following functions are not avaialble on Windows, so we'll need to define them. * strptime * pipe (defined as _pipe) * lrand48 * posix_memalign * pread, pwrite, fsync * readv, writev Signed-off-by: Lucian Petrut --- diff --git a/src/common/buffer.cc b/src/common/buffer.cc index 1751f8e8058c..695767cc4cd0 100644 --- a/src/common/buffer.cc +++ b/src/common/buffer.cc @@ -1869,6 +1869,7 @@ static int do_writev(int fd, struct iovec *vec, uint64_t offset, unsigned veclen return 0; } +#ifndef _WIN32 int buffer::list::write_fd(int fd) const { // use writev! @@ -1948,6 +1949,36 @@ int buffer::list::write_fd(int fd, uint64_t offset) const } return 0; } +#else +int buffer::list::write_fd(int fd) const +{ + // There's no writev on Windows. WriteFileGather may be an option, + // but it has strict requirements in terms of buffer size and alignment. + auto p = std::cbegin(_buffers); + uint64_t left_pbrs = get_num_buffers(); + while (left_pbrs) { + int written = 0; + while (written < p->length()) { + int r = ::write(fd, p->c_str(), p->length() - written); + if (r < 0) + return -errno; + + written += r; + } + } + + return 0; + +} +int buffer::list::write_fd(int fd, uint64_t offset) const +{ + int r = ::lseek64(fd, offset, SEEK_SET); + if (r != offset) + return -errno; + + return write_fd(fd); +} +#endif __u32 buffer::list::crc32c(__u32 crc) const { diff --git a/src/common/compat.cc b/src/common/compat.cc index 74e99165572c..23fe2fa0e9de 100644 --- a/src/common/compat.cc +++ b/src/common/compat.cc @@ -213,6 +213,9 @@ char *ceph_strerror_r(int errnum, char *buf, size_t buflen) #ifdef _WIN32 +#include +#include + // chown is not available on Windows. Plus, changing file owners is not // a common practice on Windows. int chown(const char *path, uid_t owner, gid_t group) { @@ -227,4 +230,117 @@ int lchown(const char *path, uid_t owner, gid_t group) { return 0; } -#endif /* _WIN32 */ \ No newline at end of file +int posix_memalign(void **memptr, size_t alignment, size_t size) { + *memptr = _aligned_malloc(size, alignment); + return *memptr ? 0 : errno; +} + +char *strptime(const char *s, const char *format, struct tm *tm) { + std::istringstream input(s); + input.imbue(std::locale(setlocale(LC_ALL, nullptr))); + input >> std::get_time(tm, format); + if (input.fail()) { + return nullptr; + } + return (char*)(s + input.tellg()); +} + +int pipe(int pipefd[2]) { + // We'll use the same pipe size as Linux (64kb). + return _pipe(pipefd, 0x10000, O_NOINHERIT); +} + +// lrand48 is not available on Windows. We'll generate a pseudo-random +// value in the 0 - 2^31 range by calling rand twice. +long int lrand48(void) { + long int val; + val = (long int) rand(); + val << 16; + val += (long int) rand(); + return val; +} + +int fsync(int fd) { + HANDLE handle = (HANDLE*)_get_osfhandle(fd); + if (handle == INVALID_HANDLE_VALUE) + return -1; + if (!FlushFileBuffers(handle)) + return -1; + return 0; +} + +ssize_t pwrite(int fd, const void *buf, size_t count, off_t offset) { + DWORD bytes_written = 0; + + HANDLE handle = (HANDLE*)_get_osfhandle(fd); + if (handle == INVALID_HANDLE_VALUE) + return -1; + + OVERLAPPED overlapped = { 0 }; + ULARGE_INTEGER offsetUnion; + offsetUnion.QuadPart = offset; + + overlapped.Offset = offsetUnion.LowPart; + overlapped.OffsetHigh = offsetUnion.HighPart; + + if (!WriteFile(handle, buf, count, &bytes_written, &overlapped)) + // we may consider mapping error codes, although that may + // not be exhaustive. + return -1; + + return bytes_written; +} + +ssize_t pread(int fd, void *buf, size_t count, off_t offset) { + DWORD bytes_read = 0; + + HANDLE handle = (HANDLE*)_get_osfhandle(fd); + if (handle == INVALID_HANDLE_VALUE) + return -1; + + OVERLAPPED overlapped = { 0 }; + ULARGE_INTEGER offsetUnion; + offsetUnion.QuadPart = offset; + + overlapped.Offset = offsetUnion.LowPart; + overlapped.OffsetHigh = offsetUnion.HighPart; + + if (!ReadFile(handle, buf, count, &bytes_read, &overlapped)) { + if (GetLastError() != ERROR_HANDLE_EOF) + return -1; + } + + return bytes_read; +} + +ssize_t preadv(int fd, const struct iovec *iov, int iov_cnt) { + ssize_t read = 0; + + for (int i = 0; i < iov_cnt; i++) { + int r = ::read(fd, iov[i].iov_base, iov[i].iov_len); + if (r < 0) + return r; + read += r; + if (r < iov[i].iov_len) + break; + } + + return read; +} + +ssize_t writev(int fd, const struct iovec *iov, int iov_cnt) { + ssize_t written = 0; + + for (int i = 0; i < iov_cnt; i++) { + int r = ::write(fd, iov[i].iov_base, iov[i].iov_len); + if (r < 0) + return r; + written += r; + if (r < iov[i].iov_len) + break; + } + + return written; +} + +#endif /* _WIN32 */ diff --git a/src/include/compat.h b/src/include/compat.h index 9197863e32b0..334d60eeace7 100644 --- a/src/include/compat.h +++ b/src/include/compat.h @@ -227,6 +227,11 @@ typedef union size_t _align; } cpu_set_t; +struct iovec { + void *iov_base; + size_t iov_len; +}; + #define SHUT_RD SD_RECEIVE #define SHUT_WR SD_SEND #define SHUT_RDWR SD_BOTH @@ -248,15 +253,27 @@ typedef union #define ESTALE 256 #define EREMOTEIO 257 -// O_CLOEXEC is not defined on Windows. Since handles aren't inherited -// with subprocesses unless explicitly requested, we'll define this -// flag as a no-op. -#define O_CLOEXEC 0 +#define IOV_MAX 1024 #ifdef __cplusplus extern "C" { #endif +ssize_t readv(int fd, const struct iovec *iov, int iov_cnt); +ssize_t writev(int fd, const struct iovec *iov, int iov_cnt); + +int fsync(int fd); +ssize_t pread(int fd, void *buf, size_t count, off_t offset); +ssize_t pwrite(int fd, const void *buf, size_t count, off_t offset); + +long int lrand48(void); + +int pipe(int pipefd[2]); + +int posix_memalign(void **memptr, size_t alignment, size_t size); + +char *strptime(const char *s, const char *format, struct tm *tm); + int chown(const char *path, uid_t owner, gid_t group); int fchown(int fd, uid_t owner, gid_t group); int lchown(const char *path, uid_t owner, gid_t group); @@ -265,6 +282,11 @@ int lchown(const char *path, uid_t owner, gid_t group); } #endif +// O_CLOEXEC is not defined on Windows. Since handles aren't inherited +// with subprocesses unless explicitly requested, we'll define this +// flag as a no-op. +#define O_CLOEXEC 0 + #endif /* WIN32 */ #endif /* !CEPH_COMPAT_H */ diff --git a/src/include/mempool.h b/src/include/mempool.h index 8027305688d2..79cf862c8cd7 100644 --- a/src/include/mempool.h +++ b/src/include/mempool.h @@ -31,6 +31,7 @@ #include "include/ceph_assert.h" #include "include/compact_map.h" #include "include/compact_set.h" +#include "include/compat.h" /* diff --git a/src/include/utime.h b/src/include/utime.h index 5e58f1b149e4..ab053433e2a0 100644 --- a/src/include/utime.h +++ b/src/include/utime.h @@ -24,6 +24,7 @@ #include #endif +#include "include/compat.h" #include "include/types.h" #include "include/timegm.h" #include "common/strtol.h" @@ -466,11 +467,15 @@ public: } } + #ifndef _WIN32 // apply the tm_gmtoff manually below, since none of mktime, // gmtime, and localtime seem to do it. zero it out here just in // case some other libc *does* apply it. :( auto gmtoff = tm.tm_gmtoff; tm.tm_gmtoff = 0; + #else + auto gmtoff = _timezone; + #endif /* _WIN32 */ time_t t = internal_timegm(&tm); if (epoch) diff --git a/src/include/win32/sys/uio.h b/src/include/win32/sys/uio.h new file mode 100644 index 000000000000..15e95be7fe8f --- /dev/null +++ b/src/include/win32/sys/uio.h @@ -0,0 +1 @@ +#include "include/compat.h"