diff -ruN memcached2/assoc.c memcached3/assoc.c --- memcached2/assoc.c 2006-11-24 09:14:37.203125000 -0600 +++ memcached3/assoc.c 2006-11-24 09:40:36.625000000 -0600 @@ -14,6 +14,7 @@ */ #include #include +#ifndef WIN32 #include "config.h" #include #include @@ -23,6 +24,10 @@ #include #include #include +#else +#include "Win32-Code/config.h" +#include +#endif #include #include #include diff -ruN memcached2/compat/bsd_getopt.c memcached3/compat/bsd_getopt.c --- memcached2/compat/bsd_getopt.c 1969-12-31 18:00:00.000000000 -0600 +++ memcached3/compat/bsd_getopt.c 2006-03-31 08:59:10.000000000 -0600 @@ -0,0 +1,441 @@ +/*- + * Copyright (c) 2000 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Dieter Baron and Thomas Klausner. + * + * 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 NetBSD + * Foundation, Inc. and its contributors. + * 4. Neither the name of The NetBSD Foundation 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 NETBSD FOUNDATION, INC. 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 FOUNDATION 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. + */ + +#include "bsd_getopt.h" +#include +#include +#include + +#if !defined(HAVE_GETOPT_LONG) +int opterr = 1; /* if error message should be printed */ +int optind = 1; /* index into parent argv vector */ +int optopt = '?'; /* character checked for validity */ +int optreset; /* reset getopt */ +char *optarg; /* argument associated with option */ + +#define IGNORE_FIRST (*options == '-' || *options == '+') +#define PRINT_ERROR ((opterr) && ((*options != ':') \ + || (IGNORE_FIRST && options[1] != ':'))) +#define IS_POSIXLY_CORRECT (getenv("POSIXLY_CORRECT") != NULL) +#define PERMUTE (!IS_POSIXLY_CORRECT && !IGNORE_FIRST) +/* XXX: GNU ignores PC if *options == '-' */ +#define IN_ORDER (!IS_POSIXLY_CORRECT && *options == '-') + +/* return values */ +#define BADCH (int)'?' +#define BADARG ((IGNORE_FIRST && options[1] == ':') \ + || (*options == ':') ? (int)':' : (int)'?') +#define INORDER (int)1 + +#define EMSG "" + +static int getopt_internal(int, char * const *, const char *); +static int gcd(int, int); +static void permute_args(int, int, int, char * const *); + +static char *place = EMSG; /* option letter processing */ + +/* XXX: set optreset to 1 rather than these two */ +static int nonopt_start = -1; /* first non option argument (for permute) */ +static int nonopt_end = -1; /* first option after non options (for permute) */ + +/* Error messages */ +static const char recargchar[] = "option requires an argument -- %c"; +static const char recargstring[] = "option requires an argument -- %s"; +static const char ambig[] = "ambiguous option -- %.*s"; +static const char noarg[] = "option doesn't take an argument -- %.*s"; +static const char illoptchar[] = "unknown option -- %c"; +static const char illoptstring[] = "unknown option -- %s"; + + +/* + * Compute the greatest common divisor of a and b. + */ +static int +gcd(int a, int b) +{ + int c; + + c = a % b; + while (c != 0) { + a = b; + b = c; + c = a % b; + } + + return b; +} + +/* + * Exchange the block from nonopt_start to nonopt_end with the block + * from nonopt_end to opt_end (keeping the same order of arguments + * in each block). + */ +static void +permute_args(int panonopt_start, + int panonopt_end, + int opt_end, + char * const *nargv) +{ + int cstart, cyclelen, i, j, ncycle, nnonopts, nopts, pos; + char *swap; + + /* + * compute lengths of blocks and number and size of cycles + */ + nnonopts = panonopt_end - panonopt_start; + nopts = opt_end - panonopt_end; + ncycle = gcd(nnonopts, nopts); + cyclelen = (opt_end - panonopt_start) / ncycle; + + for (i = 0; i < ncycle; i++) { + cstart = panonopt_end+i; + pos = cstart; + for (j = 0; j < cyclelen; j++) { + if (pos >= panonopt_end) + pos -= nnonopts; + else + pos += nopts; + swap = nargv[pos]; + /* LINTED const cast */ + ((char **) nargv)[pos] = nargv[cstart]; + /* LINTED const cast */ + ((char **)nargv)[cstart] = swap; + } + } +} + +/* + * getopt_internal -- + * Parse argc/argv argument vector. Called by user level routines. + * Returns -2 if -- is found (can be long option or end of options marker). + */ +static int +getopt_internal(int nargc, + char * const *nargv, + const char *options) +{ + char *oli; /* option letter list index */ + int optchar; + + optarg = NULL; + + /* + * XXX Some programs (like rsyncd) expect to be able to + * XXX re-initialize optind to 0 and have getopt_long(3) + * XXX properly function again. Work around this braindamage. + */ + if (optind == 0) + optind = 1; + + if (optreset) + nonopt_start = nonopt_end = -1; +start: + if (optreset || !*place) { /* update scanning pointer */ + optreset = 0; + if (optind >= nargc) { /* end of argument vector */ + place = EMSG; + if (nonopt_end != -1) { + /* do permutation, if we have to */ + permute_args(nonopt_start, nonopt_end, + optind, nargv); + optind -= nonopt_end - nonopt_start; + } + else if (nonopt_start != -1) { + /* + * If we skipped non-options, set optind + * to the first of them. + */ + optind = nonopt_start; + } + nonopt_start = nonopt_end = -1; + return -1; + } + if ((*(place = nargv[optind]) != '-') + || (place[1] == '\0')) { /* found non-option */ + place = EMSG; + if (IN_ORDER) { + /* + * GNU extension: + * return non-option as argument to option 1 + */ + optarg = nargv[optind++]; + return INORDER; + } + if (!PERMUTE) { + /* + * if no permutation wanted, stop parsing + * at first non-option + */ + return -1; + } + /* do permutation */ + if (nonopt_start == -1) + nonopt_start = optind; + else if (nonopt_end != -1) { + permute_args(nonopt_start, nonopt_end, + optind, nargv); + nonopt_start = optind - + (nonopt_end - nonopt_start); + nonopt_end = -1; + } + optind++; + /* process next argument */ + goto start; + } + if (nonopt_start != -1 && nonopt_end == -1) + nonopt_end = optind; + if (place[1] && *++place == '-') { /* found "--" */ + place++; + return -2; + } + } + if ((optchar = (int)*place++) == (int)':' || + (oli = strchr(options + (IGNORE_FIRST ? 1 : 0), optchar)) == NULL) { + /* option letter unknown or ':' */ + if (!*place) + ++optind; + if (PRINT_ERROR) + fprintf(stderr, illoptchar, optchar); + optopt = optchar; + return BADCH; + } + if (optchar == 'W' && oli[1] == ';') { /* -W long-option */ + /* XXX: what if no long options provided (called by getopt)? */ + if (*place) + return -2; + + if (++optind >= nargc) { /* no arg */ + place = EMSG; + if (PRINT_ERROR) + fprintf(stderr, recargchar, optchar); + optopt = optchar; + return BADARG; + } else /* white space */ + place = nargv[optind]; + /* + * Handle -W arg the same as --arg (which causes getopt to + * stop parsing). + */ + return -2; + } + if (*++oli != ':') { /* doesn't take argument */ + if (!*place) + ++optind; + } else { /* takes (optional) argument */ + optarg = NULL; + if (*place) /* no white space */ + optarg = place; + /* XXX: disable test for :: if PC? (GNU doesn't) */ + else if (oli[1] != ':') { /* arg not optional */ + if (++optind >= nargc) { /* no arg */ + place = EMSG; + if (PRINT_ERROR) + fprintf(stderr, recargchar, optchar); + optopt = optchar; + return BADARG; + } else + optarg = nargv[optind]; + } + place = EMSG; + ++optind; + } + /* dump back option letter */ + return optchar; +} + +/* + * getopt -- + * Parse argc/argv argument vector. + * + * [eventually this will replace the real getopt] + */ +int +getopt(int nargc, char * const *nargv, const char *options) +{ + int retval; + + if ((retval = getopt_internal(nargc, nargv, options)) == -2) { + ++optind; + /* + * We found an option (--), so if we skipped non-options, + * we have to permute. + */ + if (nonopt_end != -1) { + permute_args(nonopt_start, nonopt_end, optind, + nargv); + optind -= nonopt_end - nonopt_start; + } + nonopt_start = nonopt_end = -1; + retval = -1; + } + return retval; +} + +/* + * getopt_long -- + * Parse argc/argv argument vector. + */ +int +getopt_long(int nargc, + char * const *nargv, + const char *options, + const struct option *long_options, + int *idx) +{ + int retval; + + /* idx may be NULL */ + + if ((retval = getopt_internal(nargc, nargv, options)) == -2) { + char *current_argv, *has_equal; + size_t current_argv_len; + int i, match; + + current_argv = place; + match = -1; + + optind++; + place = EMSG; + + if (*current_argv == '\0') { /* found "--" */ + /* + * We found an option (--), so if we skipped + * non-options, we have to permute. + */ + if (nonopt_end != -1) { + permute_args(nonopt_start, nonopt_end, + optind, nargv); + optind -= nonopt_end - nonopt_start; + } + nonopt_start = nonopt_end = -1; + return -1; + } + if ((has_equal = strchr(current_argv, '=')) != NULL) { + /* argument found (--option=arg) */ + current_argv_len = has_equal - current_argv; + has_equal++; + } else + current_argv_len = strlen(current_argv); + + for (i = 0; long_options[i].name; i++) { + /* find matching long option */ + if (strncmp(current_argv, long_options[i].name, + current_argv_len)) + continue; + + if (strlen(long_options[i].name) == + (unsigned)current_argv_len) { + /* exact match */ + match = i; + break; + } + if (match == -1) /* partial match */ + match = i; + else { + /* ambiguous abbreviation */ + if (PRINT_ERROR) + fprintf(stderr, ambig, (int)current_argv_len, + current_argv); + optopt = 0; + return BADCH; + } + } + if (match != -1) { /* option found */ + if (long_options[match].has_arg == no_argument + && has_equal) { + if (PRINT_ERROR) + fprintf(stderr, noarg, (int)current_argv_len, + current_argv); + /* + * XXX: GNU sets optopt to val regardless of + * flag + */ + if (long_options[match].flag == NULL) + optopt = long_options[match].val; + else + optopt = 0; + return BADARG; + } + if (long_options[match].has_arg == required_argument || + long_options[match].has_arg == optional_argument) { + if (has_equal) + optarg = has_equal; + else if (long_options[match].has_arg == + required_argument) { + /* + * optional argument doesn't use + * next nargv + */ + optarg = nargv[optind++]; + } + } + if ((long_options[match].has_arg == required_argument) + && (optarg == NULL)) { + /* + * Missing argument; leading ':' + * indicates no error should be generated + */ + if (PRINT_ERROR) + fprintf(stderr, recargstring, current_argv); + /* + * XXX: GNU sets optopt to val regardless + * of flag + */ + if (long_options[match].flag == NULL) + optopt = long_options[match].val; + else + optopt = 0; + --optind; + return BADARG; + } + } else { /* unknown option */ + if (PRINT_ERROR) + fprintf(stderr, illoptstring, current_argv); + optopt = 0; + return BADCH; + } + if (long_options[match].flag) { + *long_options[match].flag = long_options[match].val; + retval = 0; + } else + retval = long_options[match].val; + if (idx) + *idx = match; + } + return retval; +} +#endif /* !GETOPT_LONG || !GETOPT */ diff -ruN memcached2/compat/bsd_getopt.h memcached3/compat/bsd_getopt.h --- memcached2/compat/bsd_getopt.h 1969-12-31 18:00:00.000000000 -0600 +++ memcached3/compat/bsd_getopt.h 2006-03-31 08:59:32.000000000 -0600 @@ -0,0 +1,33 @@ +/* bsd_getopt.h + * + * Chris Collins + */ + +/** header created for NetBSD getopt/getopt_long */ + +#ifndef HAVE_GETOPT_LONG +#ifndef _BSD_GETOPT_H +#define _BSD_GETOPT_H + +extern int opterr; +extern int optind; +extern int optopt; +extern int optreset; +extern char *optarg; + +struct option { + char *name; + int has_arg; + int *flag; + int val; +}; + +#define no_argument 0 +#define required_argument 1 +#define optional_argument 2 + +extern int getopt(int nargc, char * const *nargv, const char *options); +extern int getopt_long(int nargc, char * const *nargv, const char *options, const struct option *long_options, int *idx); + +#endif /* _BSD_GETOPT_H */ +#endif diff -ruN memcached2/doc/Win32-build.txt memcached3/doc/Win32-build.txt --- memcached2/doc/Win32-build.txt 1969-12-31 18:00:00.000000000 -0600 +++ memcached3/doc/Win32-build.txt 2006-11-24 09:44:40.437500000 -0600 @@ -0,0 +1,19 @@ +Compilation using Visual Studio 8: + +1) build libevent-1.1b as a Static Library after fixing some issues: + To build libevent you need: + a) You'll have to create the project files, as the ones provided in the project won't work + b) in the file signal-test.c: + atound line 35, it says __func__, change to __FUNCTION__ + c) in the file time-test.c: + around line 17, just above #include add the line: + #include + around line 40, it says __func__, change to __FUNCTION__ + +2) build memcached using the built libevent.lib + a) open the Win32-Prj\memcached.sln in Visual Studio + b) make sure you have added the path to your libevent.lib file: + Tools -> Options -> Projects and Solutions -> VC++ Directories -> Library files + c) build the solution. + +Other platforms such as Cygwin or MinGW have not been tested. diff -ruN memcached2/items.c memcached3/items.c --- memcached2/items.c 2006-11-24 09:18:13.421875000 -0600 +++ memcached3/items.c 2006-11-24 09:40:42.859375000 -0600 @@ -2,6 +2,7 @@ /* $Id: items.c 436 2006-11-20 21:16:56Z sgrimm $ */ #include #include +#ifndef WIN32 #include #include #include @@ -10,6 +11,9 @@ #include #include #include +#else +#include +#endif #include #include #include diff -ruN memcached2/memcached.c memcached3/memcached.c --- memcached2/memcached.c 2006-11-24 09:33:14.937500000 -0600 +++ memcached3/memcached.c 2006-11-24 09:43:02.703125000 -0600 @@ -17,6 +17,7 @@ */ #include #include +#ifndef WIN32 #include "config.h" #include #include @@ -42,6 +43,13 @@ #include #include #include +#else +#include "Win32-Code/config.h" +#include +#include +#include "Win32-Code/ntservice.h" +#include "compat/bsd_getopt.h" +#endif #include #include #include @@ -647,16 +655,20 @@ pid_t pid = getpid(); char *pos = temp; +#ifndef WIN32 struct rusage usage; getrusage(RUSAGE_SELF, &usage); +#endif pos += sprintf(pos, "STAT pid %u\r\n", pid); pos += sprintf(pos, "STAT uptime %u\r\n", now); pos += sprintf(pos, "STAT time %ld\r\n", now + stats.started); pos += sprintf(pos, "STAT version " VERSION "\r\n"); pos += sprintf(pos, "STAT pointer_size %d\r\n", 8 * sizeof(void*)); +#ifndef WIN32 pos += sprintf(pos, "STAT rusage_user %ld.%06ld\r\n", usage.ru_utime.tv_sec, usage.ru_utime.tv_usec); pos += sprintf(pos, "STAT rusage_system %ld.%06ld\r\n", usage.ru_stime.tv_sec, usage.ru_stime.tv_usec); +#endif pos += sprintf(pos, "STAT curr_items %u\r\n", stats.curr_items); pos += sprintf(pos, "STAT total_items %u\r\n", stats.total_items); pos += sprintf(pos, "STAT bytes %llu\r\n", stats.curr_bytes); @@ -705,6 +717,7 @@ #endif /* HAVE_STRUCT_MALLINFO */ #endif /* HAVE_MALLOC_H */ +#ifndef WIN32 if (strcmp(command, "stats maps") == 0) { char *wbuf; int wsize = 8192; /* should be enough */ @@ -744,6 +757,7 @@ close(fd); return; } +#endif if (strncmp(command, "stats cachedump", 15) == 0) { char *buf; @@ -1756,6 +1770,7 @@ return sfd; } +#ifndef WIN32 int server_socket_unix(char *path) { int sfd; struct linger ling = {0, 0}; @@ -1803,15 +1818,17 @@ } return sfd; } - +#endif /* invoke right before gdb is called, on assert */ void pre_gdb () { +#ifndef WIN32 int i = 0; if(l_socket) close(l_socket); if(u_socket > -1) close(u_socket); for (i=3; i<=500; i++) close(i); /* so lame */ kill(getpid(), SIGABRT); +#endif } /* @@ -1891,7 +1908,15 @@ printf("-U UDP port number to listen on (default: 0, off)\n"); printf("-s unix socket path to listen on (disables network support)\n"); printf("-l interface to listen on, default is INDRR_ANY\n"); +#ifdef WIN32 + printf("-d start tell memcached to start\n"); + printf("-d restart tell running memcached to do a graceful restart\n"); + printf("-d stop|shutdown tell running memcached to shutdown\n"); + printf("-d install install memcached service\n"); + printf("-d uninstall uninstall memcached service\n"); +#else printf("-d run as a daemon\n"); +#endif printf("-r maximize core file limit\n"); printf("-u assume identity of (only when run as root)\n"); printf("-m max memory to use for items in megabytes, default is 64 MB\n"); @@ -1975,6 +2000,80 @@ "THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n" "(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF\n" "THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n" +#ifdef WIN32 + "This product includes software developed by the NetBSD\n" + "Foundation, Inc. and its contributors.\n" + "\n" + "[ bsd_getopts ]\n" + "\n" + "Copyright (c) 2000 The NetBSD Foundation, Inc.\n" + "All rights reserved.\n" + "\n" + "This code is derived from software contributed to The NetBSD Foundation\n" + "by Dieter Baron and Thomas Klausner.\n" + "\n" + "Redistribution and use in source and binary forms, with or without\n" + "modification, are permitted provided that the following conditions\n" + "are met:\n" + "1. Redistributions of source code must retain the above copyright\n" + " notice, this list of conditions and the following disclaimer.\n" + "2. Redistributions in binary form must reproduce the above copyright\n" + " notice, this list of conditions and the following disclaimer in the\n" + " documentation and/or other materials provided with the distribution.\n" + "3. All advertising materials mentioning features or use of this software\n" + " must display the following acknowledgement:\n" + " This product includes software developed by the NetBSD\n" + " Foundation, Inc. and its contributors.\n" + "4. Neither the name of The NetBSD Foundation nor the names of its\n" + " contributors may be used to endorse or promote products derived\n" + " from this software without specific prior written permission.\n" + "\n" + "THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS\n" + "``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED\n" + "TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\n" + "PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS\n" + "BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n" + "CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n" + "SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n" + "INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\n" + "CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n" + "ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n" + "POSSIBILITY OF SUCH DAMAGE.\n" + "\n" + "\n" + "Win32 port by Kronuz\n" + "This product includes software developed by Kronuz.\n" + "\n" + "[ ntservice ]\n" + "\n" + "Copyright (c) 2006 Germán Méndez Bravo (Kronuz) \n" + "All rights reserved.\n" + "\n" + "Redistribution and use in source and binary forms, with or without\n" + "modification, are permitted provided that the following conditions\n" + "are met:\n" + "1. Redistributions of source code must retain the above copyright\n" + " notice, this list of conditions and the following disclaimer.\n" + "2. Redistributions in binary form must reproduce the above copyright\n" + " notice, this list of conditions and the following disclaimer in the\n" + " documentation and/or other materials provided with the distribution.\n" + "3. All advertising materials mentioning features or use of this software\n" + " must display the following acknowledgement:\n" + " This product includes software developed by Kronuz.\n" + "4. The name of the author may not be used to endorse or promote products\n" + " derived from this software without specific prior written permission.\n" + "\n" + "THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR\n" + "IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES\n" + "OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.\n" + "IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,\n" + "INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT\n" + "NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n" + "DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n" + "THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n" + "(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF\n" + "THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n" +#endif ); return; @@ -2046,12 +2145,21 @@ int maxcore = 0; char *username = 0; char *pid_file = NULL; + +#ifndef WIN32 struct passwd *pw; struct sigaction sa; struct rlimit rlim; /* handle SIGINT */ signal(SIGINT, sig_handler); +#else + WSADATA wsaData; + if(WSAStartup(MAKEWORD(2,0), &wsaData) != 0) { + fprintf(stderr, "Socket Initialization Error. Program aborted\n"); + return; + } +#endif /* init settings */ settings_init(); @@ -2060,7 +2168,11 @@ setbuf(stderr, NULL); /* process arguments */ +#ifndef WIN32 while ((c = getopt(argc, argv, "bp:s:U:m:Mc:khirvdl:u:P:f:s:")) != -1) { +#else + while ((c = getopt(argc, argv, "bp:s:U:m:Mc:khirvd:l:u:P:f:s:")) != -1) { +#endif switch (c) { case 'U': settings.udpport = atoi(optarg); @@ -2105,6 +2217,16 @@ break; case 'd': daemonize = 1; +#ifdef WIN32 + if(!optarg || !strcmpi(optarg, "runservice")) daemonize = 1; + else if(!strcmpi(optarg, "start")) daemonize = 2; + else if(!strcmpi(optarg, "restart")) daemonize = 3; + else if(!strcmpi(optarg, "stop")) daemonize = 4; + else if(!strcmpi(optarg, "shutdown")) daemonize = 5; + else if(!strcmpi(optarg, "install")) daemonize = 6; + else if(!strcmpi(optarg, "uninstall")) daemonize = 7; + else fprintf(stderr, "Illegal argument: \"%s\"\n", optarg); +#endif break; case 'r': maxcore = 1; @@ -2135,6 +2257,7 @@ } } +#ifndef WIN32 if (maxcore) { struct rlimit rlim_new; /* @@ -2181,6 +2304,7 @@ exit(1); } } +#endif /* * initialization order: first create the listening sockets @@ -2207,6 +2331,7 @@ } } +#ifndef WIN32 /* lose root privileges if we have them */ if (getuid()== 0 || geteuid()==0) { if (username==0 || *username=='\0') { @@ -2231,7 +2356,9 @@ exit(1); } } +#endif +#ifndef WIN32 /* daemonize if requested */ /* if we want to ensure our ability to dump core, don't chdir to / */ if (daemonize) { @@ -2242,7 +2369,41 @@ return 1; } } - +#else + switch(daemonize) { + case 2: + if(!ServiceStart()) { + fprintf(stderr, "failed to start service\n"); + return 1; + } + exit(0); + case 3: + if(!ServiceRestart()) { + fprintf(stderr, "failed to restart service\n"); + return 1; + } + exit(0); + case 4: + case 5: + if(!ServiceStop()) { + fprintf(stderr, "failed to stop service\n"); + return 1; + } + exit(0); + case 6: + if(!ServiceInstall()) { + fprintf(stderr, "failed to install service or service already installed\n"); + return 1; + } + exit(0); + case 7: + if(!ServiceUninstall()) { + fprintf(stderr, "failed to uninstall service or service not installed\n"); + return 1; + } + exit(0); + } +#endif /* initialize other stuff */ item_init(); @@ -2271,6 +2432,7 @@ #endif } +#ifndef WIN32 /* * ignore SIGPIPE signals; we can use errno==EPIPE if we * need that information @@ -2282,6 +2444,7 @@ perror("failed to ignore SIGPIPE; sigaction"); exit(1); } +#endif /* create the initial listening connection */ if (!(l_conn = conn_new(l_socket, conn_listening, EV_READ | EV_PERSIST, 1, 0))) { fprintf(stderr, "failed to create listening connection"); @@ -2303,11 +2466,21 @@ if (daemonize) save_pid(getpid(),pid_file); +#ifdef WIN32 + if (daemonize) + ServiceRun(); + else +#endif runServer(); /* remove the PID file if we're a daemon */ if (daemonize) remove_pidfile(pid_file); + +#ifdef WIN32 + WSACleanup(); +#endif + return 0; } diff -ruN memcached2/memcached.h memcached3/memcached.h --- memcached2/memcached.h 2006-11-24 09:20:53.906250000 -0600 +++ memcached3/memcached.h 2006-11-24 09:43:08.546875000 -0600 @@ -1,5 +1,9 @@ /* -*- Mode: C; tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- */ /* $Id: memcached.h 436 2006-11-20 21:16:56Z sgrimm $ */ +#ifdef WIN32 +#include "Win32-Code/win32.h" +#endif + #define DATA_BUFFER_SIZE 2048 #define UDP_READ_BUFFER_SIZE 65536 #define UDP_MAX_PAYLOAD_SIZE 1400 diff -ruN memcached2/slabs.c memcached3/slabs.c --- memcached2/slabs.c 2006-11-24 09:19:18.843750000 -0600 +++ memcached3/slabs.c 2006-11-24 09:43:14.734375000 -0600 @@ -11,6 +11,7 @@ */ #include #include +#ifndef WIN32 #include #include #include @@ -19,6 +20,9 @@ #include #include #include +#else +#include +#endif #include #include #include diff -ruN memcached2/Win32-Code/config.h memcached3/Win32-Code/config.h --- memcached2/Win32-Code/config.h 1969-12-31 18:00:00.000000000 -0600 +++ memcached3/Win32-Code/config.h 2006-11-23 13:24:42.968750000 -0600 @@ -0,0 +1,29 @@ +/* Name of package */ +#define PACKAGE "memcached" + +/* Define to the address where bug reports for this package should be sent. */ +#define PACKAGE_BUGREPORT "brad@danga.com" + +/* Define to the full name of this package. */ +#define PACKAGE_NAME "memcached Server" + +/* Define to the full name and version of this package. */ +#define PACKAGE_STRING "memcached 1.2.0" + +/* Define to the full name and version of this package. */ +#define PACKAGE_DESCRIPTION "memcached 1.2.0 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. Win32 port by Kronuz." + +/* Define to the one symbol short name of this package. */ +#define PACKAGE_TARNAME "memcached" + +/* Define to the version of this package. */ +#define PACKAGE_VERSION "1.2.0" + +/* Define to 1 if you have the ANSI C header files. */ +#define STDC_HEADERS 1 + +/* Version number of package */ +#define VERSION "1.2.0" + +/* Machine is littleendian */ +#define ENDIAN_LITTLE 1 diff -ruN memcached2/Win32-Code/ntservice.c memcached3/Win32-Code/ntservice.c --- memcached2/Win32-Code/ntservice.c 1969-12-31 18:00:00.000000000 -0600 +++ memcached3/Win32-Code/ntservice.c 2006-11-23 13:24:42.984375000 -0600 @@ -0,0 +1,265 @@ +/* ntservice.c + * + * Copyright (c) 2006 Germán Méndez Bravo (Kronuz) + * 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 Kronuz. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * 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 "config.h" + +#include +#include + +/* Extern callbacks to manage the server */ +extern void runServer(); +extern void pauseServer(); +extern void continueServer(); +extern void stopServer(); + +SERVICE_STATUS serviceStatus; +SERVICE_STATUS_HANDLE serviceStatusHandle = 0; + +void WINAPI ServiceControlHandler(DWORD controlCode) +{ + switch(controlCode) { + case SERVICE_CONTROL_SHUTDOWN: + case SERVICE_CONTROL_STOP: + /* set the service curent status */ + serviceStatus.dwCurrentState = SERVICE_STOP_PENDING; + SetServiceStatus(serviceStatusHandle, &serviceStatus); + + stopServer(); + return; + + case SERVICE_CONTROL_PAUSE: + /* set the service curent status */ + serviceStatus.dwCurrentState = SERVICE_PAUSE_PENDING; + SetServiceStatus(serviceStatusHandle, &serviceStatus); + + pauseServer(); + break; + + case SERVICE_CONTROL_CONTINUE: + /* set the service curent status */ + serviceStatus.dwCurrentState = SERVICE_CONTINUE_PENDING; + SetServiceStatus(serviceStatusHandle, &serviceStatus); + + continueServer(); + break; + + case SERVICE_CONTROL_INTERROGATE: + break; + } + + SetServiceStatus(serviceStatusHandle, &serviceStatus); +} + +void WINAPI ServiceMain(DWORD dwNumServicesArgs, LPSTR *lpServiceArgVectors) +{ + // initialise service status + serviceStatus.dwServiceType = SERVICE_WIN32; + serviceStatus.dwCurrentState = SERVICE_STOPPED; + serviceStatus.dwControlsAccepted = 0; + serviceStatus.dwWin32ExitCode = NO_ERROR; + serviceStatus.dwServiceSpecificExitCode = NO_ERROR; + serviceStatus.dwCheckPoint = 0; + serviceStatus.dwWaitHint = 0; + + serviceStatusHandle = RegisterServiceCtrlHandler(PACKAGE_NAME, ServiceControlHandler); + + if(serviceStatusHandle) { + /* set the service curent status as starting */ + serviceStatus.dwCurrentState = SERVICE_START_PENDING; + SetServiceStatus(serviceStatusHandle, &serviceStatus); + + /* set the service curent status as running and accepting shutdown */ + serviceStatus.dwControlsAccepted |= (SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN); + serviceStatus.dwCurrentState = SERVICE_RUNNING; + SetServiceStatus(serviceStatusHandle, &serviceStatus); + + /* execute the main code */ + runServer(); + + /* set the service curent status as stopping */ + serviceStatus.dwCurrentState = SERVICE_STOP_PENDING; + SetServiceStatus(serviceStatusHandle, &serviceStatus); + + /* set the service curent status as stopped and not accepting shutdown*/ + serviceStatus.dwControlsAccepted &= ~(SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN); + serviceStatus.dwCurrentState = SERVICE_STOPPED; + SetServiceStatus(serviceStatusHandle, &serviceStatus); + } +} + +int ServiceWait(SC_HANDLE service, DWORD pending, DWORD complete) +{ + SERVICE_STATUS serviceStatus; + int counter = 0; + do { + Sleep(1000); + if(counter++>10 || QueryServiceStatus(service, &serviceStatus)==0) + return FALSE; + } while(serviceStatus.dwCurrentState == pending); + return (serviceStatus.dwCurrentState == complete); +} + +void ServiceRun() +{ + SERVICE_TABLE_ENTRY serviceTable[] = + { + { PACKAGE_NAME, ServiceMain }, + { 0, 0 } + }; + + StartServiceCtrlDispatcher(serviceTable); +} + +int ServiceInstall() +{ + int ok = 0; + SC_HANDLE service; + SERVICE_DESCRIPTION sdBuf; + SC_HANDLE serviceControlManager = OpenSCManager(0, 0, SC_MANAGER_CREATE_SERVICE); + + if(serviceControlManager) { + char exe_path[MAX_PATH + 1]; + if(GetModuleFileName(0, exe_path, sizeof(exe_path)) > 0) { + char launch_cmd[MAX_PATH + 50]; + sprintf(launch_cmd, "\"%s\" -d runservice", exe_path); + service = CreateService(serviceControlManager, + PACKAGE_NAME, PACKAGE_NAME, + SERVICE_ALL_ACCESS, SERVICE_WIN32_OWN_PROCESS, + SERVICE_AUTO_START, SERVICE_ERROR_IGNORE, launch_cmd, + 0, 0, 0, 0, 0); + if(service) { + sdBuf.lpDescription = PACKAGE_DESCRIPTION; + ChangeServiceConfig2(service, SERVICE_CONFIG_DESCRIPTION, &sdBuf); + CloseServiceHandle(service); + ok = 1; + } + } + CloseServiceHandle(serviceControlManager); + } + return ok; +} + +int ServiceUninstall() +{ + int ok = 0; + SC_HANDLE service; + SERVICE_STATUS serviceStatus; + SC_HANDLE serviceControlManager = OpenSCManager(0, 0, SC_MANAGER_CONNECT); + + if(serviceControlManager) { + service = OpenService(serviceControlManager, + PACKAGE_NAME, SERVICE_QUERY_STATUS | DELETE); + if(service) { + if(QueryServiceStatus(service, &serviceStatus)) { + if(serviceStatus.dwCurrentState == SERVICE_STOPPED) + if(DeleteService(service)) + ok = 1; + } + CloseServiceHandle(service); + } + CloseServiceHandle(serviceControlManager); + } + return ok; +} + +int ServiceStart() +{ + int ok = 0; + SC_HANDLE service; + SERVICE_STATUS serviceStatus; + SC_HANDLE serviceControlManager = OpenSCManager(0, 0, SC_MANAGER_CONNECT); + + if(serviceControlManager) { + service = OpenService(serviceControlManager, + PACKAGE_NAME, SERVICE_QUERY_STATUS | SERVICE_START); + if(service) { + if(QueryServiceStatus(service, &serviceStatus)) { + if(serviceStatus.dwCurrentState == SERVICE_STOPPED) { + StartService(service, 0, NULL); + if(ServiceWait(service, SERVICE_START_PENDING, SERVICE_RUNNING)) + ok = 1; + } else if(serviceStatus.dwCurrentState == SERVICE_RUNNING) ok = 1; + } + CloseServiceHandle(service); + } + CloseServiceHandle(serviceControlManager); + } + return ok; +} + +int ServiceStop() +{ + int ok = 0; + SC_HANDLE service; + SERVICE_STATUS serviceStatus; + SC_HANDLE serviceControlManager = OpenSCManager(0, 0, SC_MANAGER_CONNECT); + + if(serviceControlManager) { + service = OpenService(serviceControlManager, + PACKAGE_NAME, SERVICE_QUERY_STATUS | SERVICE_STOP); + if(service) { + if(QueryServiceStatus(service, &serviceStatus)) { + if(serviceStatus.dwCurrentState == SERVICE_RUNNING) { + ControlService(service, SERVICE_CONTROL_STOP, &serviceStatus); + if(ServiceWait(service, SERVICE_STOP_PENDING, SERVICE_STOPPED)) + ok = 1; + CloseServiceHandle(service); + } else if(serviceStatus.dwCurrentState == SERVICE_STOPPED) ok = 1; + } + } + CloseServiceHandle(serviceControlManager); + } + return ok; +} + +int ServiceRestart() +{ + int ok = 0; + SC_HANDLE service; + SERVICE_STATUS serviceStatus; + SC_HANDLE serviceControlManager = OpenSCManager(0, 0, SC_MANAGER_CONNECT); + + if(serviceControlManager) { + service = OpenService(serviceControlManager, + PACKAGE_NAME, SERVICE_QUERY_STATUS | SERVICE_STOP); + if(service) { + ControlService(service, SERVICE_CONTROL_STOP, &serviceStatus); + if(ServiceWait(service, SERVICE_STOP_PENDING, SERVICE_STOPPED)) { + StartService(service, 0, NULL); + if(ServiceWait(service, SERVICE_START_PENDING, SERVICE_RUNNING)) + ok = 1; + } + CloseServiceHandle(service); + } + CloseServiceHandle(serviceControlManager); + } + return ok; +} diff -ruN memcached2/Win32-Code/ntservice.h memcached3/Win32-Code/ntservice.h --- memcached2/Win32-Code/ntservice.h 1969-12-31 18:00:00.000000000 -0600 +++ memcached3/Win32-Code/ntservice.h 2006-03-31 09:15:12.000000000 -0600 @@ -0,0 +1,18 @@ +/* ntservice.h + * + * Copyright (c) 2006 Germán Méndez Bravo (Kronuz) + * All rights reserved. + * + */ + +#ifndef SERVICE_H +#define SERVICE_H + +int ServiceStart(); +int ServiceStop(); +int ServiceRestart(); +int ServiceUninstall(); +int ServiceInstall(); +int ServiceRun(); + +#endif diff -ruN memcached2/Win32-Code/win32.c memcached3/Win32-Code/win32.c --- memcached2/Win32-Code/win32.c 1969-12-31 18:00:00.000000000 -0600 +++ memcached3/Win32-Code/win32.c 2006-09-10 12:29:51.000000000 -0500 @@ -0,0 +1,176 @@ +/* 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" + +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); +} diff -ruN memcached2/Win32-Code/win32.h memcached3/Win32-Code/win32.h --- memcached2/Win32-Code/win32.h 1969-12-31 18:00:00.000000000 -0600 +++ memcached3/Win32-Code/win32.h 2006-11-23 16:20:47.144990700 -0600 @@ -0,0 +1,111 @@ +/* win32.h + * + */ + +#ifndef WIN32_H +#define WIN32_H + +#include + +#pragma warning(disable : 4996) + +#if defined(_MSC_VER) +// for MSVC 6.0 +typedef __int64 int64_t; +typedef unsigned __int64 uint64_t; +#else +// default is GCC style +typedef long long int64_t; +typedef unsigned long long uint64_t; +#endif // _WIN32 && _MSC_VER +typedef int int32_t; +typedef unsigned int uint32_t; +typedef short int16_t; +typedef unsigned short uint16_t; +typedef char int8_t; +typedef unsigned char uint8_t; + +#define pid_t int +#define close(s) closesocket(s) +#define EWOULDBLOCK WSAEWOULDBLOCK +#define EAGAIN EWOULDBLOCK +#define E2BIG WSAEMSGSIZE +#define EAFNOSUPPORT WSAEOPNOTSUPP +typedef int socklen_t; + +#undef errno +#define errno WSAGetLastError() + +#define O_BLOCK 0 +#define O_NONBLOCK 1 +#define F_GETFL 3 +#define F_SETFL 4 + +#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 */ +}; + +int fcntl(SOCKET s, int cmd, int val); +int inet_aton(register const char *cp, struct in_addr *addr); + +__inline int inet_pton(int af, register const char *cp, struct in_addr *addr) +{ + if(af != AF_INET) { + WSASetLastError(EAFNOSUPPORT); + return -1; + } + return inet_aton(cp, addr); +} + +__inline size_t write(int s, void *buf, size_t len) +{ + size_t ret = send(s, buf, len, 0); + if(ret == -1 && WSAGetLastError() == WSAECONNRESET) return 0; + return ret; +} + +__inline size_t read(int s, void *buf, size_t len) +{ + size_t ret = recv(s, buf, len, 0); + if(ret == -1 && WSAGetLastError() == WSAECONNRESET) return 0; + return ret; +} + +__inline int sendmsg(int s, const struct msghdr *msg, int flags) +{ + DWORD dwBufferCount; + int error = WSASendTo((SOCKET) s, + msg->msg_iov, + msg->msg_iovlen, + &dwBufferCount, + flags, + msg->msg_name, + msg->msg_namelen, + NULL, + NULL + ); + + if(error == SOCKET_ERROR) { + dwBufferCount = -1; + error = WSAGetLastError(); + if(error == WSA_IO_PENDING) { + WSASetLastError(EAGAIN); + } else if(error == WSAECONNRESET) { + return 0; + } + } + return dwBufferCount; +} + +#endif Files memcached2/Win32-Prj/memcached.ico and memcached3/Win32-Prj/memcached.ico differ Files memcached2/Win32-Prj/memcached.ncb and memcached3/Win32-Prj/memcached.ncb differ diff -ruN memcached2/Win32-Prj/memcached.rc memcached3/Win32-Prj/memcached.rc --- memcached2/Win32-Prj/memcached.rc 1969-12-31 18:00:00.000000000 -0600 +++ memcached3/Win32-Prj/memcached.rc 2006-09-10 12:43:06.703125000 -0500 @@ -0,0 +1,34 @@ +1 ICON DISCARDABLE "memcached.ico" +1 VERSIONINFO + FILEVERSION 1,2,0,0 + PRODUCTVERSION 1,2,0,0 + FILEFLAGSMASK 0x3fL +#if defined(_DEBUG) + FILEFLAGS 0x01L +#else + FILEFLAGS 0x00L +#endif + FILEOS 0x40004L + FILETYPE 0x1L + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904b0" + BEGIN + VALUE "Comments", "Use and distribution licensed under the BSD license (the ""License""); you may not use this file except in compliance with the License. \r\n\r\nUnless required by applicable law, software distributed under the License is provided ""AS IS"" AND ANY EXPRESS OR IMPLIED WARRANTIES ARE DISCLAIMED. \r\n\r\nThis product includes software developed by Niels Provos.\r\n[ libevent ] Copyright 2000-2003 Niels Provos \r\n\r\nThis product includes software developed by the NetBSD Foundation, Inc. and its contributors.\r\n[ bsd_getopts ] Copyright (c) 2000 The NetBSD Foundation, Inc.\r\n\r\nThis product includes software developed by Kronuz.\r\n[ ntservice ] Copyright (c) 2006 Germán Méndez Bravo (Kronuz) \0" + VALUE "CompanyName", "Danga Interactive, Inc.\0" + VALUE "FileDescription", "memcached Server\0" + VALUE "FileVersion", "1.2.0\0" + VALUE "InternalName", "memcached.exe\0" + VALUE "LegalCopyright", "Copyright (c) 2003-2006, Danga Interactive, Inc. All rights reserved.\0" + VALUE "OriginalFilename", "memcached.exe\0" + VALUE "ProductName", "memcached Server\0" + VALUE "ProductVersion", "1.2.0\0" + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1200 + END +END diff -ruN memcached2/Win32-Prj/memcached.sln memcached3/Win32-Prj/memcached.sln --- memcached2/Win32-Prj/memcached.sln 1969-12-31 18:00:00.000000000 -0600 +++ memcached3/Win32-Prj/memcached.sln 2006-03-29 13:40:02.000000000 -0600 @@ -0,0 +1,20 @@ + +Microsoft Visual Studio Solution File, Format Version 9.00 +# Visual Studio 2005 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "memcached", "memcached.vcproj", "{06D065F6-F44E-4E83-A7A2-F8962A4E51A7}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + Release|Win32 = Release|Win32 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {06D065F6-F44E-4E83-A7A2-F8962A4E51A7}.Debug|Win32.ActiveCfg = Debug|Win32 + {06D065F6-F44E-4E83-A7A2-F8962A4E51A7}.Debug|Win32.Build.0 = Debug|Win32 + {06D065F6-F44E-4E83-A7A2-F8962A4E51A7}.Release|Win32.ActiveCfg = Release|Win32 + {06D065F6-F44E-4E83-A7A2-F8962A4E51A7}.Release|Win32.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal Files memcached2/Win32-Prj/memcached.suo and memcached3/Win32-Prj/memcached.suo differ diff -ruN memcached2/Win32-Prj/memcached.vcproj memcached3/Win32-Prj/memcached.vcproj --- memcached2/Win32-Prj/memcached.vcproj 1969-12-31 18:00:00.000000000 -0600 +++ memcached3/Win32-Prj/memcached.vcproj 2006-09-10 12:09:45.625000000 -0500 @@ -0,0 +1,276 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff -ruN memcached2/Win32-Prj/memcached.vcproj.KRONUZ.Owner.user memcached3/Win32-Prj/memcached.vcproj.KRONUZ.Owner.user --- memcached2/Win32-Prj/memcached.vcproj.KRONUZ.Owner.user 1969-12-31 18:00:00.000000000 -0600 +++ memcached3/Win32-Prj/memcached.vcproj.KRONUZ.Owner.user 2006-11-24 09:34:35.390625000 -0600 @@ -0,0 +1,65 @@ + + + + + + + + + + +