From 037c72fe6781df317a6c8cc04739d277cb96979f Mon Sep 17 00:00:00 2001 From: Alexandros Naskos Date: Mon, 15 Jun 2020 15:52:59 +0300 Subject: Convert paths to UTF-16 before calling CreateDirectory on windows --- src/os.cpp | 154 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 153 insertions(+), 1 deletion(-) (limited to 'src/os.cpp') diff --git a/src/os.cpp b/src/os.cpp index 26ed0dc4e1..1c61239e3b 100644 --- a/src/os.cpp +++ b/src/os.cpp @@ -6,8 +6,11 @@ */ #include "os.hpp" +#include "buffer.hpp" #include "util.hpp" #include "error.hpp" +#include "util_base.hpp" +#include #if defined(_WIN32) @@ -1426,7 +1429,8 @@ Error os_make_path(Buf *path) { Error os_make_dir(Buf *path) { #if defined(ZIG_OS_WINDOWS) - if (!CreateDirectory(buf_ptr(path), NULL)) { + PathSpace path_space = slice_to_prefixed_file_w({ (uint8_t*)buf_ptr(path), buf_len(path) }); + if (!CreateDirectoryW(&path_space.data.items[0], NULL)) { if (GetLastError() == ERROR_ALREADY_EXISTS) return ErrorPathAlreadyExists; if (GetLastError() == ERROR_PATH_NOT_FOUND) @@ -1719,6 +1723,26 @@ static uint8_t utf8CodepointSequenceLength(uint32_t c) { zig_unreachable(); } +// Ported from std.unicode.utf8ByteSequenceLength +static uint8_t utf8ByteSequenceLength(uint8_t first_byte) { + switch (clzll(~first_byte)) { + case 0: + return 1; + break; + case 2: + return 2; + break; + case 3: + return 3; + break; + case 4: + return 4; + break; + default: + zig_unreachable(); + } +} + // Ported from std/unicode.zig static size_t utf8Encode(uint32_t c, Slice out) { size_t length = utf8CodepointSequenceLength(c); @@ -1753,6 +1777,80 @@ static size_t utf8Encode(uint32_t c, Slice out) { return length; } +// Ported from std.unicode.utf8Decode2 +static uint32_t utf8Decode2(Slice bytes) { + assert(bytes.len == 2); + assert((bytes.at(0) & 0b11100000) == 0b11000000); + + uint32_t value = bytes.at(0) & 0b00011111; + assert((bytes.at(1) & 0b11000000) == 0b10000000); + value <<= 6; + value |= bytes.at(1) & 0b00111111; + + assert(value >= 0x80); + return value; +} + +// Ported from std.unicode.utf8Decode3 +static uint32_t utf8Decode3(Slice bytes) { + assert(bytes.len == 3); + assert((bytes.at(0) & 0b11110000) == 0b11100000); + + uint32_t value = bytes.at(0) & 0b00001111; + assert((bytes.at(1) & 0b11000000) == 0b10000000); + value <<= 6; + value |= bytes.at(1) & 0b00111111; + + assert((bytes.at(2) & 0b11000000) == 0b10000000); + value <<= 6; + value |= bytes.at(2) & 0b00111111; + + assert(value >= 0x80); + assert(value < 0xd800 || value > 0xdfff); + return value; +} + +// Ported from std.unicode.utf8Decode4 +static uint32_t utf8Decode4(Slice bytes) { + assert(bytes.len == 4); + assert((bytes.at(0) & 0b11111000) == 0b11110000); + + uint32_t value = bytes.at(0) & 0b00000111; + assert((bytes.at(1) & 0b11000000) == 0b10000000); + value <<= 6; + value |= bytes.at(1) & 0b00111111; + + assert((bytes.at(2) & 0b11000000) == 0b10000000); + value <<= 6; + value |= bytes.at(2) & 0b00111111; + + assert((bytes.at(3) & 0b11000000) == 0b10000000); + value <<= 6; + value |= bytes.at(3) & 0b00111111; + + assert(value >= 0x10000 && value <= 0x10FFFF); + return value; +} + +// Ported from std.unicode.utf8Decode +static uint32_t utf8Decode(Slice bytes) { + switch (bytes.len) { + case 1: + return bytes.at(0); + break; + case 2: + return utf8Decode2(bytes); + break; + case 3: + return utf8Decode3(bytes); + break; + case 4: + return utf8Decode4(bytes); + break; + default: + zig_unreachable(); + } +} // Ported from std.unicode.utf16leToUtf8Alloc static void utf16le_ptr_to_utf8(Buf *out, WCHAR *utf16le) { // optimistically guess that it will all be ascii. @@ -1770,6 +1868,60 @@ static void utf16le_ptr_to_utf8(Buf *out, WCHAR *utf16le) { out_index += utf8_len; } } + +// Ported from std.unicode.utf8ToUtf16Le +static size_t utf8_to_utf16le(WCHAR *utf16_le, Slice utf8) { + size_t dest_i = 0; + size_t src_i = 0; + while (src_i < utf8.len) { + uint8_t n = utf8ByteSequenceLength(utf8.at(src_i)); + size_t next_src_i = src_i + n; + uint32_t codepoint = utf8Decode(utf8.slice(src_i, next_src_i)); + if (codepoint < 0x10000) { + utf16_le[dest_i] = codepoint; + dest_i += 1; + } else { + WCHAR high = ((codepoint - 0x10000) >> 10) + 0xD800; + WCHAR low = (codepoint & 0x3FF) + 0xDC00; + utf16_le[dest_i] = high; + utf16_le[dest_i + 1] = low; + dest_i += 2; + } + src_i = next_src_i; + } + return dest_i; +} + +// Ported from std.os.windows.sliceToPrefixedFileW +PathSpace slice_to_prefixed_file_w(Slice path) { + PathSpace path_space; + for (size_t idx = 0; idx < path.len; idx++) { + assert(path.ptr[idx] != '*' && path.ptr[idx] != '?' && path.ptr[idx] != '"' && + path.ptr[idx] != '<' && path.ptr[idx] != '>' && path.ptr[idx] != '|'); + } + + size_t start_index; + if (memStartsWith(path, str("\\?")) || !isAbsoluteWindows(path)) { + start_index = 0; + } else { + static WCHAR prefix[4] = { u'\\', u'?', u'?', u'\\' }; + memCopy(path_space.data.slice(), Slice { prefix, 4 }); + start_index = 4; + } + + path_space.len = start_index + utf8_to_utf16le(path_space.data.slice().sliceFrom(start_index).ptr, path); + assert(path_space.len <= path_space.data.len); + + Slice path_slice = path_space.data.slice().slice(0, path_space.len); + for (size_t elem_idx = 0; elem_idx < path_slice.len; elem_idx += 1) { + if (path_slice.at(elem_idx) == '/') { + path_slice.at(elem_idx) = '\\'; + } + } + + path_space.data.items[path_space.len] = 0; + return path_space; +} #endif // Ported from std.os.getAppDataDir -- cgit v1.2.3 From 3b0b56b81a26d9ba4d42812843cf2e9407d6d2bc Mon Sep 17 00:00:00 2001 From: Alexandros Naskos Date: Mon, 15 Jun 2020 16:15:10 +0300 Subject: Switched more Windows FS calls to their wide versions --- src/os.cpp | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) (limited to 'src/os.cpp') diff --git a/src/os.cpp b/src/os.cpp index 1c61239e3b..b88e0510e3 100644 --- a/src/os.cpp +++ b/src/os.cpp @@ -776,7 +776,8 @@ Error os_fetch_file(FILE *f, Buf *out_buf) { Error os_file_exists(Buf *full_path, bool *result) { #if defined(ZIG_OS_WINDOWS) - *result = GetFileAttributes(buf_ptr(full_path)) != INVALID_FILE_ATTRIBUTES; + PathSpace path_space = slice_to_prefixed_file_w({ (uint8_t*)buf_ptr(full_path), buf_len(full_path) }); + *result = GetFileAttributesW(&path_space.data.items[0]) != INVALID_FILE_ATTRIBUTES; return ErrorNone; #else *result = access(buf_ptr(full_path), F_OK) != -1; @@ -1333,7 +1334,9 @@ Error os_rename(Buf *src_path, Buf *dest_path) { return ErrorNone; } #if defined(ZIG_OS_WINDOWS) - if (!MoveFileExA(buf_ptr(src_path), buf_ptr(dest_path), MOVEFILE_REPLACE_EXISTING)) { + PathSpace src_path_space = slice_to_prefixed_file_w({ (uint8_t*)buf_ptr(src_path), buf_len(src_path) }); + PathSpace dest_path_space = slice_to_prefixed_file_w({ (uint8_t*)buf_ptr(dest_path), buf_len(dest_path) }); + if (!MoveFileExW(&src_path_space.data.items[0], &dest_path_space.data.items[0], MOVEFILE_REPLACE_EXISTING | MOVEFILE_WRITE_THROUGH)) { return ErrorFileSystem; } #else @@ -2014,8 +2017,8 @@ Error os_self_exe_shared_libs(ZigList &paths) { Error os_file_open_rw(Buf *full_path, OsFile *out_file, OsFileAttr *attr, bool need_write, uint32_t mode) { #if defined(ZIG_OS_WINDOWS) - // TODO use CreateFileW - HANDLE result = CreateFileA(buf_ptr(full_path), + PathSpace path_space = slice_to_prefixed_file_w({ (uint8_t*)buf_ptr(full_path), buf_len(full_path) }); + HANDLE result = CreateFileW(&path_space.data.items[0], need_write ? (GENERIC_READ|GENERIC_WRITE) : GENERIC_READ, need_write ? 0 : FILE_SHARE_READ, nullptr, @@ -2119,8 +2122,9 @@ Error os_file_open_w(Buf *full_path, OsFile *out_file, OsFileAttr *attr, uint32_ Error os_file_open_lock_rw(Buf *full_path, OsFile *out_file) { #if defined(ZIG_OS_WINDOWS) + PathSpace path_space = slice_to_prefixed_file_w({ (uint8_t*)buf_ptr(full_path), buf_len(full_path) }); for (;;) { - HANDLE result = CreateFileA(buf_ptr(full_path), GENERIC_READ | GENERIC_WRITE, + HANDLE result = CreateFileW(&path_space.data.items[0], GENERIC_READ | GENERIC_WRITE, 0, nullptr, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, nullptr); if (result == INVALID_HANDLE_VALUE) { -- cgit v1.2.3 From c34bdff4bbba88feefeca6491730526b2cc9f72a Mon Sep 17 00:00:00 2001 From: Alexandros Naskos Date: Mon, 15 Jun 2020 18:38:41 +0300 Subject: Use more wide functions on windows --- src/os.cpp | 35 +++++++++++++++++------------------ src/os.hpp | 4 +++- 2 files changed, 20 insertions(+), 19 deletions(-) (limited to 'src/os.cpp') diff --git a/src/os.cpp b/src/os.cpp index b88e0510e3..d59cff62a2 100644 --- a/src/os.cpp +++ b/src/os.cpp @@ -11,6 +11,7 @@ #include "error.hpp" #include "util_base.hpp" #include +#include #if defined(_WIN32) @@ -76,6 +77,7 @@ typedef SSIZE_T ssize_t; #endif #if defined(ZIG_OS_WINDOWS) +static void utf16le_ptr_to_utf8(Buf *out, WCHAR *utf16le); static uint64_t windows_perf_freq; #elif defined(__MACH__) static clock_serv_t macos_calendar_clock; @@ -272,11 +274,13 @@ void os_path_join(Buf *dirname, Buf *basename, Buf *out_full_path) { Error os_path_real(Buf *rel_path, Buf *out_abs_path) { #if defined(ZIG_OS_WINDOWS) - buf_resize(out_abs_path, 4096); - if (_fullpath(buf_ptr(out_abs_path), buf_ptr(rel_path), buf_len(out_abs_path)) == nullptr) { - zig_panic("_fullpath failed"); + PathSpace rel_path_space = slice_to_prefixed_file_w({ (uint8_t*)buf_ptr(rel_path), buf_len(rel_path) }); + PathSpace out_abs_path_space; + + if (_wfullpath(&out_abs_path_space.data.items[0], &rel_path_space.data.items[0], PATH_MAX_WIDE) == nullptr) { + zig_panic("_wfullpath failed"); } - buf_resize(out_abs_path, strlen(buf_ptr(out_abs_path))); + utf16le_ptr_to_utf8(out_abs_path, &out_abs_path_space.data.items[0]); return ErrorNone; #elif defined(ZIG_OS_POSIX) buf_resize(out_abs_path, PATH_MAX + 1); @@ -1234,11 +1238,11 @@ Error os_fetch_file_path(Buf *full_path, Buf *out_contents) { Error os_get_cwd(Buf *out_cwd) { #if defined(ZIG_OS_WINDOWS) - char buf[4096]; - if (GetCurrentDirectory(4096, buf) == 0) { + PathSpace path_space; + if (GetCurrentDirectoryW(PATH_MAX_WIDE, &path_space.data.items[0]) == 0) { zig_panic("GetCurrentDirectory failed"); } - buf_init_from_str(out_cwd, buf); + utf16le_ptr_to_utf8(out_cwd, &path_space.data.items[0]); return ErrorNone; #elif defined(ZIG_OS_POSIX) char buf[PATH_MAX]; @@ -1538,18 +1542,13 @@ int os_init(void) { Error os_self_exe_path(Buf *out_path) { #if defined(ZIG_OS_WINDOWS) - buf_resize(out_path, 256); - for (;;) { - DWORD copied_amt = GetModuleFileName(nullptr, buf_ptr(out_path), buf_len(out_path)); - if (copied_amt <= 0) { - return ErrorFileNotFound; - } - if (copied_amt < buf_len(out_path)) { - buf_resize(out_path, copied_amt); - return ErrorNone; - } - buf_resize(out_path, buf_len(out_path) * 2); + PathSpace path_space; + DWORD copied_amt = GetModuleFileNameW(nullptr, &path_space.data.items[0], PATH_MAX_WIDE); + if (copied_amt <= 0) { + return ErrorFileNotFound; } + utf16le_ptr_to_utf8(out_path, &path_space.data.items[0]); + return ErrorNone; #elif defined(ZIG_OS_DARWIN) // How long is the executable's path? diff --git a/src/os.hpp b/src/os.hpp index 12d0298ab7..9792a42c45 100644 --- a/src/os.hpp +++ b/src/os.hpp @@ -155,8 +155,10 @@ Error ATTRIBUTE_MUST_USE os_get_app_data_dir(Buf *out_path, const char *appname) Error ATTRIBUTE_MUST_USE os_self_exe_shared_libs(ZigList &paths); +const size_t PATH_MAX_WIDE = 32767; + struct PathSpace { - Array data; + Array data; size_t len; }; -- cgit v1.2.3 From 242246f79312f3106290b9b1aea6dfd5a18368b0 Mon Sep 17 00:00:00 2001 From: Alexandros Naskos Date: Mon, 15 Jun 2020 21:51:53 +0300 Subject: UTF16 create process, utf8->utf16 fix --- src/os.cpp | 60 ++++++++++++++++++++++++++++++++---------------------------- 1 file changed, 32 insertions(+), 28 deletions(-) (limited to 'src/os.cpp') diff --git a/src/os.cpp b/src/os.cpp index d59cff62a2..e363168579 100644 --- a/src/os.cpp +++ b/src/os.cpp @@ -7,6 +7,7 @@ #include "os.hpp" #include "buffer.hpp" +#include "heap.hpp" #include "util.hpp" #include "error.hpp" #include "util_base.hpp" @@ -78,6 +79,7 @@ typedef SSIZE_T ssize_t; #if defined(ZIG_OS_WINDOWS) static void utf16le_ptr_to_utf8(Buf *out, WCHAR *utf16le); +static size_t utf8_to_utf16le(WCHAR *utf16_le, Slice utf8); static uint64_t windows_perf_freq; #elif defined(__MACH__) static clock_serv_t macos_calendar_clock; @@ -153,15 +155,21 @@ static void os_spawn_process_windows(ZigList &args, Termination *t os_windows_create_command_line(&command_line, args); PROCESS_INFORMATION piProcInfo = {0}; - STARTUPINFO siStartInfo = {0}; - siStartInfo.cb = sizeof(STARTUPINFO); + STARTUPINFOW siStartInfo = {0}; + siStartInfo.cb = sizeof(STARTUPINFOW); - const char *exe = args.at(0); - BOOL success = CreateProcessA(exe, buf_ptr(&command_line), nullptr, nullptr, TRUE, 0, nullptr, nullptr, + Slice exe_slice = str(args.at(0)); + auto exe_utf16_slice = Slice::alloc(exe_slice.len + 1); + exe_utf16_slice.ptr[utf8_to_utf16le(exe_utf16_slice.ptr, exe_slice)] = 0; + + auto command_line_utf16 = Slice::alloc(buf_len(&command_line) + 1); + command_line_utf16.ptr[utf8_to_utf16le(command_line_utf16.ptr, buf_to_slice(&command_line))] = 0; + + BOOL success = CreateProcessW(exe_utf16_slice.ptr, command_line_utf16.ptr, nullptr, nullptr, TRUE, CREATE_UNICODE_ENVIRONMENT, nullptr, nullptr, &siStartInfo, &piProcInfo); if (!success) { - zig_panic("CreateProcess failed. exe: %s command_line: %s", exe, buf_ptr(&command_line)); + zig_panic("CreateProcess failed. exe: %s command_line: %s", args.at(0), buf_ptr(&command_line)); } WaitForSingleObject(piProcInfo.hProcess, INFINITE); @@ -274,7 +282,7 @@ void os_path_join(Buf *dirname, Buf *basename, Buf *out_full_path) { Error os_path_real(Buf *rel_path, Buf *out_abs_path) { #if defined(ZIG_OS_WINDOWS) - PathSpace rel_path_space = slice_to_prefixed_file_w({ (uint8_t*)buf_ptr(rel_path), buf_len(rel_path) }); + PathSpace rel_path_space = slice_to_prefixed_file_w(buf_to_slice(rel_path)); PathSpace out_abs_path_space; if (_wfullpath(&out_abs_path_space.data.items[0], &rel_path_space.data.items[0], PATH_MAX_WIDE) == nullptr) { @@ -780,7 +788,7 @@ Error os_fetch_file(FILE *f, Buf *out_buf) { Error os_file_exists(Buf *full_path, bool *result) { #if defined(ZIG_OS_WINDOWS) - PathSpace path_space = slice_to_prefixed_file_w({ (uint8_t*)buf_ptr(full_path), buf_len(full_path) }); + PathSpace path_space = slice_to_prefixed_file_w(buf_to_slice(full_path)); *result = GetFileAttributesW(&path_space.data.items[0]) != INVALID_FILE_ATTRIBUTES; return ErrorNone; #else @@ -1338,8 +1346,8 @@ Error os_rename(Buf *src_path, Buf *dest_path) { return ErrorNone; } #if defined(ZIG_OS_WINDOWS) - PathSpace src_path_space = slice_to_prefixed_file_w({ (uint8_t*)buf_ptr(src_path), buf_len(src_path) }); - PathSpace dest_path_space = slice_to_prefixed_file_w({ (uint8_t*)buf_ptr(dest_path), buf_len(dest_path) }); + PathSpace src_path_space = slice_to_prefixed_file_w(buf_to_slice(src_path)); + PathSpace dest_path_space = slice_to_prefixed_file_w(buf_to_slice(dest_path)); if (!MoveFileExW(&src_path_space.data.items[0], &dest_path_space.data.items[0], MOVEFILE_REPLACE_EXISTING | MOVEFILE_WRITE_THROUGH)) { return ErrorFileSystem; } @@ -1436,7 +1444,14 @@ Error os_make_path(Buf *path) { Error os_make_dir(Buf *path) { #if defined(ZIG_OS_WINDOWS) - PathSpace path_space = slice_to_prefixed_file_w({ (uint8_t*)buf_ptr(path), buf_len(path) }); + PathSpace path_space = slice_to_prefixed_file_w(buf_to_slice(path)); + if (memEql(buf_to_slice(path), str("C:\\dev\\tést"))) { + for (size_t i = 0; i < path_space.len; i++) { + fprintf(stderr, "%d ", path_space.data.items[i]); + } + fprintf(stderr, "\n"); + } + if (!CreateDirectoryW(&path_space.data.items[0], NULL)) { if (GetLastError() == ERROR_ALREADY_EXISTS) return ErrorPathAlreadyExists; @@ -1727,22 +1742,11 @@ static uint8_t utf8CodepointSequenceLength(uint32_t c) { // Ported from std.unicode.utf8ByteSequenceLength static uint8_t utf8ByteSequenceLength(uint8_t first_byte) { - switch (clzll(~first_byte)) { - case 0: - return 1; - break; - case 2: - return 2; - break; - case 3: - return 3; - break; - case 4: - return 4; - break; - default: - zig_unreachable(); - } + if (first_byte < 0b10000000) return 1; + if ((first_byte & 0b11100000) == 0b11000000) return 2; + if ((first_byte & 0b11110000) == 0b11100000) return 3; + if ((first_byte & 0b11111000) == 0b11110000) return 4; + zig_unreachable(); } // Ported from std/unicode.zig @@ -2016,7 +2020,7 @@ Error os_self_exe_shared_libs(ZigList &paths) { Error os_file_open_rw(Buf *full_path, OsFile *out_file, OsFileAttr *attr, bool need_write, uint32_t mode) { #if defined(ZIG_OS_WINDOWS) - PathSpace path_space = slice_to_prefixed_file_w({ (uint8_t*)buf_ptr(full_path), buf_len(full_path) }); + PathSpace path_space = slice_to_prefixed_file_w(buf_to_slice(full_path)); HANDLE result = CreateFileW(&path_space.data.items[0], need_write ? (GENERIC_READ|GENERIC_WRITE) : GENERIC_READ, need_write ? 0 : FILE_SHARE_READ, @@ -2121,7 +2125,7 @@ Error os_file_open_w(Buf *full_path, OsFile *out_file, OsFileAttr *attr, uint32_ Error os_file_open_lock_rw(Buf *full_path, OsFile *out_file) { #if defined(ZIG_OS_WINDOWS) - PathSpace path_space = slice_to_prefixed_file_w({ (uint8_t*)buf_ptr(full_path), buf_len(full_path) }); + PathSpace path_space = slice_to_prefixed_file_w(buf_to_slice(full_path)); for (;;) { HANDLE result = CreateFileW(&path_space.data.items[0], GENERIC_READ | GENERIC_WRITE, 0, nullptr, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, nullptr); -- cgit v1.2.3 From 2c8a3aaf855475cabef4e8275581a12b06417a02 Mon Sep 17 00:00:00 2001 From: Alexandros Naskos Date: Mon, 15 Jun 2020 22:21:01 +0300 Subject: Use _wfopen instead of fopen on windows --- src/os.cpp | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) (limited to 'src/os.cpp') diff --git a/src/os.cpp b/src/os.cpp index e363168579..33d98fd416 100644 --- a/src/os.cpp +++ b/src/os.cpp @@ -1037,7 +1037,12 @@ Error os_exec_process(ZigList &args, } Error os_write_file(Buf *full_path, Buf *contents) { +#if defined(ZIG_OS_WINDOWS) + PathSpace path_space = slice_to_prefixed_file_w(buf_to_slice(full_path)); + FILE *f = _wfopen(&path_space.data.items[0], L"wb"); +#else FILE *f = fopen(buf_ptr(full_path), "wb"); +#endif if (!f) { zig_panic("os_write_file failed for %s", buf_ptr(full_path)); } @@ -1072,7 +1077,12 @@ static Error copy_open_files(FILE *src_f, FILE *dest_f) { Error os_dump_file(Buf *src_path, FILE *dest_file) { Error err; +#if defined(ZIG_OS_WINDOWS) + PathSpace path_space = slice_to_prefixed_file_w(buf_to_slice(src_path)); + FILE *src_f = _wfopen(&path_space.data.items[0], L"rb"); +#else FILE *src_f = fopen(buf_ptr(src_path), "rb"); +#endif if (!src_f) { int err = errno; if (err == ENOENT) { @@ -1189,7 +1199,12 @@ Error os_update_file(Buf *src_path, Buf *dst_path) { } Error os_copy_file(Buf *src_path, Buf *dest_path) { +#if defined(ZIG_OS_WINDOWS) + PathSpace src_path_space = slice_to_prefixed_file_w(buf_to_slice(src_path)); + FILE *src_f = _wfopen(&src_path_space.data.items[0], L"rb"); +#else FILE *src_f = fopen(buf_ptr(src_path), "rb"); +#endif if (!src_f) { int err = errno; if (err == ENOENT) { @@ -1200,7 +1215,12 @@ Error os_copy_file(Buf *src_path, Buf *dest_path) { return ErrorFileSystem; } } +#if defined(ZIG_OS_WINDOWS) + PathSpace dest_path_space = slice_to_prefixed_file_w(buf_to_slice(dest_path)); + FILE *dest_f = _wfopen(&dest_path_space.data.items[0], L"wb"); +#else FILE *dest_f = fopen(buf_ptr(dest_path), "wb"); +#endif if (!dest_f) { int err = errno; if (err == ENOENT) { @@ -1221,7 +1241,12 @@ Error os_copy_file(Buf *src_path, Buf *dest_path) { } Error os_fetch_file_path(Buf *full_path, Buf *out_contents) { +#if defined(ZIG_OS_WINDOWS) + PathSpace path_space = slice_to_prefixed_file_w(buf_to_slice(full_path)); + FILE *f = _wfopen(&path_space.data.items[0], L"rb"); +#else FILE *f = fopen(buf_ptr(full_path), "rb"); +#endif if (!f) { switch (errno) { case EACCES: -- cgit v1.2.3