Skip to content

Commit a8fcb8d

Browse files
committed
Term IO implemented to support Vista and Win7
1 parent fb93bb9 commit a8fcb8d

File tree

4 files changed

+205
-144
lines changed

4 files changed

+205
-144
lines changed

contrib/win32/win32compat/fileio.c

Lines changed: 95 additions & 73 deletions
Original file line numberDiff line numberDiff line change
@@ -43,8 +43,11 @@
4343
#define WRITE_BUFFER_SIZE 100*1024
4444
#define errno_from_Win32LastError() errno_from_Win32Error(GetLastError())
4545

46+
int termio_initiate_read(struct w32_io* pio);
47+
int termio_initiate_write(struct w32_io* pio, DWORD num_bytes);
48+
4649
/* maps Win32 error to errno */
47-
int
50+
int
4851
errno_from_Win32Error(int win32_error)
4952
{
5053
switch (win32_error) {
@@ -68,7 +71,7 @@ static int pipe_counter = 0;
6871
* pipe() implementation. Creates an inbound named pipe, uses CreateFile to connect
6972
* to it. These handles are associated with read end and write end of the pipe
7073
*/
71-
int
74+
int
7275
fileio_pipe(struct w32_io* pio[2]) {
7376
HANDLE read_handle = INVALID_HANDLE_VALUE, write_handle = INVALID_HANDLE_VALUE;
7477
struct w32_io *pio_read = NULL, *pio_write = NULL;
@@ -82,7 +85,7 @@ fileio_pipe(struct w32_io* pio[2]) {
8285
}
8386

8487
/* 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",
8689
GetCurrentProcessId(), pipe_counter++)) {
8790
errno = EOTHER;
8891
debug("pipe - ERROR sprintf_s %d", errno);
@@ -163,15 +166,15 @@ struct createFile_flags {
163166
};
164167

165168
/* maps open() file modes and flags to ones needed by CreateFile */
166-
static int
169+
static int
167170
createFile_flags_setup(int flags, int mode, struct createFile_flags* cf_flags) {
168171

169172
/* check flags */
170173
int rwflags = flags & 0xf;
171174
int c_s_flags = flags & 0xfffffff0;
172175

173-
/*
174-
* should be one of one of the following access modes:
176+
/*
177+
* should be one of one of the following access modes:
175178
* O_RDONLY, O_WRONLY, or O_RDWR
176179
*/
177180
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) {
182185

183186
/*only following create and status flags currently supported*/
184187
if (c_s_flags & ~(O_NONBLOCK | O_APPEND | O_CREAT | O_TRUNC
185-
| O_EXCL | O_BINARY)) {
188+
| O_EXCL | O_BINARY)) {
186189
debug("open - ERROR: Unsupported flags: %d", flags);
187190
errno = ENOTSUP;
188191
return -1;
@@ -234,8 +237,8 @@ createFile_flags_setup(int flags, int mode, struct createFile_flags* cf_flags) {
234237
}
235238

236239
/* 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) {
239242
struct w32_io* pio = NULL;
240243
struct createFile_flags cf_flags;
241244
HANDLE handle;
@@ -253,9 +256,9 @@ fileio_open(const char *pathname, int flags, int mode) {
253256
return NULL;
254257

255258
/* 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);
259262

260263
if (handle == INVALID_HANDLE_VALUE) {
261264
errno = errno_from_Win32LastError();
@@ -280,13 +283,13 @@ fileio_open(const char *pathname, int flags, int mode) {
280283
}
281284

282285
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
286289
) {
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",
290293
pio, pio->read_details.pending, dwErrorCode, dwNumberOfBytesTransfered);
291294
pio->read_details.error = dwErrorCode;
292295
pio->read_details.remaining = dwNumberOfBytesTransfered;
@@ -296,11 +299,11 @@ VOID CALLBACK ReadCompletionRoutine(
296299
}
297300

298301
/* initiate an async read */
299-
int
302+
int
300303
fileio_ReadFileEx(struct w32_io* pio) {
301304
debug2("ReadFileEx io:%p", pio);
302305

303-
if (pio->read_details.buf == NULL){
306+
if (pio->read_details.buf == NULL) {
304307
pio->read_details.buf = malloc(READ_BUFFER_SIZE);
305308
if (!pio->read_details.buf) {
306309
errno = ENOMEM;
@@ -311,7 +314,7 @@ fileio_ReadFileEx(struct w32_io* pio) {
311314
}
312315

313316
if (ReadFileEx(WINHANDLE(pio), pio->read_details.buf, pio->read_details.buf_size,
314-
&pio->read_overlapped, &ReadCompletionRoutine))
317+
&pio->read_overlapped, &ReadCompletionRoutine))
315318
pio->read_details.pending = TRUE;
316319
else {
317320
errno = errno_from_Win32LastError();
@@ -323,7 +326,7 @@ fileio_ReadFileEx(struct w32_io* pio) {
323326
}
324327

325328
/* read() implementation */
326-
int
329+
int
327330
fileio_read(struct w32_io* pio, void *dst, unsigned int max) {
328331
int bytes_copied;
329332

@@ -344,15 +347,21 @@ fileio_read(struct w32_io* pio, void *dst, unsigned int max) {
344347
}
345348

346349
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;
354364
}
355-
return -1;
356365
}
357366

358367
/* pick up APC if IO has completed */
@@ -375,7 +384,7 @@ fileio_read(struct w32_io* pio, void *dst, unsigned int max) {
375384
if (pio->read_details.error) {
376385
errno = errno_from_Win32Error(pio->read_details.error);
377386
/*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) ||
379388
(pio->read_details.error == ERROR_HANDLE_EOF)) {
380389
debug2("read - (2) no more data, io:%p", pio);
381390
errno = 0;
@@ -391,8 +400,8 @@ fileio_read(struct w32_io* pio, void *dst, unsigned int max) {
391400
memcpy(dst, pio->read_details.buf + pio->read_details.completed, bytes_copied);
392401
pio->read_details.remaining -= bytes_copied;
393402
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);
396405
return bytes_copied;
397406
}
398407

@@ -401,25 +410,25 @@ VOID CALLBACK WriteCompletionRoutine(
401410
_In_ DWORD dwNumberOfBytesTransfered,
402411
_Inout_ LPOVERLAPPED lpOverlapped
403412
) {
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);
409418
pio->write_details.error = dwErrorCode;
410419
/* TODO - assert that remaining == dwNumberOfBytesTransfered */
411420
if ((dwErrorCode == 0) && (pio->write_details.remaining != dwNumberOfBytesTransfered)) {
412421
debug("WriteCB - ERROR: broken assumption, io:%p, wrote:%d, remaining:%d", pio,
413422
dwNumberOfBytesTransfered, pio->write_details.remaining);
414423
DebugBreak();
415-
}
424+
}
416425
pio->write_details.remaining -= dwNumberOfBytesTransfered;
417426
pio->write_details.pending = FALSE;
418427
*((__int64*)&lpOverlapped->Offset) += dwNumberOfBytesTransfered;
419428
}
420429

421430
/* write() implementation */
422-
int
431+
int
423432
fileio_write(struct w32_io* pio, const void *buf, unsigned int max) {
424433
int bytes_copied;
425434

@@ -461,44 +470,54 @@ fileio_write(struct w32_io* pio, const void *buf, unsigned int max) {
461470
bytes_copied = min(max, pio->write_details.buf_size);
462471
memcpy(pio->write_details.buf, buf, bytes_copied);
463472

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
470479
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;
477489
}
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);
482498
return -1;
483499
}
484-
debug2("write - reporting %d bytes written, io:%p", bytes_copied, pio);
485-
return bytes_copied;
486500
}
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;
493506
}
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;
495512
return -1;
496513
}
514+
debug2("write - reporting %d bytes written, io:%p", bytes_copied, pio);
515+
return bytes_copied;
497516

498517
}
499518

500519
/* fstat() implemetation */
501-
int
520+
int
502521
fileio_fstat(struct w32_io* pio, struct _stat64 *buf) {
503522

504523
int fd = _open_osfhandle((intptr_t)pio->handle, 0);
@@ -511,12 +530,12 @@ fileio_fstat(struct w32_io* pio, struct _stat64 *buf) {
511530
return _fstat64(fd, buf);
512531
}
513532

514-
int
533+
int
515534
fileio_stat(const char *path, struct _stat64 *buf) {
516535
return _stat64(path, buf);
517536
}
518537

519-
long
538+
long
520539
fileio_lseek(struct w32_io* pio, long offset, int origin) {
521540
debug2("lseek - pio:%p", pio);
522541
if (origin != SEEK_SET) {
@@ -531,7 +550,7 @@ fileio_lseek(struct w32_io* pio, long offset, int origin) {
531550
}
532551

533552
/* fdopen implementation */
534-
FILE*
553+
FILE*
535554
fileio_fdopen(struct w32_io* pio, const char *mode) {
536555

537556
int fd_flags = 0;
@@ -570,20 +589,23 @@ fileio_fdopen(struct w32_io* pio, const char *mode) {
570589
return _fdopen(fd, mode);
571590
}
572591

573-
int
592+
int
574593
fileio_on_select(struct w32_io* pio, BOOL rd) {
575594

576595
if (!rd)
577596
return 0;
578597

579598
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);
581603

582604
return 0;
583605
}
584606

585607

586-
int
608+
int
587609
fileio_close(struct w32_io* pio) {
588610

589611
debug2("fileclose - pio:%p", pio);
@@ -605,7 +627,7 @@ fileio_close(struct w32_io* pio) {
605627
return 0;
606628
}
607629

608-
BOOL
630+
BOOL
609631
fileio_is_io_available(struct w32_io* pio, BOOL rd) {
610632
if (rd) {
611633
if (pio->read_details.remaining || pio->read_details.error)

0 commit comments

Comments
 (0)