mirror of
https://github.com/PowerShell/openssh-portable.git
synced 2025-07-31 01:35:11 +02:00
Fixed wstat fix for file permission issue
https://github.com/PowerShell/Win32-OpenSSH/issues/176 1.If there are no sufficient permissions to open a file then _wstat64() is returning file not present but it should return the accessed denied.Fixed this. 2.Code cleanup in the posix compat files to align with the openbsd coding standard.
This commit is contained in:
parent
73180c876d
commit
4d0c1db166
@ -124,9 +124,8 @@ GetCursorPositionReport()
|
||||
|
||||
out = _snprintf_s(cursor_report, sizeof(cursor_report), _TRUNCATE,
|
||||
CURSOR_REPORT_FORMAT_STRING, ConGetCursorY() + 1, ConGetCursorX() + 1);
|
||||
if (out > 0) {
|
||||
if (out > 0)
|
||||
return cursor_report;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
@ -32,9 +32,10 @@
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
#include <io.h>
|
||||
#include "w32fd.h"
|
||||
#include <errno.h>
|
||||
#include <stddef.h>
|
||||
|
||||
#include "w32fd.h"
|
||||
#include "inc\utf.h"
|
||||
#include "misc_internal.h"
|
||||
|
||||
@ -44,6 +45,14 @@
|
||||
#define WRITE_BUFFER_SIZE 100*1024
|
||||
#define errno_from_Win32LastError() errno_from_Win32Error(GetLastError())
|
||||
|
||||
struct createFile_flags {
|
||||
DWORD dwDesiredAccess;
|
||||
DWORD dwShareMode;
|
||||
SECURITY_ATTRIBUTES securityAttributes;
|
||||
DWORD dwCreationDisposition;
|
||||
DWORD dwFlagsAndAttributes;
|
||||
};
|
||||
|
||||
int termio_initiate_read(struct w32_io* pio);
|
||||
int termio_initiate_write(struct w32_io* pio, DWORD num_bytes);
|
||||
|
||||
@ -73,7 +82,8 @@ static int pipe_counter = 0;
|
||||
* to it. These handles are associated with read end and write end of the pipe
|
||||
*/
|
||||
int
|
||||
fileio_pipe(struct w32_io* pio[2]) {
|
||||
fileio_pipe(struct w32_io* pio[2])
|
||||
{
|
||||
HANDLE read_handle = INVALID_HANDLE_VALUE, write_handle = INVALID_HANDLE_VALUE;
|
||||
struct w32_io *pio_read = NULL, *pio_write = NULL;
|
||||
char pipe_name[PATH_MAX];
|
||||
@ -158,18 +168,10 @@ error:
|
||||
return -1;
|
||||
}
|
||||
|
||||
struct createFile_flags {
|
||||
DWORD dwDesiredAccess;
|
||||
DWORD dwShareMode;
|
||||
SECURITY_ATTRIBUTES securityAttributes;
|
||||
DWORD dwCreationDisposition;
|
||||
DWORD dwFlagsAndAttributes;
|
||||
};
|
||||
|
||||
/* maps open() file modes and flags to ones needed by CreateFile */
|
||||
static int
|
||||
createFile_flags_setup(int flags, int mode, struct createFile_flags* cf_flags) {
|
||||
|
||||
createFile_flags_setup(int flags, int mode, struct createFile_flags* cf_flags)
|
||||
{
|
||||
/* check flags */
|
||||
int rwflags = flags & 0x3;
|
||||
int c_s_flags = flags & 0xfffffff0;
|
||||
@ -185,8 +187,7 @@ createFile_flags_setup(int flags, int mode, struct createFile_flags* cf_flags) {
|
||||
}
|
||||
|
||||
/*only following create and status flags currently supported*/
|
||||
if (c_s_flags & ~(O_NONBLOCK | O_APPEND | O_CREAT | O_TRUNC
|
||||
| O_EXCL | O_BINARY)) {
|
||||
if (c_s_flags & ~(O_NONBLOCK | O_APPEND | O_CREAT | O_TRUNC | O_EXCL | O_BINARY)) {
|
||||
debug("open - ERROR: Unsupported flags: %d", flags);
|
||||
errno = ENOTSUP;
|
||||
return -1;
|
||||
@ -240,7 +241,8 @@ createFile_flags_setup(int flags, int mode, struct createFile_flags* cf_flags) {
|
||||
|
||||
/* open() implementation. Uses CreateFile to open file, console, device, etc */
|
||||
struct w32_io*
|
||||
fileio_open(const char *path_utf8, int flags, int mode) {
|
||||
fileio_open(const char *path_utf8, int flags, int mode)
|
||||
{
|
||||
struct w32_io* pio = NULL;
|
||||
struct createFile_flags cf_flags;
|
||||
HANDLE handle;
|
||||
@ -256,7 +258,7 @@ struct w32_io*
|
||||
|
||||
if ((path_utf16 = utf8_to_utf16(path_utf8)) == NULL) {
|
||||
errno = ENOMEM;
|
||||
debug("utf8_to_utf16 failed - ERROR:%d", GetLastError());
|
||||
debug("utf8_to_utf16 failed for file:%s error:%d", path_utf8, GetLastError());
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@ -269,7 +271,7 @@ struct w32_io*
|
||||
|
||||
if (handle == INVALID_HANDLE_VALUE) {
|
||||
errno = errno_from_Win32LastError();
|
||||
debug("open - CreateFile ERROR:%d", GetLastError());
|
||||
debug("failed to open file:%s error:%d", path_utf8, GetLastError());
|
||||
free(path_utf16);
|
||||
return NULL;
|
||||
}
|
||||
@ -279,7 +281,7 @@ struct w32_io*
|
||||
if (pio == NULL) {
|
||||
CloseHandle(handle);
|
||||
errno = ENOMEM;
|
||||
debug("open - ERROR:%d", errno);
|
||||
debug("fileio_open(), failed to allocate memory error:%d", errno);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@ -292,13 +294,10 @@ struct w32_io*
|
||||
return pio;
|
||||
}
|
||||
|
||||
VOID CALLBACK ReadCompletionRoutine(
|
||||
_In_ DWORD dwErrorCode,
|
||||
_In_ DWORD dwNumberOfBytesTransfered,
|
||||
_Inout_ LPOVERLAPPED lpOverlapped
|
||||
) {
|
||||
struct w32_io* pio =
|
||||
(struct w32_io*)((char*)lpOverlapped - offsetof(struct w32_io, read_overlapped));
|
||||
VOID CALLBACK
|
||||
ReadCompletionRoutine(_In_ DWORD dwErrorCode, _In_ DWORD dwNumberOfBytesTransfered, _Inout_ LPOVERLAPPED lpOverlapped)
|
||||
{
|
||||
struct w32_io* pio = (struct w32_io*)((char*)lpOverlapped - offsetof(struct w32_io, read_overlapped));
|
||||
debug2("ReadCB pio:%p, pending_state:%d, error:%d, received:%d",
|
||||
pio, pio->read_details.pending, dwErrorCode, dwNumberOfBytesTransfered);
|
||||
pio->read_details.error = dwErrorCode;
|
||||
@ -311,7 +310,8 @@ VOID CALLBACK ReadCompletionRoutine(
|
||||
/* initiate an async read */
|
||||
/* TODO: make this a void func, store error in context */
|
||||
int
|
||||
fileio_ReadFileEx(struct w32_io* pio, unsigned int bytes_requested) {
|
||||
fileio_ReadFileEx(struct w32_io* pio, unsigned int bytes_requested)
|
||||
{
|
||||
debug2("ReadFileEx io:%p", pio);
|
||||
|
||||
if (pio->read_details.buf == NULL) {
|
||||
@ -342,11 +342,11 @@ fileio_ReadFileEx(struct w32_io* pio, unsigned int bytes_requested) {
|
||||
|
||||
/* read() implementation */
|
||||
int
|
||||
fileio_read(struct w32_io* pio, void *dst, unsigned int max) {
|
||||
fileio_read(struct w32_io* pio, void *dst, unsigned int max)
|
||||
{
|
||||
int bytes_copied;
|
||||
|
||||
debug3("read - io:%p remaining:%d", pio, pio->read_details.remaining);
|
||||
|
||||
/* if read is pending */
|
||||
if (pio->read_details.pending) {
|
||||
if (w32_io_is_blocking(pio)) {
|
||||
@ -426,11 +426,11 @@ fileio_read(struct w32_io* pio, void *dst, unsigned int max) {
|
||||
return bytes_copied;
|
||||
}
|
||||
|
||||
VOID CALLBACK WriteCompletionRoutine(
|
||||
_In_ DWORD dwErrorCode,
|
||||
VOID CALLBACK
|
||||
WriteCompletionRoutine(_In_ DWORD dwErrorCode,
|
||||
_In_ DWORD dwNumberOfBytesTransfered,
|
||||
_Inout_ LPOVERLAPPED lpOverlapped
|
||||
) {
|
||||
_Inout_ LPOVERLAPPED lpOverlapped)
|
||||
{
|
||||
struct w32_io* pio =
|
||||
(struct w32_io*)((char*)lpOverlapped - offsetof(struct w32_io, write_overlapped));
|
||||
debug2("WriteCB - pio:%p, pending_state:%d, error:%d, transferred:%d of remaining: %d",
|
||||
@ -450,21 +450,18 @@ VOID CALLBACK WriteCompletionRoutine(
|
||||
|
||||
/* write() implementation */
|
||||
int
|
||||
fileio_write(struct w32_io* pio, const void *buf, unsigned int max) {
|
||||
fileio_write(struct w32_io* pio, const void *buf, unsigned int max)
|
||||
{
|
||||
int bytes_copied;
|
||||
|
||||
debug2("write - io:%p", pio);
|
||||
|
||||
if (pio->write_details.pending) {
|
||||
if (w32_io_is_blocking(pio))
|
||||
{
|
||||
if (w32_io_is_blocking(pio)) {
|
||||
debug2("write - io pending, blocking call made, io:%p", pio);
|
||||
while (pio->write_details.pending) {
|
||||
while (pio->write_details.pending)
|
||||
if (wait_for_any_event(NULL, 0, INFINITE) == -1)
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
errno = EAGAIN;
|
||||
debug2("write - IO is already pending, io:%p", pio);
|
||||
return -1;
|
||||
@ -502,14 +499,12 @@ fileio_write(struct w32_io* pio, const void *buf, unsigned int max) {
|
||||
}
|
||||
else
|
||||
return -1;
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
if (WriteFileEx(WINHANDLE(pio), pio->write_details.buf, bytes_copied,
|
||||
&pio->write_overlapped, &WriteCompletionRoutine)) {
|
||||
pio->write_details.pending = TRUE;
|
||||
pio->write_details.remaining = bytes_copied;
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
errno = errno_from_Win32LastError();
|
||||
/* read end of the pipe closed ? */
|
||||
if ((FILETYPE(pio) == FILE_TYPE_PIPE) && (errno == ERROR_BROKEN_PIPE)) {
|
||||
@ -531,6 +526,7 @@ fileio_write(struct w32_io* pio, const void *buf, unsigned int max) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* execute APC to give a chance for write to complete */
|
||||
SleepEx(0, TRUE);
|
||||
|
||||
@ -548,8 +544,8 @@ fileio_write(struct w32_io* pio, const void *buf, unsigned int max) {
|
||||
|
||||
/* fstat() implemetation */
|
||||
int
|
||||
fileio_fstat(struct w32_io* pio, struct _stat64 *buf) {
|
||||
|
||||
fileio_fstat(struct w32_io* pio, struct _stat64 *buf)
|
||||
{
|
||||
int fd = _open_osfhandle((intptr_t)pio->handle, 0);
|
||||
debug2("fstat - pio:%p", pio);
|
||||
if (fd == -1) {
|
||||
@ -561,12 +557,23 @@ fileio_fstat(struct w32_io* pio, struct _stat64 *buf) {
|
||||
}
|
||||
|
||||
int
|
||||
fileio_stat(const char *path, struct _stat64 *buf) {
|
||||
fileio_stat(const char *path, struct _stat64 *buf)
|
||||
{
|
||||
wchar_t wpath[PATH_MAX];
|
||||
wchar_t* wtmp = NULL;
|
||||
struct w32_io* pio;
|
||||
|
||||
if ((wtmp = utf8_to_utf16(path)) == NULL)
|
||||
fatal("failed to covert input arguments");
|
||||
|
||||
/* If we doesn't have sufficient permissions then _wstat4() is returning
|
||||
* file not found so added fileio_open() which will set the errorno correctly (access denied)
|
||||
*/
|
||||
if (NULL == (pio = fileio_open(path, O_RDONLY, 0)))
|
||||
return -1;
|
||||
|
||||
fileio_close(pio);
|
||||
|
||||
wcscpy(&wpath[0], wtmp);
|
||||
free(wtmp);
|
||||
|
||||
@ -574,7 +581,8 @@ fileio_stat(const char *path, struct _stat64 *buf) {
|
||||
}
|
||||
|
||||
long
|
||||
fileio_lseek(struct w32_io* pio, long offset, int origin) {
|
||||
fileio_lseek(struct w32_io* pio, long offset, int origin)
|
||||
{
|
||||
debug2("lseek - pio:%p", pio);
|
||||
if (origin != SEEK_SET) {
|
||||
debug("lseek - ERROR, origin is not supported %d", origin);
|
||||
@ -589,13 +597,12 @@ fileio_lseek(struct w32_io* pio, long offset, int origin) {
|
||||
|
||||
/* fdopen implementation */
|
||||
FILE*
|
||||
fileio_fdopen(struct w32_io* pio, const char *mode) {
|
||||
|
||||
fileio_fdopen(struct w32_io* pio, const char *mode)
|
||||
{
|
||||
int fd_flags = 0;
|
||||
debug2("fdopen - io:%p", pio);
|
||||
|
||||
/* logic below doesn't work with overlapped file HANDLES */
|
||||
|
||||
if (mode[1] == '\0') {
|
||||
switch (*mode) {
|
||||
case 'r':
|
||||
@ -611,8 +618,7 @@ fileio_fdopen(struct w32_io* pio, const char *mode) {
|
||||
debug("fdopen - ERROR unsupported mode %s", mode);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
errno = ENOTSUP;
|
||||
debug("fdopen - ERROR unsupported mode %s", mode);
|
||||
return NULL;
|
||||
@ -630,8 +636,8 @@ fileio_fdopen(struct w32_io* pio, const char *mode) {
|
||||
}
|
||||
|
||||
void
|
||||
fileio_on_select(struct w32_io* pio, BOOL rd) {
|
||||
|
||||
fileio_on_select(struct w32_io* pio, BOOL rd)
|
||||
{
|
||||
if (!rd)
|
||||
return;
|
||||
|
||||
@ -643,8 +649,7 @@ fileio_on_select(struct w32_io* pio, BOOL rd) {
|
||||
errno = 0;
|
||||
return;
|
||||
}
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
if (fileio_ReadFileEx(pio, INT_MAX) != 0) {
|
||||
pio->read_details.error = errno;
|
||||
errno = 0;
|
||||
@ -653,16 +658,15 @@ fileio_on_select(struct w32_io* pio, BOOL rd) {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
fileio_close(struct w32_io* pio) {
|
||||
|
||||
fileio_close(struct w32_io* pio)
|
||||
{
|
||||
debug2("fileclose - pio:%p", pio);
|
||||
|
||||
CancelIo(WINHANDLE(pio));
|
||||
//let queued APCs (if any) drain
|
||||
/* let queued APCs (if any) drain */
|
||||
SleepEx(0, TRUE);
|
||||
if (pio->type != STD_IO_FD) {//STD handles are never explicitly closed
|
||||
if (pio->type != STD_IO_FD) { /* STD handles are never explicitly closed */
|
||||
CloseHandle(WINHANDLE(pio));
|
||||
|
||||
if (pio->read_details.buf)
|
||||
@ -677,14 +681,14 @@ fileio_close(struct w32_io* pio) {
|
||||
}
|
||||
|
||||
BOOL
|
||||
fileio_is_io_available(struct w32_io* pio, BOOL rd) {
|
||||
fileio_is_io_available(struct w32_io* pio, BOOL rd)
|
||||
{
|
||||
if (rd) {
|
||||
if (pio->read_details.remaining || pio->read_details.error)
|
||||
return TRUE;
|
||||
else
|
||||
return FALSE;
|
||||
}
|
||||
else { //write
|
||||
} else { /* write */
|
||||
return (pio->write_details.pending == FALSE) ? TRUE : FALSE;
|
||||
}
|
||||
}
|
@ -30,11 +30,12 @@
|
||||
|
||||
#include <Windows.h>
|
||||
#include <stdio.h>
|
||||
#include <time.h>
|
||||
#include <Shlwapi.h>
|
||||
|
||||
#include "inc\sys\stat.h"
|
||||
#include "inc\sys\statvfs.h"
|
||||
#include "inc\sys\time.h"
|
||||
#include <time.h>
|
||||
#include <Shlwapi.h>
|
||||
#include "misc_internal.h"
|
||||
#include "inc\dlfcn.h"
|
||||
#include "inc\dirent.h"
|
||||
@ -43,13 +44,102 @@
|
||||
#include "inc\fcntl.h"
|
||||
#include "signal_internal.h"
|
||||
|
||||
int usleep(unsigned int useconds)
|
||||
static char* s_programdir = NULL;
|
||||
|
||||
/* Maximum reparse buffer info size. The max user defined reparse
|
||||
* data is 16KB, plus there's a header.
|
||||
*/
|
||||
#define MAX_REPARSE_SIZE 17000
|
||||
#define IO_REPARSE_TAG_SYMBOLIC_LINK IO_REPARSE_TAG_RESERVED_ZERO
|
||||
#define IO_REPARSE_TAG_MOUNT_POINT (0xA0000003L) /* winnt ntifs */
|
||||
#define IO_REPARSE_TAG_HSM (0xC0000004L) /* winnt ntifs */
|
||||
#define IO_REPARSE_TAG_SIS (0x80000007L) /* winnt ntifs */
|
||||
#define REPARSE_MOUNTPOINT_HEADER_SIZE 8
|
||||
|
||||
typedef struct _REPARSE_DATA_BUFFER {
|
||||
ULONG ReparseTag;
|
||||
USHORT ReparseDataLength;
|
||||
USHORT Reserved;
|
||||
union {
|
||||
struct {
|
||||
USHORT SubstituteNameOffset;
|
||||
USHORT SubstituteNameLength;
|
||||
USHORT PrintNameOffset;
|
||||
USHORT PrintNameLength;
|
||||
WCHAR PathBuffer[1];
|
||||
} SymbolicLinkReparseBuffer;
|
||||
|
||||
struct {
|
||||
USHORT SubstituteNameOffset;
|
||||
USHORT SubstituteNameLength;
|
||||
USHORT PrintNameOffset;
|
||||
USHORT PrintNameLength;
|
||||
WCHAR PathBuffer[1];
|
||||
} MountPointReparseBuffer;
|
||||
|
||||
struct {
|
||||
UCHAR DataBuffer[1];
|
||||
} GenericReparseBuffer;
|
||||
};
|
||||
} REPARSE_DATA_BUFFER, *PREPARSE_DATA_BUFFER;
|
||||
|
||||
/* Windows CRT defines error string messages only till 43 in errno.h
|
||||
* This is an extended list that defines messages for EADDRINUSE through EWOULDBLOCK
|
||||
*/
|
||||
char* _sys_errlist_ext[] = {
|
||||
"Address already in use", /* EADDRINUSE 100 */
|
||||
"Address not available", /* EADDRNOTAVAIL 101 */
|
||||
"Address family not supported", /* EAFNOSUPPORT 102 */
|
||||
"Connection already in progress", /* EALREADY 103 */
|
||||
"Bad message", /* EBADMSG 104 */
|
||||
"Operation canceled", /* ECANCELED 105 */
|
||||
"Connection aborted", /* ECONNABORTED 106 */
|
||||
"Connection refused", /* ECONNREFUSED 107 */
|
||||
"Connection reset", /* ECONNRESET 108 */
|
||||
"Destination address required", /* EDESTADDRREQ 109 */
|
||||
"Host is unreachable", /* EHOSTUNREACH 110 */
|
||||
"Identifier removed", /* EIDRM 111 */
|
||||
"Operation in progress", /* EINPROGRESS 112 */
|
||||
"Socket is connected", /* EISCONN 113 */
|
||||
"Too many levels of symbolic links", /* ELOOP 114 */
|
||||
"Message too long", /* EMSGSIZE 115 */
|
||||
"Network is down", /* ENETDOWN 116 */
|
||||
"Connection aborted by network", /* ENETRESET 117 */
|
||||
"Network unreachable", /* ENETUNREACH 118 */
|
||||
"No buffer space available", /* ENOBUFS 119 */
|
||||
"No message is available on the STREAM head read queue",/* ENODATA 120 */
|
||||
"Link has been severed", /* ENOLINK 121 */
|
||||
"No message of the desired type", /* ENOMSG 122 */
|
||||
"Protocol not available", /* ENOPROTOOPT 123 */
|
||||
"No STREAM resources", /* ENOSR 124 */
|
||||
"Not a STREAM", /* ENOSTR 125 */
|
||||
"The socket is not connected", /* ENOTCONN 126 */
|
||||
"enotecoverable", /* ENOTRECOVERABLE 127 */
|
||||
"Not a socket", /* ENOTSOCK 128 */
|
||||
"Operation not supported", /* ENOTSUP 129 */
|
||||
"Operation not supported on socket", /* EOPNOTSUPP 130 */
|
||||
"eother", /* EOTHER 131 */
|
||||
"Value too large to be stored in data type", /* EOVERFLOW 132 */
|
||||
"eownerdead", /* EOWNERDEAD 133 */
|
||||
"Protocol error", /* EPROTO 134 */
|
||||
"Protocol not supported", /* EPROTONOSUPPORT 135 */
|
||||
"Protocol wrong type for socket", /* EPROTOTYPE 136 */
|
||||
"Timer expired", /* ETIME 137 */
|
||||
"Connection timed out", /* ETIMEDOUT 138 */
|
||||
"Text file busy", /* ETXTBSY 139 */
|
||||
"Operation would block" /* EWOULDBLOCK 140 */
|
||||
};
|
||||
|
||||
int
|
||||
usleep(unsigned int useconds)
|
||||
{
|
||||
Sleep(useconds / 1000);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int nanosleep(const struct timespec *req, struct timespec *rem) {
|
||||
int
|
||||
nanosleep(const struct timespec *req, struct timespec *rem)
|
||||
{
|
||||
HANDLE timer;
|
||||
LARGE_INTEGER li;
|
||||
|
||||
@ -91,8 +181,7 @@ int nanosleep(const struct timespec *req, struct timespec *rem) {
|
||||
int
|
||||
gettimeofday(struct timeval *tv, void *tz)
|
||||
{
|
||||
union
|
||||
{
|
||||
union {
|
||||
FILETIME ft;
|
||||
unsigned long long ns;
|
||||
} timehelper;
|
||||
@ -115,20 +204,27 @@ gettimeofday(struct timeval *tv, void *tz)
|
||||
}
|
||||
|
||||
void
|
||||
explicit_bzero(void *b, size_t len) {
|
||||
explicit_bzero(void *b, size_t len)
|
||||
{
|
||||
SecureZeroMemory(b, len);
|
||||
}
|
||||
|
||||
HMODULE dlopen(const char *filename, int flags) {
|
||||
HMODULE
|
||||
dlopen(const char *filename, int flags)
|
||||
{
|
||||
return LoadLibraryA(filename);
|
||||
}
|
||||
|
||||
int dlclose(HMODULE handle) {
|
||||
int
|
||||
dlclose(HMODULE handle)
|
||||
{
|
||||
FreeLibrary(handle);
|
||||
return 0;
|
||||
}
|
||||
|
||||
FARPROC dlsym(HMODULE handle, const char *symbol) {
|
||||
FARPROC
|
||||
dlsym(HMODULE handle, const char *symbol)
|
||||
{
|
||||
return GetProcAddress(handle, symbol);
|
||||
}
|
||||
|
||||
@ -137,7 +233,8 @@ FARPROC dlsym(HMODULE handle, const char *symbol) {
|
||||
* only r, w, a are supported for now
|
||||
*/
|
||||
FILE *
|
||||
w32_fopen_utf8(const char *path, const char *mode) {
|
||||
w32_fopen_utf8(const char *path, const char *mode)
|
||||
{
|
||||
wchar_t wpath[PATH_MAX], wmode[5];
|
||||
FILE* f;
|
||||
char utf8_bom[] = { 0xEF,0xBB,0xBF };
|
||||
@ -166,8 +263,7 @@ w32_fopen_utf8(const char *path, const char *mode) {
|
||||
return NULL;
|
||||
}*/
|
||||
|
||||
}
|
||||
else if (mode[0] == 'r' && fseek(f, 0, SEEK_SET) != EBADF) {
|
||||
} else if (mode[0] == 'r' && fseek(f, 0, SEEK_SET) != EBADF) {
|
||||
/* read out UTF-8 BOM if present*/
|
||||
if (fread(first3_bytes, 3, 1, f) != 1 ||
|
||||
memcmp(first3_bytes, utf8_bom, 3) != 0) {
|
||||
@ -181,29 +277,34 @@ w32_fopen_utf8(const char *path, const char *mode) {
|
||||
|
||||
|
||||
wchar_t *
|
||||
utf8_to_utf16(const char *utf8) {
|
||||
utf8_to_utf16(const char *utf8)
|
||||
{
|
||||
int needed = 0;
|
||||
wchar_t* utf16 = NULL;
|
||||
if ((needed = MultiByteToWideChar(CP_UTF8, 0, utf8, -1, NULL, 0)) == 0 ||
|
||||
(utf16 = malloc(needed * sizeof(wchar_t))) == NULL ||
|
||||
MultiByteToWideChar(CP_UTF8, 0, utf8, -1, utf16, needed) == 0)
|
||||
return NULL;
|
||||
|
||||
return utf16;
|
||||
}
|
||||
|
||||
char *
|
||||
utf16_to_utf8(const wchar_t* utf16) {
|
||||
utf16_to_utf8(const wchar_t* utf16)
|
||||
{
|
||||
int needed = 0;
|
||||
char* utf8 = NULL;
|
||||
if ((needed = WideCharToMultiByte(CP_UTF8, 0, utf16, -1, NULL, 0, NULL, NULL)) == 0 ||
|
||||
(utf8 = malloc(needed)) == NULL ||
|
||||
WideCharToMultiByte(CP_UTF8, 0, utf16, -1, utf8, needed, NULL, NULL) == 0)
|
||||
return NULL;
|
||||
|
||||
return utf8;
|
||||
}
|
||||
|
||||
static char* s_programdir = NULL;
|
||||
char* w32_programdir() {
|
||||
char *
|
||||
w32_programdir()
|
||||
{
|
||||
if (s_programdir != NULL)
|
||||
return s_programdir;
|
||||
|
||||
@ -211,7 +312,6 @@ char* w32_programdir() {
|
||||
return NULL;
|
||||
|
||||
/* null terminate after directory path */
|
||||
{
|
||||
char* tail = s_programdir + strlen(s_programdir);
|
||||
while (tail > s_programdir && *tail != '\\' && *tail != '/')
|
||||
tail--;
|
||||
@ -220,10 +320,8 @@ char* w32_programdir() {
|
||||
*tail = '\0';
|
||||
else
|
||||
*tail = '.'; /* current directory */
|
||||
}
|
||||
|
||||
return s_programdir;
|
||||
|
||||
}
|
||||
|
||||
int
|
||||
@ -233,7 +331,9 @@ daemon(int nochdir, int noclose)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int w32_ioctl(int d, int request, ...) {
|
||||
int
|
||||
w32_ioctl(int d, int request, ...)
|
||||
{
|
||||
va_list valist;
|
||||
va_start(valist, request);
|
||||
|
||||
@ -258,7 +358,8 @@ int w32_ioctl(int d, int request, ...) {
|
||||
}
|
||||
|
||||
int
|
||||
spawn_child(char* cmd, int in, int out, int err, DWORD flags) {
|
||||
spawn_child(char* cmd, int in, int out, int err, DWORD flags)
|
||||
{
|
||||
PROCESS_INFORMATION pi;
|
||||
STARTUPINFOW si;
|
||||
BOOL b;
|
||||
@ -276,7 +377,6 @@ spawn_child(char* cmd, int in, int out, int err, DWORD flags) {
|
||||
if (t[0] == '\0' || t[0] == '\\' || t[0] == '.' || t[1] == ':')
|
||||
break;
|
||||
add_module_path = 1;
|
||||
|
||||
} while (0);
|
||||
|
||||
/* add current module path to start if needed */
|
||||
@ -292,8 +392,7 @@ spawn_child(char* cmd, int in, int out, int err, DWORD flags) {
|
||||
ctr += strlen(w32_programdir());
|
||||
*ctr++ = '\\';
|
||||
memcpy(ctr, cmd, strlen(cmd) + 1);
|
||||
}
|
||||
else
|
||||
} else
|
||||
abs_cmd = cmd;
|
||||
|
||||
debug("spawning %s", abs_cmd);
|
||||
@ -322,8 +421,7 @@ spawn_child(char* cmd, int in, int out, int err, DWORD flags) {
|
||||
pi.dwProcessId = -1;
|
||||
}
|
||||
CloseHandle(pi.hThread);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
errno = GetLastError();
|
||||
pi.dwProcessId = -1;
|
||||
}
|
||||
@ -343,15 +441,9 @@ strmode(mode_t mode, char *p)
|
||||
case S_IFCHR: /* character special */
|
||||
*p++ = 'c';
|
||||
break;
|
||||
//case S_IFBLK: /* block special */
|
||||
// *p++ = 'b';
|
||||
// break;
|
||||
case S_IFREG: /* regular */
|
||||
*p++ = '-';
|
||||
break;
|
||||
//case S_IFLNK: /* symbolic link */
|
||||
// *p++ = 'l';
|
||||
// break;
|
||||
#ifdef S_IFSOCK
|
||||
case S_IFSOCK: /* socket */
|
||||
*p++ = 's';
|
||||
@ -365,81 +457,83 @@ strmode(mode_t mode, char *p)
|
||||
break;
|
||||
}
|
||||
|
||||
// The below code is commented as the group, other is not applicable on the windows.
|
||||
// This will be properly fixed in next releases.
|
||||
// As of now we are keeping "*" for everything.
|
||||
/* The below code is commented as the group, other is not applicable on the windows.
|
||||
* This will be properly fixed in next releases.
|
||||
* As of now we are keeping "*" for everything.
|
||||
*/
|
||||
const char *permissions = "********* ";
|
||||
strncpy(p, permissions, strlen(permissions) + 1);
|
||||
p = p + strlen(p);
|
||||
///* usr */
|
||||
//if (mode & S_IRUSR)
|
||||
// *p++ = 'r';
|
||||
//else
|
||||
// *p++ = '-';
|
||||
//if (mode & S_IWUSR)
|
||||
// *p++ = 'w';
|
||||
//else
|
||||
// *p++ = '-';
|
||||
//switch (mode & (S_IXUSR)) {
|
||||
//case 0:
|
||||
// *p++ = '-';
|
||||
/* //usr
|
||||
if (mode & S_IRUSR)
|
||||
*p++ = 'r';
|
||||
else
|
||||
*p++ = '-';
|
||||
if (mode & S_IWUSR)
|
||||
*p++ = 'w';
|
||||
else
|
||||
*p++ = '-';
|
||||
switch (mode & (S_IXUSR)) {
|
||||
case 0:
|
||||
*p++ = '-';
|
||||
break;
|
||||
case S_IXUSR:
|
||||
*p++ = 'x';
|
||||
break;
|
||||
//case S_ISUID:
|
||||
// *p++ = 'S';
|
||||
// break;
|
||||
//case S_IXUSR:
|
||||
// *p++ = 'x';
|
||||
//case S_IXUSR | S_ISUID:
|
||||
// *p++ = 's';
|
||||
// break;
|
||||
// //case S_ISUID:
|
||||
// // *p++ = 'S';
|
||||
// // break;
|
||||
// //case S_IXUSR | S_ISUID:
|
||||
// // *p++ = 's';
|
||||
// // break;
|
||||
//}
|
||||
///* group */
|
||||
//if (mode & S_IRGRP)
|
||||
// *p++ = 'r';
|
||||
//else
|
||||
// *p++ = '-';
|
||||
//if (mode & S_IWGRP)
|
||||
// *p++ = 'w';
|
||||
//else
|
||||
// *p++ = '-';
|
||||
//switch (mode & (S_IXGRP)) {
|
||||
//case 0:
|
||||
// *p++ = '-';
|
||||
}
|
||||
// group
|
||||
if (mode & S_IRGRP)
|
||||
*p++ = 'r';
|
||||
else
|
||||
*p++ = '-';
|
||||
if (mode & S_IWGRP)
|
||||
*p++ = 'w';
|
||||
else
|
||||
*p++ = '-';
|
||||
switch (mode & (S_IXGRP)) {
|
||||
case 0:
|
||||
*p++ = '-';
|
||||
break;
|
||||
case S_IXGRP:
|
||||
*p++ = 'x';
|
||||
break;
|
||||
//case S_ISGID:
|
||||
// *p++ = 'S';
|
||||
// break;
|
||||
//case S_IXGRP:
|
||||
// *p++ = 'x';
|
||||
//case S_IXGRP | S_ISGID:
|
||||
// *p++ = 's';
|
||||
// break;
|
||||
// //case S_ISGID:
|
||||
// // *p++ = 'S';
|
||||
// // break;
|
||||
// //case S_IXGRP | S_ISGID:
|
||||
// // *p++ = 's';
|
||||
// // break;
|
||||
//}
|
||||
///* other */
|
||||
//if (mode & S_IROTH)
|
||||
// *p++ = 'r';
|
||||
//else
|
||||
// *p++ = '-';
|
||||
//if (mode & S_IWOTH)
|
||||
// *p++ = 'w';
|
||||
//else
|
||||
// *p++ = '-';
|
||||
//switch (mode & (S_IXOTH)) {
|
||||
//case 0:
|
||||
// *p++ = '-';
|
||||
// break;
|
||||
//case S_IXOTH:
|
||||
// *p++ = 'x';
|
||||
// break;
|
||||
//}
|
||||
//*p++ = ' '; /* will be a '+' if ACL's implemented */
|
||||
}
|
||||
// other
|
||||
if (mode & S_IROTH)
|
||||
*p++ = 'r';
|
||||
else
|
||||
*p++ = '-';
|
||||
if (mode & S_IWOTH)
|
||||
*p++ = 'w';
|
||||
else
|
||||
*p++ = '-';
|
||||
switch (mode & (S_IXOTH)) {
|
||||
case 0:
|
||||
*p++ = '-';
|
||||
break;
|
||||
case S_IXOTH:
|
||||
*p++ = 'x';
|
||||
break;
|
||||
}
|
||||
*p++ = ' '; // will be a '+' if ACL's implemented */
|
||||
*p = '\0';
|
||||
}
|
||||
|
||||
int
|
||||
w32_chmod(const char *pathname, mode_t mode) {
|
||||
w32_chmod(const char *pathname, mode_t mode)
|
||||
{
|
||||
int ret;
|
||||
wchar_t *resolvedPathName_utf16 = utf8_to_utf16(sanitized_path(pathname));
|
||||
if (resolvedPathName_utf16 == NULL) {
|
||||
@ -452,15 +546,16 @@ w32_chmod(const char *pathname, mode_t mode) {
|
||||
}
|
||||
|
||||
int
|
||||
w32_chown(const char *pathname, unsigned int owner, unsigned int group) {
|
||||
w32_chown(const char *pathname, unsigned int owner, unsigned int group)
|
||||
{
|
||||
/* TODO - implement this */
|
||||
errno = EOPNOTSUPP;
|
||||
return -1;
|
||||
}
|
||||
|
||||
static void
|
||||
unix_time_to_file_time(ULONG t, LPFILETIME pft) {
|
||||
|
||||
unix_time_to_file_time(ULONG t, LPFILETIME pft)
|
||||
{
|
||||
ULONGLONG ull;
|
||||
ull = UInt32x32To64(t, 10000000) + 116444736000000000;
|
||||
|
||||
@ -469,7 +564,8 @@ unix_time_to_file_time(ULONG t, LPFILETIME pft) {
|
||||
}
|
||||
|
||||
static int
|
||||
settimes(wchar_t * path, FILETIME *cretime, FILETIME *acttime, FILETIME *modtime) {
|
||||
settimes(wchar_t * path, FILETIME *cretime, FILETIME *acttime, FILETIME *modtime)
|
||||
{
|
||||
HANDLE handle;
|
||||
handle = CreateFileW(path, GENERIC_WRITE, FILE_SHARE_WRITE,
|
||||
NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL);
|
||||
@ -493,7 +589,8 @@ settimes(wchar_t * path, FILETIME *cretime, FILETIME *acttime, FILETIME *modtime
|
||||
}
|
||||
|
||||
int
|
||||
w32_utimes(const char *filename, struct timeval *tvp) {
|
||||
w32_utimes(const char *filename, struct timeval *tvp)
|
||||
{
|
||||
int ret;
|
||||
FILETIME acttime, modtime;
|
||||
wchar_t *resolvedPathName_utf16 = utf8_to_utf16(sanitized_path(filename));
|
||||
@ -512,21 +609,24 @@ w32_utimes(const char *filename, struct timeval *tvp) {
|
||||
}
|
||||
|
||||
int
|
||||
w32_symlink(const char *target, const char *linkpath) {
|
||||
// Not supported in windows
|
||||
w32_symlink(const char *target, const char *linkpath)
|
||||
{
|
||||
/* Not supported in windows */
|
||||
errno = EOPNOTSUPP;
|
||||
return -1;
|
||||
}
|
||||
|
||||
int
|
||||
link(const char *oldpath, const char *newpath) {
|
||||
// Not supported in windows
|
||||
link(const char *oldpath, const char *newpath)
|
||||
{
|
||||
/* Not supported in windows */
|
||||
errno = EOPNOTSUPP;
|
||||
return -1;
|
||||
}
|
||||
|
||||
int
|
||||
w32_rename(const char *old_name, const char *new_name) {
|
||||
w32_rename(const char *old_name, const char *new_name)
|
||||
{
|
||||
wchar_t *resolvedOldPathName_utf16 = utf8_to_utf16(sanitized_path(old_name));
|
||||
wchar_t *resolvedNewPathName_utf16 = utf8_to_utf16(sanitized_path(new_name));
|
||||
|
||||
@ -542,20 +642,19 @@ w32_rename(const char *old_name, const char *new_name) {
|
||||
*/
|
||||
struct _stat64 st;
|
||||
if (fileio_stat(sanitized_path(new_name), &st) != -1) {
|
||||
if(((st.st_mode & _S_IFMT) == _S_IFREG)) {
|
||||
if (((st.st_mode & _S_IFMT) == _S_IFREG))
|
||||
w32_unlink(new_name);
|
||||
} else {
|
||||
else {
|
||||
DIR *dirp = opendir(new_name);
|
||||
if (NULL != dirp) {
|
||||
struct dirent *dp = readdir(dirp);
|
||||
closedir(dirp);
|
||||
|
||||
if (dp == NULL) {
|
||||
if (dp == NULL)
|
||||
w32_rmdir(new_name);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int returnStatus = _wrename(resolvedOldPathName_utf16, resolvedNewPathName_utf16);
|
||||
free(resolvedOldPathName_utf16);
|
||||
@ -565,8 +664,8 @@ w32_rename(const char *old_name, const char *new_name) {
|
||||
}
|
||||
|
||||
int
|
||||
w32_unlink(const char *path) {
|
||||
|
||||
w32_unlink(const char *path)
|
||||
{
|
||||
wchar_t *resolvedPathName_utf16 = utf8_to_utf16(sanitized_path(path));
|
||||
if (NULL == resolvedPathName_utf16) {
|
||||
errno = ENOMEM;
|
||||
@ -580,7 +679,8 @@ w32_unlink(const char *path) {
|
||||
}
|
||||
|
||||
int
|
||||
w32_rmdir(const char *path) {
|
||||
w32_rmdir(const char *path)
|
||||
{
|
||||
wchar_t *resolvedPathName_utf16 = utf8_to_utf16(sanitized_path(path));
|
||||
if (NULL == resolvedPathName_utf16) {
|
||||
errno = ENOMEM;
|
||||
@ -594,7 +694,8 @@ w32_rmdir(const char *path) {
|
||||
}
|
||||
|
||||
int
|
||||
w32_chdir(const char *dirname_utf8) {
|
||||
w32_chdir(const char *dirname_utf8)
|
||||
{
|
||||
wchar_t *dirname_utf16 = utf8_to_utf16(dirname_utf8);
|
||||
if (dirname_utf16 == NULL) {
|
||||
errno = ENOMEM;
|
||||
@ -608,7 +709,8 @@ w32_chdir(const char *dirname_utf8) {
|
||||
}
|
||||
|
||||
char *
|
||||
w32_getcwd(char *buffer, int maxlen) {
|
||||
w32_getcwd(char *buffer, int maxlen)
|
||||
{
|
||||
wchar_t wdirname[PATH_MAX];
|
||||
char* putf8 = NULL;
|
||||
|
||||
@ -623,8 +725,8 @@ w32_getcwd(char *buffer, int maxlen) {
|
||||
}
|
||||
|
||||
int
|
||||
w32_mkdir(const char *path_utf8, unsigned short mode) {
|
||||
|
||||
w32_mkdir(const char *path_utf8, unsigned short mode)
|
||||
{
|
||||
wchar_t *path_utf16 = utf8_to_utf16(sanitized_path(path_utf8));
|
||||
if (path_utf16 == NULL) {
|
||||
errno = ENOMEM;
|
||||
@ -646,11 +748,12 @@ w32_mkdir(const char *path_utf8, unsigned short mode) {
|
||||
}
|
||||
|
||||
int
|
||||
w32_stat(const char *path, struct w32_stat *buf) {
|
||||
w32_stat(const char *path, struct w32_stat *buf)
|
||||
{
|
||||
return fileio_stat(sanitized_path(path), (struct _stat64*)buf);
|
||||
}
|
||||
|
||||
// if file is symbolic link, copy its link into "link" .
|
||||
/* if file is symbolic link, copy its link into "link" */
|
||||
int
|
||||
readlink(const char *path, char *link, int linklen)
|
||||
{
|
||||
@ -658,9 +761,10 @@ readlink(const char *path, char *link, int linklen)
|
||||
return 0;
|
||||
}
|
||||
|
||||
// convert forward slash to back slash
|
||||
/* convert forward slash to back slash */
|
||||
void
|
||||
convertToBackslash(char *str) {
|
||||
convertToBackslash(char *str)
|
||||
{
|
||||
while (*str) {
|
||||
if (*str == '/')
|
||||
*str = '\\';
|
||||
@ -668,9 +772,10 @@ convertToBackslash(char *str) {
|
||||
}
|
||||
}
|
||||
|
||||
// convert back slash to forward slash
|
||||
/* convert back slash to forward slash */
|
||||
void
|
||||
convertToForwardslash(char *str) {
|
||||
convertToForwardslash(char *str)
|
||||
{
|
||||
while (*str) {
|
||||
if (*str == '\\')
|
||||
*str = '/';
|
||||
@ -683,16 +788,16 @@ convertToForwardslash(char *str) {
|
||||
* path to produce a canonicalized absolute pathname.
|
||||
*/
|
||||
char *
|
||||
realpath(const char *path, char resolved[PATH_MAX]) {
|
||||
realpath(const char *path, char resolved[PATH_MAX])
|
||||
{
|
||||
char tempPath[PATH_MAX];
|
||||
|
||||
if ((path[0] == '/') && path[1] && (path[2] == ':')) {
|
||||
strncpy(resolved, path + 1, strlen(path)); // skip the first '/'
|
||||
} else {
|
||||
if ((path[0] == '/') && path[1] && (path[2] == ':'))
|
||||
strncpy(resolved, path + 1, strlen(path)); /* skip the first '/' */
|
||||
else
|
||||
strncpy(resolved, path, strlen(path) + 1);
|
||||
}
|
||||
|
||||
if ((resolved[0]) && (resolved[1] == ':') && (resolved[2] == '\0')) { // make "x:" as "x:\\"
|
||||
if ((resolved[0]) && (resolved[1] == ':') && (resolved[2] == '\0')) { /* make "x:" as "x:\\" */
|
||||
resolved[2] = '\\';
|
||||
resolved[3] = '\0';
|
||||
}
|
||||
@ -702,68 +807,36 @@ realpath(const char *path, char resolved[PATH_MAX]) {
|
||||
|
||||
convertToForwardslash(tempPath);
|
||||
|
||||
resolved[0] = '/'; // will be our first slash in /x:/users/test1 format
|
||||
resolved[0] = '/'; /* will be our first slash in /x:/users/test1 format */
|
||||
strncpy(resolved + 1, tempPath, sizeof(tempPath) - 1);
|
||||
return resolved;
|
||||
}
|
||||
|
||||
char*
|
||||
sanitized_path(const char *path) {
|
||||
sanitized_path(const char *path)
|
||||
{
|
||||
static char newPath[PATH_MAX] = { '\0', };
|
||||
|
||||
if (path[0] == '/' && path[1]) {
|
||||
if (path[2] == ':') {
|
||||
if (path[3] == '\0') { // make "/x:" as "x:\\"
|
||||
if (path[3] == '\0') { /* make "/x:" as "x:\\" */
|
||||
strncpy(newPath, path + 1, strlen(path) - 1);
|
||||
newPath[2] = '\\';
|
||||
newPath[3] = '\0';
|
||||
|
||||
return newPath;
|
||||
} else {
|
||||
return (char *)(path + 1); // skip the first "/"
|
||||
}
|
||||
} else
|
||||
return (char *)(path + 1); /* skip the first "/" */
|
||||
}
|
||||
}
|
||||
|
||||
return (char *)path;
|
||||
}
|
||||
|
||||
// Maximum reparse buffer info size. The max user defined reparse
|
||||
// data is 16KB, plus there's a header.
|
||||
#define MAX_REPARSE_SIZE 17000
|
||||
#define IO_REPARSE_TAG_SYMBOLIC_LINK IO_REPARSE_TAG_RESERVED_ZERO
|
||||
#define IO_REPARSE_TAG_MOUNT_POINT (0xA0000003L) // winnt ntifs
|
||||
#define IO_REPARSE_TAG_HSM (0xC0000004L) // winnt ntifs
|
||||
#define IO_REPARSE_TAG_SIS (0x80000007L) // winnt ntifs
|
||||
#define REPARSE_MOUNTPOINT_HEADER_SIZE 8
|
||||
|
||||
typedef struct _REPARSE_DATA_BUFFER {
|
||||
ULONG ReparseTag;
|
||||
USHORT ReparseDataLength;
|
||||
USHORT Reserved;
|
||||
union {
|
||||
struct {
|
||||
USHORT SubstituteNameOffset;
|
||||
USHORT SubstituteNameLength;
|
||||
USHORT PrintNameOffset;
|
||||
USHORT PrintNameLength;
|
||||
WCHAR PathBuffer[1];
|
||||
} SymbolicLinkReparseBuffer;
|
||||
struct {
|
||||
USHORT SubstituteNameOffset;
|
||||
USHORT SubstituteNameLength;
|
||||
USHORT PrintNameOffset;
|
||||
USHORT PrintNameLength;
|
||||
WCHAR PathBuffer[1];
|
||||
} MountPointReparseBuffer;
|
||||
struct {
|
||||
UCHAR DataBuffer[1];
|
||||
} GenericReparseBuffer;
|
||||
};
|
||||
} REPARSE_DATA_BUFFER, *PREPARSE_DATA_BUFFER;
|
||||
|
||||
BOOL
|
||||
ResolveLink(wchar_t * tLink, wchar_t *ret, DWORD * plen, DWORD Flags) {
|
||||
ResolveLink(wchar_t * tLink, wchar_t *ret, DWORD * plen, DWORD Flags)
|
||||
{
|
||||
HANDLE fileHandle;
|
||||
BYTE reparseBuffer[MAX_REPARSE_SIZE];
|
||||
PBYTE reparseData;
|
||||
@ -771,43 +844,34 @@ ResolveLink(wchar_t * tLink, wchar_t *ret, DWORD * plen, DWORD Flags) {
|
||||
PREPARSE_DATA_BUFFER msReparseInfo = (PREPARSE_DATA_BUFFER)reparseBuffer;
|
||||
DWORD returnedLength;
|
||||
|
||||
if (Flags & FILE_ATTRIBUTE_DIRECTORY)
|
||||
{
|
||||
if (Flags & FILE_ATTRIBUTE_DIRECTORY) {
|
||||
fileHandle = CreateFileW(tLink, 0,
|
||||
FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
|
||||
OPEN_EXISTING,
|
||||
FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT, 0);
|
||||
|
||||
}
|
||||
else {
|
||||
|
||||
//
|
||||
// Open the file
|
||||
//
|
||||
} else {
|
||||
/* Open the file */
|
||||
fileHandle = CreateFileW(tLink, 0,
|
||||
FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
|
||||
OPEN_EXISTING,
|
||||
FILE_FLAG_OPEN_REPARSE_POINT, 0);
|
||||
}
|
||||
if (fileHandle == INVALID_HANDLE_VALUE)
|
||||
{
|
||||
|
||||
if (fileHandle == INVALID_HANDLE_VALUE) {
|
||||
swprintf_s(ret, *plen, L"%ls", tLink);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
if (GetFileAttributesW(tLink) & FILE_ATTRIBUTE_REPARSE_POINT) {
|
||||
|
||||
if (DeviceIoControl(fileHandle, FSCTL_GET_REPARSE_POINT,
|
||||
NULL, 0, reparseInfo, sizeof(reparseBuffer),
|
||||
&returnedLength, NULL)) {
|
||||
|
||||
if (IsReparseTagMicrosoft(reparseInfo->ReparseTag)) {
|
||||
|
||||
switch (reparseInfo->ReparseTag) {
|
||||
case 0x80000000 | IO_REPARSE_TAG_SYMBOLIC_LINK:
|
||||
case IO_REPARSE_TAG_MOUNT_POINT:
|
||||
if (*plen >= msReparseInfo->MountPointReparseBuffer.SubstituteNameLength)
|
||||
{
|
||||
if (*plen >= msReparseInfo->MountPointReparseBuffer.SubstituteNameLength) {
|
||||
reparseData = (PBYTE)&msReparseInfo->SymbolicLinkReparseBuffer.PathBuffer;
|
||||
WCHAR temp[1024];
|
||||
wcsncpy_s(temp, 1024,
|
||||
@ -815,9 +879,7 @@ ResolveLink(wchar_t * tLink, wchar_t *ret, DWORD * plen, DWORD Flags) {
|
||||
(size_t)msReparseInfo->MountPointReparseBuffer.SubstituteNameLength);
|
||||
temp[msReparseInfo->MountPointReparseBuffer.SubstituteNameLength] = 0;
|
||||
swprintf_s(ret, *plen, L"%ls", &temp[4]);
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
swprintf_s(ret, *plen, L"%ls", tLink);
|
||||
return FALSE;
|
||||
}
|
||||
@ -828,16 +890,16 @@ ResolveLink(wchar_t * tLink, wchar_t *ret, DWORD * plen, DWORD Flags) {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
} else
|
||||
swprintf_s(ret, *plen, L"%ls", tLink);
|
||||
}
|
||||
|
||||
CloseHandle(fileHandle);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
int statvfs(const char *path, struct statvfs *buf) {
|
||||
int
|
||||
statvfs(const char *path, struct statvfs *buf)
|
||||
{
|
||||
DWORD sectorsPerCluster;
|
||||
DWORD bytesPerSector;
|
||||
DWORD freeClusters;
|
||||
@ -845,8 +907,7 @@ int statvfs(const char *path, struct statvfs *buf) {
|
||||
|
||||
wchar_t* path_utf16 = utf8_to_utf16(sanitized_path(path));
|
||||
if (GetDiskFreeSpaceW(path_utf16, §orsPerCluster, &bytesPerSector,
|
||||
&freeClusters, &totalClusters) == TRUE)
|
||||
{
|
||||
&freeClusters, &totalClusters) == TRUE) {
|
||||
debug3("path : [%s]", path);
|
||||
debug3("sectorsPerCluster : [%lu]", sectorsPerCluster);
|
||||
debug3("bytesPerSector : [%lu]", bytesPerSector);
|
||||
@ -868,74 +929,25 @@ int statvfs(const char *path, struct statvfs *buf) {
|
||||
|
||||
free(path_utf16);
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
debug3("ERROR: Cannot get free space for [%s]. Error code is : %d.\n",
|
||||
path, GetLastError());
|
||||
} else {
|
||||
debug3("ERROR: Cannot get free space for [%s]. Error code is : %d.\n", path, GetLastError());
|
||||
|
||||
free(path_utf16);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
int fstatvfs(int fd, struct statvfs *buf) {
|
||||
int
|
||||
fstatvfs(int fd, struct statvfs *buf)
|
||||
{
|
||||
errno = ENOTSUP;
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* w32_strerror start */
|
||||
/* Windows CRT defines error string messages only till 43 in errno.h*/
|
||||
/* This is an extended list that defines messages for EADDRINUSE through EWOULDBLOCK*/
|
||||
char* _sys_errlist_ext[] = {
|
||||
"Address already in use", // EADDRINUSE 100
|
||||
"Address not available", // EADDRNOTAVAIL 101
|
||||
"Address family not supported", // EAFNOSUPPORT 102
|
||||
"Connection already in progress", // EALREADY 103
|
||||
"Bad message", // EBADMSG 104
|
||||
"Operation canceled", // ECANCELED 105
|
||||
"Connection aborted", // ECONNABORTED 106
|
||||
"Connection refused", // ECONNREFUSED 107
|
||||
"Connection reset", // ECONNRESET 108
|
||||
"Destination address required", // EDESTADDRREQ 109
|
||||
"Host is unreachable", // EHOSTUNREACH 110
|
||||
"Identifier removed", // EIDRM 111
|
||||
"Operation in progress", // EINPROGRESS 112
|
||||
"Socket is connected", // EISCONN 113
|
||||
"Too many levels of symbolic links", // ELOOP 114
|
||||
"Message too long", // EMSGSIZE 115
|
||||
"Network is down", // ENETDOWN 116
|
||||
"Connection aborted by network", // ENETRESET 117
|
||||
"Network unreachable", // ENETUNREACH 118
|
||||
"No buffer space available", // ENOBUFS 119
|
||||
"No message is available on the STREAM head read queue", // ENODATA 120
|
||||
"Link has been severed", // ENOLINK 121
|
||||
"No message of the desired type", // ENOMSG 122
|
||||
"Protocol not available", // ENOPROTOOPT 123
|
||||
"No STREAM resources", // ENOSR 124
|
||||
"Not a STREAM", // ENOSTR 125
|
||||
"The socket is not connected", // ENOTCONN 126
|
||||
"enotecoverable", // ENOTRECOVERABLE 127
|
||||
"Not a socket", // ENOTSOCK 128
|
||||
"Operation not supported", // ENOTSUP 129
|
||||
"Operation not supported on socket", // EOPNOTSUPP 130
|
||||
"eother", // EOTHER 131
|
||||
"Value too large to be stored in data type", // EOVERFLOW 132
|
||||
"eownerdead", // EOWNERDEAD 133
|
||||
"Protocol error", // EPROTO 134
|
||||
"Protocol not supported", // EPROTONOSUPPORT 135
|
||||
"Protocol wrong type for socket", // EPROTOTYPE 136
|
||||
"Timer expired", // ETIME 137
|
||||
"Connection timed out", // ETIMEDOUT 138
|
||||
"Text file busy", // ETXTBSY 139
|
||||
"Operation would block" // EWOULDBLOCK 140
|
||||
};
|
||||
|
||||
char *
|
||||
w32_strerror(int errnum) {
|
||||
w32_strerror(int errnum)
|
||||
{
|
||||
if (errnum >= EADDRINUSE && errnum <= EWOULDBLOCK)
|
||||
return _sys_errlist_ext[errnum - EADDRINUSE];
|
||||
return strerror(errnum);
|
||||
}
|
||||
|
||||
/* w32_strerror end */
|
@ -31,22 +31,27 @@
|
||||
#include "inc\sys\types.h"
|
||||
|
||||
/* uuidswap.c defs */
|
||||
void temporarily_use_uid(struct passwd *pw){
|
||||
void
|
||||
temporarily_use_uid(struct passwd *pw)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
void
|
||||
permanently_drop_suid(uid_t uid) {
|
||||
permanently_drop_suid(uid_t uid)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
void
|
||||
restore_uid(void) {
|
||||
restore_uid(void)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
void
|
||||
permanently_set_uid(struct passwd *pw) {
|
||||
permanently_set_uid(struct passwd *pw)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
@ -56,74 +61,88 @@ int muxserver_sock = -1;
|
||||
typedef struct Channel Channel;
|
||||
unsigned int muxclient_command = 0;
|
||||
void
|
||||
muxserver_listen(void){
|
||||
muxserver_listen(void)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
void
|
||||
mux_exit_message(Channel *c, int exitval) {
|
||||
mux_exit_message(Channel *c, int exitval)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
void
|
||||
mux_tty_alloc_failed(Channel *c) {
|
||||
mux_tty_alloc_failed(Channel *c)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
void
|
||||
muxclient(const char *path) {
|
||||
muxclient(const char *path)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
innetgr(const char *netgroup, const char *host,
|
||||
const char *user, const char *domain) {
|
||||
innetgr(const char *netgroup, const char *host, const char *user, const char *domain)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
/* groupaccess.c*/
|
||||
int
|
||||
ga_init(const char *user, gid_t base) {
|
||||
ga_init(const char *user, gid_t base)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
int
|
||||
ga_match(char * const *groups, int n) {
|
||||
ga_match(char * const *groups, int n)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
int
|
||||
ga_match_pattern_list(const char *group_pattern) {
|
||||
ga_match_pattern_list(const char *group_pattern)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
void
|
||||
ga_free(void) {
|
||||
ga_free(void)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
int chroot(const char *path) {
|
||||
int
|
||||
chroot(const char *path)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
int initgroups(const char *user, gid_t group) {
|
||||
int
|
||||
initgroups(const char *user, gid_t group)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
/* sshd.c */
|
||||
int
|
||||
setgroups(gid_t group, char* name) {
|
||||
setgroups(gid_t group, char* name)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
setsid(void) {
|
||||
setsid(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int startup_handler(void) {
|
||||
int
|
||||
startup_handler(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -36,6 +36,7 @@
|
||||
#include <DsGetDC.h>
|
||||
#define SECURITY_WIN32
|
||||
#include <security.h>
|
||||
|
||||
#include "inc\pwd.h"
|
||||
#include "inc\grp.h"
|
||||
#include "inc\utf.h"
|
||||
@ -45,8 +46,10 @@ static struct passwd pw;
|
||||
static char* pw_shellpath = NULL;
|
||||
#define SHELL_HOST "\\ssh-shellhost.exe"
|
||||
|
||||
|
||||
int
|
||||
initialize_pw() {
|
||||
initialize_pw()
|
||||
{
|
||||
if (pw_shellpath == NULL) {
|
||||
if ((pw_shellpath = malloc(strlen(w32_programdir()) + strlen(SHELL_HOST) + 1)) == NULL)
|
||||
fatal("initialize_pw - out of memory");
|
||||
@ -59,6 +62,7 @@ initialize_pw() {
|
||||
*head = '\0';
|
||||
}
|
||||
}
|
||||
|
||||
if (pw.pw_shell != pw_shellpath) {
|
||||
memset(&pw, 0, sizeof(pw));
|
||||
pw.pw_shell = pw_shellpath;
|
||||
@ -71,7 +75,8 @@ initialize_pw() {
|
||||
}
|
||||
|
||||
void
|
||||
reset_pw() {
|
||||
reset_pw()
|
||||
{
|
||||
initialize_pw();
|
||||
if (pw.pw_name)
|
||||
free(pw.pw_name);
|
||||
@ -88,7 +93,8 @@ reset_pw() {
|
||||
}
|
||||
|
||||
static struct passwd*
|
||||
get_passwd(const char *user_utf8, LPWSTR user_sid) {
|
||||
get_passwd(const char *user_utf8, LPWSTR user_sid)
|
||||
{
|
||||
struct passwd *ret = NULL;
|
||||
wchar_t *user_utf16 = NULL, *uname_utf16, *udom_utf16, *tmp;
|
||||
char *uname_utf8 = NULL, *udom_utf8 = NULL, *pw_home_utf8 = NULL, *user_sid_utf8 = NULL;
|
||||
@ -196,12 +202,14 @@ done:
|
||||
}
|
||||
|
||||
struct passwd*
|
||||
w32_getpwnam(const char *user_utf8) {
|
||||
w32_getpwnam(const char *user_utf8)
|
||||
{
|
||||
return get_passwd(user_utf8, NULL);
|
||||
}
|
||||
|
||||
struct passwd*
|
||||
w32_getpwuid(uid_t uid) {
|
||||
w32_getpwuid(uid_t uid)
|
||||
{
|
||||
wchar_t* wuser = NULL;
|
||||
char* user_utf8 = NULL;
|
||||
ULONG needed = 0;
|
||||
@ -243,50 +251,62 @@ done:
|
||||
|
||||
|
||||
|
||||
char *group_from_gid(gid_t gid, int nogroup) {
|
||||
char *
|
||||
group_from_gid(gid_t gid, int nogroup)
|
||||
{
|
||||
return "-";
|
||||
}
|
||||
|
||||
char *user_from_uid(uid_t uid, int nouser) {
|
||||
char *
|
||||
user_from_uid(uid_t uid, int nouser)
|
||||
{
|
||||
return "-";
|
||||
}
|
||||
|
||||
uid_t
|
||||
getuid(void) {
|
||||
getuid(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
gid_t
|
||||
getgid(void) {
|
||||
getgid(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
uid_t
|
||||
geteuid(void) {
|
||||
geteuid(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
gid_t
|
||||
getegid(void) {
|
||||
getegid(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
setuid(uid_t uid) {
|
||||
setuid(uid_t uid)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
setgid(gid_t gid) {
|
||||
setgid(gid_t gid)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
seteuid(uid_t uid) {
|
||||
seteuid(uid_t uid)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
setegid(gid_t gid) {
|
||||
setegid(gid_t gid)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
@ -28,10 +28,11 @@
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "w32fd.h"
|
||||
#include <errno.h>
|
||||
#include "w32fd.h"
|
||||
#include "signal_internal.h"
|
||||
#include "inc\signal.h"
|
||||
|
||||
#undef signal
|
||||
#undef raise
|
||||
#undef SIGINT
|
||||
@ -48,30 +49,27 @@
|
||||
|
||||
/* pending signals to be processed */
|
||||
sigset_t pending_signals;
|
||||
|
||||
/* signal handler table*/
|
||||
sighandler_t sig_handlers[W32_SIGMAX];
|
||||
extern struct _children children;
|
||||
|
||||
static VOID CALLBACK
|
||||
sigint_APCProc(
|
||||
_In_ ULONG_PTR dwParam
|
||||
) {
|
||||
sigint_APCProc(_In_ ULONG_PTR dwParam)
|
||||
{
|
||||
debug3("SIGINT APCProc()");
|
||||
sigaddset(&pending_signals, W32_SIGINT);
|
||||
}
|
||||
|
||||
static VOID CALLBACK
|
||||
sigterm_APCProc(
|
||||
_In_ ULONG_PTR dwParam
|
||||
) {
|
||||
sigterm_APCProc(_In_ ULONG_PTR dwParam)
|
||||
{
|
||||
debug3("SIGTERM APCProc()");
|
||||
sigaddset(&pending_signals, W32_SIGTERM);
|
||||
}
|
||||
|
||||
static VOID CALLBACK
|
||||
sigtstp_APCProc(
|
||||
_In_ ULONG_PTR dwParam
|
||||
) {
|
||||
sigtstp_APCProc(_In_ ULONG_PTR dwParam)
|
||||
{
|
||||
debug3("SIGTSTP APCProc()");
|
||||
sigaddset(&pending_signals, W32_SIGTSTP);
|
||||
}
|
||||
@ -100,35 +98,31 @@ native_sig_handler(DWORD dwCtrlType)
|
||||
}
|
||||
|
||||
static VOID CALLBACK
|
||||
sigwinch_APCProc(
|
||||
_In_ ULONG_PTR dwParam
|
||||
) {
|
||||
sigwinch_APCProc(_In_ ULONG_PTR dwParam)
|
||||
{
|
||||
debug3("SIGTERM APCProc()");
|
||||
sigaddset(&pending_signals, W32_SIGWINCH);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
queue_terminal_window_change_event() {
|
||||
queue_terminal_window_change_event()
|
||||
{
|
||||
QueueUserAPC(sigwinch_APCProc, main_thread, (ULONG_PTR)NULL);
|
||||
}
|
||||
|
||||
void
|
||||
sw_init_signal_handler_table() {
|
||||
int i;
|
||||
|
||||
sw_init_signal_handler_table()
|
||||
{
|
||||
SetConsoleCtrlHandler(native_sig_handler, TRUE);
|
||||
sigemptyset(&pending_signals);
|
||||
/* this automatically sets all to W32_SIG_DFL (0)*/
|
||||
memset(sig_handlers, 0, sizeof(sig_handlers));
|
||||
}
|
||||
|
||||
extern struct _children children;
|
||||
|
||||
sighandler_t
|
||||
w32_signal(int signum, sighandler_t handler) {
|
||||
w32_signal(int signum, sighandler_t handler)
|
||||
{
|
||||
sighandler_t prev;
|
||||
|
||||
debug2("signal() sig:%d, handler:%p", signum, handler);
|
||||
if (signum >= W32_SIGMAX) {
|
||||
errno = EINVAL;
|
||||
@ -141,7 +135,8 @@ w32_signal(int signum, sighandler_t handler) {
|
||||
}
|
||||
|
||||
int
|
||||
w32_sigprocmask(int how, const sigset_t *set, sigset_t *oldset) {
|
||||
w32_sigprocmask(int how, const sigset_t *set, sigset_t *oldset)
|
||||
{
|
||||
/* this is only used by sshd to block SIGCHLD while doing waitpid() */
|
||||
/* our implementation of waidpid() is never interrupted, so no need to implement this for now*/
|
||||
debug3("sigprocmask() how:%d");
|
||||
@ -151,7 +146,8 @@ w32_sigprocmask(int how, const sigset_t *set, sigset_t *oldset) {
|
||||
|
||||
|
||||
int
|
||||
w32_raise(int sig) {
|
||||
w32_raise(int sig)
|
||||
{
|
||||
debug("raise sig:%d", sig);
|
||||
if (sig == W32_SIGSEGV)
|
||||
return raise(SIGSEGV); /* raise native exception handler*/
|
||||
@ -185,7 +181,8 @@ w32_raise(int sig) {
|
||||
|
||||
/* processes pending signals, return -1 and errno=EINTR if any are processed*/
|
||||
static int
|
||||
sw_process_pending_signals() {
|
||||
sw_process_pending_signals()
|
||||
{
|
||||
sigset_t pending_tmp = pending_signals;
|
||||
BOOL sig_int = FALSE; /* has any signal actually interrupted */
|
||||
|
||||
@ -266,55 +263,49 @@ wait_for_any_event(HANDLE* events, int num_events, DWORD milli_seconds)
|
||||
debug3("wait() on %d events and %d children", num_events, live_children);
|
||||
/* TODO - implement signal catching and handling */
|
||||
if (num_all_events) {
|
||||
DWORD ret = WaitForMultipleObjectsEx(num_all_events, all_events, FALSE,
|
||||
milli_seconds, TRUE);
|
||||
DWORD ret = WaitForMultipleObjectsEx(num_all_events, all_events, FALSE, milli_seconds, TRUE);
|
||||
if ((ret >= WAIT_OBJECT_0) && (ret <= WAIT_OBJECT_0 + num_all_events - 1)) {
|
||||
//woken up by event signalled
|
||||
/* is this due to a child process going down*/
|
||||
/* woken up by event signalled
|
||||
* is this due to a child process going down
|
||||
*/
|
||||
if (live_children && ((ret - WAIT_OBJECT_0) < live_children)) {
|
||||
sigaddset(&pending_signals, W32_SIGCHLD);
|
||||
sw_child_to_zombie(ret - WAIT_OBJECT_0);
|
||||
}
|
||||
}
|
||||
else if (ret == WAIT_IO_COMPLETION) {
|
||||
} else if (ret == WAIT_IO_COMPLETION) {
|
||||
/* APC processed due to IO or signal*/
|
||||
}
|
||||
else if (ret == WAIT_TIMEOUT) {
|
||||
} else if (ret == WAIT_TIMEOUT) {
|
||||
/* timed out */
|
||||
return 0;
|
||||
}
|
||||
/* some other error*/
|
||||
else {
|
||||
} else { /* some other error*/
|
||||
errno = EOTHER;
|
||||
debug("ERROR: unxpected wait end: %d", ret);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
DWORD ret = SleepEx(milli_seconds, TRUE);
|
||||
if (ret == WAIT_IO_COMPLETION) {
|
||||
/* APC processed due to IO or signal*/
|
||||
}
|
||||
else if (ret == 0) {
|
||||
} else if (ret == 0) {
|
||||
/* timed out */
|
||||
return 0;
|
||||
}
|
||||
else { //some other error
|
||||
} else { /* some other error */
|
||||
errno = EOTHER;
|
||||
debug("ERROR: unxpected SleepEx error: %d", ret);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
if (pending_signals) {
|
||||
if (pending_signals)
|
||||
return sw_process_pending_signals();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
sw_initialize() {
|
||||
sw_initialize()
|
||||
{
|
||||
memset(&children, 0, sizeof(children));
|
||||
sw_init_signal_handler_table();
|
||||
if (sw_init_timer() != 0)
|
||||
|
@ -35,16 +35,16 @@ struct _timer_info timer_info;
|
||||
extern sigset_t pending_signals;
|
||||
|
||||
static VOID CALLBACK
|
||||
sigalrm_APC(
|
||||
_In_opt_ LPVOID lpArgToCompletionRoutine,
|
||||
sigalrm_APC(_In_opt_ LPVOID lpArgToCompletionRoutine,
|
||||
_In_ DWORD dwTimerLowValue,
|
||||
_In_ DWORD dwTimerHighValue
|
||||
) {
|
||||
_In_ DWORD dwTimerHighValue)
|
||||
{
|
||||
sigaddset(&pending_signals, W32_SIGALRM);
|
||||
}
|
||||
|
||||
unsigned int
|
||||
w32_alarm(unsigned int sec) {
|
||||
w32_alarm(unsigned int sec)
|
||||
{
|
||||
LARGE_INTEGER due;
|
||||
ULONGLONG sec_passed;
|
||||
int ret = 0;
|
||||
@ -59,7 +59,7 @@ w32_alarm(unsigned int sec) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
due.QuadPart = -10000000LL; //1 sec in 100 nanosec intervals
|
||||
due.QuadPart = -10000000LL; /* 1 sec in 100 nanosec intervals */
|
||||
due.QuadPart *= sec;
|
||||
/* this call resets the timer if it is already active */
|
||||
if (!SetWaitableTimer(timer_info.timer, &due, 0, sigalrm_APC, NULL, FALSE)) {
|
||||
@ -75,16 +75,19 @@ w32_alarm(unsigned int sec) {
|
||||
}
|
||||
timer_info.ticks_at_start = GetTickCount64();
|
||||
timer_info.run_time_sec = sec;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int
|
||||
sw_init_timer() {
|
||||
sw_init_timer()
|
||||
{
|
||||
memset(&timer_info, 0, sizeof(timer_info));
|
||||
timer_info.timer = CreateWaitableTimer(NULL, TRUE, NULL);
|
||||
if (timer_info.timer == NULL) {
|
||||
errno = ENOMEM;
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
@ -34,7 +34,8 @@
|
||||
struct _children children;
|
||||
|
||||
int
|
||||
register_child(HANDLE child, DWORD pid) {
|
||||
register_child(HANDLE child, DWORD pid)
|
||||
{
|
||||
DWORD first_zombie_index;
|
||||
|
||||
debug("Register child %p pid %d, %d zombies of %d", child, pid,
|
||||
@ -43,6 +44,7 @@ register_child(HANDLE child, DWORD pid) {
|
||||
errno = ENOMEM;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (children.num_zombies) {
|
||||
first_zombie_index = children.num_children - children.num_zombies;
|
||||
children.handles[children.num_children] = children.handles[first_zombie_index];
|
||||
@ -50,26 +52,23 @@ register_child(HANDLE child, DWORD pid) {
|
||||
|
||||
children.handles[first_zombie_index] = child;
|
||||
children.process_id[first_zombie_index] = pid;
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
children.handles[children.num_children] = child;
|
||||
children.process_id[children.num_children] = pid;
|
||||
}
|
||||
|
||||
|
||||
children.num_children++;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
sw_remove_child_at_index(DWORD index) {
|
||||
sw_remove_child_at_index(DWORD index)
|
||||
{
|
||||
DWORD last_non_zombie;
|
||||
|
||||
debug("Unregister child at index %d, %d zombies of %d", index,
|
||||
children.num_zombies, children.num_children);
|
||||
|
||||
if ((index >= children.num_children)
|
||||
|| (children.num_children == 0)) {
|
||||
if ((index >= children.num_children) || (children.num_children == 0)) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
@ -78,15 +77,13 @@ sw_remove_child_at_index(DWORD index) {
|
||||
if (children.num_zombies == 0) {
|
||||
children.handles[index] = children.handles[children.num_children - 1];
|
||||
children.process_id[index] = children.process_id[children.num_children - 1];
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
/* if its a zombie */
|
||||
if (index >= (children.num_children - children.num_zombies)) {
|
||||
children.handles[index] = children.handles[children.num_children - 1];
|
||||
children.process_id[index] = children.process_id[children.num_children - 1];
|
||||
children.num_zombies--;
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
last_non_zombie = children.num_children - children.num_zombies - 1;
|
||||
children.handles[index] = children.handles[last_non_zombie];
|
||||
children.process_id[index] = children.process_id[last_non_zombie];
|
||||
@ -101,7 +98,8 @@ sw_remove_child_at_index(DWORD index) {
|
||||
}
|
||||
|
||||
int
|
||||
sw_child_to_zombie(DWORD index) {
|
||||
sw_child_to_zombie(DWORD index)
|
||||
{
|
||||
DWORD last_non_zombie, zombie_pid;
|
||||
HANDLE zombie_handle;
|
||||
|
||||
@ -114,7 +112,6 @@ sw_child_to_zombie(DWORD index) {
|
||||
}
|
||||
|
||||
last_non_zombie = children.num_children - children.num_zombies - 1;
|
||||
|
||||
if (last_non_zombie != index) {
|
||||
/* swap */
|
||||
zombie_pid = children.process_id[index];
|
||||
@ -129,7 +126,8 @@ sw_child_to_zombie(DWORD index) {
|
||||
}
|
||||
|
||||
int
|
||||
w32_kill(int pid, int sig) {
|
||||
w32_kill(int pid, int sig)
|
||||
{
|
||||
int child_index, i;
|
||||
if (pid == GetCurrentProcessId())
|
||||
return w32_raise(sig);
|
||||
@ -148,7 +146,9 @@ w32_kill(int pid, int sig) {
|
||||
}
|
||||
|
||||
|
||||
int waitpid(int pid, int *status, int options) {
|
||||
int
|
||||
waitpid(int pid, int *status, int options)
|
||||
{
|
||||
DWORD index, ret, ret_id, exit_code, timeout = 0;
|
||||
HANDLE process = NULL;
|
||||
|
||||
@ -230,20 +230,19 @@ int waitpid(int pid, int *status, int options) {
|
||||
if (status)
|
||||
*status = exit_code;
|
||||
return ret_id;
|
||||
}
|
||||
else if (ret == WAIT_TIMEOUT) {
|
||||
} else if (ret == WAIT_TIMEOUT) {
|
||||
/* TODO - assert that WNOHANG was specified*/
|
||||
return 0;
|
||||
}
|
||||
|
||||
DebugBreak();//fatal
|
||||
DebugBreak(); /* fatal */
|
||||
return -1;
|
||||
}
|
||||
|
||||
void
|
||||
sw_cleanup_child_zombies() {
|
||||
sw_cleanup_child_zombies()
|
||||
{
|
||||
int pid = 1;
|
||||
while (pid > 0) {
|
||||
while (pid > 0)
|
||||
pid = waitpid(-1, NULL, WNOHANG);
|
||||
}
|
||||
}
|
@ -33,19 +33,26 @@
|
||||
#include <mswsock.h>
|
||||
#include <errno.h>
|
||||
#include <VersionHelpers.h>
|
||||
#include "w32fd.h"
|
||||
#include <stddef.h>
|
||||
#include "w32fd.h"
|
||||
#include "inc\utf.h"
|
||||
|
||||
#define INTERNAL_SEND_BUFFER_SIZE 70*1024 //70KB
|
||||
|
||||
#define INTERNAL_RECV_BUFFER_SIZE 70*1024 //70KB
|
||||
|
||||
#define errno_from_WSALastError() errno_from_WSAError(WSAGetLastError())
|
||||
|
||||
/* state info that needs to be persisted for an inprocess acceptEx call*/
|
||||
struct acceptEx_context {
|
||||
char lpOutputBuf[1024];
|
||||
SOCKET accept_socket;
|
||||
LPFN_ACCEPTEX lpfnAcceptEx;
|
||||
LPFN_GETACCEPTEXSOCKADDRS lpfnGuidGetAcceptExSockaddrs;
|
||||
DWORD bytes_received;
|
||||
};
|
||||
|
||||
/* maps WSAError to errno */
|
||||
static
|
||||
int errno_from_WSAError(int wsaerrno)
|
||||
static int
|
||||
errno_from_WSAError(int wsaerrno)
|
||||
{
|
||||
/* TODO - create a mapping table - more efficient */
|
||||
switch (wsaerrno) {
|
||||
@ -70,43 +77,34 @@ int errno_from_WSAError(int wsaerrno)
|
||||
case WSAECONNRESET:
|
||||
return ECONNRESET;
|
||||
default:
|
||||
/* */
|
||||
return wsaerrno - 10000;
|
||||
}
|
||||
}
|
||||
|
||||
/* called before any other calls to socketio_ functions */
|
||||
int
|
||||
socketio_initialize() {
|
||||
socketio_initialize()
|
||||
{
|
||||
WSADATA wsaData = { 0 };
|
||||
return WSAStartup(MAKEWORD(2, 2), &wsaData);
|
||||
}
|
||||
|
||||
/* cleanup */
|
||||
int
|
||||
socketio_done() {
|
||||
socketio_done()
|
||||
{
|
||||
WSACleanup();
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* state info that needs to be persisted for an inprocess acceptEx call*/
|
||||
struct acceptEx_context {
|
||||
char lpOutputBuf[1024];
|
||||
SOCKET accept_socket;
|
||||
LPFN_ACCEPTEX lpfnAcceptEx;
|
||||
LPFN_GETACCEPTEXSOCKADDRS lpfnGuidGetAcceptExSockaddrs;
|
||||
DWORD bytes_received;
|
||||
};
|
||||
|
||||
/* initiate async acceptEx*/
|
||||
/* TODO - always return 0, set error in context, accept() will pick it up*/
|
||||
int
|
||||
socketio_acceptEx(struct w32_io* pio) {
|
||||
socketio_acceptEx(struct w32_io* pio)
|
||||
{
|
||||
struct acceptEx_context *context;
|
||||
|
||||
debug3("acceptEx - io:%p", pio);
|
||||
context = (struct acceptEx_context *)pio->internal.context;
|
||||
|
||||
ResetEvent(pio->read_overlapped.hEvent);
|
||||
|
||||
/* create accepting socket */
|
||||
@ -128,8 +126,7 @@ socketio_acceptEx(struct w32_io* pio) {
|
||||
{
|
||||
/* we are already connected. Set event so subsequent select will catch */
|
||||
SetEvent(pio->read_overlapped.hEvent);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
/* if overlapped io is in progress, we are good */
|
||||
if (WSAGetLastError() != ERROR_IO_PENDING) {
|
||||
errno = errno_from_WSALastError();
|
||||
@ -143,12 +140,10 @@ socketio_acceptEx(struct w32_io* pio) {
|
||||
}
|
||||
|
||||
void
|
||||
CALLBACK WSARecvCompletionRoutine(
|
||||
IN DWORD dwError,
|
||||
CALLBACK WSARecvCompletionRoutine(IN DWORD dwError,
|
||||
IN DWORD cbTransferred,
|
||||
IN LPWSAOVERLAPPED lpOverlapped,
|
||||
IN DWORD dwFlags
|
||||
)
|
||||
IN DWORD dwFlags)
|
||||
{
|
||||
struct w32_io* pio =
|
||||
(struct w32_io*)((char*)lpOverlapped - offsetof(struct w32_io, read_overlapped));
|
||||
@ -165,7 +160,8 @@ CALLBACK WSARecvCompletionRoutine(
|
||||
/* initiates async receive operation*/
|
||||
/* TODO - always return 0, or make this a void func. any error should be put in context*/
|
||||
int
|
||||
socketio_WSARecv(struct w32_io* pio, BOOL* completed) {
|
||||
socketio_WSARecv(struct w32_io* pio, BOOL* completed)
|
||||
{
|
||||
int ret = 0;
|
||||
WSABUF wsabuf;
|
||||
DWORD recv_flags = 0;
|
||||
@ -176,12 +172,9 @@ socketio_WSARecv(struct w32_io* pio, BOOL* completed) {
|
||||
|
||||
/* initialize recv buffers if needed */
|
||||
wsabuf.len = INTERNAL_RECV_BUFFER_SIZE;
|
||||
if (pio->read_details.buf == NULL)
|
||||
{
|
||||
if (pio->read_details.buf == NULL) {
|
||||
wsabuf.buf = malloc(wsabuf.len);
|
||||
|
||||
if (!wsabuf.buf)
|
||||
{
|
||||
if (!wsabuf.buf) {
|
||||
errno = ENOMEM;
|
||||
debug("WSARecv - ERROR:%d, io:%p", errno, pio);
|
||||
return -1;
|
||||
@ -189,29 +182,22 @@ socketio_WSARecv(struct w32_io* pio, BOOL* completed) {
|
||||
|
||||
pio->read_details.buf = wsabuf.buf;
|
||||
pio->read_details.buf_size = wsabuf.len;
|
||||
}
|
||||
else
|
||||
} else
|
||||
wsabuf.buf = pio->read_details.buf;
|
||||
|
||||
|
||||
ret = WSARecv(pio->sock, &wsabuf, 1, NULL, &recv_flags, &pio->read_overlapped,
|
||||
&WSARecvCompletionRoutine);
|
||||
if (ret == 0)
|
||||
{
|
||||
ret = WSARecv(pio->sock, &wsabuf, 1, NULL, &recv_flags, &pio->read_overlapped, &WSARecvCompletionRoutine);
|
||||
if (ret == 0) {
|
||||
pio->read_details.pending = TRUE;
|
||||
/* receive has completed but APC is pending to be scheduled */
|
||||
debug2("WSARecv - WSARecv() returned 0, io:%p", pio);
|
||||
if (completed)
|
||||
*completed = TRUE;
|
||||
}
|
||||
else { /* (ret == SOCKET_ERROR) */
|
||||
if (WSAGetLastError() == WSA_IO_PENDING)
|
||||
{
|
||||
} else { /* (ret == SOCKET_ERROR) */
|
||||
if (WSAGetLastError() == WSA_IO_PENDING) {
|
||||
/* io is initiated and pending */
|
||||
debug2("WSARecv - reported IO pending");
|
||||
pio->read_details.pending = TRUE;
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
errno = errno_from_WSALastError();
|
||||
debug("WSARecv - WSARecv() ERROR: io:%p %d", pio, errno);
|
||||
return -1;
|
||||
@ -223,7 +209,8 @@ socketio_WSARecv(struct w32_io* pio, BOOL* completed) {
|
||||
|
||||
/* implements socket() */
|
||||
struct w32_io*
|
||||
socketio_socket(int domain, int type, int protocol) {
|
||||
socketio_socket(int domain, int type, int protocol)
|
||||
{
|
||||
struct w32_io *pio = (struct w32_io*)malloc(sizeof(struct w32_io));
|
||||
if (!pio) {
|
||||
errno = ENOMEM;
|
||||
@ -255,8 +242,8 @@ socketio_socket(int domain, int type, int protocol) {
|
||||
|
||||
/* implements setsockopt() */
|
||||
int
|
||||
socketio_setsockopt(struct w32_io* pio, int level, int optname, const char* optval,
|
||||
int optlen) {
|
||||
socketio_setsockopt(struct w32_io* pio, int level, int optname, const char* optval, int optlen)
|
||||
{
|
||||
if ((optname == SO_KEEPALIVE) || (optname == SO_REUSEADDR) ||
|
||||
(optname == TCP_NODELAY) || (optname == IPV6_V6ONLY))
|
||||
SET_ERRNO_ON_ERROR(setsockopt(pio->sock, level, optname, optval, optlen));
|
||||
@ -269,25 +256,29 @@ socketio_setsockopt(struct w32_io* pio, int level, int optname, const char* optv
|
||||
|
||||
/* implements getsockopt() */
|
||||
int
|
||||
socketio_getsockopt(struct w32_io* pio, int level, int optname, char* optval, int* optlen) {
|
||||
socketio_getsockopt(struct w32_io* pio, int level, int optname, char* optval, int* optlen)
|
||||
{
|
||||
SET_ERRNO_ON_ERROR(getsockopt(pio->sock, level, optname, optval, optlen));
|
||||
}
|
||||
|
||||
/* implements getsockname() */
|
||||
int
|
||||
socketio_getsockname(struct w32_io* pio, struct sockaddr* name, int* namelen) {
|
||||
socketio_getsockname(struct w32_io* pio, struct sockaddr* name, int* namelen)
|
||||
{
|
||||
SET_ERRNO_ON_ERROR(getsockname(pio->sock, name, namelen));
|
||||
}
|
||||
|
||||
/* implements getpeername */
|
||||
int
|
||||
socketio_getpeername(struct w32_io* pio, struct sockaddr* name, int* namelen) {
|
||||
socketio_getpeername(struct w32_io* pio, struct sockaddr* name, int* namelen)
|
||||
{
|
||||
SET_ERRNO_ON_ERROR(getpeername(pio->sock, name, namelen));
|
||||
}
|
||||
|
||||
/* implements listen() */
|
||||
int
|
||||
socketio_listen(struct w32_io* pio, int backlog) {
|
||||
socketio_listen(struct w32_io* pio, int backlog)
|
||||
{
|
||||
struct acceptEx_context* context;
|
||||
|
||||
if (SOCKET_ERROR == listen(pio->sock, backlog)) {
|
||||
@ -313,8 +304,7 @@ socketio_listen(struct w32_io* pio, int backlog) {
|
||||
SIO_GET_EXTENSION_FUNCTION_POINTER,
|
||||
&GuidAcceptEx, sizeof(GuidAcceptEx),
|
||||
&context->lpfnAcceptEx, sizeof(context->lpfnAcceptEx),
|
||||
&dwBytes, NULL, NULL))
|
||||
{
|
||||
&dwBytes, NULL, NULL)) {
|
||||
free(context);
|
||||
errno = errno_from_WSALastError();
|
||||
debug("listen - Ioctl1 ERROR:%d, io:%p", errno, pio);
|
||||
@ -325,8 +315,7 @@ socketio_listen(struct w32_io* pio, int backlog) {
|
||||
SIO_GET_EXTENSION_FUNCTION_POINTER,
|
||||
&GuidGetAcceptExSockaddrs, sizeof(GuidGetAcceptExSockaddrs),
|
||||
&context->lpfnGuidGetAcceptExSockaddrs, sizeof(context->lpfnGuidGetAcceptExSockaddrs),
|
||||
&dwBytes, NULL, NULL))
|
||||
{
|
||||
&dwBytes, NULL, NULL)) {
|
||||
free(context);
|
||||
errno = errno_from_WSALastError();
|
||||
debug("listen - Ioctl2 ERROR:%d, io:%p", errno, pio);
|
||||
@ -351,17 +340,17 @@ socketio_listen(struct w32_io* pio, int backlog) {
|
||||
|
||||
/* implements bind() */
|
||||
int
|
||||
socketio_bind(struct w32_io* pio, const struct sockaddr *name, int namelen) {
|
||||
socketio_bind(struct w32_io* pio, const struct sockaddr *name, int namelen)
|
||||
{
|
||||
SET_ERRNO_ON_ERROR(bind(pio->sock, name, namelen));
|
||||
}
|
||||
|
||||
/* implements recv() */
|
||||
int
|
||||
socketio_recv(struct w32_io* pio, void *buf, size_t len, int flags) {
|
||||
socketio_recv(struct w32_io* pio, void *buf, size_t len, int flags)
|
||||
{
|
||||
BOOL completed = FALSE;
|
||||
|
||||
debug3("recv - io:%p", pio);
|
||||
|
||||
if ((buf == NULL) || (len == 0)) {
|
||||
errno = EINVAL;
|
||||
debug("recv - ERROR: invalid arguments, buf:%p, len:%d, io:%p", buf, len, pio);
|
||||
@ -375,7 +364,6 @@ socketio_recv(struct w32_io* pio, void *buf, size_t len, int flags) {
|
||||
}
|
||||
|
||||
/* TODO - ensure socket is in accepted or connected state */
|
||||
|
||||
/* /io is initiated and pending */
|
||||
if (pio->read_details.pending) {
|
||||
/* if recv is now in blocking mode, wait for data to be available */
|
||||
@ -385,8 +373,7 @@ socketio_recv(struct w32_io* pio, void *buf, size_t len, int flags) {
|
||||
if (0 != wait_for_any_event(NULL, 0, INFINITE))
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
errno = EAGAIN;
|
||||
debug2("recv - io is already pending, io:%p", pio);
|
||||
return -1;
|
||||
@ -394,8 +381,7 @@ socketio_recv(struct w32_io* pio, void *buf, size_t len, int flags) {
|
||||
}
|
||||
|
||||
/* if we have some buffer copy it and return #bytes copied */
|
||||
if (pio->read_details.remaining)
|
||||
{
|
||||
if (pio->read_details.remaining) {
|
||||
int num_bytes_copied = min((int)len, pio->read_details.remaining);
|
||||
memcpy(buf, pio->read_details.buf + pio->read_details.completed,
|
||||
num_bytes_copied);
|
||||
@ -406,15 +392,13 @@ socketio_recv(struct w32_io* pio, void *buf, size_t len, int flags) {
|
||||
return num_bytes_copied;
|
||||
}
|
||||
|
||||
|
||||
/* if there was an error on async call, return */
|
||||
if (pio->read_details.error) {
|
||||
if (pio->read_details.error == ERROR_GRACEFUL_DISCONNECT) {
|
||||
debug2("recv - connection closed, io:%p", pio);
|
||||
/* connection is closed */
|
||||
return 0;
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
errno = errno_from_WSAError(pio->read_details.error);
|
||||
debug("recv - from CB ERROR:%d, io:%p", pio->read_details.error, pio);
|
||||
pio->read_details.error = 0;
|
||||
@ -437,16 +421,14 @@ socketio_recv(struct w32_io* pio, void *buf, size_t len, int flags) {
|
||||
}
|
||||
}
|
||||
|
||||
if (w32_io_is_blocking(pio))
|
||||
{
|
||||
if (w32_io_is_blocking(pio)) {
|
||||
/* wait until io is done */
|
||||
debug3("recv - socket in blocking mode, io:%p", pio);
|
||||
while (socketio_is_io_available(pio, TRUE) == FALSE) {
|
||||
if (0 != wait_for_any_event(NULL, 0, INFINITE))
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
if (socketio_is_io_available(pio, TRUE) == FALSE) {
|
||||
errno = EAGAIN;
|
||||
debug2("recv - IO is pending, io:%p", pio);
|
||||
@ -458,14 +440,12 @@ 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) {
|
||||
if (pio->read_details.error == ERROR_GRACEFUL_DISCONNECT) {
|
||||
/* connection is closed */
|
||||
debug2("recv - connection closed(2), io:%p", pio);
|
||||
return 0;
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
errno = errno_from_WSAError(pio->read_details.error);
|
||||
pio->read_details.error = 0;
|
||||
debug("recv - from CB(2) ERROR:%d, io:%p", errno, pio);
|
||||
@ -481,26 +461,21 @@ socketio_recv(struct w32_io* pio, void *buf, size_t len, int flags) {
|
||||
debug2("recv - (2) returning %d bytes from completed IO, remaining:%d, io:%p",
|
||||
num_bytes_copied, pio->read_details.remaining, pio);
|
||||
return num_bytes_copied;
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
/* this should not happen */
|
||||
errno = EOTHER;
|
||||
debug("recv - (2) ERROR:Unexpected IO state, io:%p", pio);
|
||||
return -1;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void
|
||||
CALLBACK WSASendCompletionRoutine(
|
||||
IN DWORD dwError,
|
||||
CALLBACK WSASendCompletionRoutine(IN DWORD dwError,
|
||||
IN DWORD cbTransferred,
|
||||
IN LPWSAOVERLAPPED lpOverlapped,
|
||||
IN DWORD dwFlags
|
||||
)
|
||||
IN DWORD dwFlags)
|
||||
{
|
||||
struct w32_io* pio =
|
||||
(struct w32_io*)((char*)lpOverlapped - offsetof(struct w32_io, write_overlapped));
|
||||
struct w32_io* pio = (struct w32_io*)((char*)lpOverlapped - offsetof(struct w32_io, write_overlapped));
|
||||
debug2("WSASendCB - io:%p, pending_state:%d, error:%d, sent:%d of remaining:%d",
|
||||
pio, pio->write_details.pending, dwError, cbTransferred,
|
||||
pio->write_details.remaining);
|
||||
@ -517,12 +492,12 @@ CALLBACK WSASendCompletionRoutine(
|
||||
|
||||
/* implementation of send() */
|
||||
int
|
||||
socketio_send(struct w32_io* pio, const void *buf, size_t len, int flags) {
|
||||
socketio_send(struct w32_io* pio, const void *buf, size_t len, int flags)
|
||||
{
|
||||
int ret = 0;
|
||||
WSABUF wsabuf;
|
||||
|
||||
debug2("send - io:%p", pio);
|
||||
|
||||
if ((buf == NULL) || (len == 0)) {
|
||||
errno = EINVAL;
|
||||
debug("send - ERROR invalid arguments, buf:%p, len:%d, io:%p", buf, len, pio);
|
||||
@ -536,26 +511,20 @@ socketio_send(struct w32_io* pio, const void *buf, size_t len, int flags) {
|
||||
}
|
||||
|
||||
/* TODO - ensure socket is in accepted or connected state */
|
||||
|
||||
/* if io is already pending */
|
||||
if (pio->write_details.pending)
|
||||
{
|
||||
if (w32_io_is_blocking(pio))
|
||||
{
|
||||
if (pio->write_details.pending) {
|
||||
if (w32_io_is_blocking(pio)) {
|
||||
debug2("send - io is pending, call is blocking, io:%p", pio);
|
||||
while (pio->write_details.pending) {
|
||||
while (pio->write_details.pending)
|
||||
if (wait_for_any_event(NULL, 0, INFINITE) == -1)
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
errno = EAGAIN;
|
||||
debug2("send - IO currently pending, EAGAIN, io:%p", pio);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (pio->write_details.error) {
|
||||
errno = errno_from_WSAError(pio->write_details.error);
|
||||
debug("ERROR:%d, io:%p", errno, pio);
|
||||
@ -564,11 +533,9 @@ socketio_send(struct w32_io* pio, const void *buf, size_t len, int flags) {
|
||||
|
||||
/* initialize buffers if needed */
|
||||
wsabuf.len = INTERNAL_SEND_BUFFER_SIZE;
|
||||
if (pio->write_details.buf == NULL)
|
||||
{
|
||||
if (pio->write_details.buf == NULL) {
|
||||
wsabuf.buf = malloc(wsabuf.len);
|
||||
if (!wsabuf.buf)
|
||||
{
|
||||
if (!wsabuf.buf) {
|
||||
errno = ENOMEM;
|
||||
debug("send - ERROR:%d, io:%p", errno, pio);
|
||||
return -1;
|
||||
@ -576,20 +543,16 @@ socketio_send(struct w32_io* pio, const void *buf, size_t len, int flags) {
|
||||
|
||||
pio->write_details.buf = wsabuf.buf;
|
||||
pio->write_details.buf_size = wsabuf.len;
|
||||
}
|
||||
else {
|
||||
} else
|
||||
wsabuf.buf = pio->write_details.buf;
|
||||
}
|
||||
|
||||
wsabuf.len = min(wsabuf.len, (int)len);
|
||||
memcpy(wsabuf.buf, buf, wsabuf.len);
|
||||
|
||||
/* TODO - implement flags support if needed */
|
||||
ret = WSASend(pio->sock, &wsabuf, 1, NULL, 0, &pio->write_overlapped,
|
||||
&WSASendCompletionRoutine);
|
||||
ret = WSASend(pio->sock, &wsabuf, 1, NULL, 0, &pio->write_overlapped, &WSASendCompletionRoutine);
|
||||
|
||||
if (ret == 0)
|
||||
{
|
||||
if (ret == 0) {
|
||||
/* send has completed and APC is scheduled, let it run */
|
||||
debug2("send - WSASend() returned 0, APC scheduled io:%p", pio);
|
||||
pio->write_details.pending = TRUE;
|
||||
@ -603,16 +566,13 @@ socketio_send(struct w32_io* pio, const void *buf, size_t len, int flags) {
|
||||
|
||||
/* return num of bytes written */
|
||||
return wsabuf.len;
|
||||
}
|
||||
else {
|
||||
if (WSAGetLastError() == WSA_IO_PENDING)
|
||||
{
|
||||
} else {
|
||||
if (WSAGetLastError() == WSA_IO_PENDING) {
|
||||
/* io is initiated and pending */
|
||||
debug2("send - WSASend reported IO pending, io:%p", pio);
|
||||
pio->write_details.pending = TRUE;
|
||||
pio->write_details.remaining = wsabuf.len;
|
||||
if (w32_io_is_blocking(pio))
|
||||
{
|
||||
if (w32_io_is_blocking(pio)) {
|
||||
/* wait until io is done */
|
||||
debug3("send - waiting as socket is in blocking mode, io:%p", pio);
|
||||
while (pio->write_details.pending)
|
||||
@ -626,8 +586,7 @@ socketio_send(struct w32_io* pio, const void *buf, size_t len, int flags) {
|
||||
|
||||
debug3("send - returning %d, io:%p", wsabuf.len, pio);
|
||||
return wsabuf.len;
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
errno = errno_from_WSALastError();
|
||||
debug("send - WSASend() ERROR:%d, io:%p", errno, pio);
|
||||
return -1;
|
||||
@ -637,19 +596,21 @@ socketio_send(struct w32_io* pio, const void *buf, size_t len, int flags) {
|
||||
|
||||
/* shutdown() implementation */
|
||||
int
|
||||
socketio_shutdown(struct w32_io* pio, int how) {
|
||||
socketio_shutdown(struct w32_io* pio, int how)
|
||||
{
|
||||
SET_ERRNO_ON_ERROR(shutdown(pio->sock, how));
|
||||
}
|
||||
|
||||
/* socket close() implementation */
|
||||
int
|
||||
socketio_close(struct w32_io* pio) {
|
||||
socketio_close(struct w32_io* pio)
|
||||
{
|
||||
debug2("close - io:%p", pio);
|
||||
closesocket(pio->sock);
|
||||
/* wait for pending io to abort */
|
||||
SleepEx(0, TRUE);
|
||||
if ( ((pio->internal.state == SOCK_CONNECTED) || (pio->internal.state == SOCK_ACCEPTED))
|
||||
&& (pio->read_details.pending || pio->write_details.pending)) {
|
||||
if (((pio->internal.state == SOCK_CONNECTED) || (pio->internal.state == SOCK_ACCEPTED)) &&
|
||||
(pio->read_details.pending || pio->write_details.pending)) {
|
||||
debug2("close - IO is still pending on closed socket. read:%d, write:%d, io:%p",
|
||||
pio->read_details.pending, pio->write_details.pending, pio);
|
||||
DebugBreak();
|
||||
@ -657,20 +618,16 @@ socketio_close(struct w32_io* pio) {
|
||||
if (pio->internal.state == SOCK_LISTENING) {
|
||||
if (pio->read_overlapped.hEvent)
|
||||
CloseHandle(pio->read_overlapped.hEvent);
|
||||
if (pio->internal.context)
|
||||
{
|
||||
if (pio->internal.context) {
|
||||
struct acceptEx_context *ctx = (struct acceptEx_context*)pio->internal.context;
|
||||
if (ctx->accept_socket != INVALID_SOCKET)
|
||||
closesocket(ctx->accept_socket);
|
||||
free(pio->internal.context);
|
||||
}
|
||||
|
||||
}
|
||||
else if (pio->internal.state == SOCK_CONNECTING) {
|
||||
} else if (pio->internal.state == SOCK_CONNECTING) {
|
||||
if (pio->write_overlapped.hEvent)
|
||||
CloseHandle(pio->write_overlapped.hEvent);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
if (pio->read_details.buf)
|
||||
free(pio->read_details.buf);
|
||||
|
||||
@ -684,7 +641,8 @@ socketio_close(struct w32_io* pio) {
|
||||
|
||||
/* accept() implementation */
|
||||
struct w32_io*
|
||||
socketio_accept(struct w32_io* pio, struct sockaddr* addr, int* addrlen) {
|
||||
socketio_accept(struct w32_io* pio, struct sockaddr* addr, int* addrlen)
|
||||
{
|
||||
struct w32_io *accept_io = NULL;
|
||||
int iResult = 0;
|
||||
struct acceptEx_context* context;
|
||||
@ -694,10 +652,9 @@ socketio_accept(struct w32_io* pio, struct sockaddr* addr, int* addrlen) {
|
||||
debug3("accept - io:%p", pio);
|
||||
/* start io if not already started */
|
||||
if (pio->read_details.pending == FALSE) {
|
||||
if (socketio_acceptEx(pio) != 0) {
|
||||
if (socketio_acceptEx(pio) != 0)
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if (w32_io_is_blocking(pio)) {
|
||||
/* block until accept io is complete */
|
||||
@ -705,15 +662,13 @@ socketio_accept(struct w32_io* pio, struct sockaddr* addr, int* addrlen) {
|
||||
if (-1 == wait_for_any_event(&pio->read_overlapped.hEvent,
|
||||
1, INFINITE))
|
||||
return NULL;
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
/* if i/o is not ready */
|
||||
if (FALSE == socketio_is_io_available(pio, TRUE)) {
|
||||
errno = EAGAIN;
|
||||
debug2("accept is pending, io:%p", pio);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
context = (struct acceptEx_context*)pio->internal.context;
|
||||
@ -769,7 +724,8 @@ on_error:
|
||||
|
||||
/* initiates an async connect*/
|
||||
int
|
||||
socketio_connectex(struct w32_io* pio, const struct sockaddr* name, int namelen) {
|
||||
socketio_connectex(struct w32_io* pio, const struct sockaddr* name, int namelen)
|
||||
{
|
||||
|
||||
struct sockaddr_in tmp_addr4;
|
||||
struct sockaddr_in6 tmp_addr6;
|
||||
@ -786,22 +742,19 @@ socketio_connectex(struct w32_io* pio, const struct sockaddr* name, int namelen)
|
||||
tmp_addr6.sin6_port = 0;
|
||||
tmp_addr = (SOCKADDR*)&tmp_addr6;
|
||||
tmp_addr_len = sizeof(tmp_addr6);
|
||||
}
|
||||
else if (name->sa_family == AF_INET) {
|
||||
} else if (name->sa_family == AF_INET) {
|
||||
ZeroMemory(&tmp_addr4, sizeof(tmp_addr4));
|
||||
tmp_addr4.sin_family = AF_INET;
|
||||
tmp_addr4.sin_port = 0;
|
||||
tmp_addr = (SOCKADDR*)&tmp_addr4;
|
||||
tmp_addr_len = sizeof(tmp_addr4);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
errno = ENOTSUP;
|
||||
debug("connectex - ERROR: unsuppored address family:%d, io:%p", name->sa_family, pio);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (SOCKET_ERROR == bind(pio->sock, tmp_addr, (int)tmp_addr_len))
|
||||
{
|
||||
if (SOCKET_ERROR == bind(pio->sock, tmp_addr, (int)tmp_addr_len)) {
|
||||
errno = errno_from_WSALastError();
|
||||
debug("connectex - ERROR: bind failed :%d, io:%p", WSAGetLastError(), pio);
|
||||
return -1;
|
||||
@ -810,8 +763,7 @@ socketio_connectex(struct w32_io* pio, const struct sockaddr* name, int namelen)
|
||||
if (SOCKET_ERROR == WSAIoctl(pio->sock, SIO_GET_EXTENSION_FUNCTION_POINTER,
|
||||
&connectex_guid, sizeof(connectex_guid),
|
||||
&ConnectEx, sizeof(ConnectEx),
|
||||
&tmp_bytes, NULL, NULL))
|
||||
{
|
||||
&tmp_bytes, NULL, NULL)) {
|
||||
errno = errno_from_WSALastError();
|
||||
debug("connectex - ioctl ERROR:%d, io:%p", WSAGetLastError(), pio);
|
||||
return -1;
|
||||
@ -829,8 +781,7 @@ socketio_connectex(struct w32_io* pio, const struct sockaddr* name, int namelen)
|
||||
&pio->write_overlapped)) {
|
||||
/* set completion event to indicates that async connect has completed */
|
||||
SetEvent(pio->write_overlapped.hEvent);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
if (WSAGetLastError() != ERROR_IO_PENDING) {
|
||||
CloseHandle(pio->write_overlapped.hEvent);
|
||||
pio->write_overlapped.hEvent = 0;
|
||||
@ -847,7 +798,8 @@ socketio_connectex(struct w32_io* pio, const struct sockaddr* name, int namelen)
|
||||
|
||||
/* connect implementation */
|
||||
int
|
||||
socketio_connect(struct w32_io* pio, const struct sockaddr* name, int namelen) {
|
||||
socketio_connect(struct w32_io* pio, const struct sockaddr* name, int namelen)
|
||||
{
|
||||
|
||||
debug3("connect - io:%p", pio);
|
||||
if (pio->write_details.pending == FALSE) {
|
||||
@ -858,29 +810,25 @@ socketio_connect(struct w32_io* pio, const struct sockaddr* name, int namelen) {
|
||||
if (w32_io_is_blocking(pio)) {
|
||||
/* block until connect io is complete */
|
||||
while (FALSE == socketio_is_io_available(pio, TRUE)) {
|
||||
if (-1 == wait_for_any_event(&pio->write_overlapped.hEvent,
|
||||
1, INFINITE))
|
||||
if (-1 == wait_for_any_event(&pio->write_overlapped.hEvent, 1, INFINITE))
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
/* if i/o is not ready */
|
||||
if (FALSE == socketio_is_io_available(pio, TRUE)) {
|
||||
errno = EINPROGRESS;
|
||||
debug2("connect - in progress, io:%p", pio);
|
||||
return -1;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return socketio_finish_connect(pio);
|
||||
}
|
||||
|
||||
int
|
||||
socketio_finish_connect(struct w32_io* pio) {
|
||||
|
||||
socketio_finish_connect(struct w32_io* pio)
|
||||
{
|
||||
debug3("finish_connect, io:%p", pio);
|
||||
|
||||
if (pio->write_details.error) {
|
||||
errno = errno_from_WSAError(pio->write_details.error);
|
||||
debug("finish_connect - ERROR: async io completed with error: %d, io:%p", errno, pio);
|
||||
@ -903,31 +851,27 @@ socketio_finish_connect(struct w32_io* pio) {
|
||||
|
||||
/* checks if a given io is ready/available */
|
||||
BOOL
|
||||
socketio_is_io_available(struct w32_io* pio, BOOL rd) {
|
||||
|
||||
socketio_is_io_available(struct w32_io* pio, BOOL rd)
|
||||
{
|
||||
if ((pio->internal.state == SOCK_LISTENING) ||
|
||||
(pio->internal.state == SOCK_CONNECTING)) {
|
||||
DWORD numBytes = 0;
|
||||
DWORD flags;
|
||||
BOOL sock_listening = (pio->internal.state == SOCK_LISTENING);
|
||||
OVERLAPPED *overlapped =
|
||||
sock_listening ? &pio->read_overlapped : &pio->write_overlapped;
|
||||
BOOL pending =
|
||||
sock_listening ? pio->read_details.pending : pio->write_details.pending;
|
||||
OVERLAPPED *overlapped = sock_listening ? &pio->read_overlapped : &pio->write_overlapped;
|
||||
BOOL pending = sock_listening ? pio->read_details.pending : pio->write_details.pending;
|
||||
|
||||
if (pending)
|
||||
/* if there is an error to be picked up */
|
||||
if (sock_listening) {
|
||||
if (pio->read_details.error)
|
||||
return TRUE;
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
if (pio->write_details.error)
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
if (WSAGetOverlappedResult(pio->sock, overlapped,
|
||||
&numBytes, FALSE, &flags))
|
||||
if (WSAGetOverlappedResult(pio->sock, overlapped, &numBytes, FALSE, &flags))
|
||||
return TRUE;
|
||||
else if (WSAGetLastError() != WSA_IO_INCOMPLETE) {
|
||||
if (sock_listening)
|
||||
@ -938,31 +882,27 @@ socketio_is_io_available(struct w32_io* pio, BOOL rd) {
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
else if (rd) {
|
||||
} else if (rd) {
|
||||
if (pio->read_details.remaining || pio->read_details.error)
|
||||
return TRUE;
|
||||
else
|
||||
return FALSE;
|
||||
}
|
||||
else {
|
||||
} else
|
||||
return (pio->write_details.pending == FALSE) ? TRUE : FALSE;
|
||||
}
|
||||
|
||||
}
|
||||
/*start async io (if needed) for accept and recv*/
|
||||
void
|
||||
socketio_on_select(struct w32_io* pio, BOOL rd) {
|
||||
|
||||
socketio_on_select(struct w32_io* pio, BOOL rd)
|
||||
{
|
||||
enum w32_io_sock_state sock_state = pio->internal.state;
|
||||
|
||||
debug2("on_select - io:%p type:%d rd:%d", pio, pio->type, rd);
|
||||
|
||||
//nothing to do for writes (that includes connect)
|
||||
/* nothing to do for writes (that includes connect) */
|
||||
if (!rd)
|
||||
return;
|
||||
|
||||
//listening socket - acceptEx if needed
|
||||
/* listening socket - acceptEx if needed */
|
||||
if (sock_state == SOCK_LISTENING) {
|
||||
if (pio->read_details.pending == FALSE)
|
||||
if (socketio_acceptEx(pio) != 0) {
|
||||
@ -973,9 +913,8 @@ socketio_on_select(struct w32_io* pio, BOOL rd) {
|
||||
SetEvent(pio->read_overlapped.hEvent);
|
||||
return;
|
||||
}
|
||||
}
|
||||
else {
|
||||
//connected socket - WSARecv if needed
|
||||
} else {
|
||||
/* connected socket - WSARecv if needed */
|
||||
if ((!pio->read_details.pending) && (!socketio_is_io_available(pio, rd)))
|
||||
if (socketio_WSARecv(pio, NULL) != 0) {
|
||||
/* set error, recv() will pick it */
|
||||
@ -984,38 +923,38 @@ socketio_on_select(struct w32_io* pio, BOOL rd) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
int
|
||||
w32_gethostname(char *name_utf8, size_t len) {
|
||||
w32_gethostname(char *name_utf8, size_t len)
|
||||
{
|
||||
wchar_t name_utf16[256];
|
||||
char* tmp_name_utf8 = NULL;
|
||||
|
||||
if (IsWindows8OrGreater()) {
|
||||
/* TODO - GetHostNameW not present in Win7, do GetProcAddr on Win8+*/
|
||||
// if (GetHostNameW(name_utf16, 256) == SOCKET_ERROR) {
|
||||
// errno = errno_from_WSALastError();
|
||||
// return -1;
|
||||
// }
|
||||
|
||||
// if ((tmp_name_utf8 = utf16_to_utf8(name_utf16)) == NULL ||
|
||||
// strlen(tmp_name_utf8) >= len) {
|
||||
// errno = EFAULT; //??
|
||||
// return -1;
|
||||
// }
|
||||
|
||||
// memcpy(name_utf8, tmp_name_utf8, strlen(tmp_name_utf8) + 1);
|
||||
// free(tmp_name_utf8);
|
||||
// return 0;
|
||||
return gethostname(name_utf8, len);
|
||||
/* if (GetHostNameW(name_utf16, 256) == SOCKET_ERROR) {
|
||||
errno = errno_from_WSALastError();
|
||||
return -1;
|
||||
}
|
||||
else
|
||||
|
||||
if ((tmp_name_utf8 = utf16_to_utf8(name_utf16)) == NULL ||
|
||||
strlen(tmp_name_utf8) >= len) {
|
||||
errno = EFAULT; //??
|
||||
return -1;
|
||||
}
|
||||
|
||||
memcpy(name_utf8, tmp_name_utf8, strlen(tmp_name_utf8) + 1);
|
||||
free(tmp_name_utf8);
|
||||
return 0; */
|
||||
return gethostname(name_utf8, len);
|
||||
} else
|
||||
return gethostname(name_utf8, len);
|
||||
}
|
||||
|
||||
void
|
||||
w32_freeaddrinfo(struct addrinfo *ai) {
|
||||
w32_freeaddrinfo(struct addrinfo *ai)
|
||||
{
|
||||
struct addrinfo *cur;
|
||||
while (ai) {
|
||||
cur = ai;
|
||||
@ -1030,7 +969,8 @@ w32_freeaddrinfo(struct addrinfo *ai) {
|
||||
|
||||
int
|
||||
w32_getaddrinfo(const char *node_utf8, const char *service_utf8,
|
||||
const struct addrinfo *hints, struct addrinfo **res) {
|
||||
const struct addrinfo *hints, struct addrinfo **res)
|
||||
{
|
||||
int ret = 0;
|
||||
wchar_t *node_utf16 = NULL, *service_utf16 = NULL;
|
||||
struct addrinfoW *info_w = NULL;
|
||||
@ -1083,5 +1023,3 @@ done:
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
|
@ -67,7 +67,8 @@ void fd_table_set(struct w32_io* pio, int index);
|
||||
|
||||
/* initializes mapping table*/
|
||||
static int
|
||||
fd_table_initialize() {
|
||||
fd_table_initialize()
|
||||
{
|
||||
memset(&fd_table, 0, sizeof(fd_table));
|
||||
memset(&w32_io_stdin, 0, sizeof(w32_io_stdin));
|
||||
w32_io_stdin.std_handle = STD_INPUT_HANDLE;
|
||||
@ -86,7 +87,8 @@ fd_table_initialize() {
|
||||
|
||||
/* get a free slot in mapping table with least index*/
|
||||
static int
|
||||
fd_table_get_min_index() {
|
||||
fd_table_get_min_index()
|
||||
{
|
||||
int min_index = 0;
|
||||
unsigned char* bitmap = fd_table.occupied.bitmap;
|
||||
unsigned char tmp;
|
||||
@ -102,9 +104,7 @@ fd_table_get_min_index() {
|
||||
}
|
||||
|
||||
tmp = *bitmap;
|
||||
|
||||
while (tmp & 0x80)
|
||||
{
|
||||
while (tmp & 0x80) {
|
||||
tmp <<= 1;
|
||||
min_index++;
|
||||
}
|
||||
@ -114,7 +114,8 @@ fd_table_get_min_index() {
|
||||
|
||||
/* maps pio to fd (specified by index)*/
|
||||
static void
|
||||
fd_table_set(struct w32_io* pio, int index) {
|
||||
fd_table_set(struct w32_io* pio, int index)
|
||||
{
|
||||
fd_table.w32_ios[index] = pio;
|
||||
pio->table_index = index;
|
||||
assert(pio->type != UNKNOWN_FD);
|
||||
@ -131,9 +132,9 @@ fd_table_clear(int index)
|
||||
}
|
||||
|
||||
void
|
||||
w32posix_initialize() {
|
||||
if ((fd_table_initialize() != 0)
|
||||
|| (socketio_initialize() != 0))
|
||||
w32posix_initialize()
|
||||
{
|
||||
if ((fd_table_initialize() != 0) || (socketio_initialize() != 0))
|
||||
DebugBreak();
|
||||
main_thread = OpenThread(THREAD_SET_CONTEXT | SYNCHRONIZE, FALSE, GetCurrentThreadId());
|
||||
if ((main_thread == NULL) || (sw_initialize() != 0) || w32_programdir() == NULL) {
|
||||
@ -143,7 +144,8 @@ w32posix_initialize() {
|
||||
}
|
||||
|
||||
void
|
||||
w32posix_done() {
|
||||
w32posix_done()
|
||||
{
|
||||
socketio_done();
|
||||
}
|
||||
|
||||
@ -159,7 +161,8 @@ w32_io_is_blocking(struct w32_io* pio)
|
||||
* as it decides on what fds can be set.
|
||||
*/
|
||||
BOOL
|
||||
w32_io_is_io_available(struct w32_io* pio, BOOL rd) {
|
||||
w32_io_is_io_available(struct w32_io* pio, BOOL rd)
|
||||
{
|
||||
if (pio->type == SOCK_FD)
|
||||
return socketio_is_io_available(pio, rd);
|
||||
else
|
||||
@ -195,7 +198,8 @@ w32_io_on_select(struct w32_io* pio, BOOL rd)
|
||||
} while (0)
|
||||
|
||||
int
|
||||
w32_socket(int domain, int type, int protocol) {
|
||||
w32_socket(int domain, int type, int protocol)
|
||||
{
|
||||
int min_index = fd_table_get_min_index();
|
||||
struct w32_io* pio = NULL;
|
||||
|
||||
@ -216,7 +220,6 @@ w32_socket(int domain, int type, int protocol) {
|
||||
int
|
||||
w32_accept(int fd, struct sockaddr* addr, int* addrlen)
|
||||
{
|
||||
|
||||
CHECK_FD(fd);
|
||||
CHECK_SOCK_IO(fd_table.w32_ios[fd]);
|
||||
int min_index = fd_table_get_min_index();
|
||||
@ -236,72 +239,72 @@ w32_accept(int fd, struct sockaddr* addr, int* addrlen)
|
||||
}
|
||||
|
||||
int
|
||||
w32_setsockopt(int fd, int level, int optname, const void* optval, int optlen) {
|
||||
|
||||
w32_setsockopt(int fd, int level, int optname, const void* optval, int optlen)
|
||||
{
|
||||
CHECK_FD(fd);
|
||||
CHECK_SOCK_IO(fd_table.w32_ios[fd]);
|
||||
return socketio_setsockopt(fd_table.w32_ios[fd], level, optname, (const char*)optval, optlen);
|
||||
}
|
||||
|
||||
int
|
||||
w32_getsockopt(int fd, int level, int optname, void* optval, int* optlen) {
|
||||
|
||||
w32_getsockopt(int fd, int level, int optname, void* optval, int* optlen)
|
||||
{
|
||||
CHECK_FD(fd);
|
||||
CHECK_SOCK_IO(fd_table.w32_ios[fd]);
|
||||
return socketio_getsockopt(fd_table.w32_ios[fd], level, optname, (char*)optval, optlen);
|
||||
}
|
||||
|
||||
int
|
||||
w32_getsockname(int fd, struct sockaddr* name, int* namelen) {
|
||||
|
||||
w32_getsockname(int fd, struct sockaddr* name, int* namelen)
|
||||
{
|
||||
CHECK_FD(fd);
|
||||
CHECK_SOCK_IO(fd_table.w32_ios[fd]);
|
||||
return socketio_getsockname(fd_table.w32_ios[fd], name, namelen);
|
||||
}
|
||||
|
||||
int
|
||||
w32_getpeername(int fd, struct sockaddr* name, int* namelen) {
|
||||
|
||||
w32_getpeername(int fd, struct sockaddr* name, int* namelen)
|
||||
{
|
||||
CHECK_FD(fd);
|
||||
CHECK_SOCK_IO(fd_table.w32_ios[fd]);
|
||||
return socketio_getpeername(fd_table.w32_ios[fd], name, namelen);
|
||||
}
|
||||
|
||||
int
|
||||
w32_listen(int fd, int backlog) {
|
||||
|
||||
w32_listen(int fd, int backlog)
|
||||
{
|
||||
CHECK_FD(fd);
|
||||
CHECK_SOCK_IO(fd_table.w32_ios[fd]);
|
||||
return socketio_listen(fd_table.w32_ios[fd], backlog);
|
||||
}
|
||||
|
||||
int
|
||||
w32_bind(int fd, const struct sockaddr *name, int namelen) {
|
||||
|
||||
w32_bind(int fd, const struct sockaddr *name, int namelen)
|
||||
{
|
||||
CHECK_FD(fd);
|
||||
CHECK_SOCK_IO(fd_table.w32_ios[fd]);
|
||||
return socketio_bind(fd_table.w32_ios[fd], name, namelen);
|
||||
}
|
||||
|
||||
int
|
||||
w32_connect(int fd, const struct sockaddr* name, int namelen) {
|
||||
|
||||
w32_connect(int fd, const struct sockaddr* name, int namelen)
|
||||
{
|
||||
CHECK_FD(fd);
|
||||
CHECK_SOCK_IO(fd_table.w32_ios[fd]);
|
||||
return socketio_connect(fd_table.w32_ios[fd], name, namelen);
|
||||
}
|
||||
|
||||
int
|
||||
w32_recv(int fd, void *buf, size_t len, int flags) {
|
||||
|
||||
w32_recv(int fd, void *buf, size_t len, int flags)
|
||||
{
|
||||
CHECK_FD(fd);
|
||||
CHECK_SOCK_IO(fd_table.w32_ios[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) {
|
||||
|
||||
w32_send(int fd, const void *buf, size_t len, int flags)
|
||||
{
|
||||
CHECK_FD(fd);
|
||||
CHECK_SOCK_IO(fd_table.w32_ios[fd]);
|
||||
return socketio_send(fd_table.w32_ios[fd], buf, len, flags);
|
||||
@ -309,7 +312,8 @@ w32_send(int fd, const void *buf, size_t len, int flags) {
|
||||
|
||||
|
||||
int
|
||||
w32_shutdown(int fd, int how) {
|
||||
w32_shutdown(int fd, int how)
|
||||
{
|
||||
debug2("shutdown - fd:%d how:%d", fd, how);
|
||||
CHECK_FD(fd);
|
||||
CHECK_SOCK_IO(fd_table.w32_ios[fd]);
|
||||
@ -317,7 +321,8 @@ w32_shutdown(int fd, int how) {
|
||||
}
|
||||
|
||||
int
|
||||
w32_socketpair(int domain, int type, int protocol, int sv[2]) {
|
||||
w32_socketpair(int domain, int type, int protocol, int sv[2])
|
||||
{
|
||||
errno = ENOTSUP;
|
||||
debug("socketpair - ERROR not supported");
|
||||
return -1;
|
||||
@ -325,7 +330,8 @@ w32_socketpair(int domain, int type, int protocol, int sv[2]) {
|
||||
|
||||
|
||||
int
|
||||
w32_pipe(int *pfds) {
|
||||
w32_pipe(int *pfds)
|
||||
{
|
||||
int read_index, write_index;
|
||||
struct w32_io* pio[2];
|
||||
|
||||
@ -352,11 +358,13 @@ w32_pipe(int *pfds) {
|
||||
pfds[1] = write_index;
|
||||
debug("pipe - r-h:%d,io:%p,fd:%d w-h:%d,io:%p,fd:%d",
|
||||
pio[0]->handle, pio[0], read_index, pio[1]->handle, pio[1], write_index);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
w32_open(const char *pathname, int flags, ...) {
|
||||
w32_open(const char *pathname, int flags, ...)
|
||||
{
|
||||
int min_index = fd_table_get_min_index();
|
||||
struct w32_io* pio;
|
||||
|
||||
@ -376,9 +384,9 @@ w32_open(const char *pathname, int flags, ...) {
|
||||
}
|
||||
|
||||
int
|
||||
w32_read(int fd, void *dst, size_t max) {
|
||||
w32_read(int fd, void *dst, size_t max)
|
||||
{
|
||||
CHECK_FD(fd);
|
||||
|
||||
if (fd_table.w32_ios[fd]->type == SOCK_FD)
|
||||
return socketio_recv(fd_table.w32_ios[fd], dst, max, 0);
|
||||
|
||||
@ -386,7 +394,8 @@ w32_read(int fd, void *dst, size_t max) {
|
||||
}
|
||||
|
||||
int
|
||||
w32_write(int fd, const void *buf, unsigned int max) {
|
||||
w32_write(int fd, const void *buf, unsigned int max)
|
||||
{
|
||||
CHECK_FD(fd);
|
||||
|
||||
if (fd_table.w32_ios[fd]->type == SOCK_FD)
|
||||
@ -395,37 +404,39 @@ w32_write(int fd, const void *buf, unsigned int max) {
|
||||
return fileio_write(fd_table.w32_ios[fd], buf, max);
|
||||
}
|
||||
|
||||
int w32_writev(int fd, const struct iovec *iov, int iovcnt) {
|
||||
int
|
||||
w32_writev(int fd, const struct iovec *iov, int iovcnt)
|
||||
{
|
||||
int written = 0;
|
||||
int i = 0;
|
||||
|
||||
CHECK_FD(fd);
|
||||
|
||||
for (i = 0; i < iovcnt; i++) {
|
||||
int ret = w32_write(fd, iov[i].iov_base, iov[i].iov_len);
|
||||
|
||||
if (ret > 0) {
|
||||
if (ret > 0)
|
||||
written += ret;
|
||||
}
|
||||
}
|
||||
|
||||
return written;
|
||||
}
|
||||
|
||||
int
|
||||
w32_fstat(int fd, struct w32_stat *buf) {
|
||||
w32_fstat(int fd, struct w32_stat *buf)
|
||||
{
|
||||
CHECK_FD(fd);
|
||||
return fileio_fstat(fd_table.w32_ios[fd], (struct _stat64*)buf);
|
||||
}
|
||||
|
||||
long
|
||||
w32_lseek(int fd, long offset, int origin) {
|
||||
w32_lseek(int fd, long offset, int origin)
|
||||
{
|
||||
CHECK_FD(fd);
|
||||
return fileio_lseek(fd_table.w32_ios[fd], offset, origin);
|
||||
}
|
||||
|
||||
int
|
||||
w32_isatty(int fd) {
|
||||
w32_isatty(int fd)
|
||||
{
|
||||
struct w32_io* pio;
|
||||
if ((fd < 0) || (fd > MAX_FDS - 1) || fd_table.w32_ios[fd] == NULL) {
|
||||
errno = EBADF;
|
||||
@ -433,7 +444,6 @@ w32_isatty(int fd) {
|
||||
}
|
||||
|
||||
pio = fd_table.w32_ios[fd];
|
||||
|
||||
if (FILETYPE(pio) == FILE_TYPE_CHAR)
|
||||
return 1;
|
||||
else {
|
||||
@ -443,7 +453,8 @@ w32_isatty(int fd) {
|
||||
}
|
||||
|
||||
FILE*
|
||||
w32_fdopen(int fd, const char *mode) {
|
||||
w32_fdopen(int fd, const char *mode)
|
||||
{
|
||||
errno = 0;
|
||||
if ((fd < 0) || (fd > MAX_FDS - 1) || fd_table.w32_ios[fd] == NULL) {
|
||||
errno = EBADF;
|
||||
@ -454,9 +465,9 @@ w32_fdopen(int fd, const char *mode) {
|
||||
}
|
||||
|
||||
int
|
||||
w32_close(int fd) {
|
||||
w32_close(int fd)
|
||||
{
|
||||
struct w32_io* pio;
|
||||
|
||||
if ((fd < 0) || (fd > MAX_FDS - 1) || fd_table.w32_ios[fd] == NULL) {
|
||||
errno = EBADF;
|
||||
return -1;
|
||||
@ -480,7 +491,8 @@ w32_close(int fd) {
|
||||
}
|
||||
|
||||
static int
|
||||
w32_io_process_fd_flags(struct w32_io* pio, int flags) {
|
||||
w32_io_process_fd_flags(struct w32_io* pio, int flags)
|
||||
{
|
||||
DWORD shi_flags;
|
||||
if (flags & ~FD_CLOEXEC) {
|
||||
debug("fcntl - ERROR unsupported flags %d, io:%p", flags, pio);
|
||||
@ -502,7 +514,8 @@ w32_io_process_fd_flags(struct w32_io* pio, int flags) {
|
||||
}
|
||||
|
||||
int
|
||||
w32_fcntl(int fd, int cmd, ... /* arg */) {
|
||||
w32_fcntl(int fd, int cmd, ... /* arg */)
|
||||
{
|
||||
va_list valist;
|
||||
va_start(valist, cmd);
|
||||
int ret = 0;
|
||||
@ -536,8 +549,8 @@ w32_fcntl(int fd, int cmd, ... /* arg */) {
|
||||
|
||||
#define SELECT_EVENT_LIMIT 32
|
||||
int
|
||||
w32_select(int fds, w32_fd_set* readfds, w32_fd_set* writefds, w32_fd_set* exceptfds,
|
||||
const struct timeval *timeout) {
|
||||
w32_select(int fds, w32_fd_set* readfds, w32_fd_set* writefds, w32_fd_set* exceptfds, const struct timeval *timeout)
|
||||
{
|
||||
ULONGLONG ticks_start = GetTickCount64(), ticks_spent;
|
||||
w32_fd_set read_ready_fds, write_ready_fds;
|
||||
HANDLE events[SELECT_EVENT_LIMIT];
|
||||
@ -566,12 +579,12 @@ w32_select(int fds, w32_fd_set* readfds, w32_fd_set* writefds, w32_fd_set* excep
|
||||
}
|
||||
|
||||
/* TODO - see if this needs to be supported */
|
||||
//if (exceptfds) {
|
||||
// errno = EOPNOTSUPP;
|
||||
// debug("select - ERROR: exceptfds not supported");
|
||||
// DebugBreak();
|
||||
// return -1;
|
||||
//}
|
||||
/* if (exceptfds) {
|
||||
errno = EOPNOTSUPP;
|
||||
debug("select - ERROR: exceptfds not supported");
|
||||
DebugBreak();
|
||||
return -1;
|
||||
} */
|
||||
|
||||
if (readfds) {
|
||||
for (i = 0; i < fds; i++)
|
||||
@ -602,11 +615,10 @@ w32_select(int fds, w32_fd_set* readfds, w32_fd_set* writefds, w32_fd_set* excep
|
||||
* that select needs to listen on
|
||||
*/
|
||||
for (int i = 0; i < fds; i++) {
|
||||
|
||||
if (readfds && FD_ISSET(i, readfds)) {
|
||||
w32_io_on_select(fd_table.w32_ios[i], TRUE);
|
||||
if ((fd_table.w32_ios[i]->type == SOCK_FD)
|
||||
&& (fd_table.w32_ios[i]->internal.state == SOCK_LISTENING)) {
|
||||
if ((fd_table.w32_ios[i]->type == SOCK_FD) &&
|
||||
(fd_table.w32_ios[i]->internal.state == SOCK_LISTENING)) {
|
||||
if (num_events == SELECT_EVENT_LIMIT) {
|
||||
debug("select - ERROR: max #events breach");
|
||||
errno = ENOMEM;
|
||||
@ -618,8 +630,8 @@ w32_select(int fds, w32_fd_set* readfds, w32_fd_set* writefds, w32_fd_set* excep
|
||||
|
||||
if (writefds && FD_ISSET(i, writefds)) {
|
||||
w32_io_on_select(fd_table.w32_ios[i], FALSE);
|
||||
if ((fd_table.w32_ios[i]->type == SOCK_FD)
|
||||
&& (fd_table.w32_ios[i]->internal.state == SOCK_CONNECTING)) {
|
||||
if ((fd_table.w32_ios[i]->type == SOCK_FD) &&
|
||||
(fd_table.w32_ios[i]->internal.state == SOCK_CONNECTING)) {
|
||||
if (num_events == SELECT_EVENT_LIMIT) {
|
||||
debug("select - ERROR: max #events reached for select");
|
||||
errno = ENOMEM;
|
||||
@ -636,7 +648,6 @@ w32_select(int fds, w32_fd_set* readfds, w32_fd_set* writefds, w32_fd_set* excep
|
||||
|
||||
/* see if any io is ready */
|
||||
for (i = 0; i < fds; i++) {
|
||||
|
||||
if (readfds && FD_ISSET(i, readfds)) {
|
||||
if (w32_io_is_io_available(fd_table.w32_ios[i], TRUE)) {
|
||||
FD_SET(i, &read_ready_fds);
|
||||
@ -677,7 +688,6 @@ w32_select(int fds, w32_fd_set* readfds, w32_fd_set* writefds, w32_fd_set* excep
|
||||
/* check on fd status */
|
||||
out_ready_fds = 0;
|
||||
for (int i = 0; i < fds; i++) {
|
||||
|
||||
if (readfds && FD_ISSET(i, readfds)) {
|
||||
if (w32_io_is_io_available(fd_table.w32_ios[i], TRUE)) {
|
||||
FD_SET(i, &read_ready_fds);
|
||||
@ -695,7 +705,6 @@ w32_select(int fds, w32_fd_set* readfds, w32_fd_set* writefds, w32_fd_set* excep
|
||||
|
||||
if (out_ready_fds == 0)
|
||||
debug3("select - wait ended without any IO completion, looping again");
|
||||
|
||||
}
|
||||
|
||||
/* clear out fds that are not ready yet */
|
||||
@ -709,8 +718,8 @@ w32_select(int fds, w32_fd_set* readfds, w32_fd_set* writefds, w32_fd_set* excep
|
||||
if (FD_ISSET(i, writefds)) {
|
||||
if (FD_ISSET(i, &write_ready_fds)) {
|
||||
/* for connect() completed sockets finish WSA connect process*/
|
||||
if ((fd_table.w32_ios[i]->type == SOCK_FD)
|
||||
&& ((fd_table.w32_ios[i]->internal.state == SOCK_CONNECTING)))
|
||||
if ((fd_table.w32_ios[i]->type == SOCK_FD) &&
|
||||
((fd_table.w32_ios[i]->internal.state == SOCK_CONNECTING)))
|
||||
if (socketio_finish_connect(fd_table.w32_ios[i]) != 0) {
|
||||
/* finalizeing connect failed - recored error */
|
||||
/* error gets picked up later recv and/or send*/
|
||||
@ -730,7 +739,8 @@ w32_select(int fds, w32_fd_set* readfds, w32_fd_set* writefds, w32_fd_set* excep
|
||||
}
|
||||
|
||||
int
|
||||
w32_dup(int oldfd) {
|
||||
w32_dup(int oldfd)
|
||||
{
|
||||
int min_index;
|
||||
struct w32_io* pio;
|
||||
HANDLE src, target;
|
||||
@ -773,7 +783,8 @@ w32_dup(int oldfd) {
|
||||
}
|
||||
|
||||
int
|
||||
w32_dup2(int oldfd, int newfd) {
|
||||
w32_dup2(int oldfd, int newfd)
|
||||
{
|
||||
CHECK_FD(oldfd);
|
||||
errno = EOPNOTSUPP;
|
||||
debug("dup2 - ERROR: not implemented yet");
|
||||
@ -781,14 +792,17 @@ w32_dup2(int oldfd, int newfd) {
|
||||
}
|
||||
|
||||
HANDLE
|
||||
w32_fd_to_handle(int fd) {
|
||||
w32_fd_to_handle(int fd)
|
||||
{
|
||||
HANDLE h = fd_table.w32_ios[fd]->handle;
|
||||
if (fd <= STDERR_FILENO)
|
||||
h = GetStdHandle(fd_table.w32_ios[fd]->std_handle);
|
||||
return h;
|
||||
}
|
||||
|
||||
int w32_allocate_fd_for_handle(HANDLE h, BOOL is_sock) {
|
||||
int
|
||||
w32_allocate_fd_for_handle(HANDLE h, BOOL is_sock)
|
||||
{
|
||||
int min_index = fd_table_get_min_index();
|
||||
struct w32_io* pio;
|
||||
|
||||
@ -811,9 +825,9 @@ int w32_allocate_fd_for_handle(HANDLE h, BOOL is_sock) {
|
||||
|
||||
|
||||
int
|
||||
w32_ftruncate(int fd, off_t length) {
|
||||
w32_ftruncate(int fd, off_t length)
|
||||
{
|
||||
LARGE_INTEGER new_postion;
|
||||
|
||||
CHECK_FD(fd);
|
||||
|
||||
new_postion.QuadPart = length;
|
||||
@ -826,8 +840,8 @@ w32_ftruncate(int fd, off_t length) {
|
||||
}
|
||||
|
||||
int
|
||||
w32_fsync(int fd) {
|
||||
w32_fsync(int fd)
|
||||
{
|
||||
CHECK_FD(fd);
|
||||
|
||||
return FlushFileBuffers(w32_fd_to_handle(fd));
|
||||
}
|
||||
|
@ -2,6 +2,32 @@
|
||||
* Author: Manoj Ampalam <manoj.ampalam@microsoft.com>
|
||||
*
|
||||
* Definitions for Win32 wrapper functions with POSIX like signatures
|
||||
*
|
||||
* Copyright (c) 2015 Microsoft Corp.
|
||||
* All rights reserved
|
||||
*
|
||||
* Microsoft openssh win32 port
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
@ -32,24 +58,18 @@ struct w32_io {
|
||||
OVERLAPPED read_overlapped;
|
||||
OVERLAPPED write_overlapped;
|
||||
struct {
|
||||
/*internal read buffer*/
|
||||
char *buf;
|
||||
char *buf; /*internal read buffer*/
|
||||
DWORD buf_size;
|
||||
/*bytes in internal buffer remaining to be read by application*/
|
||||
DWORD remaining;
|
||||
/*bytes in internal buffer already read by application*/
|
||||
DWORD completed;
|
||||
DWORD remaining; /*bytes in internal buffer remaining to be read by application*/
|
||||
DWORD completed; /*bytes in internal buffer already read by application*/
|
||||
BOOL pending; /*waiting on a read operation to complete*/
|
||||
DWORD error; /*error reported on async read or accept completion*/
|
||||
}read_details;
|
||||
struct {
|
||||
/*internal write buffer*/
|
||||
char *buf;
|
||||
char *buf; /*internal write buffer*/
|
||||
DWORD buf_size;
|
||||
/*bytes in internal buffer remaining to be written to network*/
|
||||
DWORD remaining;
|
||||
/*bytes in internal buffer already written to network*/
|
||||
DWORD completed;
|
||||
DWORD remaining; /*bytes in internal buffer remaining to be written to network*/
|
||||
DWORD completed; /*bytes in internal buffer already written to network*/
|
||||
BOOL pending; /*waiting on a write operation to complete*/
|
||||
DWORD error; /*error reported on async write or connect completion*/
|
||||
}write_details;
|
||||
@ -89,10 +109,8 @@ BOOL socketio_is_io_available(struct w32_io* pio, BOOL rd);
|
||||
void socketio_on_select(struct w32_io* pio, BOOL rd);
|
||||
struct w32_io* socketio_socket(int domain, int type, int protocol);
|
||||
struct w32_io* socketio_accept(struct w32_io* pio, struct sockaddr* addr, int* addrlen);
|
||||
int socketio_setsockopt(struct w32_io* pio, int level, int optname,
|
||||
const char* optval, int optlen);
|
||||
int socketio_getsockopt(struct w32_io* pio, int level, int optname,
|
||||
char* optval, int* optlen);
|
||||
int socketio_setsockopt(struct w32_io* pio, int level, int optname, const char* optval, int optlen);
|
||||
int socketio_getsockopt(struct w32_io* pio, int level, int optname, char* optval, int* optlen);
|
||||
int socketio_getsockname(struct w32_io* pio, struct sockaddr* name, int* namelen);
|
||||
int socketio_getpeername(struct w32_io* pio, struct sockaddr* name, int* namelen);
|
||||
int socketio_listen(struct w32_io* pio, int backlog);
|
||||
@ -145,16 +163,16 @@ int termio_close(struct w32_io* pio);
|
||||
/* If O_CREAT and O_EXCL are set, open() shall fail if the file exists */
|
||||
/* #define O_EXCL 0x400 */
|
||||
/* #define O_BINARY 0x8000 //Gives raw data (while O_TEXT normalises line endings */
|
||||
// open modes
|
||||
/* open modes */
|
||||
#ifndef S_IRUSR
|
||||
#define S_IRUSR 00400 //user has read permission
|
||||
#endif // ! S_IRUSR
|
||||
#define S_IRUSR 00400 /* user has read permission */
|
||||
#endif /* ! S_IRUSR */
|
||||
#ifndef S_IWUSR
|
||||
#define S_IWUSR 00200 //user has write permission
|
||||
#define S_IWUSR 00200 /* user has write permission */
|
||||
#endif
|
||||
#ifndef S_IRGRP
|
||||
#define S_IRGRP 00040 //group has read permission
|
||||
#define S_IRGRP 00040 /* group has read permission */
|
||||
#endif
|
||||
#ifndef S_IROTH
|
||||
#define S_IROTH 00004 //others have read permission
|
||||
#define S_IROTH 00004 /* others have read permission */
|
||||
#endif
|
@ -27,11 +27,11 @@
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
|
||||
#include <Windows.h>
|
||||
#include <io.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include "inc\syslog.h"
|
||||
#include "misc_internal.h"
|
||||
|
||||
@ -39,14 +39,15 @@
|
||||
static int logfd = -1;
|
||||
|
||||
void
|
||||
openlog(char *ident, unsigned int option, int facility) {
|
||||
openlog(char *ident, unsigned int option, int facility)
|
||||
{
|
||||
if (logfd != -1 || ident == NULL)
|
||||
return;
|
||||
|
||||
wchar_t path[PATH_MAX], log_file[PATH_MAX + 12];
|
||||
if (GetModuleFileNameW(NULL, path, PATH_MAX) == 0)
|
||||
|
||||
return;
|
||||
|
||||
path[PATH_MAX - 1] = '\0';
|
||||
|
||||
/* split path root and module */
|
||||
@ -64,20 +65,20 @@ openlog(char *ident, unsigned int option, int facility) {
|
||||
memcpy(p, L"log\0", 8);
|
||||
}
|
||||
|
||||
logfd = _wopen(log_file, O_WRONLY | O_CREAT | O_APPEND,
|
||||
S_IREAD | S_IWRITE);
|
||||
logfd = _wopen(log_file, O_WRONLY | O_CREAT | O_APPEND, S_IREAD | S_IWRITE);
|
||||
if (logfd != -1)
|
||||
SetHandleInformation((HANDLE)_get_osfhandle(logfd),
|
||||
HANDLE_FLAG_INHERIT, 0);
|
||||
SetHandleInformation((HANDLE)_get_osfhandle(logfd), HANDLE_FLAG_INHERIT, 0);
|
||||
}
|
||||
|
||||
void
|
||||
closelog(void) {
|
||||
closelog(void)
|
||||
{
|
||||
/*NOOP*/
|
||||
}
|
||||
|
||||
void
|
||||
syslog(int priority, const char *format, const char *formatBuffer) {
|
||||
syslog(int priority, const char *format, const char *formatBuffer)
|
||||
{
|
||||
char msgbufTimestamp[MSGBUFSIZ];
|
||||
SYSTEMTIME st;
|
||||
|
||||
|
@ -1,19 +1,43 @@
|
||||
// win32_dirent.c
|
||||
// directory entry functions in Windows platform like Ubix/Linux
|
||||
// opendir(), readdir(), closedir().
|
||||
/*
|
||||
* Copyright (c) 2016 Microsoft Corp.
|
||||
* All rights reserved
|
||||
*
|
||||
* directory entry functions in Windows platform like Ubix/Linux
|
||||
* opendir(), readdir(), closedir().
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <windows.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <ctype.h>
|
||||
#include <string.h>
|
||||
#include "inc\utf.h"
|
||||
|
||||
#include "inc\utf.h"
|
||||
#include "inc\dirent.h"
|
||||
#include "inc\libgen.h"
|
||||
#include "misc_internal.h"
|
||||
|
||||
|
||||
struct DIR_ {
|
||||
intptr_t hFile;
|
||||
struct _wfinddata_t c_file;
|
||||
@ -22,7 +46,8 @@ struct DIR_ {
|
||||
|
||||
/* Open a directory stream on NAME.
|
||||
Return a DIR stream on the directory, or NULL if it could not be opened. */
|
||||
DIR * opendir(const char *name)
|
||||
DIR *
|
||||
opendir(const char *name)
|
||||
{
|
||||
struct _wfinddata_t c_file;
|
||||
intptr_t hFile;
|
||||
@ -36,7 +61,7 @@ DIR * opendir(const char *name)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// add *.* for Windows _findfirst() search pattern
|
||||
/* add *.* for Windows _findfirst() search pattern */
|
||||
swprintf_s(searchstr, PATH_MAX, L"%s\\*.*", wname);
|
||||
free(wname);
|
||||
|
||||
@ -60,7 +85,8 @@ DIR * opendir(const char *name)
|
||||
|
||||
/* Close the directory stream DIRP.
|
||||
Return 0 if successful, -1 if not. */
|
||||
int closedir(DIR *dirp)
|
||||
int
|
||||
closedir(DIR *dirp)
|
||||
{
|
||||
if (dirp && (dirp->hFile)) {
|
||||
_findclose(dirp->hFile);
|
||||
@ -75,7 +101,8 @@ int closedir(DIR *dirp)
|
||||
Return a pointer to a `struct dirent' describing the entry,
|
||||
or NULL for EOF or error. The storage returned may be overwritten
|
||||
by a later readdir call on the same DIR stream. */
|
||||
struct dirent *readdir(void *avp)
|
||||
struct dirent *
|
||||
readdir(void *avp)
|
||||
{
|
||||
static struct dirent pdirentry;
|
||||
struct _wfinddata_t c_file;
|
||||
@ -86,8 +113,7 @@ struct dirent *readdir(void *avp)
|
||||
if (dirp->first) {
|
||||
memcpy(&c_file, &dirp->c_file, sizeof(c_file));
|
||||
dirp->first = 0;
|
||||
}
|
||||
else if (_wfindnext(dirp->hFile, &c_file) != 0)
|
||||
} else if (_wfindnext(dirp->hFile, &c_file) != 0)
|
||||
return NULL;
|
||||
|
||||
if (wcscmp(c_file.name, L".") == 0 || wcscmp(c_file.name, L"..") == 0)
|
||||
@ -101,13 +127,14 @@ struct dirent *readdir(void *avp)
|
||||
strncpy(pdirentry.d_name, tmp, strlen(tmp) + 1);
|
||||
free(tmp);
|
||||
|
||||
pdirentry.d_ino = 1; // a fictious one like UNIX to say it is nonzero
|
||||
pdirentry.d_ino = 1; /* a fictious one like UNIX to say it is nonzero */
|
||||
return &pdirentry;
|
||||
}
|
||||
}
|
||||
|
||||
// return last part of a path. The last path being a filename.
|
||||
char *basename(char *path)
|
||||
/* return last part of a path. The last path being a filename */
|
||||
char *
|
||||
basename(char *path)
|
||||
{
|
||||
char *pdest;
|
||||
|
||||
@ -120,5 +147,5 @@ char *basename(char *path)
|
||||
if (pdest)
|
||||
return (pdest + 1);
|
||||
|
||||
return path; // path does not have a slash
|
||||
return path; /* path does not have a slash */
|
||||
}
|
||||
|
@ -32,33 +32,38 @@
|
||||
|
||||
#include "inc\zlib.h"
|
||||
|
||||
|
||||
int
|
||||
deflateEnd(z_streamp strm) {
|
||||
deflateEnd(z_streamp strm)
|
||||
{
|
||||
return Z_DATA_ERROR;
|
||||
}
|
||||
|
||||
int
|
||||
inflateEnd(z_streamp strm) {
|
||||
inflateEnd(z_streamp strm)
|
||||
{
|
||||
return Z_DATA_ERROR;
|
||||
}
|
||||
|
||||
int
|
||||
deflateInit(z_streamp strm, int level) {
|
||||
deflateInit(z_streamp strm, int level)
|
||||
{
|
||||
return Z_DATA_ERROR;
|
||||
}
|
||||
|
||||
int
|
||||
inflateInit(z_streamp strm) {
|
||||
inflateInit(z_streamp strm)
|
||||
{
|
||||
return Z_DATA_ERROR;
|
||||
}
|
||||
|
||||
int
|
||||
deflate(z_streamp strm, int flush) {
|
||||
deflate(z_streamp strm, int flush)
|
||||
{
|
||||
return Z_DATA_ERROR;
|
||||
}
|
||||
|
||||
int
|
||||
inflate(z_streamp strm, int flush) {
|
||||
inflate(z_streamp strm, int flush)
|
||||
{
|
||||
return Z_DATA_ERROR;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user