X-Git-Url: https://wimlib.net/git/?a=blobdiff_plain;f=src%2Fwin32_replacements.c;h=26f4b4b7969398ea7c6b81adb696d803703cbcd5;hb=b27e5a1c6b1662eda54ce751b8586fd7d5fb5133;hp=89289b0e056ab708a3696bee00094073c69876db;hpb=a92076249aa233d18ecc378062e654729e27c0d8;p=wimlib diff --git a/src/win32_replacements.c b/src/win32_replacements.c index 89289b0e..26f4b4b7 100644 --- a/src/win32_replacements.c +++ b/src/win32_replacements.c @@ -4,7 +4,7 @@ */ /* - * Copyright (C) 2013 Eric Biggers + * Copyright (C) 2013-2016 Eric Biggers * * This file is free software; you can redistribute it and/or modify it under * the terms of the GNU Lesser General Public License as published by the Free @@ -339,7 +339,7 @@ err: /* Use the Win32 API to get the number of processors. */ unsigned -win32_get_number_of_processors(void) +get_available_cpus(void) { SYSTEM_INFO sysinfo; GetSystemInfo(&sysinfo); @@ -348,7 +348,7 @@ win32_get_number_of_processors(void) /* Use the Win32 API to get the amount of available memory. */ u64 -win32_get_avail_memory(void) +get_available_memory(void) { MEMORYSTATUSEX status = { .dwLength = sizeof(status), @@ -483,51 +483,70 @@ 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; + DWORD err = 0; h = (HANDLE)_get_osfhandle(fd); if (h == INVALID_HANDLE_VALUE) - goto err; + goto error; if (GetFileType(h) == FILE_TYPE_PIPE) { errno = ESPIPE; - goto err; + goto error; } /* Get original position */ relative_offset.QuadPart = 0; - if (!SetFilePointerEx(h, relative_offset, &orig_offset, FILE_CURRENT)) - goto err_set_errno; + if (!SetFilePointerEx(h, relative_offset, &orig_offset, FILE_CURRENT)) { + err = GetLastError(); + win32_error(err, L"Failed to get original file position"); + goto error; + } memset(&overlapped, 0, sizeof(overlapped)); overlapped.Offset = 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); - if (!bret) - goto err_set_errno; + bret = ReadFile(h, buf, count, &result, &overlapped); + if (!bret) { + err = GetLastError(); + win32_error(err, L"Failed to %s %zu bytes at offset %"PRIu64, + (is_pwrite ? "write" : "read"), count, offset); + goto error; + } + + wimlib_assert(result <= count); /* Restore the original position */ - if (!SetFilePointerEx(h, orig_offset, NULL, FILE_BEGIN)) - goto err_set_errno; + if (!SetFilePointerEx(h, orig_offset, NULL, FILE_BEGIN)) { + err = GetLastError(); + win32_error(err, L"Failed to restore file position to %"PRIu64, + offset); + goto error; + } - return bytes_read_or_written; -err_set_errno: - set_errno_from_GetLastError(); -err: + return result; + +error: + if (err) + set_errno_from_win32_error(err); return -1; } @@ -535,7 +554,7 @@ err: * 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); } @@ -544,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