Skip to content

Commit d8f101e

Browse files
committed
Handle multibyte paths on Windows
1 parent ee39300 commit d8f101e

File tree

1 file changed

+50
-2
lines changed

1 file changed

+50
-2
lines changed

src/io.c

Lines changed: 50 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -408,6 +408,28 @@ dispatch_io_create_f(dispatch_io_type_t type, dispatch_fd_t fd,
408408

409409
#if defined(_WIN32)
410410
#define _is_separator(ch) ((ch) == '/' || (ch) == '\\')
411+
412+
static WCHAR *
413+
_dispatch_win32_copy_wide_from_utf8(const char *str) {
414+
int cchLength = MultiByteToWideChar(CP_UTF8, 0, str, -1, NULL, 0);
415+
if (cchLength <= 0) {
416+
return NULL;
417+
}
418+
419+
WCHAR *wszResult = malloc(cchLength * sizeof(WCHAR));
420+
if (!wszResult) {
421+
return NULL;
422+
}
423+
424+
cchLength = MultiByteToWideChar(CP_UTF8, 0, str, -1, wszResult, cchLength);
425+
if (cchLength) {
426+
return wszResult;
427+
}
428+
429+
free(wszResult);
430+
return NULL;
431+
}
432+
411433
#else
412434
#define _is_separator(ch) ((ch) == '/')
413435
#endif
@@ -447,10 +469,23 @@ dispatch_io_create_with_path(dispatch_io_type_t type, const char *path,
447469
_dispatch_retain(channel);
448470
dispatch_async(channel->queue, ^{
449471
int err = 0;
472+
#if defined(_WIN32)
473+
struct _stat st;
474+
wchar_t *wszPath = _dispatch_win32_copy_wide_from_utf8(path);
475+
if (!wszPath) {
476+
err = (int)GetLastError();
477+
free(path_data);
478+
_dispatch_io_init(channel, NULL, queue, err, cleanup_handler);
479+
_dispatch_release(channel);
480+
_dispatch_release(queue);
481+
return;
482+
}
483+
#else
450484
struct stat st;
485+
#endif
451486
_dispatch_io_syscall_switch_noerr(err,
452487
#if defined(_WIN32)
453-
stat(path_data->path, &st),
488+
_wstat(wszPath, &st),
454489
#else
455490
(path_data->oflag & O_NOFOLLOW) == O_NOFOLLOW
456491
#if __APPLE__
@@ -476,7 +511,11 @@ dispatch_io_create_with_path(dispatch_io_type_t type, const char *path,
476511
*c = 0;
477512
int perr;
478513
_dispatch_io_syscall_switch_noerr(perr,
514+
#if defined(_WIN32)
515+
_wstat(wszPath, &st),
516+
#else
479517
stat(path_data->path, &st),
518+
#endif
480519
case 0:
481520
// Since the parent directory exists, open() will
482521
// create a regular file after the fd_entry has
@@ -493,6 +532,9 @@ dispatch_io_create_with_path(dispatch_io_type_t type, const char *path,
493532
}
494533
break;
495534
);
535+
#if defined(_WIN32)
536+
free(wszPath);
537+
#endif
496538
channel->err = err;
497539
if (err) {
498540
free(path_data);
@@ -1333,9 +1375,15 @@ _dispatch_fd_entry_guarded_open(dispatch_fd_entry_t fd_entry, const char *path,
13331375
} else if (oflag & _O_TRUNC) {
13341376
dwCreationDisposition = TRUNCATE_EXISTING;
13351377
}
1336-
return (dispatch_fd_t)CreateFile(path, dwDesiredAccess,
1378+
WCHAR *wszPath = _dispatch_win32_copy_wide_from_utf8(path);
1379+
if (!wszPath) {
1380+
return -1;
1381+
}
1382+
dispatch_fd_t fd = (dispatch_fd_t)CreateFileW(wszPath, dwDesiredAccess,
13371383
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL,
13381384
dwCreationDisposition, 0, NULL);
1385+
free(wszPath);
1386+
return fd;
13391387
#else
13401388
return open(path, oflag, mode);
13411389
#endif

0 commit comments

Comments
 (0)