@@ -406,15 +406,29 @@ dispatch_io_create_f(dispatch_io_type_t type, dispatch_fd_t fd,
406406^(int error ){ cleanup_handler (context , error ); });
407407}
408408
409+ #if defined(_WIN32 )
410+ #define _is_separator (ch ) ((ch) == '/' || (ch) == '\\')
411+ #else
412+ #define _is_separator (ch ) ((ch) == '/')
413+ #endif
414+
409415dispatch_io_t
410416dispatch_io_create_with_path (dispatch_io_type_t type , const char * path ,
411417int oflag , mode_t mode , dispatch_queue_t queue ,
412418void (^cleanup_handler )(int error ))
413419{
414- if ((type != DISPATCH_IO_STREAM && type != DISPATCH_IO_RANDOM ) ||
415- !(* path == '/' )) {
420+ if (type != DISPATCH_IO_STREAM && type != DISPATCH_IO_RANDOM ) {
421+ return DISPATCH_BAD_INPUT ;
422+ }
423+ #if defined(_WIN32 )
424+ if (PathIsRelativeA (path )) {
425+ return DISPATCH_BAD_INPUT ;
426+ }
427+ #else
428+ if (!_is_separator (* path )) {
416429return DISPATCH_BAD_INPUT ;
417430}
431+ #endif
418432size_t pathlen = strlen (path );
419433dispatch_io_path_data_t path_data = malloc (sizeof (* path_data ) + pathlen + 1 );
420434if (!path_data ) {
@@ -449,9 +463,15 @@ dispatch_io_create_with_path(dispatch_io_type_t type, const char *path,
449463break ;
450464default :
451465if ((path_data -> oflag & O_CREAT ) &&
452- (* (path_data -> path + path_data -> pathlen - 1 ) != '/' )) {
466+ ! _is_separator (* (path_data -> path + path_data -> pathlen - 1 ))) {
453467// Check parent directory
454- char * c = strrchr (path_data -> path , '/' );
468+ char * c = NULL ;
469+ for (ssize_t i = (ssize_t )path_data -> pathlen - 1 ; i >= 0 ; i -- ) {
470+ if (_is_separator (path_data -> path [i ])) {
471+ c = & path_data -> path [i ];
472+ break ;
473+ }
474+ }
455475dispatch_assert (c );
456476* c = 0 ;
457477int perr ;
@@ -465,7 +485,11 @@ dispatch_io_create_with_path(dispatch_io_type_t type, const char *path,
465485err = 0 ;
466486break ;
467487);
488+ #if defined(_WIN32 )
489+ * c = '\\' ;
490+ #else
468491* c = '/' ;
492+ #endif
469493}
470494break ;
471495);
@@ -1287,18 +1311,31 @@ _dispatch_fd_entry_guarded_open(dispatch_fd_entry_t fd_entry, const char *path,
12871311#if defined(_WIN32 )
12881312(void )mode ;
12891313DWORD dwDesiredAccess = 0 ;
1290- if (oflag & _O_RDWR )
1291- dwDesiredAccess = GENERIC_READ | GENERIC_WRITE ;
1292- else if (oflag & _O_RDONLY )
1293- dwDesiredAccess = GENERIC_READ ;
1294- else if (oflag & _O_WRONLY )
1295- dwDesiredAccess = GENERIC_WRITE ;
1314+ switch (oflag & (_O_RDONLY | _O_WRONLY | _O_RDWR )) {
1315+ case _O_RDONLY :
1316+ dwDesiredAccess = GENERIC_READ ;
1317+ break ;
1318+ case _O_WRONLY :
1319+ dwDesiredAccess = GENERIC_WRITE ;
1320+ break ;
1321+ case _O_RDWR :
1322+ dwDesiredAccess = GENERIC_READ | GENERIC_WRITE ;
1323+ break ;
1324+ }
12961325DWORD dwCreationDisposition = OPEN_EXISTING ;
1297- if (oflag & _O_CREAT )
1326+ if (oflag & _O_CREAT ) {
12981327dwCreationDisposition = OPEN_ALWAYS ;
1299- if (oflag & _O_TRUNC )
1300- dwCreationDisposition = CREATE_ALWAYS ;
1301- return (dispatch_fd_t )CreateFile (path , dwDesiredAccess , 0 , NULL , dwCreationDisposition , 0 , NULL );
1328+ if (oflag & _O_EXCL ) {
1329+ dwCreationDisposition = CREATE_NEW ;
1330+ } else if (oflag & _O_TRUNC ) {
1331+ dwCreationDisposition = CREATE_ALWAYS ;
1332+ }
1333+ } else if (oflag & _O_TRUNC ) {
1334+ dwCreationDisposition = TRUNCATE_EXISTING ;
1335+ }
1336+ return (dispatch_fd_t )CreateFile (path , dwDesiredAccess ,
1337+ FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE , NULL ,
1338+ dwCreationDisposition , 0 , NULL );
13021339#else
13031340return open (path , oflag , mode );
13041341#endif
0 commit comments