From b27e5a1c6b1662eda54ce751b8586fd7d5fb5133 Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Sun, 15 May 2016 13:15:05 -0500 Subject: [PATCH] Do not use read() and write() from MSVCRT --- include/wimlib/win32.h | 10 ++++-- src/file_io.c | 9 +++++- src/win32_replacements.c | 66 ++++++++++++++++++++++++++++++++++++---- 3 files changed, 76 insertions(+), 9 deletions(-) diff --git a/include/wimlib/win32.h b/include/wimlib/win32.h index 46d48a80..f0f99cc7 100644 --- a/include/wimlib/win32.h +++ b/include/wimlib/win32.h @@ -52,10 +52,16 @@ extern FILE * win32_open_logfile(const wchar_t *path); extern ssize_t -pread(int fd, void *buf, size_t count, off_t offset); +win32_read(int fd, void *buf, size_t count); extern ssize_t -pwrite(int fd, const void *buf, size_t count, off_t offset); +win32_write(int fd, const void *buf, size_t count); + +extern ssize_t +win32_pread(int fd, void *buf, size_t count, off_t offset); + +extern ssize_t +win32_pwrite(int fd, const void *buf, size_t count, off_t offset); #endif /* __WIN32__ */ diff --git a/src/file_io.c b/src/file_io.c index 26584b9a..8fbd01f9 100644 --- a/src/file_io.c +++ b/src/file_io.c @@ -29,7 +29,14 @@ #include "wimlib/error.h" #include "wimlib/file_io.h" #include "wimlib/util.h" -#include "wimlib/win32.h" /* For pread(), pwrite() replacements */ + +#ifdef __WIN32__ +# include "wimlib/win32.h" +# define read win32_read +# define write win32_write +# define pread win32_pread +# define pwrite win32_pwrite +#endif /* * Wrapper around read() that checks for errors and keeps retrying until all diff --git a/src/win32_replacements.c b/src/win32_replacements.c index 05b07db9..26f4b4b7 100644 --- a/src/win32_replacements.c +++ b/src/win32_replacements.c @@ -483,13 +483,15 @@ win32_strerror_r_replacement(int errnum, wchar_t *buf, size_t buflen) return 0; } +#define MAX_IO_AMOUNT 1048576 + static int do_pread_or_pwrite(int fd, void *buf, size_t count, off_t offset, bool is_pwrite) { HANDLE h; LARGE_INTEGER orig_offset; - DWORD bytes_read_or_written; + DWORD result = 0xFFFFFFFF; LARGE_INTEGER relative_offset; OVERLAPPED overlapped; BOOL bret; @@ -517,10 +519,12 @@ do_pread_or_pwrite(int fd, void *buf, size_t count, off_t offset, overlapped.OffsetHigh = offset >> 32; /* Do the read or write at the specified offset */ + count = min(count, MAX_IO_AMOUNT); + SetLastError(0); if (is_pwrite) - bret = WriteFile(h, buf, count, &bytes_read_or_written, &overlapped); + bret = WriteFile(h, buf, count, &result, &overlapped); else - bret = ReadFile(h, buf, count, &bytes_read_or_written, &overlapped); + bret = ReadFile(h, buf, count, &result, &overlapped); if (!bret) { err = GetLastError(); win32_error(err, L"Failed to %s %zu bytes at offset %"PRIu64, @@ -528,6 +532,8 @@ do_pread_or_pwrite(int fd, void *buf, size_t count, off_t offset, goto error; } + wimlib_assert(result <= count); + /* Restore the original position */ if (!SetFilePointerEx(h, orig_offset, NULL, FILE_BEGIN)) { err = GetLastError(); @@ -536,7 +542,7 @@ do_pread_or_pwrite(int fd, void *buf, size_t count, off_t offset, goto error; } - return bytes_read_or_written; + return result; error: if (err) @@ -548,7 +554,7 @@ error: * offset, so it is not safe to use with readers/writers on the same file * descriptor. */ ssize_t -pread(int fd, void *buf, size_t count, off_t offset) +win32_pread(int fd, void *buf, size_t count, off_t offset) { return do_pread_or_pwrite(fd, buf, count, offset, false); } @@ -557,11 +563,59 @@ pread(int fd, void *buf, size_t count, off_t offset) * offset, so it is not safe to use with readers/writers on the same file * descriptor. */ ssize_t -pwrite(int fd, const void *buf, size_t count, off_t offset) +win32_pwrite(int fd, const void *buf, size_t count, off_t offset) { return do_pread_or_pwrite(fd, (void*)buf, count, offset, true); } +/* Replacement for read() which doesn't hide the Win32 error code */ +ssize_t +win32_read(int fd, void *buf, size_t count) +{ + HANDLE h = (HANDLE)_get_osfhandle(fd); + DWORD result = 0xFFFFFFFF; + + if (h == INVALID_HANDLE_VALUE) + return -1; + + count = min(count, MAX_IO_AMOUNT); + SetLastError(0); + if (!ReadFile(h, buf, count, &result, NULL)) { + DWORD err = GetLastError(); + win32_error(err, + L"Error reading %zu bytes from fd %d", count, fd); + set_errno_from_win32_error(err); + return -1; + } + + wimlib_assert(result <= count); + return result; +} + +/* Replacement for write() which doesn't hide the Win32 error code */ +ssize_t +win32_write(int fd, const void *buf, size_t count) +{ + HANDLE h = (HANDLE)_get_osfhandle(fd); + DWORD result = 0xFFFFFFFF; + + if (h == INVALID_HANDLE_VALUE) + return -1; + + count = min(count, MAX_IO_AMOUNT); + SetLastError(0); + if (!WriteFile(h, buf, count, &result, NULL)) { + DWORD err = GetLastError(); + win32_error(err, + L"Error writing %zu bytes to fd %d", count, fd); + set_errno_from_win32_error(err); + return -1; + } + + wimlib_assert(result <= count); + return result; +} + /* Replacement for glob() in Windows native builds that operates on wide * characters. */ int -- 2.43.0