@@ -407,9 +407,13 @@ dispatch_io_create_f(dispatch_io_type_t type, dispatch_fd_t fd,
407
407
}
408
408
409
409
#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 ;
411
413
#else
412
414
#define _is_separator (ch ) ((ch) == '/')
415
+ #define _dispatch_stat stat
416
+ typedef struct stat _dispatch_stat_t ;
413
417
#endif
414
418
415
419
dispatch_io_t
@@ -424,33 +428,51 @@ dispatch_io_create_with_path(dispatch_io_type_t type, const char *path,
424
428
if (PathIsRelativeA (path )) {
425
429
return DISPATCH_BAD_INPUT ;
426
430
}
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
+ }
427
449
#else
428
450
if (!_is_separator (* path )) {
429
451
return DISPATCH_BAD_INPUT ;
430
452
}
431
- #endif
432
453
size_t pathlen = strlen (path );
433
454
dispatch_io_path_data_t path_data = malloc (sizeof (* path_data ) + pathlen + 1 );
434
455
if (!path_data ) {
435
456
return DISPATCH_OUT_OF_MEMORY ;
436
457
}
458
+ path_data -> pathlen = pathlen ;
459
+ memcpy (path_data -> path , path , pathlen + 1 );
460
+ #endif
437
461
dispatch_io_t channel = _dispatch_io_create (type );
438
462
channel -> fd = -1 ;
439
463
_dispatch_channel_debug ("create with path %s" , channel , path );
440
464
channel -> fd_actual = -1 ;
441
465
path_data -> channel = channel ;
442
466
path_data -> oflag = oflag ;
443
467
path_data -> mode = mode ;
444
- path_data -> pathlen = pathlen ;
445
- memcpy (path_data -> path , path , pathlen + 1 );
446
468
_dispatch_retain (queue );
447
469
_dispatch_retain (channel );
448
470
dispatch_async (channel -> queue , ^{
449
471
int err = 0 ;
450
- struct stat st ;
472
+ _dispatch_stat_t st ;
451
473
_dispatch_io_syscall_switch_noerr (err ,
452
474
#if defined(_WIN32 )
453
- stat (path_data -> path , & st ),
475
+ _dispatch_stat (path_data -> path , & st ),
454
476
#else
455
477
(path_data -> oflag & O_NOFOLLOW ) == O_NOFOLLOW
456
478
#if __APPLE__
@@ -465,7 +487,7 @@ dispatch_io_create_with_path(dispatch_io_type_t type, const char *path,
465
487
if ((path_data -> oflag & O_CREAT ) &&
466
488
!_is_separator (* (path_data -> path + path_data -> pathlen - 1 ))) {
467
489
// Check parent directory
468
- char * c = NULL ;
490
+ dispatch_io_path_char_t * c = NULL ;
469
491
for (ssize_t i = (ssize_t )path_data -> pathlen - 1 ; i >= 0 ; i -- ) {
470
492
if (_is_separator (path_data -> path [i ])) {
471
493
c = & path_data -> path [i ];
@@ -476,7 +498,7 @@ dispatch_io_create_with_path(dispatch_io_type_t type, const char *path,
476
498
* c = 0 ;
477
499
int perr ;
478
500
_dispatch_io_syscall_switch_noerr (perr ,
479
- stat (path_data -> path , & st ),
501
+ _dispatch_stat (path_data -> path , & st ),
480
502
case 0 :
481
503
// Since the parent directory exists, open() will
482
504
// 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,
486
508
break ;
487
509
);
488
510
#if defined(_WIN32 )
489
- * c = '\\' ;
511
+ * c = L '\\' ;
490
512
#else
491
513
* c = '/' ;
492
514
#endif
@@ -602,7 +624,11 @@ dispatch_io_create_with_io(dispatch_io_type_t type, dispatch_io_t in_channel,
602
624
mode_t mode = in_channel -> fd_entry -> stat .mode ;
603
625
dev_t dev = in_channel -> fd_entry -> stat .dev ;
604
626
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
605
630
in_channel -> fd_entry -> path_data -> pathlen + 1 ;
631
+ #endif
606
632
dispatch_io_path_data_t path_data = malloc (path_data_len );
607
633
memcpy (path_data , in_channel -> fd_entry -> path_data ,
608
634
path_data_len );
@@ -1292,7 +1318,7 @@ _dispatch_fd_entry_unguard(dispatch_fd_entry_t fd_entry) { (void)fd_entry; }
1292
1318
#endif // DISPATCH_USE_GUARDED_FD
1293
1319
1294
1320
static 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 ,
1296
1322
int oflag , mode_t mode ) {
1297
1323
#if DISPATCH_USE_GUARDED_FD
1298
1324
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,
1333
1359
} else if (oflag & _O_TRUNC ) {
1334
1360
dwCreationDisposition = TRUNCATE_EXISTING ;
1335
1361
}
1336
- return (dispatch_fd_t )CreateFile (path , dwDesiredAccess ,
1362
+ return (dispatch_fd_t )CreateFileW (path , dwDesiredAccess ,
1337
1363
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE , NULL ,
1338
1364
dwCreationDisposition , 0 , NULL );
1339
1365
#else
@@ -1597,7 +1623,11 @@ _dispatch_fd_entry_create_with_path(dispatch_io_path_data_t path_data,
1597
1623
// On devs lock queue
1598
1624
dispatch_fd_entry_t fd_entry = _dispatch_fd_entry_create (
1599
1625
path_data -> channel -> queue );
1626
+ #if defined(_WIN32 )
1627
+ _dispatch_fd_entry_debug ("create: path %S" , fd_entry , path_data -> path );
1628
+ #else
1600
1629
_dispatch_fd_entry_debug ("create: path %s" , fd_entry , path_data -> path );
1630
+ #endif
1601
1631
if (S_ISREG (mode )) {
1602
1632
#if defined(_WIN32 )
1603
1633
_dispatch_disk_init (fd_entry , 0 );
0 commit comments