@@ -407,9 +407,13 @@ dispatch_io_create_f(dispatch_io_type_t type, dispatch_fd_t fd,
407407}
408408
409409#if defined(_WIN32 )
410- #define _is_separator (ch ) ((ch) == '/' || (ch) == '\\')
410+ #define _is_separator (ch ) ((ch) == L'/' || (ch) == L'\\')
411+ #define _dispatch_stat _wstati64
412+ typedef struct _stati64 _dispatch_stat_t ;
411413#else
412414#define _is_separator (ch ) ((ch) == '/')
415+ #define _dispatch_stat stat
416+ typedef struct stat _dispatch_stat_t ;
413417#endif
414418
415419dispatch_io_t
@@ -424,33 +428,51 @@ dispatch_io_create_with_path(dispatch_io_type_t type, const char *path,
424428 if (PathIsRelativeA (path )) {
425429 return DISPATCH_BAD_INPUT ;
426430 }
431+ int cchLength = MultiByteToWideChar (CP_UTF8 , MB_ERR_INVALID_CHARS , path , -1 , NULL , 0 );
432+ if (!cchLength ) {
433+ dispatch_assert (GetLastError () == ERROR_NO_UNICODE_TRANSLATION );
434+ return DISPATCH_BAD_INPUT ;
435+ }
436+ dispatch_io_path_data_t path_data = malloc (sizeof (* path_data ) + sizeof (WCHAR ) * cchLength );
437+ if (!path_data ) {
438+ return DISPATCH_OUT_OF_MEMORY ;
439+ }
440+ path_data -> pathlen = cchLength - 1 ; // Don't include terminating null character
441+ cchLength = MultiByteToWideChar (CP_UTF8 , MB_ERR_INVALID_CHARS , path , -1 , path_data -> path , cchLength );
442+ if (!cchLength ) {
443+ free (path_data );
444+ // We already checked the input when measuring buffer length.
445+ // Any error at this point seems fatal.
446+ DISPATCH_INTERNAL_CRASH (GetLastError (), "MultiByteToWideChar" );
447+ return DISPATCH_BAD_INPUT ;
448+ }
427449#else
428450 if (!_is_separator (* path )) {
429451 return DISPATCH_BAD_INPUT ;
430452 }
431- #endif
432453 size_t pathlen = strlen (path );
433454 dispatch_io_path_data_t path_data = malloc (sizeof (* path_data ) + pathlen + 1 );
434455 if (!path_data ) {
435456 return DISPATCH_OUT_OF_MEMORY ;
436457 }
458+ path_data -> pathlen = pathlen ;
459+ memcpy (path_data -> path , path , pathlen + 1 );
460+ #endif
437461 dispatch_io_t channel = _dispatch_io_create (type );
438462 channel -> fd = -1 ;
439463 _dispatch_channel_debug ("create with path %s" , channel , path );
440464 channel -> fd_actual = -1 ;
441465 path_data -> channel = channel ;
442466 path_data -> oflag = oflag ;
443467 path_data -> mode = mode ;
444- path_data -> pathlen = pathlen ;
445- memcpy (path_data -> path , path , pathlen + 1 );
446468 _dispatch_retain (queue );
447469 _dispatch_retain (channel );
448470 dispatch_async (channel -> queue , ^{
449471 int err = 0 ;
450- struct stat st ;
472+ _dispatch_stat_t st ;
451473 _dispatch_io_syscall_switch_noerr (err ,
452474#if defined(_WIN32 )
453- stat (path_data -> path , & st ),
475+ _dispatch_stat (path_data -> path , & st ),
454476#else
455477 (path_data -> oflag & O_NOFOLLOW ) == O_NOFOLLOW
456478#if __APPLE__
@@ -465,7 +487,7 @@ dispatch_io_create_with_path(dispatch_io_type_t type, const char *path,
465487 if ((path_data -> oflag & O_CREAT ) &&
466488 !_is_separator (* (path_data -> path + path_data -> pathlen - 1 ))) {
467489 // Check parent directory
468- char * c = NULL ;
490+ dispatch_io_path_char_t * c = NULL ;
469491 for (ssize_t i = (ssize_t )path_data -> pathlen - 1 ; i >= 0 ; i -- ) {
470492 if (_is_separator (path_data -> path [i ])) {
471493 c = & path_data -> path [i ];
@@ -476,7 +498,7 @@ dispatch_io_create_with_path(dispatch_io_type_t type, const char *path,
476498 * c = 0 ;
477499 int perr ;
478500 _dispatch_io_syscall_switch_noerr (perr ,
479- stat (path_data -> path , & st ),
501+ _dispatch_stat (path_data -> path , & st ),
480502 case 0 :
481503 // Since the parent directory exists, open() will
482504 // create a regular file after the fd_entry has
@@ -486,7 +508,7 @@ dispatch_io_create_with_path(dispatch_io_type_t type, const char *path,
486508 break ;
487509 );
488510#if defined(_WIN32 )
489- * c = '\\' ;
511+ * c = L '\\' ;
490512#else
491513 * c = '/' ;
492514#endif
@@ -602,7 +624,11 @@ dispatch_io_create_with_io(dispatch_io_type_t type, dispatch_io_t in_channel,
602624 mode_t mode = in_channel -> fd_entry -> stat .mode ;
603625 dev_t dev = in_channel -> fd_entry -> stat .dev ;
604626 size_t path_data_len = sizeof (struct dispatch_io_path_data_s ) +
627+ #if defined(_WIN32 )
628+ sizeof (WCHAR ) * (in_channel -> fd_entry -> path_data -> pathlen + 1 );
629+ #else
605630 in_channel -> fd_entry -> path_data -> pathlen + 1 ;
631+ #endif
606632 dispatch_io_path_data_t path_data = malloc (path_data_len );
607633 memcpy (path_data , in_channel -> fd_entry -> path_data ,
608634 path_data_len );
@@ -1292,7 +1318,7 @@ _dispatch_fd_entry_unguard(dispatch_fd_entry_t fd_entry) { (void)fd_entry; }
12921318#endif // DISPATCH_USE_GUARDED_FD
12931319
12941320static inline dispatch_fd_t
1295- _dispatch_fd_entry_guarded_open (dispatch_fd_entry_t fd_entry , const char * path ,
1321+ _dispatch_fd_entry_guarded_open (dispatch_fd_entry_t fd_entry , const dispatch_io_path_char_t * path ,
12961322 int oflag , mode_t mode ) {
12971323#if DISPATCH_USE_GUARDED_FD
12981324 guardid_t guard = (uintptr_t )fd_entry ;
@@ -1333,7 +1359,7 @@ _dispatch_fd_entry_guarded_open(dispatch_fd_entry_t fd_entry, const char *path,
13331359 } else if (oflag & _O_TRUNC ) {
13341360 dwCreationDisposition = TRUNCATE_EXISTING ;
13351361 }
1336- return (dispatch_fd_t )CreateFile (path , dwDesiredAccess ,
1362+ return (dispatch_fd_t )CreateFileW (path , dwDesiredAccess ,
13371363 FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE , NULL ,
13381364 dwCreationDisposition , 0 , NULL );
13391365#else
@@ -1597,7 +1623,11 @@ _dispatch_fd_entry_create_with_path(dispatch_io_path_data_t path_data,
15971623 // On devs lock queue
15981624 dispatch_fd_entry_t fd_entry = _dispatch_fd_entry_create (
15991625 path_data -> channel -> queue );
1626+ #if defined(_WIN32 )
1627+ _dispatch_fd_entry_debug ("create: path %S" , fd_entry , path_data -> path );
1628+ #else
16001629 _dispatch_fd_entry_debug ("create: path %s" , fd_entry , path_data -> path );
1630+ #endif
16011631 if (S_ISREG (mode )) {
16021632#if defined(_WIN32 )
16031633 _dispatch_disk_init (fd_entry , 0 );
0 commit comments