This commit is contained in:
Manoj Ampalam 2016-01-31 01:10:48 -08:00
parent 406105949d
commit 1a72ebe3a2
2 changed files with 82 additions and 29 deletions

View File

@ -17,6 +17,10 @@ static int errno_from_Win32Error(int win32_error)
return EACCES;
case ERROR_OUTOFMEMORY:
return ENOMEM;
case ERROR_FILE_EXISTS:
return EEXIST;
case ERROR_FILE_NOT_FOUND:
return ENOENT;
default:
return EOTHER;
}
@ -136,6 +140,13 @@ static int createFile_flags_setup(int flags, int mode, struct createFile_flags*
return -1;
}
//validate mode
if (mode &~(S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)) {
debug("ERROR: unsupported mode: %d", mode);
errno = ENOTSUP;
return -1;
}
switch (rwflags) {
case O_RDONLY:
cf_flags->dwDesiredAccess = GENERIC_READ;
@ -153,8 +164,24 @@ static int createFile_flags_setup(int flags, int mode, struct createFile_flags*
cf_flags->securityAttributes.lpSecurityDescriptor = NULL;
cf_flags->securityAttributes.bInheritHandle = TRUE;
cf_flags->securityAttributes.nLength = 0;
cf_flags->dwCreationDisposition = CREATE_NEW;
cf_flags->dwCreationDisposition = OPEN_EXISTING;
if (c_s_flags & O_TRUNC)
cf_flags->dwCreationDisposition = TRUNCATE_EXISTING;
if (c_s_flags & O_CREAT) {
if (c_s_flags & O_EXCL)
cf_flags->dwCreationDisposition = CREATE_NEW;
else
cf_flags->dwCreationDisposition = OPEN_ALWAYS;
}
if (c_s_flags & O_APPEND)
cf_flags->dwDesiredAccess = FILE_APPEND_DATA;
cf_flags->dwFlagsAndAttributes = FILE_FLAG_OVERLAPPED | SECURITY_IMPERSONATION;
//TODO - map mode
return 0;
}
@ -167,17 +194,18 @@ struct w32_io* fileio_open(const char *pathname, int flags, int mode) {
if (pathname == NULL) {
errno = EINVAL;
debug("ERROR:%d", errno);
return -1;
return NULL;
}
if (createFile_flags_setup(flags, mode, &cf_flags) == -1)
return NULL;
handle = CreateFileA(pathname, cf_flags.dwDesiredAccess, cf_flags.dwShareMode, &cf_flags.securityAttributes, cf_flags.dwCreationDisposition, cf_flags.dwFlagsAndAttributes, NULL);
if (handle == NULL) {
if (handle == INVALID_HANDLE_VALUE) {
errno = errno_from_Win32LastError();
debug("ERROR:%d", errno);
return NULL;
}
@ -185,13 +213,16 @@ struct w32_io* fileio_open(const char *pathname, int flags, int mode) {
if (pio == NULL) {
CloseHandle(handle);
errno = ENOMEM;
debug("ERROR:%d", errno);
return NULL;
}
memset(pio, 0, sizeof(struct w32_io));
if (flags & O_NONBLOCK)
pio->fd_status_flags = O_NONBLOCK;
pio->handle = handle;
pio->type = FILE_FD;
return pio;
}
@ -202,6 +233,7 @@ VOID CALLBACK ReadCompletionRoutine(
_Inout_ LPOVERLAPPED lpOverlapped
) {
struct w32_io* pio = (struct w32_io*)((char*)lpOverlapped - offsetof(struct w32_io, read_overlapped));
debug("pio:%p, pending_state:%d, error:%d, transferred:%d", pio, pio->read_details.pending, dwErrorCode, dwNumberOfBytesTransfered);
pio->read_details.error = dwErrorCode;
pio->read_details.remaining = dwNumberOfBytesTransfered;
pio->read_details.completed = 0;
@ -244,6 +276,7 @@ int fileio_read(struct w32_io* pio, void *dst, unsigned int max) {
//if read is pending
if (pio->read_details.pending) {
errno = EAGAIN;
debug("IO is already pending");
return -1;
}
@ -252,6 +285,7 @@ int fileio_read(struct w32_io* pio, void *dst, unsigned int max) {
if (-1 == fileio_ReadFileEx(pio)) {
if ((pio->type == PIPE_FD) && (errno == ERROR_NEGATIVE_SEEK)) {//write end of the pipe closed
debug("no more data");
errno = 0;
return 0;
}
@ -267,27 +301,24 @@ int fileio_read(struct w32_io* pio, void *dst, unsigned int max) {
return -1;
}
}
else {
if (pio->read_details.pending) {
errno = EAGAIN;
return -1;
}
else {
if (pio->read_details.error) {
errno = EOTHER;
return -1;
}
}
else if (pio->read_details.pending) {
errno = EAGAIN;
debug("IO is pending");
return -1;
}
}
if (pio->read_details.error) {
errno = errno_from_Win32LastError(pio->read_details.error);
if (errno == ERROR_BROKEN_PIPE) { //write end of the pipe is closed or pipe broken
errno = errno_from_Win32Error(pio->read_details.error);
if ((errno == ERROR_BROKEN_PIPE) || //write end of the pipe is closed or pipe broken
(errno == ERROR_HANDLE_EOF)) { //end of file reached
debug("no more data");
errno = 0;
pio->read_details.error = 0;
return 0;
}
debug("ERROR:%d", errno);
pio->read_details.error = 0;
return -1;
}
@ -295,6 +326,7 @@ int fileio_read(struct w32_io* pio, void *dst, unsigned int max) {
memcpy(dst, pio->read_details.buf + pio->read_details.completed, bytes_copied);
pio->read_details.remaining -= bytes_copied;
pio->read_details.completed += bytes_copied;
debug("read %d bytes", bytes_copied);
return bytes_copied;
}
@ -304,6 +336,7 @@ VOID CALLBACK WriteCompletionRoutine(
_Inout_ LPOVERLAPPED lpOverlapped
) {
struct w32_io* pio = (struct w32_io*)((char*)lpOverlapped - offsetof(struct w32_io, write_overlapped));
debug("pio:%p, pending_state:%d, remaining:%d, error:%d, transferred:%d", pio, pio->write_details.pending, pio->write_details.remaining, dwErrorCode, dwNumberOfBytesTransfered);
pio->write_details.error = dwErrorCode;
//assert that remaining == dwNumberOfBytesTransfered
pio->write_details.remaining -= dwNumberOfBytesTransfered;
@ -319,6 +352,7 @@ int fileio_write(struct w32_io* pio, const void *buf, unsigned int max) {
{
//this covers the scenario when the fd was previously non blocking (and hence io is still pending)
//wait for previous io to complete
debug("waiting for prior unblocking write to complete before proceeding with this blocking write");
while (pio->write_details.pending) {
if (wait_for_any_event(NULL, 0, INFINITE) == -1)
return -1;
@ -326,12 +360,15 @@ int fileio_write(struct w32_io* pio, const void *buf, unsigned int max) {
}
else {
errno = EAGAIN;
debug("IO is already pending");
return -1;
}
}
if (pio->write_details.error) {
errno = errno_from_Win32LastError(pio->write_details.error);
errno = errno_from_Win32Error(pio->write_details.error);
debug("ERROR:%d on prior unblocking write", errno);
pio->write_details.error = 0;
return -1;
}
@ -339,6 +376,7 @@ int fileio_write(struct w32_io* pio, const void *buf, unsigned int max) {
pio->write_details.buf = malloc(WRITE_BUFFER_SIZE);
if (pio->write_details.buf == NULL) {
errno = ENOMEM;
debug("ERROR:%d", errno);
return -1;
}
pio->write_details.buf_size = WRITE_BUFFER_SIZE;
@ -350,6 +388,7 @@ int fileio_write(struct w32_io* pio, const void *buf, unsigned int max) {
if (WriteFileEx(pio->handle, pio->write_details.buf, bytes_copied, &pio->write_overlapped, &WriteCompletionRoutine))
{
pio->write_details.pending = TRUE;
//let APC execute if IO was complete
SleepEx(0, TRUE);
if (w32_io_is_blocking(pio)) {
@ -359,7 +398,9 @@ int fileio_write(struct w32_io* pio, const void *buf, unsigned int max) {
}
}
if (!pio->write_details.pending && pio->write_details.error){
errno = EOTHER;
errno = errno_from_Win32Error(pio->write_details.error);
pio->write_details.error = 0;
debug("ERROR:%d", errno);
return -1;
}
return bytes_copied;
@ -367,8 +408,11 @@ int fileio_write(struct w32_io* pio, const void *buf, unsigned int max) {
else
{
errno = errno_from_Win32LastError();
if ((pio->type == PIPE_FD) && (errno == ERROR_NEGATIVE_SEEK)) //read end of the pipe closed
if ((pio->type == PIPE_FD) && (errno == ERROR_NEGATIVE_SEEK)) {//read end of the pipe closed
debug("ERROR:read end of the pipe closed");
errno = EPIPE;
}
debug("ERROR:%d", errno);
return -1;
}
@ -376,7 +420,7 @@ int fileio_write(struct w32_io* pio, const void *buf, unsigned int max) {
int fileio_fstat(struct w32_io* pio, struct stat *buf) {
int fd = _open_osfhandle((intptr_t)pio->handle, 0);
debug("pio:%p", pio);
if (fd == -1) {
errno = EOTHER;
return -1;
@ -387,14 +431,14 @@ int fileio_fstat(struct w32_io* pio, struct stat *buf) {
int fileio_isatty(struct w32_io* pio) {
return 0;
return (pio->type == CONSOLE_FD) ? TRUE : FALSE;
}
FILE* fileio_fdopen(struct w32_io* pio, const char *mode) {
int fd_flags = 0;
debug("pio:%p", pio);
if (mode[1] == '\0') {
switch (*mode) {
@ -408,11 +452,13 @@ FILE* fileio_fdopen(struct w32_io* pio, const char *mode) {
break;
default:
errno = ENOTSUP;
debug("ERROR:%d", errno);
return NULL;
}
}
else {
errno = ENOTSUP;
debug("ERROR:%d", errno);
return NULL;
}
@ -420,6 +466,7 @@ FILE* fileio_fdopen(struct w32_io* pio, const char *mode) {
if (fd == -1) {
errno = EOTHER;
debug("ERROR:%d", errno);
return NULL;
}
@ -442,6 +489,7 @@ int fileio_on_select(struct w32_io* pio, BOOL rd) {
int fileio_close(struct w32_io* pio) {
debug("pio:%p", pio);
CancelIo(pio->handle);
//let queued APCs (if any) drain
SleepEx(0, TRUE);

View File

@ -16,13 +16,13 @@ void fd_table_set(struct w32_io* pio, int index);
int fd_table_initialize() {
memset(&fd_table, 0, sizeof(fd_table));
memset(&w32_io_stdin, 0, sizeof(w32_io_stdin));
w32_io_stdin.handle = STD_INPUT_HANDLE;
w32_io_stdin.handle = (HANDLE)STD_INPUT_HANDLE;
fd_table_set(&w32_io_stdin, STDIN_FILENO);
memset(&w32_io_stdout, 0, sizeof(w32_io_stdout));
w32_io_stdout.handle = STD_OUTPUT_HANDLE;
w32_io_stdout.handle = (HANDLE)STD_OUTPUT_HANDLE;
fd_table_set(&w32_io_stdout, STDOUT_FILENO);
memset(&w32_io_stderr, 0, sizeof(w32_io_stderr));
w32_io_stderr.handle = STD_ERROR_HANDLE;
w32_io_stderr.handle = (HANDLE)STD_ERROR_HANDLE;
fd_table_set(&w32_io_stderr, STDERR_FILENO);
return 0;
}
@ -265,7 +265,12 @@ int w32_isatty(int fd) {
}
FILE* w32_fdopen(int fd, const char *mode) {
CHECK_FD(fd);
if ((fd > MAX_FDS - 1) || fd_table.w32_ios[fd] == NULL) {
errno = EBADF;
debug("bad fd: %d", fd);
return NULL;
}
return fileio_fdopen(fd_table.w32_ios[fd], mode);
}