43
43
#define WRITE_BUFFER_SIZE 100*1024
44
44
#define errno_from_Win32LastError () errno_from_Win32Error(GetLastError())
45
45
46
+ int termio_initiate_read (struct w32_io * pio );
47
+ int termio_initiate_write (struct w32_io * pio , DWORD num_bytes );
48
+
46
49
/* maps Win32 error to errno */
47
- int
50
+ int
48
51
errno_from_Win32Error (int win32_error )
49
52
{
50
53
switch (win32_error ) {
@@ -68,7 +71,7 @@ static int pipe_counter = 0;
68
71
* pipe() implementation. Creates an inbound named pipe, uses CreateFile to connect
69
72
* to it. These handles are associated with read end and write end of the pipe
70
73
*/
71
- int
74
+ int
72
75
fileio_pipe (struct w32_io * pio [2 ]) {
73
76
HANDLE read_handle = INVALID_HANDLE_VALUE , write_handle = INVALID_HANDLE_VALUE ;
74
77
struct w32_io * pio_read = NULL , * pio_write = NULL ;
@@ -82,7 +85,7 @@ fileio_pipe(struct w32_io* pio[2]) {
82
85
}
83
86
84
87
/* create name for named pipe */
85
- if (-1 == sprintf_s (pipe_name , MAX_PATH , "\\\\.\\Pipe\\W32PosixPipe.%08x.%08x" ,
88
+ if (-1 == sprintf_s (pipe_name , MAX_PATH , "\\\\.\\Pipe\\W32PosixPipe.%08x.%08x" ,
86
89
GetCurrentProcessId (), pipe_counter ++ )) {
87
90
errno = EOTHER ;
88
91
debug ("pipe - ERROR sprintf_s %d" , errno );
@@ -163,15 +166,15 @@ struct createFile_flags {
163
166
};
164
167
165
168
/* maps open() file modes and flags to ones needed by CreateFile */
166
- static int
169
+ static int
167
170
createFile_flags_setup (int flags , int mode , struct createFile_flags * cf_flags ) {
168
171
169
172
/* check flags */
170
173
int rwflags = flags & 0xf ;
171
174
int c_s_flags = flags & 0xfffffff0 ;
172
175
173
- /*
174
- * should be one of one of the following access modes:
176
+ /*
177
+ * should be one of one of the following access modes:
175
178
* O_RDONLY, O_WRONLY, or O_RDWR
176
179
*/
177
180
if ((rwflags != O_RDONLY ) && (rwflags != O_WRONLY ) && (rwflags != O_RDWR )) {
@@ -182,7 +185,7 @@ createFile_flags_setup(int flags, int mode, struct createFile_flags* cf_flags) {
182
185
183
186
/*only following create and status flags currently supported*/
184
187
if (c_s_flags & ~(O_NONBLOCK | O_APPEND | O_CREAT | O_TRUNC
185
- | O_EXCL | O_BINARY )) {
188
+ | O_EXCL | O_BINARY )) {
186
189
debug ("open - ERROR: Unsupported flags: %d" , flags );
187
190
errno = ENOTSUP ;
188
191
return -1 ;
@@ -234,8 +237,8 @@ createFile_flags_setup(int flags, int mode, struct createFile_flags* cf_flags) {
234
237
}
235
238
236
239
/* open() implementation. Uses CreateFile to open file, console, device, etc */
237
- struct w32_io *
238
- fileio_open (const char * pathname , int flags , int mode ) {
240
+ struct w32_io *
241
+ fileio_open (const char * pathname , int flags , int mode ) {
239
242
struct w32_io * pio = NULL ;
240
243
struct createFile_flags cf_flags ;
241
244
HANDLE handle ;
@@ -253,9 +256,9 @@ fileio_open(const char *pathname, int flags, int mode) {
253
256
return NULL ;
254
257
255
258
/* TODO - Use unicode version.*/
256
- handle = CreateFileA (pathname , cf_flags .dwDesiredAccess , cf_flags .dwShareMode ,
257
- & cf_flags .securityAttributes , cf_flags .dwCreationDisposition ,
258
- cf_flags .dwFlagsAndAttributes , NULL );
259
+ handle = CreateFileA (pathname , cf_flags .dwDesiredAccess , cf_flags .dwShareMode ,
260
+ & cf_flags .securityAttributes , cf_flags .dwCreationDisposition ,
261
+ cf_flags .dwFlagsAndAttributes , NULL );
259
262
260
263
if (handle == INVALID_HANDLE_VALUE ) {
261
264
errno = errno_from_Win32LastError ();
@@ -280,13 +283,13 @@ fileio_open(const char *pathname, int flags, int mode) {
280
283
}
281
284
282
285
VOID CALLBACK ReadCompletionRoutine (
283
- _In_ DWORD dwErrorCode ,
284
- _In_ DWORD dwNumberOfBytesTransfered ,
285
- _Inout_ LPOVERLAPPED lpOverlapped
286
+ _In_ DWORD dwErrorCode ,
287
+ _In_ DWORD dwNumberOfBytesTransfered ,
288
+ _Inout_ LPOVERLAPPED lpOverlapped
286
289
) {
287
- struct w32_io * pio =
288
- (struct w32_io * )((char * )lpOverlapped - offsetof(struct w32_io , read_overlapped ));
289
- debug2 ("ReadCB pio:%p, pending_state:%d, error:%d, received:%d" ,
290
+ struct w32_io * pio =
291
+ (struct w32_io * )((char * )lpOverlapped - offsetof(struct w32_io , read_overlapped ));
292
+ debug2 ("ReadCB pio:%p, pending_state:%d, error:%d, received:%d" ,
290
293
pio , pio -> read_details .pending , dwErrorCode , dwNumberOfBytesTransfered );
291
294
pio -> read_details .error = dwErrorCode ;
292
295
pio -> read_details .remaining = dwNumberOfBytesTransfered ;
@@ -296,11 +299,11 @@ VOID CALLBACK ReadCompletionRoutine(
296
299
}
297
300
298
301
/* initiate an async read */
299
- int
302
+ int
300
303
fileio_ReadFileEx (struct w32_io * pio ) {
301
304
debug2 ("ReadFileEx io:%p" , pio );
302
305
303
- if (pio -> read_details .buf == NULL ){
306
+ if (pio -> read_details .buf == NULL ) {
304
307
pio -> read_details .buf = malloc (READ_BUFFER_SIZE );
305
308
if (!pio -> read_details .buf ) {
306
309
errno = ENOMEM ;
@@ -311,7 +314,7 @@ fileio_ReadFileEx(struct w32_io* pio) {
311
314
}
312
315
313
316
if (ReadFileEx (WINHANDLE (pio ), pio -> read_details .buf , pio -> read_details .buf_size ,
314
- & pio -> read_overlapped , & ReadCompletionRoutine ))
317
+ & pio -> read_overlapped , & ReadCompletionRoutine ))
315
318
pio -> read_details .pending = TRUE;
316
319
else {
317
320
errno = errno_from_Win32LastError ();
@@ -323,7 +326,7 @@ fileio_ReadFileEx(struct w32_io* pio) {
323
326
}
324
327
325
328
/* read() implementation */
326
- int
329
+ int
327
330
fileio_read (struct w32_io * pio , void * dst , unsigned int max ) {
328
331
int bytes_copied ;
329
332
@@ -344,15 +347,21 @@ fileio_read(struct w32_io* pio, void *dst, unsigned int max) {
344
347
}
345
348
346
349
if (fileio_is_io_available (pio , TRUE) == FALSE) {
347
- if (-1 == fileio_ReadFileEx (pio )) {
348
- if ((FILETYPE (pio ) == FILE_TYPE_PIPE )
349
- && (errno == ERROR_NEGATIVE_SEEK )) {
350
- /* write end of the pipe closed */
351
- debug2 ("read - no more data, io:%p" , pio );
352
- errno = 0 ;
353
- return 0 ;
350
+ if (FILETYPE (pio ) == FILE_TYPE_CHAR ) {
351
+ if (-1 == termio_initiate_read (pio ))
352
+ return -1 ;
353
+ }
354
+ else {
355
+ if (-1 == fileio_ReadFileEx (pio )) {
356
+ if ((FILETYPE (pio ) == FILE_TYPE_PIPE )
357
+ && (errno == ERROR_NEGATIVE_SEEK )) {
358
+ /* write end of the pipe closed */
359
+ debug2 ("read - no more data, io:%p" , pio );
360
+ errno = 0 ;
361
+ return 0 ;
362
+ }
363
+ return -1 ;
354
364
}
355
- return -1 ;
356
365
}
357
366
358
367
/* pick up APC if IO has completed */
@@ -375,7 +384,7 @@ fileio_read(struct w32_io* pio, void *dst, unsigned int max) {
375
384
if (pio -> read_details .error ) {
376
385
errno = errno_from_Win32Error (pio -> read_details .error );
377
386
/*write end of the pipe is closed or pipe broken or eof reached*/
378
- if ((pio -> read_details .error == ERROR_BROKEN_PIPE ) ||
387
+ if ((pio -> read_details .error == ERROR_BROKEN_PIPE ) ||
379
388
(pio -> read_details .error == ERROR_HANDLE_EOF )) {
380
389
debug2 ("read - (2) no more data, io:%p" , pio );
381
390
errno = 0 ;
@@ -391,8 +400,8 @@ fileio_read(struct w32_io* pio, void *dst, unsigned int max) {
391
400
memcpy (dst , pio -> read_details .buf + pio -> read_details .completed , bytes_copied );
392
401
pio -> read_details .remaining -= bytes_copied ;
393
402
pio -> read_details .completed += bytes_copied ;
394
- debug2 ("read - io:%p read: %d remaining: %d" , pio , bytes_copied ,
395
- pio -> read_details .remaining );
403
+ debug2 ("read - io:%p read: %d remaining: %d" , pio , bytes_copied ,
404
+ pio -> read_details .remaining );
396
405
return bytes_copied ;
397
406
}
398
407
@@ -401,25 +410,25 @@ VOID CALLBACK WriteCompletionRoutine(
401
410
_In_ DWORD dwNumberOfBytesTransfered ,
402
411
_Inout_ LPOVERLAPPED lpOverlapped
403
412
) {
404
- struct w32_io * pio =
405
- (struct w32_io * )((char * )lpOverlapped - offsetof(struct w32_io , write_overlapped ));
406
- debug2 ("WriteCB - pio:%p, pending_state:%d, error:%d, transferred:%d of remaining: %d" ,
407
- pio , pio -> write_details .pending , dwErrorCode , dwNumberOfBytesTransfered ,
408
- pio -> write_details .remaining );
413
+ struct w32_io * pio =
414
+ (struct w32_io * )((char * )lpOverlapped - offsetof(struct w32_io , write_overlapped ));
415
+ debug2 ("WriteCB - pio:%p, pending_state:%d, error:%d, transferred:%d of remaining: %d" ,
416
+ pio , pio -> write_details .pending , dwErrorCode , dwNumberOfBytesTransfered ,
417
+ pio -> write_details .remaining );
409
418
pio -> write_details .error = dwErrorCode ;
410
419
/* TODO - assert that remaining == dwNumberOfBytesTransfered */
411
420
if ((dwErrorCode == 0 ) && (pio -> write_details .remaining != dwNumberOfBytesTransfered )) {
412
421
debug ("WriteCB - ERROR: broken assumption, io:%p, wrote:%d, remaining:%d" , pio ,
413
422
dwNumberOfBytesTransfered , pio -> write_details .remaining );
414
423
DebugBreak ();
415
- }
424
+ }
416
425
pio -> write_details .remaining -= dwNumberOfBytesTransfered ;
417
426
pio -> write_details .pending = FALSE;
418
427
* ((__int64 * )& lpOverlapped -> Offset ) += dwNumberOfBytesTransfered ;
419
428
}
420
429
421
430
/* write() implementation */
422
- int
431
+ int
423
432
fileio_write (struct w32_io * pio , const void * buf , unsigned int max ) {
424
433
int bytes_copied ;
425
434
@@ -461,44 +470,54 @@ fileio_write(struct w32_io* pio, const void *buf, unsigned int max) {
461
470
bytes_copied = min (max , pio -> write_details .buf_size );
462
471
memcpy (pio -> write_details .buf , buf , bytes_copied );
463
472
464
- if (WriteFileEx ( WINHANDLE ( pio ), pio -> write_details . buf , bytes_copied ,
465
- & pio -> write_overlapped , & WriteCompletionRoutine ) ) {
466
- pio -> write_details .pending = TRUE;
467
- pio -> write_details .remaining = bytes_copied ;
468
- /* execute APC if write has completed */
469
- if ( wait_for_any_event ( NULL , 0 , 0 ) == -1 )
473
+ if (FILETYPE ( pio ) == FILE_TYPE_CHAR ) {
474
+ if ( termio_initiate_write ( pio , bytes_copied ) == 0 ) {
475
+ pio -> write_details .pending = TRUE;
476
+ pio -> write_details .remaining = bytes_copied ;
477
+ }
478
+ else
470
479
return -1 ;
471
-
472
- if (w32_io_is_blocking (pio )) {
473
- while (pio -> write_details .pending ) {
474
- if (wait_for_any_event (NULL , 0 , INFINITE ) == -1 )
475
- return -1 ;
476
- }
480
+ }
481
+ else {
482
+ if (WriteFileEx (WINHANDLE (pio ), pio -> write_details .buf , bytes_copied ,
483
+ & pio -> write_overlapped , & WriteCompletionRoutine )) {
484
+ pio -> write_details .pending = TRUE;
485
+ pio -> write_details .remaining = bytes_copied ;
486
+ /* execute APC if write has completed */
487
+ if (wait_for_any_event (NULL , 0 , 0 ) == -1 )
488
+ return -1 ;
477
489
}
478
- if (!pio -> write_details .pending && pio -> write_details .error ) {
479
- errno = errno_from_Win32Error (pio -> write_details .error );
480
- debug ("write - ERROR from cb:%d, io:%p" , pio -> write_details .error , pio );
481
- pio -> write_details .error = 0 ;
490
+ else {
491
+ errno = errno_from_Win32LastError ();
492
+ /* read end of the pipe closed ? */
493
+ if ((FILETYPE (pio ) == FILE_TYPE_PIPE ) && (errno == ERROR_NEGATIVE_SEEK )) {
494
+ debug ("write - ERROR:read end of the pipe closed, io:%p" , pio );
495
+ errno = EPIPE ;
496
+ }
497
+ debug ("write ERROR from cb(2):%d, io:%p" , errno , pio );
482
498
return -1 ;
483
499
}
484
- debug2 ("write - reporting %d bytes written, io:%p" , bytes_copied , pio );
485
- return bytes_copied ;
486
500
}
487
- else {
488
- errno = errno_from_Win32LastError ();
489
- /* read end of the pipe closed ? */
490
- if ((FILETYPE (pio ) == FILE_TYPE_PIPE ) && (errno == ERROR_NEGATIVE_SEEK )) {
491
- debug ("write - ERROR:read end of the pipe closed, io:%p" , pio );
492
- errno = EPIPE ;
501
+
502
+ if (w32_io_is_blocking (pio )) {
503
+ while (pio -> write_details .pending ) {
504
+ if (wait_for_any_event (NULL , 0 , INFINITE ) == -1 )
505
+ return -1 ;
493
506
}
494
- debug ("write ERROR from cb(2):%d, io:%p" , errno , pio );
507
+ }
508
+ if (!pio -> write_details .pending && pio -> write_details .error ) {
509
+ errno = errno_from_Win32Error (pio -> write_details .error );
510
+ debug ("write - ERROR from cb:%d, io:%p" , pio -> write_details .error , pio );
511
+ pio -> write_details .error = 0 ;
495
512
return -1 ;
496
513
}
514
+ debug2 ("write - reporting %d bytes written, io:%p" , bytes_copied , pio );
515
+ return bytes_copied ;
497
516
498
517
}
499
518
500
519
/* fstat() implemetation */
501
- int
520
+ int
502
521
fileio_fstat (struct w32_io * pio , struct _stat64 * buf ) {
503
522
504
523
int fd = _open_osfhandle ((intptr_t )pio -> handle , 0 );
@@ -511,12 +530,12 @@ fileio_fstat(struct w32_io* pio, struct _stat64 *buf) {
511
530
return _fstat64 (fd , buf );
512
531
}
513
532
514
- int
533
+ int
515
534
fileio_stat (const char * path , struct _stat64 * buf ) {
516
535
return _stat64 (path , buf );
517
536
}
518
537
519
- long
538
+ long
520
539
fileio_lseek (struct w32_io * pio , long offset , int origin ) {
521
540
debug2 ("lseek - pio:%p" , pio );
522
541
if (origin != SEEK_SET ) {
@@ -531,7 +550,7 @@ fileio_lseek(struct w32_io* pio, long offset, int origin) {
531
550
}
532
551
533
552
/* fdopen implementation */
534
- FILE *
553
+ FILE *
535
554
fileio_fdopen (struct w32_io * pio , const char * mode ) {
536
555
537
556
int fd_flags = 0 ;
@@ -570,20 +589,23 @@ fileio_fdopen(struct w32_io* pio, const char *mode) {
570
589
return _fdopen (fd , mode );
571
590
}
572
591
573
- int
592
+ int
574
593
fileio_on_select (struct w32_io * pio , BOOL rd ) {
575
594
576
595
if (!rd )
577
596
return 0 ;
578
597
579
598
if (!pio -> read_details .pending && !fileio_is_io_available (pio , rd ))
580
- return fileio_ReadFileEx (pio );
599
+ if (FILETYPE (pio ) == FILE_TYPE_CHAR )
600
+ return termio_initiate_read (pio );
601
+ else
602
+ return fileio_ReadFileEx (pio );
581
603
582
604
return 0 ;
583
605
}
584
606
585
607
586
- int
608
+ int
587
609
fileio_close (struct w32_io * pio ) {
588
610
589
611
debug2 ("fileclose - pio:%p" , pio );
@@ -605,7 +627,7 @@ fileio_close(struct w32_io* pio) {
605
627
return 0 ;
606
628
}
607
629
608
- BOOL
630
+ BOOL
609
631
fileio_is_io_available (struct w32_io * pio , BOOL rd ) {
610
632
if (rd ) {
611
633
if (pio -> read_details .remaining || pio -> read_details .error )
0 commit comments