diff --git a/contrib/win32/w32-posix-prototype/win32posix/win32posix/debug.c b/contrib/win32/w32-posix-prototype/win32posix/win32posix/debug.c new file mode 100644 index 0000000..b74a541 --- /dev/null +++ b/contrib/win32/w32-posix-prototype/win32posix/win32posix/debug.c @@ -0,0 +1,33 @@ +#include +#include +#include + + +FILE* log; + +void debug_initialize() { + char filename[MAX_PATH]; + int len = 0; + SYSTEMTIME time; + + len = GetModuleFileNameA(NULL, filename, MAX_PATH); + GetLocalTime(&time); + + sprintf(filename + len, "_%d_%d_%d.log", time.wHour, time.wMinute, time.wSecond); + + log = fopen(filename, "w"); +} + +void debug_done() { + fclose(log); +} + + +void write_log(const char *source_name, const char *function_name, int line_num, const char *fmt, ...) { + va_list args; + fprintf(log,"\n%s:%s:%d: ", source_name, function_name, line_num); + va_start(args, fmt); + fprintf(log,fmt, args); + va_end(args); + fflush(log); +} \ No newline at end of file diff --git a/contrib/win32/w32-posix-prototype/win32posix/win32posix/debug.h b/contrib/win32/w32-posix-prototype/win32posix/win32posix/debug.h new file mode 100644 index 0000000..0694b18 --- /dev/null +++ b/contrib/win32/w32-posix-prototype/win32posix/win32posix/debug.h @@ -0,0 +1,7 @@ + + +#define debug(cformat, ...) write_log(__FILE__, __FUNCTION__, __LINE__, cformat, __VA_ARGS__) + +void debug_initialize(); +void debug_done(); +void write_log(const char *source_name,const char *function_name, int line_num, const char *fmt, ...); diff --git a/contrib/win32/w32-posix-prototype/win32posix/win32posix/fileio.c b/contrib/win32/w32-posix-prototype/win32posix/win32posix/fileio.c index d72f68c..00f0f9b 100644 --- a/contrib/win32/w32-posix-prototype/win32posix/win32posix/fileio.c +++ b/contrib/win32/w32-posix-prototype/win32posix/win32posix/fileio.c @@ -31,7 +31,13 @@ int fileio_pipe(struct w32_io* pio[2]) { char pipe_name[MAX_PATH]; SECURITY_ATTRIBUTES sec_attributes; - if (-1 == sprintf_s(pipe_name, MAX_PATH, "\\\\.\\Pipe\\RemoteExeAnon.%08x.%08x", GetCurrentProcessId(), pipe_number++)) + if (pio == NULL) { + errno = EFAULT; + return -1; + } + + + if (-1 == sprintf_s(pipe_name, MAX_PATH, "\\\\.\\Pipe\\W32PosixPipe.%08x.%08x", GetCurrentProcessId(), pipe_number++)) goto error; sec_attributes.bInheritHandle = TRUE; @@ -200,8 +206,13 @@ int fileio_read(struct w32_io* pio, void *dst, unsigned int max) { if (fileio_is_io_available(pio, TRUE) == FALSE) { - if (-1 == fileio_ReadFileEx(pio)) + if (-1 == fileio_ReadFileEx(pio)) { + if ((pio->type == PIPE_FD) && (errno == ERROR_NEGATIVE_SEEK)) {//write end of the pipe closed + errno = 0; + return 0; + } return -1; + } //Pick up APC if IO has completed SleepEx(0, TRUE); @@ -228,7 +239,11 @@ int fileio_read(struct w32_io* pio, void *dst, unsigned int max) { } if (pio->read_details.error) { - errno = EOTHER; + errno = errno_from_Win32Error(pio->read_details.error); + if (errno == ERROR_BROKEN_PIPE) { //write end of the pipe is closed or pipe broken + errno = 0; + return 0; + } return -1; } @@ -256,12 +271,23 @@ int fileio_write(struct w32_io* pio, const void *buf, unsigned int max) { int bytes_copied; if (pio->write_details.pending) { - errno = EAGAIN; - return -1; + if (w32_io_is_blocking(pio)) + { + //this covers the scenario when the fd was previously non blocking (and hence io is still pending) + //wait for previous io to complete + while (pio->write_details.pending) { + if (wait_for_any_event(NULL, 0, INFINITE) == -1) + return -1; + } + } + else { + errno = EAGAIN; + return -1; + } } if (pio->write_details.error) { - errno = EOTHER; + errno = errno_from_Win32Error(pio->write_details.error); return -1; } @@ -297,6 +323,8 @@ int fileio_write(struct w32_io* pio, const void *buf, unsigned int max) { else { errno = errno_from_Win32Error(); + if ((pio->type == PIPE_FD) && (errno == ERROR_NEGATIVE_SEEK)) //read end of the pipe closed + errno = EPIPE; return -1; } diff --git a/contrib/win32/w32-posix-prototype/win32posix/win32posix/socketio.c b/contrib/win32/w32-posix-prototype/win32posix/win32posix/socketio.c index d469f03..788d50c 100644 --- a/contrib/win32/w32-posix-prototype/win32posix/win32posix/socketio.c +++ b/contrib/win32/w32-posix-prototype/win32posix/win32posix/socketio.c @@ -127,8 +127,6 @@ int socketio_acceptEx(struct w32_io* pio) { return 0; } -#define RECV_CONNECTION_CLOSED 1234 - void CALLBACK WSARecvCompletionRoutine( IN DWORD dwError, IN DWORD cbTransferred, @@ -138,7 +136,7 @@ void CALLBACK WSARecvCompletionRoutine( { struct w32_io* pio = (struct w32_io*)((char*)lpOverlapped - offsetof(struct w32_io, read_overlapped)); if (!dwError && !cbTransferred) - dwError = RECV_CONNECTION_CLOSED; + dwError = ERROR_GRACEFUL_DISCONNECT; pio->read_details.error = dwError; pio->read_details.remaining = cbTransferred; pio->read_details.completed = 0; @@ -270,7 +268,7 @@ int socketio_recv(struct w32_io* pio, void *buf, size_t len, int flags) { //if there was an error on async call, return if (pio->read_details.error) { - if (pio->read_details.error == RECV_CONNECTION_CLOSED) { + if (pio->read_details.error == ERROR_GRACEFUL_DISCONNECT) { //connection is closed return 0; } @@ -313,7 +311,7 @@ int socketio_recv(struct w32_io* pio, void *buf, size_t len, int flags) { //by this time we should have some bytes in internal buffer or an error from callback if (pio->read_details.error) { - if (pio->read_details.error == RECV_CONNECTION_CLOSED) { + if (pio->read_details.error == ERROR_GRACEFUL_DISCONNECT) { //connection is closed return 0; } @@ -361,12 +359,24 @@ int socketio_send(struct w32_io* pio, const void *buf, size_t len, int flags) { //if io is already pending if (pio->write_details.pending) { - errno = EAGAIN; - return -1; + if (w32_io_is_blocking(pio)) + { + //this covers the scenario when the fd was previously non blocking (and hence io is still pending) + //wait for previous io to complete + while (pio->write_details.pending) { + if (wait_for_any_event(NULL, 0, INFINITE) == -1) + return -1; + } + } + else { + errno = EAGAIN; + return -1; + } } + if (pio->write_details.error) { - errno = EOTHER; + errno = errno_from_WSAError(pio->write_details.error); return -1; } diff --git a/contrib/win32/w32-posix-prototype/win32posix/win32posix/w32fd.c b/contrib/win32/w32-posix-prototype/win32posix/win32posix/w32fd.c index daa36a6..8a68ec9 100644 --- a/contrib/win32/w32-posix-prototype/win32posix/win32posix/w32fd.c +++ b/contrib/win32/w32-posix-prototype/win32posix/win32posix/w32fd.c @@ -16,13 +16,13 @@ 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; - fd_table_set(&w32_io_stdin, stdin); + fd_table_set(&w32_io_stdin, STDIN_FILENO); memset(&w32_io_stdout, 0, sizeof(w32_io_stdout)); w32_io_stdout.handle = STD_OUTPUT_HANDLE; - fd_table_set(&w32_io_stdout, stdout); + fd_table_set(&w32_io_stdout, STDOUT_FILENO); memset(&w32_io_stderr, 0, sizeof(w32_io_stderr)); w32_io_stderr.handle = STD_ERROR_HANDLE; - fd_table_set(&w32_io_stderr, stderr); + fd_table_set(&w32_io_stderr, STDERR_FILENO); return 0; } @@ -36,7 +36,8 @@ int fd_table_get_min_index() { bitmap++; min_index += 8; if (min_index >= MAX_FDS) { - errno = ENOMEM; + errno = EMFILE; + debug("ERROR: MAX_FDS limit reached"); return -1; } } @@ -53,7 +54,6 @@ int fd_table_get_min_index() { } void fd_table_set(struct w32_io* pio, int index) { - fd_table.w32_ios[index] = pio; pio->table_index = index; FD_SET(index, &(fd_table.occupied)); @@ -67,11 +67,13 @@ void fd_table_clear(int index) } void w32posix_initialize() { + debug_initialize(); fd_table_initialize(); socketio_initialize(); } void w32posix_done() { + debug_done(); socketio_done(); } @@ -114,6 +116,7 @@ int w32_socket(int domain, int type, int protocol) { } fd_table_set(pio, min_index); + debug("socket:%p, io:%p, fd:%d ", pio->sock, pio, min_index); return min_index; } @@ -131,93 +134,71 @@ int w32_accept(int fd, struct sockaddr* addr, int* addrlen) } fd_table_set(pio, min_index); + debug("socket:%p, io:%p, fd:%d ", pio->sock, pio, min_index); return min_index; } +#define CHECK_FD(fd) \ +do { \ + if ((fd > MAX_FDS - 1) || fd_table.w32_ios[fd] == NULL) { \ + errno = EBADF; \ + debug("bad fd: %d", fd); \ + return -1; \ + } \ +} while (0) + int w32_setsockopt(int fd, int level, int optname, const char* optval, int optlen) { - if (fd_table.w32_ios[fd] == NULL) { - errno = EBADF; - return -1; - } + CHECK_FD(fd); return socketio_setsockopt(fd_table.w32_ios[fd], level, optname, optval, optlen); } int w32_getsockopt(int fd, int level, int optname, char* optval, int* optlen) { - if (fd_table.w32_ios[fd] == NULL) { - errno = EBADF; - return -1; - } + CHECK_FD(fd); return socketio_getsockopt(fd_table.w32_ios[fd], level, optname, optval, optlen); } int w32_getsockname(int fd, struct sockaddr* name, int* namelen) { - if (fd_table.w32_ios[fd] == NULL) { - errno = EBADF; - return -1; - } + CHECK_FD(fd); return socketio_getsockname(fd_table.w32_ios[fd], name, namelen); } int w32_getpeername(int fd, struct sockaddr* name, int* namelen) { - if (fd_table.w32_ios[fd] == NULL) { - errno = EBADF; - return -1; - } + CHECK_FD(fd); return socketio_getpeername(fd_table.w32_ios[fd], name, namelen); } int w32_listen(int fd, int backlog) { - if (fd_table.w32_ios[fd] == NULL) { - errno = EBADF; - return -1; - } + CHECK_FD(fd); return socketio_listen(fd_table.w32_ios[fd], backlog); } int w32_bind(int fd, const struct sockaddr *name, int namelen) { - if (fd_table.w32_ios[fd] == NULL) { - errno = EBADF; - return -1; - } + CHECK_FD(fd); return socketio_bind(fd_table.w32_ios[fd], name, namelen); } int w32_connect(int fd, const struct sockaddr* name, int namelen) { - if (fd_table.w32_ios[fd] == NULL) { - errno = EBADF; - return -1; - } + CHECK_FD(fd); return socketio_connect(fd_table.w32_ios[fd], name, namelen); } int w32_recv(int fd, void *buf, size_t len, int flags) { - if (fd_table.w32_ios[fd] == NULL) { - errno = EBADF; - return -1; - } + CHECK_FD(fd); return socketio_recv(fd_table.w32_ios[fd], buf, len, flags); } int w32_send(int fd, const void *buf, size_t len, int flags) { - if (fd_table.w32_ios[fd] == NULL) { - errno = EBADF; - return -1; - } + CHECK_FD(fd); return socketio_send(fd_table.w32_ios[fd], buf, len, flags); } int w32_shutdown(int fd, int how) { - if (fd_table.w32_ios[fd] == NULL) { - errno = EBADF; - return -1; - } + CHECK_FD(fd); return socketio_shutdown(fd_table.w32_ios[fd], how); } - - //file io int w32_pipe(int *pfds){ int read_index, write_index; @@ -241,6 +222,8 @@ int w32_pipe(int *pfds){ fd_table_set(pio[1], write_index); pfds[0] = read_index; pfds[1] = write_index; + debug("read end: handle:%p, io:%p, fd:%d", pio[0]->handle, pio[0], read_index); + debug("write end: handle:%p, io:%p, fd:%d", pio[1]->handle, pio[1], write_index); return 0; } @@ -256,60 +239,44 @@ int w32_open(const char *pathname, int flags, ...) { return -1; fd_table_set(pio, min_index); + debug("handle:%p, io:%p, fd:%d", pio->handle, pio, min_index); return min_index; } int w32_read(int fd, void *dst, unsigned int max) { - if (fd_table.w32_ios[fd] == NULL) { - errno = EBADF; - return -1; - } + CHECK_FD(fd); return fileio_read(fd_table.w32_ios[fd], dst, max); } int w32_write(int fd, const void *buf, unsigned int max) { - if (fd_table.w32_ios[fd] == NULL) { - errno = EBADF; - return -1; - } + CHECK_FD(fd); return fileio_write(fd_table.w32_ios[fd], buf, max); } int w32_fstat(int fd, struct stat *buf) { - if (fd_table.w32_ios[fd] == NULL) { - errno = EBADF; - return -1; - } + CHECK_FD(fd); return fileio_fstat(fd_table.w32_ios[fd], buf); } int w32_isatty(int fd) { - if (fd_table.w32_ios[fd] == NULL) { - errno = EBADF; - return -1; - } - + CHECK_FD(fd); return fileio_isatty(fd_table.w32_ios[fd]); } FILE* w32_fdopen(int fd, const char *mode) { - if (fd_table.w32_ios[fd] == NULL) { - errno = EBADF; - return NULL; - } - + CHECK_FD(fd); return fileio_fdopen(fd_table.w32_ios[fd], mode); } //Common IO int w32_close(int fd) { - struct w32_io* pio = fd_table.w32_ios[fd]; - if (pio == NULL) { - errno = EBADF; - return -1; - } + struct w32_io* pio; + CHECK_FD(fd); + pio = fd_table.w32_ios[fd]; + + debug("io:%p, type:%d, fd:%d, table_index:%d", pio, pio->type, fd, pio->table_index); fd_table_clear(pio->table_index); if ((pio->type == LISTEN_FD) || (pio->type == SOCK_FD)) { return socketio_close(pio); @@ -322,10 +289,7 @@ int w32_fcntl(int fd, int cmd, ... /* arg */) { va_list valist; va_start(valist, cmd); - if (fd_table.w32_ios[fd] == NULL) { - errno = EBADF; - return -1; - } + CHECK_FD(fd); switch (cmd){ case F_GETFL: @@ -341,39 +305,55 @@ int w32_fcntl(int fd, int cmd, ... /* arg */) { return 0; default: errno = EINVAL; + debug("ERROR: cmd:%d", cmd); return -1; } } int w32_select(int fds, fd_set* readfds, fd_set* writefds, fd_set* exceptfds, const struct timeval *timeout) { - int in_ready_fds = 0, out_ready_fds = 0; + int in_ready_fds = 0, out_ready_fds = 0, i; fd_set read_ready_fds, write_ready_fds; - HANDLE events[10]; + HANDLE events[32]; int num_events = 0; memset(&read_ready_fds, 0, sizeof(fd_set)); memset(&write_ready_fds, 0, sizeof(fd_set)); - if (fds > MAX_FDS - 1) { + if (fds > MAX_FDS ) { errno = EINVAL; + debug("ERROR: fds: %d", fds); return -1; } - if (!readfds && !writefds && !exceptfds) { + if (!readfds && !writefds) { errno = EINVAL; + debug("ERROR: null fd_sets"); return -1; } + if (exceptfds) { + errno = EOPNOTSUPP; + debug("ERROR: exceptfds not supported"); + return -1; + } + + if (readfds) { + for (i = 0; i < fds; i++) + if (FD_ISSET(i, readfds)) + CHECK_FD(i); + } + + if (writefds) { + for (i = 0; i < fds; i++) + if (FD_ISSET(i, writefds)) + CHECK_FD(i); + } + //see if any io is ready - for (int i = 0; i < fds; i++) { + for (i = 0; i < fds; i++) { if (readfds && FD_ISSET(i, readfds)) { - if (fd_table.w32_ios[i] == NULL) { - errno = EBADF; - return -1; - } - in_ready_fds++; if (w32_io_is_io_available(fd_table.w32_ios[i], TRUE)) { FD_SET(i, &read_ready_fds); @@ -382,33 +362,29 @@ int w32_select(int fds, fd_set* readfds, fd_set* writefds, fd_set* exceptfds, co } if (writefds && FD_ISSET(i, writefds)) { - if (fd_table.w32_ios[i] == NULL) { - errno = EBADF; - return -1; - } - in_ready_fds++; if (w32_io_is_io_available(fd_table.w32_ios[i], FALSE)) { FD_SET(i, &write_ready_fds); out_ready_fds++; } } - } //if none of input fds are set return error if (in_ready_fds == 0) { errno = EINVAL; + debug("ERROR: empty fd_sets"); return -1; } - //if some fds are already ready, return + //if io on some fds is already ready, return if (out_ready_fds) { if (readfds) *readfds = read_ready_fds; if (writefds) *writefds = write_ready_fds; + debug("IO ready:%d, no wait", out_ready_fds); return out_ready_fds; } diff --git a/contrib/win32/w32-posix-prototype/win32posix/win32posix/w32fd.h b/contrib/win32/w32-posix-prototype/win32posix/win32posix/w32fd.h index f2ddaaa..a6f8b4f 100644 --- a/contrib/win32/w32-posix-prototype/win32posix/win32posix/w32fd.h +++ b/contrib/win32/w32-posix-prototype/win32posix/win32posix/w32fd.h @@ -1,5 +1,6 @@ #include #include +#include "debug.h" enum w32_io_type { UNKOWN_FD = 0,