diff options
author | Patrick Galbraith <patg@northscale.com> | 2010-03-25 21:02:50 +0100 |
---|---|---|
committer | Trond Norbye <Trond.Norbye@gmail.com> | 2010-03-29 22:58:09 +0200 |
commit | 95c3be87e841a9e20139e2eb3f705dfab6b53252 (patch) | |
tree | 2441681cdc526dfd06b3325498878882fa170857 /win32 | |
parent | 04e0609f4fbf048cd540df7278c3afcd08aa1260 (diff) | |
download | memcached-95c3be87e841a9e20139e2eb3f705dfab6b53252.tar.gz |
Changes to memcached source required for compilation on windows
Diffstat (limited to 'win32')
-rw-r--r-- | win32/Makefile.mingw | 49 | ||||
-rw-r--r-- | win32/config.h | 92 | ||||
-rw-r--r-- | win32/config.sh | 17 | ||||
-rw-r--r-- | win32/defs.c | 51 | ||||
-rw-r--r-- | win32/dlfcn.c | 62 | ||||
-rw-r--r-- | win32/dlfcn.h | 12 | ||||
-rw-r--r-- | win32/sysexits.h | 114 | ||||
-rw-r--r-- | win32/win32.c | 395 | ||||
-rw-r--r-- | win32/win32.h | 205 |
9 files changed, 997 insertions, 0 deletions
diff --git a/win32/Makefile.mingw b/win32/Makefile.mingw new file mode 100644 index 0000000..6a66ece --- /dev/null +++ b/win32/Makefile.mingw @@ -0,0 +1,49 @@ +# Hard coded Makefile for windows + +CC = gcc + +OBJDIR = .libs .libs/win32 +BINARIES= memcached.exe .libs/default_engine.so +LIB=-L/lib -L/usr/lib -L/usr/local/lib +INCLUDE=-I/include -I/usr/include -I/usr/local/include + +all: ${BINARIES} + +CFLAGS = -std=gnu99 -O2 -DNDEBUG -fno-strict-aliasing -Wall \ + -Wstrict-prototypes -Wmissing-prototypes -Wmissing-declarations -Wredundant-decls \ + ${INCLUDE} -Iinclude -Iwin32 -I.libs -DHAVE_CONFIG_H + +MEMCACHED_SRC = cache.c config_parser.c globals.c hash.c isasl.c memcached.c \ + sasl_defs.c stats.c stdin_check.c thread.c util.c \ + win32/defs.c win32/dlfcn.c win32/win32.c + +MEMCACHED_OBJS = ${MEMCACHED_SRC:%.c=.libs/%.o} + +DEFAULT_ENGINE_SRC = assoc.c default_engine.c items.c slabs.c util.c +DEFAULT_ENGINE_OBJS = ${DEFAULT_ENGINE_SRC:%.c=.libs/%.o} + +GENFILES=.libs/config_version.h + +memcached.exe: ${OBJDIR} ${GENFILES} $(MEMCACHED_OBJS) + ${LINK.c} -o memcached.exe $(MEMCACHED_OBJS) \ + ${LIB} -levent -lmswsock \ + -lws2_32 -lpthread + +.libs/default_engine.so: ${OBJDIR} $(DEFAULT_ENGINE_OBJS) + ${LINK.c} -o $@ -shared ${DEFAULT_ENGINE_OBJS} \ + ${LIB} -lpthread + +.libs/config_version.h: + ./win32/config.sh + +.libs .libs/win32:; -@mkdir $@ + +.libs/%.o: %.c + ${COMPILE.c} -MMD $< -o $@ + +clean: + $(RM) ${MEMCACHED_OBJS} ${DEFAULT_ENGINE_OBJS} \ + ${BINARIES} ${MEMCACHED_OBJS:.o=.d} ${DEFAULT_ENGINE_OBJS:.o=.d} \ + ${GENFILES} + +-include ${MEMCACHED_OBJS:.o=.d} ${DEFAULT_ENGINE_OBJS:.o=.d} diff --git a/win32/config.h b/win32/config.h new file mode 100644 index 0000000..cff6914 --- /dev/null +++ b/win32/config.h @@ -0,0 +1,92 @@ +#ifndef _CONFIG_H +#define _CONFIG_H + +/* Name of package */ +#define PACKAGE "memcached" + +/* Define to the address where bug reports for this package should be sent. */ +#define PACKAGE_BUGREPORT "memcached@googlegroups.com" + +/* Define to the full name of this package. */ +#define PACKAGE_NAME "memcached" + +/* Define to the full name and version of this package. */ +#define PACKAGE_DESCRIPTION "memcached is a high-performance, distributed memory object caching system, generic in nature, but intended for use in speeding up dynamic web applications by alleviating database load." + +/* Define to the one symbol short name of this package. */ +#define PACKAGE_TARNAME "memcached" + +#include "config_version.h" + +/* Define to 1 if you have the ANSI C header files. */ +#define STDC_HEADERS 1 + +/* machine is littleendian */ +#define ENDIAN_LITTLE 1 + +#define ENABLE_ISASL 1 + +#define HAVE_DLFCN_H 1 + +/* Define to empty if `const' does not conform to ANSI C. */ +/* #undef const */ + +/* define to int if socklen_t not available */ +/* #undef socklen_t */ +/* Windows-specific includes */ +#include <sys/types.h> +#include <sys/stat.h> +#include "win32.h" +#include <winsock2.h> +#include <ws2tcpip.h> +#include <process.h> +/* PRIu64 */ +#include <inttypes.h> +#include <stdbool.h> +#include <stdint.h> + +/*******************************/ +/* HACKS to compile under UNIX */ + +#define S_ISSOCK(mode) 0 +#define RLIMIT_CORE 4 +#define RLIM_INFINITY ((unsigned long int) (-0UL)) +#define RLIMIT_NOFILE 7 + +/* Create expected type and struct definitions */ + +typedef short int _uid_t; + +struct passwd { + char * pw_name; + char * pw_passwd; + _uid_t pw_uid; + _uid_t pw_gid; + char * pw_gecos; + char * pw_dir; + char * pw_shell; +}; + +struct sockaddr_un { + unsigned short int sun_family; + char sun_path[108]; +}; + +struct rlimit { + unsigned long int rlim_cur, rlim_max; +}; + +/* Function prototypes expected by UNIX code + * - function definitions in dummy_defs.c + */ + +int lstat(const char *path, struct stat *tstat); +int sigignore(int sig); +int getrlimit(int __resource, struct rlimit * __rlimits); +int setrlimit(int __resource, struct rlimit * __rlimits); +_uid_t getuid(void); +_uid_t geteuid(void); +struct passwd *getpwnam(const char *name); +int setuid(_uid_t uid); +int setgid(_uid_t gid); +#endif // _CONFIG_H diff --git a/win32/config.sh b/win32/config.sh new file mode 100644 index 0000000..acd0ab3 --- /dev/null +++ b/win32/config.sh @@ -0,0 +1,17 @@ +#! /bin/sh +MEMC_VERSION=`git describe | tr '-' '_'`; +cat > .libs/config_version.h << EOF +#ifndef CONFIG_VERSION_H +#define CONFIG_VERSION_H + +/* Define to the full name and version of this package. */ +#define PACKAGE_STRING "memcached $MEMC_VERSION" + +/* Define to the version of this package. */ +#define PACKAGE_VERSION "$MEMC_VERSION" + +/* Version number of package */ +#define VERSION "$MEMC_VERSION" + +#endif // CONFIG_VERSION_H +EOF diff --git a/win32/defs.c b/win32/defs.c new file mode 100644 index 0000000..279a8ef --- /dev/null +++ b/win32/defs.c @@ -0,0 +1,51 @@ +/* dummy_defs.c + * + * Create blank UNIX function definitions to allow win32 builds. */ + +#include <config.h> + +int lstat(const char *path, struct stat *tstat) { + return -1; +} + +int getrlimit(int __resource, struct rlimit *__rlimits) { + /* HACK ALERT: This function MUST BE called from main() before any * + * network operation for Windows networking to work. Since the * + * main() is calling getrlimit() that is NOT meaningful for * + * Windows, this function is being used to invoke WSAStartup() * + * below only once during the the first call to getrlimit() * + */ + static int onceonly = 0; + WSADATA wsaData; + if (!onceonly) { + onceonly = 1; + if (WSAStartup(MAKEWORD(2,0), &wsaData) != 0) { + fprintf(stderr, "Socket Initialization Error. Program aborted\n"); + exit(EXIT_FAILURE); + } + } + return 0; +} + +int setrlimit(int __resource, struct rlimit *__rlimits) { + return 0; +} + +_uid_t getuid(void) { + return -1; +} +_uid_t geteuid(void) { + return -1; +} + +struct passwd *getpwnam(const char *name) { + return 0; +} + +int setuid(_uid_t uid) { + return -1; +} + +int setgid(_uid_t gid) { + return -1; +} diff --git a/win32/dlfcn.c b/win32/dlfcn.c new file mode 100644 index 0000000..f5ff594 --- /dev/null +++ b/win32/dlfcn.c @@ -0,0 +1,62 @@ +/* -*- Mode: C; tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +#include <stdio.h> +#include <windows.h> +#include <dlfcn.h> +#include <stdbool.h> + +/* + * Keep track if the user tried to call dlopen(NULL, xx) to be able to give a sane + * error message + */ +static bool self = false; + +void* dlopen(const char* path, int mode) { + if (path == NULL) { + // We don't support opening ourself + self = true; + return NULL; + } + + void* handle = LoadLibrary(path); + if (handle == NULL) { + char *buf = malloc(strlen(path) + 20); + sprintf(buf, "%s.dll", path); + handle = LoadLibrary(buf); + free(buf); + } + + return handle; +} + +void* dlsym(void* handle, const char* symbol) { + return GetProcAddress(handle, symbol); +} + +int dlclose(void* handle) { + // dlclose returns zero on success. + // FreeLibrary returns nonzero on success. + return FreeLibrary(handle) != 0; +} + +static char dlerror_buf[200]; + +const char *dlerror(void) { + if (self) { + return "not supported"; + } + + DWORD err = GetLastError(); + LPVOID error_msg; + if (FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | + FORMAT_MESSAGE_FROM_SYSTEM | + FORMAT_MESSAGE_IGNORE_INSERTS, + NULL, err, 0, (LPTSTR)&error_msg, 0, NULL) != 0) { + strncpy(dlerror_buf, error_msg, sizeof(dlerror_buf)); + dlerror_buf[sizeof(dlerror_buf) - 1] = '\0'; + LocalFree(error_msg); + } else { + return "Failed to get error message"; + } + + return dlerror_buf; +} diff --git a/win32/dlfcn.h b/win32/dlfcn.h new file mode 100644 index 0000000..850d622 --- /dev/null +++ b/win32/dlfcn.h @@ -0,0 +1,12 @@ +#ifndef DLFCN_H +#define DLFCN_H +void* dlopen(const char* path, int mode); +void* dlsym(void* handle, const char* symbol); +int dlclose(void* handle); +const char *dlerror(void); + +#define RTLD_LAZY 1 +#define RTLD_LOCAL 2 + +#define RTLD_NOW 0x00002 +#endif diff --git a/win32/sysexits.h b/win32/sysexits.h new file mode 100644 index 0000000..ccc247b --- /dev/null +++ b/win32/sysexits.h @@ -0,0 +1,114 @@ +/* + * Copyright (c) 1987, 1993 + * The Regents of the University of California. All rights reserved. + * + * 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. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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. + * + * @(#)sysexits.h 8.1 (Berkeley) 6/2/93 + */ + +#ifndef _SYSEXITS_H +#define _SYSEXITS_H 1 + +/* + * SYSEXITS.H -- Exit status codes for system programs. + * + * This include file attempts to categorize possible error + * exit statuses for system programs, notably delivermail + * and the Berkeley network. + * + * Error numbers begin at EX__BASE to reduce the possibility of + * clashing with other exit statuses that random programs may + * already return. The meaning of the codes is approximately + * as follows: + * + * EX_USAGE -- The command was used incorrectly, e.g., with + * the wrong number of arguments, a bad flag, a bad + * syntax in a parameter, or whatever. + * EX_DATAERR -- The input data was incorrect in some way. + * This should only be used for user's data & not + * system files. + * EX_NOINPUT -- An input file (not a system file) did not + * exist or was not readable. This could also include + * errors like "No message" to a mailer (if it cared + * to catch it). + * EX_NOUSER -- The user specified did not exist. This might + * be used for mail addresses or remote logins. + * EX_NOHOST -- The host specified did not exist. This is used + * in mail addresses or network requests. + * EX_UNAVAILABLE -- A service is unavailable. This can occur + * if a support program or file does not exist. This + * can also be used as a catchall message when something + * you wanted to do doesn't work, but you don't know + * why. + * EX_SOFTWARE -- An internal software error has been detected. + * This should be limited to non-operating system related + * errors as possible. + * EX_OSERR -- An operating system error has been detected. + * This is intended to be used for such things as "cannot + * fork", "cannot create pipe", or the like. It includes + * things like getuid returning a user that does not + * exist in the passwd file. + * EX_OSFILE -- Some system file (e.g., /etc/passwd, /etc/utmp, + * etc.) does not exist, cannot be opened, or has some + * sort of error (e.g., syntax error). + * EX_CANTCREAT -- A (user specified) output file cannot be + * created. + * EX_IOERR -- An error occurred while doing I/O on some file. + * EX_TEMPFAIL -- temporary failure, indicating something that + * is not really an error. In sendmail, this means + * that a mailer (e.g.) could not create a connection, + * and the request should be reattempted later. + * EX_PROTOCOL -- the remote system returned something that + * was "not possible" during a protocol exchange. + * EX_NOPERM -- You did not have sufficient permission to + * perform the operation. This is not intended for + * file system problems, which should use NOINPUT or + * CANTCREAT, but rather for higher level permissions. + */ + +#define EX_OK 0 /* successful termination */ + +#define EX__BASE 64 /* base value for error messages */ + +#define EX_USAGE 64 /* command line usage error */ +#define EX_DATAERR 65 /* data format error */ +#define EX_NOINPUT 66 /* cannot open input */ +#define EX_NOUSER 67 /* addressee unknown */ +#define EX_NOHOST 68 /* host name unknown */ +#define EX_UNAVAILABLE 69 /* service unavailable */ +#define EX_SOFTWARE 70 /* internal software error */ +#define EX_OSERR 71 /* system error (e.g., can't fork) */ +#define EX_OSFILE 72 /* critical OS file missing */ +#define EX_CANTCREAT 73 /* can't create (user) output file */ +#define EX_IOERR 74 /* input/output error */ +#define EX_TEMPFAIL 75 /* temp failure; user is invited to retry */ +#define EX_PROTOCOL 76 /* remote error in protocol */ +#define EX_NOPERM 77 /* permission denied */ +#define EX_CONFIG 78 /* configuration error */ + +#define EX__MAX 78 /* maximum listed value */ + +#endif /* sysexits.h */ diff --git a/win32/win32.c b/win32/win32.c new file mode 100644 index 0000000..7c0e174 --- /dev/null +++ b/win32/win32.c @@ -0,0 +1,395 @@ +/* Copyright (c) 1983, 1990, 1993 + * The Regents of the University of California. All rights reserved. + * + * 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. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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. + * + * Portions Copyright (c) 1993 by Digital Equipment Corporation. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies, and that + * the name of Digital Equipment Corporation not be used in advertising or + * publicity pertaining to distribution of the document or software without + * specific, written prior permission. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT + * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + * + */ + +#include "win32.h" +#include <limits.h> +#include <ctype.h> +#include <time.h> + +int fcntl(SOCKET s, int cmd, int val) +{ + u_long imode = 1; + switch(cmd) { + case F_SETFL: + switch(val) { + case O_NONBLOCK: + imode = 1; + if(ioctlsocket(s, FIONBIO, &imode) == SOCKET_ERROR) + return -1; + break; + case O_BLOCK: + imode = 0; + if(ioctlsocket(s, FIONBIO, &imode) == SOCKET_ERROR) + return -1; + break; + default: + return -1; + } + case F_GETFL: + return 0; + default: + return -1; + } +} + +/* + * Check whether "cp" is a valid ascii representation + * of an Internet address and convert to a binary address. + * Returns 1 if the address is valid, 0 if not. + * This replaces inet_addr, the return value from which + * cannot distinguish between failure and a local broadcast address. + */ +int inet_aton(register const char *cp, struct in_addr *addr) +{ + register uint32_t val; + register int base, n; + register char c; + u_int parts[4]; + register u_int *pp = parts; + + c = *cp; + for (;;) { + /* + * Collect number up to ``.''. + * Values are specified as for C: + * 0x=hex, 0=octal, isdigit=decimal. + */ + if (!isdigit(c)) + return (0); + val = 0; base = 10; + if (c == '0') { + c = *++cp; + if (c == 'x' || c == 'X') + base = 16, c = *++cp; + else + base = 8; + } + for (;;) { + if (isascii(c) && isdigit(c)) { + val = (val * base) + (c - '0'); + c = *++cp; + } else if (base == 16 && isascii(c) && isxdigit(c)) { + val = (val << 4) | + (c + 10 - (islower(c) ? 'a' : 'A')); + c = *++cp; + } else + break; + } + if (c == '.') { + /* + * Internet format: + * a.b.c.d + * a.b.c (with c treated as 16 bits) + * a.b (with b treated as 24 bits) + */ + if (pp >= parts + 3) + return (0); + *pp++ = val; + c = *++cp; + } else + break; + } + /* + * Check for trailing characters. + */ + if (c != '\0' && (!isascii(c) || !isspace(c))) + return (0); + /* + * Concoct the address according to + * the number of parts specified. + */ + n = pp - parts + 1; + switch (n) { + + case 0: + return (0); /* initial nondigit */ + + case 1: /* a -- 32 bits */ + break; + + case 2: /* a.b -- 8.24 bits */ + if (val > 0xffffff) + return (0); + val |= parts[0] << 24; + break; + + case 3: /* a.b.c -- 8.8.16 bits */ + if (val > 0xffff) + return (0); + val |= (parts[0] << 24) | (parts[1] << 16); + break; + + case 4: /* a.b.c.d -- 8.8.8.8 bits */ + if (val > 0xff) + return (0); + val |= (parts[0] << 24) | (parts[1] << 16) | (parts[2] << 8); + break; + } + if (addr) + addr->s_addr = htonl(val); + return (1); +} + +int createLocalListSock(struct sockaddr_in *serv_addr) { + SOCKET sockfd; + int slen; + + if ((sockfd = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP)) == INVALID_SOCKET) { + fprintf(stderr,"socket call for local server socket failed. Error Number %d.\n",WSAGetLastError()); + fflush(stderr); + return(-1); + } + serv_addr->sin_family = AF_INET; + serv_addr->sin_addr.s_addr = inet_addr("127.0.0.1"); + serv_addr->sin_port = htons(0); + if (bind(sockfd,(struct sockaddr *)serv_addr,sizeof(*serv_addr)) != 0) { + fprintf(stderr,"bind of local server socket failed. Error Number %d.\n",WSAGetLastError()); + fflush(stderr); + return(-1); + } + slen = sizeof(*serv_addr); + if (getsockname(sockfd,(struct sockaddr *)serv_addr,&slen) != 0) { + fprintf(stderr,"getsockname on local server socket failed. Error Number %d.\n",WSAGetLastError()); + fflush(stderr); + return(-1); + } + if (listen(sockfd,5) == SOCKET_ERROR) { + fprintf(stderr,"listen on local server socket failed. Error Number %d.\n",WSAGetLastError()); + fflush(stderr); + return(-1); + } + return((int)sockfd); +} + +int createLocalSocketPair(int listSock, int *fds, struct sockaddr_in *serv_addr) { + struct sockaddr_in cli_addr; + fd_set myset; + struct timeval tv; + socklen_t lon; + int valopt, tmpVal; + + if ((fds[0] = (int)socket(AF_INET,SOCK_STREAM,IPPROTO_TCP)) == INVALID_SOCKET) { + fprintf(stderr,"socket call for local client socket failed. Error Number %d.\n",WSAGetLastError()); + fflush(stderr); + return(-1); + } + if (fcntl(fds[0],F_SETFL,O_NONBLOCK) < 0) { + fprintf(stderr,"fcntl call for local server socket failed. Error Number %d.\n",WSAGetLastError()); + fflush(stderr); + return(-1); + } + if (connect(fds[0],(struct sockaddr *)serv_addr,sizeof(*serv_addr)) == SOCKET_ERROR) { + tmpVal = WSAGetLastError(); + if (tmpVal != WSAEWOULDBLOCK) { + fprintf(stderr,"connect call for local server socket failed. Error Number %d.\n",tmpVal); + fflush(stderr); + return(-1); + } + } + else { + fprintf(stderr,"connect call for non-blocking local client socket unexpectedly succeeds.\n"); + fflush(stderr); + return(-1); + } + Sleep(10); + tmpVal = sizeof(cli_addr); + if ((fds[1] = (int)accept(listSock, (struct sockaddr *)&cli_addr, &tmpVal))== INVALID_SOCKET) { + fprintf(stderr,"accept call for local server socket failed. Error Number %d.\n",WSAGetLastError()); + fflush(stderr); + return(-1); + } + if (fcntl(fds[1],F_SETFL,O_NONBLOCK) < 0) { + fprintf(stderr,"fcntl call for local server socket failed. Error Number %d.\n",WSAGetLastError()); + fflush(stderr); + return(-1); + } + tv.tv_sec = 15; + tv.tv_usec = 0; + FD_ZERO(&myset); + FD_SET(fds[0], &myset); + tmpVal = select(fds[0] + 1, NULL, &myset, NULL, &tv); + if (tmpVal == SOCKET_ERROR) { + fprintf(stderr,"socket call for local server socket failed. Error Number %d.\n",WSAGetLastError()); + fflush(stderr); + return(-1); + } + else if (tmpVal > 0) { + lon = sizeof(int); + if (!getsockopt(fds[0], SOL_SOCKET, SO_ERROR, (void*)(&valopt), &lon)) { + if (valopt) { + fprintf(stderr,"getsockopt indicates error on connect completion.\n"); + return(-1); + } + } + else { + fprintf(stderr,"getsockopt call for local client socket failed. Error Number %d.\n",WSAGetLastError()); + fflush(stderr); + return(-1); + } + } + else if (!tmpVal) { + fprintf(stderr,"select on connect complete timed out.\n"); + fflush(stderr); + return(-1); + } + return(0); +} + +unsigned __int64 strtoull(const char *p,char **pend,int base) { + unsigned __int64 number = 0; + int c; + int error; + + while (('\b' == *p) || ('\t' == *p)) // skip leading white space + p++; + if (*p == '+') + p++; + switch (base) { + case 0: + base = 10; // assume decimal base + if (*p == '0') { + base = 8; // could be octal + p++; + switch (*p) { + case 'x': + case 'X': + base = 16; // hex + p++; + break; +#if BINARY + case 'b': + case 'B': + base = 2; // binary + p++; + break; +#endif + } + } + break; + case 16: // skip over '0x' and '0X' + if (*p == '0' && (p[1] == 'x' || p[1] == 'X')) + p += 2; + break; +#if BINARY + case 2: // skip over '0b' and '0B' + if (*p == '0' && (p[1] == 'b' || p[1] == 'B')) + p += 2; + break; +#endif + } + error = 0; + while (1) { + c = *p; + if ('0' <= c && c <= '9') + c -= '0'; + else if ('a' <= c && c <= 'z') + c -= 'a' - 10; + else if ('A' <= c && c <= 'Z') + c -= 'A' - 10; + else // unrecognized character + break; + if (c >= base) // not in number base + break; + if ((ULLONG_MAX - c) / base < number) + error = 1; + number = number * base + c; + p++; + } + if (pend) + *pend = (char *)p; + if (error) { + number = ULLONG_MAX; + errno = ERANGE; + } + return number; +} + +int getrusage(int who, struct rusage * rusage) { + FILETIME starttime; + FILETIME exittime; + FILETIME kerneltime; + FILETIME usertime; + ULARGE_INTEGER li; + + if (rusage == (struct rusage *)NULL) { + errno = EFAULT; + return -1; + } + memset(rusage, 0, sizeof(struct rusage)); + if (GetProcessTimes(GetCurrentProcess(), + &starttime, &exittime, &kerneltime, + &usertime) == 0) { + /* Where is dosmaperr declared. Will address later. */ + /* _dosmaperr(GetLastError()); */ + return -1; + } + /* Convert FILETIMEs (0.1 us) to struct timeval */ + memcpy(&li, &kerneltime, sizeof(FILETIME)); + li.QuadPart /= 10L; /* Convert to microseconds */ + rusage->ru_stime.tv_sec = (long)(li.QuadPart / 1000000L); + rusage->ru_stime.tv_usec = li.QuadPart % 1000000L; + memcpy(&li, &usertime, sizeof(FILETIME)); + li.QuadPart /= 10L; /* Convert to microseconds */ + rusage->ru_utime.tv_sec = (long)(li.QuadPart / 1000000L); + rusage->ru_utime.tv_usec = li.QuadPart % 1000000L; + return(0); +} + +int sleep(int seconds) { + Sleep(seconds*1000); + return 0; +} + +int kill(int pid, int sig) { + if (TerminateProcess((HANDLE)pid, 0)) + return 0; + return -1; +} diff --git a/win32/win32.h b/win32/win32.h new file mode 100644 index 0000000..c69a7c5 --- /dev/null +++ b/win32/win32.h @@ -0,0 +1,205 @@ +/* win32.h + * + */ + +#ifndef WIN32_H +#define WIN32_H + +#undef _WIN32_WINNT +#define _WIN32_WINNT 0x0501 /* Needed to resolve getaddrinfo et al. */ + +#include <winsock2.h> +#include <ws2tcpip.h> + +#include <stdio.h> +#include <io.h> +#include <time.h> +#include <fcntl.h> +#include <errno.h> +#include <stdint.h> +#include <process.h> + +#define EWOULDBLOCK EAGAIN +#define EAFNOSUPPORT 47 +#define EADDRINUSE WSAEADDRINUSE +#define EAI_SYSTEM -11 + +typedef char *caddr_t; + +#define O_BLOCK 0 +#define O_NONBLOCK 1 +#define F_GETFL 3 +#define F_SETFL 4 + +#define RUSAGE_SELF 0 + +#define IOV_MAX 1024 +struct iovec { + u_long iov_len; + char FAR* iov_base; +}; + +struct msghdr { + void *msg_name; /* Socket name */ + int msg_namelen; /* Length of name */ + struct iovec *msg_iov; /* Data blocks */ + int msg_iovlen; /* Number of blocks */ + void *msg_accrights; /* Per protocol magic (eg BSD file descriptor passing) */ + int msg_accrightslen; /* Length of rights list */ +}; + +#if defined(_MSC_VER) || defined(_MSC_EXTENSIONS) + #define DELTA_EPOCH_IN_MICROSECS 11644473600000000Ui64 +#else + #define DELTA_EPOCH_IN_MICROSECS 11644473600000000ULL +#endif + +/* Structure which says how much of each resource has been used. */ +struct rusage { + /* Total amount of user time used. */ + struct timeval ru_utime; + /* Total amount of system time used. */ + struct timeval ru_stime; + /* Maximum resident set size (in kilobytes). */ + long int ru_maxrss; + /* Amount of sharing of text segment memory + with other processes (kilobyte-seconds). */ + long int ru_ixrss; + /* Amount of data segment memory used (kilobyte-seconds). */ + long int ru_idrss; + /* Amount of stack memory used (kilobyte-seconds). */ + long int ru_isrss; + /* Number of soft page faults (i.e. those serviced by reclaiming + a page from the list of pages awaiting reallocation. */ + long int ru_minflt; + /* Number of hard page faults (i.e. those that required I/O). */ + long int ru_majflt; + /* Number of times a process was swapped out of physical memory. */ + long int ru_nswap; + /* Number of input operations via the file system. Note: This + and `ru_oublock' do not include operations with the cache. */ + long int ru_inblock; + /* Number of output operations via the file system. */ + long int ru_oublock; + /* Number of IPC messages sent. */ + long int ru_msgsnd; + /* Number of IPC messages received. */ + long int ru_msgrcv; + /* Number of signals delivered. */ + long int ru_nsignals; + /* Number of voluntary context switches, i.e. because the process + gave up the process before it had to (usually to wait for some + resource to be available). */ + long int ru_nvcsw; + /* Number of involuntary context switches, i.e. a higher priority process + became runnable or the current process used up its time slice. */ + long int ru_nivcsw; +}; + +int fcntl(SOCKET s, int cmd, int val); +int inet_aton(register const char *cp, struct in_addr *addr); + +#define close(s) closesocket(s) + +static inline void mapErr(int error) { + switch(error) { + default: + break; + case WSAEPFNOSUPPORT: + errno = EAFNOSUPPORT; + break; + case WSA_IO_PENDING: + case WSATRY_AGAIN: + errno = EAGAIN; + break; + case WSAEWOULDBLOCK: + errno = EWOULDBLOCK; + break; + case WSAEMSGSIZE: + errno = E2BIG; + break; + case WSAECONNRESET: + errno = 0; + break; + } +} + +#define write mem_write + +static inline size_t mem_write(int s, void *buf, size_t len) +{ + DWORD dwBufferCount = 0; + int error; + + WSABUF wsabuf = { len, (char *)buf} ; + if(WSASend(s, &wsabuf, 1, &dwBufferCount, 0, NULL, NULL) == 0) { + return dwBufferCount; + } + error = WSAGetLastError(); + if(error == WSAECONNRESET) return 0; + mapErr(error); + return -1; +} + +#define read mem_read + +static inline size_t mem_read(int s, void *buf, size_t len) +{ + DWORD flags = 0; + DWORD dwBufferCount; + WSABUF wsabuf = { len, (char *)buf }; + int error; + + if(WSARecv((SOCKET)s, + &wsabuf, + 1, + &dwBufferCount, + &flags, + NULL, + NULL + ) == 0) { + return dwBufferCount; + } + error = WSAGetLastError(); + if (error == WSAECONNRESET) return 0; + mapErr(error); + return -1; +} + +static inline int sendmsg(int s, const struct msghdr *msg, int flags) +{ + DWORD dwBufferCount; + int error; + + if(WSASendTo((SOCKET) s, + (LPWSABUF)msg->msg_iov, + (DWORD)msg->msg_iovlen, + &dwBufferCount, + flags, + msg->msg_name, + msg->msg_namelen, + NULL, + NULL + ) == 0) { + return dwBufferCount; + } + error = WSAGetLastError(); + if (error == WSAECONNRESET) return 0; + mapErr(error); + return -1; +} + +int createLocalListSock(struct sockaddr_in *saddr); +int createLocalSocketPair(int listSock, int *fds, struct sockaddr_in *saddr); +int getrusage(int who, struct rusage *usage); +int kill(int pid, int sig); +int sleep(int seconds); + +#ifndef _WIN64 +static inline void _set_errno(int err) +{ + errno = err; +} +#endif + +#endif |