Skip to content

Commit

Permalink
include,common: Add functions missing on Windows
Browse files Browse the repository at this point in the history
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 <[email protected]>
  • Loading branch information
petrutlucian94 committed Jul 8, 2020
1 parent ad1338c commit 8cd9278
Show file tree
Hide file tree
Showing 6 changed files with 181 additions and 5 deletions.
31 changes: 31 additions & 0 deletions src/common/buffer.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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!
Expand Down Expand Up @@ -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
{
Expand Down
118 changes: 117 additions & 1 deletion src/common/compat.cc
Original file line number Diff line number Diff line change
Expand Up @@ -213,6 +213,9 @@ char *ceph_strerror_r(int errnum, char *buf, size_t buflen)

#ifdef _WIN32

#include <iomanip>
#include <ctime>

// 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) {
Expand All @@ -227,4 +230,117 @@ int lchown(const char *path, uid_t owner, gid_t group) {
return 0;
}

#endif /* _WIN32 */
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 */
30 changes: 26 additions & 4 deletions src/include/compat.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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);
Expand All @@ -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 */
1 change: 1 addition & 0 deletions src/include/mempool.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
#include "include/ceph_assert.h"
#include "include/compact_map.h"
#include "include/compact_set.h"
#include "include/compat.h"


/*
Expand Down
5 changes: 5 additions & 0 deletions src/include/utime.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
#include <seastar/core/lowres_clock.hh>
#endif

#include "include/compat.h"
#include "include/types.h"
#include "include/timegm.h"
#include "common/strtol.h"
Expand Down Expand Up @@ -466,11 +467,15 @@ class utime_t {
}
}

#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)
Expand Down
1 change: 1 addition & 0 deletions src/include/win32/sys/uio.h
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
#include "include/compat.h"

0 comments on commit 8cd9278

Please sign in to comment.