* details.
*
* You should have received a copy of the GNU Lesser General Public License
- * along with this file; if not, see http://www.gnu.org/licenses/.
+ * along with this file; if not, see https://www.gnu.org/licenses/.
*/
-#ifdef __WIN32__
+#ifdef _WIN32
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include <errno.h>
-#include <pthread.h>
#include <io.h> /* for _get_osfhandle() */
#include <fcntl.h>
#include "wimlib/assert.h"
#include "wimlib/glob.h"
#include "wimlib/error.h"
+#include "wimlib/timestamp.h"
#include "wimlib/util.h"
static int
p = tmpname;
p = wmempcpy(p, dstpath, dstlen);
p = wmempcpy(p, orig_suffix, ARRAY_LEN(orig_suffix));
- randomize_char_array_with_alnum(p, num_rand_chars);
+ get_random_alnum_chars(p, num_rand_chars);
p += num_rand_chars;
*p = L'\0';
}
return -1;
}
-/* This really could be replaced with _wcserror_s, but this doesn't seem to
- * actually be available in MSVCRT.DLL on Windows XP (perhaps it's statically
- * linked in by Visual Studio...?). */
-int
-win32_strerror_r_replacement(int errnum, wchar_t *buf, size_t buflen)
-{
- static pthread_mutex_t strerror_lock = PTHREAD_MUTEX_INITIALIZER;
-
- pthread_mutex_lock(&strerror_lock);
- mbstowcs(buf, strerror(errnum), buflen);
- buf[buflen - 1] = '\0';
- pthread_mutex_unlock(&strerror_lock);
- return 0;
-}
+#define MAX_IO_AMOUNT 1048576
static int
do_pread_or_pwrite(int fd, void *buf, size_t count, off_t offset,
{
HANDLE h;
LARGE_INTEGER orig_offset;
- DWORD bytes_read_or_written;
+ DWORD result = 0xFFFFFFFF;
LARGE_INTEGER relative_offset;
OVERLAPPED overlapped;
BOOL bret;
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,
goto error;
}
+ wimlib_assert(result <= count);
+
/* Restore the original position */
if (!SetFilePointerEx(h, orig_offset, NULL, FILE_BEGIN)) {
err = GetLastError();
goto error;
}
- return bytes_read_or_written;
+ return result;
error:
if (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);
}
* 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
pglob->gl_pathv[pglob->gl_pathc++] = path;
} while (FindNextFileW(hFind, &dat));
err = GetLastError();
- CloseHandle(hFind);
+ FindClose(hFind);
if (err != ERROR_NO_MORE_FILES) {
set_errno_from_win32_error(err);
ret = GLOB_ABORTED;
return 0;
oom:
- CloseHandle(hFind);
+ FindClose(hFind);
errno = ENOMEM;
ret = GLOB_NOSPACE;
fail_globfree:
return fp;
}
-#endif /* __WIN32__ */
+#define RtlGenRandom SystemFunction036
+BOOLEAN WINAPI RtlGenRandom(PVOID RandomBuffer, ULONG RandomBufferLength);
+
+/*
+ * Generate @n cryptographically secure random bytes (thread-safe)
+ *
+ * This is the Windows version. It uses RtlGenRandom() (actually called
+ * SystemFunction036) from advapi32.dll.
+ */
+void
+get_random_bytes(void *p, size_t n)
+{
+ while (n != 0) {
+ u32 count = min(n, UINT32_MAX);
+
+ if (!RtlGenRandom(p, count)) {
+ win32_error(GetLastError(),
+ L"RtlGenRandom() failed (count=%u)", count);
+ wimlib_assert(0);
+ count = 0;
+ }
+ p += count;
+ n -= count;
+ }
+}
+
+/* Retrieve the current time as a WIM timestamp. */
+u64
+now_as_wim_timestamp(void)
+{
+ FILETIME ft;
+
+ GetSystemTimeAsFileTime(&ft);
+
+ return ((u64)ft.dwHighDateTime << 32) | ft.dwLowDateTime;
+}
+
+#endif /* _WIN32 */