Initial patch to add rrdcache support to Win32

"Steven Hartland" <[email protected]> Thu, 3 Oct 2013 12:18:44 +0100
Newsgroups gmane.comp.db.rrdtool.devel
Message-ID <[email protected]>
Hi guys just finished an initial run through on a patch which
enables rrdcached client support on Win32 over tcp connections,
Unix sockets are still not supported for obvious reasons.

Patch comprises of a number of changes:
1. Added generic mutex support (mutex.c, mutex.h)
2. Switched to using send & recv instead of fgets, fputs etc
   as the later aren't support for sockets on Win32.
3. Fixed some compile issues relating to include of rrd_config.h
4. Switched rindex -> strrchr (rindex is old anyway)
5. Eliminated use of this as a variable.
6. Fixed unused warning for "struct stat st"
7. Removed conflicting definition of struct timeval
8. Fix debug project definitions

This has been compiled and tested on Visual C++ 2008 and perl 5.8
on Win32.

Be interested to hear feedback on this.

    Regards
    Steve

================================================
This e.mail is private and confidential between Multiplay (UK) Ltd. and the person or entity to whom it is addressed. In the event of misdirection, the recipient is prohibited from using, copying, printing or otherwise disseminating it or any information contained in it. 

In the event of misdirection, illegible or incomplete transmission please telephone +44 845 868 1337
or return the E.mail to [email protected].

_______________________________________________
rrd-developers mailing list
[email protected]
https://lists.oetiker.ch/cgi-bin/listinfo/rrd-developers
win32-rrdcache.patch (application/octet-stream, 23.7 KB)
--- bindings/perl-shared/RRDs.xs.orig	Tue Oct  1 19:53:23 2013
+++ bindings/perl-shared/RRDs.xs	Tue Oct  1 19:53:46 2013
@@ -434,7 +434,6 @@ rrd_restore(...)
        OUTPUT:
                RETVAL
 
-#ifndef WIN32
 int
 rrd_flushcached(...)
 	PROTOTYPE: @
@@ -445,5 +444,3 @@ rrd_flushcached(...)
 		rrdcode(rrd_flushcached);
 	OUTPUT:
 		RETVAL
-
-#endif
--- src/Makefile.am.orig	Thu May 23 08:55:08 2013
+++ src/Makefile.am	Wed Oct  2 11:24:56 2013
@@ -43,7 +43,8 @@ RRD_C_FILES =		\
 	rrd_flushcached.c \
 	rrd_fetch.c	\
 	rrd_resize.c \
-	rrd_tune.c
+	rrd_tune.c \
+	mutex.c
 
 if BUILD_RRDGRAPH
 RRD_C_FILES += rrd_graph.c	\
@@ -56,6 +57,7 @@ endif
 noinst_HEADERS = \
 	unused.h \
         gettext.h \
+	mutex.h \
 	rrd_getopt.h rrd_parsetime.h \
 	rrd_config_bottom.h rrd_i18n.h \
 	rrd_format.h rrd_tool.h rrd_xport.h rrd.h rrd_rpncalc.h \
--- src/mutex.c.orig	Wed Oct  2 11:20:51 2013
+++ src/mutex.c	Tue Oct  1 21:28:57 2013
@@ -0,0 +1,51 @@
+/*
+ *
+ * mutex.c
+ *
+ * Cross platform mutex
+ *
+ */
+
+#include "mutex.h"
+
+int mutex_init(mutex_t *mutex)
+{
+#ifdef WIN32
+        *mutex = CreateMutex(NULL, FALSE, NULL);
+        return (*mutex == NULL);
+#else
+        return pthread_mutex_init(mutex, NULL);;
+#endif
+}
+
+int mutex_lock(mutex_t *mutex)
+{
+#ifdef WIN32
+	if (*mutex == NULL) { /* static initializer? */
+		HANDLE p = CreateMutex(NULL, FALSE, NULL);
+		if (InterlockedCompareExchangePointer((PVOID*)mutex, (PVOID)p, NULL) != NULL)
+			CloseHandle(p);
+	}
+	return (WaitForSingleObject(*mutex, INFINITE) == WAIT_FAILED);
+#else
+	return pthread_mutex_lock(mutex);
+#endif
+}
+
+int mutex_unlock(mutex_t *mutex)
+{
+#ifdef WIN32
+	return (ReleaseMutex(*mutex) == 0);
+#else
+	return pthread_mutex_unlock(mutex);
+#endif
+}
+
+int mutex_cleanup(mutex_t *mutex)
+{
+#ifdef WIN32
+	return (CloseHandle(mutex) == 0);
+#else
+	return pthread_mutex_destroy(mutex);
+#endif
+}
\ No newline at end of file
--- src/mutex.h.orig	Wed Oct  2 11:20:51 2013
+++ src/mutex.h	Tue Oct  1 21:26:39 2013
@@ -0,0 +1,28 @@
+/*
+ *  mutex.h - Cross platform mutex
+ */
+
+#ifndef MUTEX__H
+#define MUTEX__H
+
+#ifdef WIN32
+#include <windows.h>
+#include <process.h>
+#else
+#include <pthread.h>
+#endif
+
+#ifndef WIN32
+#define mutex_t			pthread_mutex_t
+#define MUTEX_INITIALIZER	PTHREAD_MUTEX_INITIALIZER;
+#else
+#define mutex_t			HANDLE
+#define MUTEX_INITIALIZER	NULL
+#endif
+
+int mutex_init(mutex_t *mutex);
+int mutex_lock(mutex_t *mutex);
+int mutex_unlock(mutex_t *mutex);
+int mutex_cleanup(mutex_t *mutex);
+
+#endif /* MUTEX__H */
--- src/rrd_client.c.orig	Wed Oct  2 11:07:03 2013
+++ src/rrd_client.c	Wed Oct  2 11:18:31 2013
@@ -25,26 +25,32 @@
  *   Sebastian tokkee Harl <sh at tokkee.org>
  **/
 
+#ifdef WIN32
+#include <time.h>
+#include <ws2tcpip.h>
+#include <winsock2.h>
+#include <io.h>
+#include <fcntl.h>
+#endif
 #include "rrd.h"
 #include "rrd_tool.h"
 #include "rrd_client.h"
+#include "mutex.h"
 
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
-#include <strings.h>
 #include <errno.h>
 #include <assert.h>
+#ifndef WIN32
+#include <strings.h>
 #include <pthread.h>
-#include <sys/types.h>
 #include <sys/socket.h>
 #include <sys/un.h>
 #include <netdb.h>
-#include <limits.h>
-
-#ifndef ENODATA
-#define ENODATA ENOENT
 #endif
+#include <sys/types.h>
+#include <limits.h>
 
 struct rrdc_response_s
 {
@@ -55,11 +61,15 @@ struct rrdc_response_s
 };
 typedef struct rrdc_response_s rrdc_response_t;
 
-static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
+static mutex_t lock = MUTEX_INITIALIZER;
 static int sd = -1;
-static FILE *sh = NULL;
 static char *sd_path = NULL; /* cache the path for sd */
 
+#define BUFFER_SIZE 4096
+static char _inbuf[BUFFER_SIZE];
+static char *inbuf = _inbuf;
+static size_t inbuf_used = 0;
+
 /* get_path: Return a path name appropriate to be sent to the daemon.
  *
  * When talking to a local daemon (thru a UNIX socket), relative path names
@@ -103,15 +113,14 @@ static const char *get_path (const char 
 /* One must hold `lock' when calling `close_connection'. */
 static void close_connection (void) /* {{{ */
 {
-  if (sh != NULL)
-  {
-    fclose (sh);
-    sh = NULL;
-    sd = -1;
-  }
-  else if (sd >= 0)
+  if (sd >= 0)
   {
+#ifdef WIN32
+    closesocket(sd);
+    WSACleanup();
+#else
     close (sd);
+#endif
     sd = -1;
   }
 
@@ -173,7 +182,7 @@ static int buffer_add_string (const char
 static int buffer_add_value (const char *value, /* {{{ */
     char **buffer_ret, size_t *buffer_size_ret)
 {
-  char temp[4096];
+  char temp[BUFFER_SIZE];
 
   if (strncmp (value, "N:", 2) == 0)
     snprintf (temp, sizeof (temp), "%lu:%s",
@@ -226,19 +235,77 @@ static void response_free (rrdc_response
   free (res);
 } /* }}} void response_free */
 
+static int recvline (char *buf, size_t n) /* {{{ */
+{
+	size_t len;
+	char *s, *p, *t;
+
+	/* Sanity check */
+	if (n <= 0)
+		return (-1);
+
+	s = buf;
+	n--; /* leave space for the NULL */
+	while (n != 0)
+	{
+		/*
+         * If the buffer is empty, refill it.
+         */
+		if ((len = inbuf_used) <= 0)
+		{
+			inbuf = _inbuf;
+			inbuf_used = recv (sd, inbuf, BUFFER_SIZE, 0);
+			if (inbuf_used <= 0)
+			{
+				if (s == buf)
+				{
+					/* EOF/error: stop with partial or no line */
+					return (-1);
+				}
+			}
+			len = inbuf_used;
+		}
+		p = inbuf;
+		/*
+         * Scan through at most n bytes of the current buffer,
+         * looking for '\n'.  If found, copy up to and including
+         * newline, and stop.  Otherwise, copy entire chunk
+         * and loop.
+         */
+		if (len > n)
+			len = n;
+		t = (char*)memchr((void *)p, '\n', len);
+		if (t != NULL)
+		{
+			len = ++t - p;
+			inbuf_used -= len;
+			inbuf = t;
+			(void)memcpy((void *)s, (void *)p, len);
+			s[len] = 0;
+			return (1);
+		}
+		inbuf_used -= len;
+		inbuf += len;
+		(void)memcpy((void *)s, (void *)p, len);
+		s += len;
+		n -= len;
+	}
+	*s = 0;
+	return (1);
+} /* }}} int recvline */
+
 static int response_read (rrdc_response_t **ret_response) /* {{{ */
 {
   rrdc_response_t *ret = NULL;
   int status = 0;
 
-  char buffer[4096];
-  char *buffer_ptr;
+  char buffer[BUFFER_SIZE];
 
   size_t i;
 
 #define DIE(code) do { status = code; goto err_out; } while(0)
 
-  if (sh == NULL)
+  if (sd == -1)
     DIE(-1);
 
   ret = (rrdc_response_t *) malloc (sizeof (rrdc_response_t));
@@ -248,8 +315,7 @@ static int response_read (rrdc_response_
   ret->lines = NULL;
   ret->lines_num = 0;
 
-  buffer_ptr = fgets (buffer, sizeof (buffer), sh);
-  if (buffer_ptr == NULL)
+  if (recvline (buffer, sizeof (buffer)) == -1)
     DIE(-3);
 
   chomp (buffer);
@@ -277,8 +343,7 @@ static int response_read (rrdc_response_
 
   for (i = 0; i < ret->lines_num; i++)
   {
-    buffer_ptr = fgets (buffer, sizeof (buffer), sh);
-    if (buffer_ptr == NULL)
+    if (recvline (buffer, sizeof (buffer)) == -1)
       DIE(-6);
 
     chomp (buffer);
@@ -290,7 +355,6 @@ static int response_read (rrdc_response_
 
 out:
   *ret_response = ret;
-  fflush(sh);
   return (status);
 
 err_out:
@@ -302,24 +366,39 @@ err_out:
 
 } /* }}} rrdc_response_t *response_read */
 
+static int sendall (const char *msg, size_t len) /* {{{ */
+{
+  int ret = 0;
+  char *bufp = (char*)msg;
+
+  while (ret != -1 && len > 0) {
+    ret = send(sd, msg, len, 0);
+    if (ret > 0) {
+      bufp += ret;
+      len -= ret;
+    }
+  }
+
+  return ret;
+} /* }}} int sendall */
+
 static int request (const char *buffer, size_t buffer_size, /* {{{ */
     rrdc_response_t **ret_response)
 {
   int status;
   rrdc_response_t *res;
 
-  if (sh == NULL)
+  if (sd == -1)
     return (ENOTCONN);
 
-  status = (int) fwrite (buffer, buffer_size, /* nmemb = */ 1, sh);
-  if (status != 1)
+  status = sendall (buffer, buffer_size);
+  if (status == -1)
   {
     close_connection ();
     rrd_set_error("request: socket error (%d) while talking to rrdcached",
                   status);
     return (-1);
   }
-  fflush (sh);
 
   res = NULL;
   status = response_read (&res);
@@ -363,8 +442,12 @@ int rrdc_is_connected(const char *daemon
 
 } /* }}} int rrdc_is_connected */
 
+
 static int rrdc_connect_unix (const char *path) /* {{{ */
 {
+#ifdef WIN32
+  return (EPROTONOSUPPORT);
+#else
   struct sockaddr_un sa;
   int status;
 
@@ -399,6 +482,7 @@ static int rrdc_connect_unix (const char
   }
 
   return (0);
+#endif
 } /* }}} int rrdc_connect_unix */
 
 static int rrdc_connect_network (const char *addr_orig) /* {{{ */
@@ -453,7 +537,7 @@ static int rrdc_connect_network (const c
   } /* if (*addr == '[') */
   else
   {
-    port = rindex(addr, ':');
+    port = strrchr(addr, ':');
     if (port != NULL)
     {
       *port = 0;
@@ -461,15 +545,28 @@ static int rrdc_connect_network (const c
     }
   }
 
+#ifdef WIN32
+  WORD wVersionRequested;
+  WSADATA wsaData;
+
+  wVersionRequested = MAKEWORD(2, 0);
+  status = WSAStartup(wVersionRequested, &wsaData);
+  if (status != 0)
+  {
+    rrd_set_error("failed to initialise socket library %d", status);
+    return (-1);
+  }
+#endif
+
   ai_res = NULL;
   status = getaddrinfo (addr,
                         port == NULL ? RRDCACHED_DEFAULT_PORT : port,
                         &ai_hints, &ai_res);
   if (status != 0)
   {
-    rrd_set_error ("failed to resolve address `%s' (port %s): %s",
+    rrd_set_error ("failed to resolve address '%s' (port %s): %s (%d)",
         addr, port == NULL ? RRDCACHED_DEFAULT_PORT : port,
-        gai_strerror (status));
+        gai_strerror (status), status);
     return (-1);
   }
 
@@ -490,15 +587,6 @@ static int rrdc_connect_network (const c
       close_connection();
       continue;
     }
-
-    sh = fdopen (sd, "r+");
-    if (sh == NULL)
-    {
-      status = errno;
-      close_connection ();
-      continue;
-    }
-
     assert (status == 0);
     break;
   } /* for (ai_ptr) */
@@ -521,12 +609,12 @@ int rrdc_connect (const char *addr) /* {
     return 0;
   }
 
-  pthread_mutex_lock(&lock);
+  mutex_lock(&lock);
 
   if (sd >= 0 && sd_path != NULL && strcmp(addr, sd_path) == 0)
   {
     /* connection to the same daemon; use cached connection */
-    pthread_mutex_unlock (&lock);
+    mutex_unlock (&lock);
     return (0);
   }
   else
@@ -558,17 +646,17 @@ int rrdc_connect (const char *addr) /* {
       free (err);
   }
 
-  pthread_mutex_unlock (&lock);
+  mutex_unlock (&lock);
   return (status);
 } /* }}} int rrdc_connect */
 
 int rrdc_disconnect (void) /* {{{ */
 {
-  pthread_mutex_lock (&lock);
+  mutex_lock (&lock);
 
   close_connection();
 
-  pthread_mutex_unlock (&lock);
+  mutex_unlock (&lock);
 
   return (0);
 } /* }}} int rrdc_disconnect */
@@ -576,7 +664,7 @@ int rrdc_disconnect (void) /* {{{ */
 int rrdc_update (const char *filename, int values_num, /* {{{ */
 		const char * const *values)
 {
-  char buffer[4096];
+  char buffer[BUFFER_SIZE];
   char *buffer_ptr;
   size_t buffer_free;
   size_t buffer_size;
@@ -593,18 +681,18 @@ int rrdc_update (const char *filename, i
   if (status != 0)
     return (ENOBUFS);
 
-  pthread_mutex_lock (&lock);
+  mutex_lock (&lock);
   filename = get_path (filename, file_path);
   if (filename == NULL)
   {
-    pthread_mutex_unlock (&lock);
+    mutex_unlock (&lock);
     return (-1);
   }
 
   status = buffer_add_string (filename, &buffer_ptr, &buffer_free);
   if (status != 0)
   {
-    pthread_mutex_unlock (&lock);
+    mutex_unlock (&lock);
     return (ENOBUFS);
   }
 
@@ -613,7 +701,7 @@ int rrdc_update (const char *filename, i
     status = buffer_add_value (values[i], &buffer_ptr, &buffer_free);
     if (status != 0)
     {
-      pthread_mutex_unlock (&lock);
+      mutex_unlock (&lock);
       return (ENOBUFS);
     }
   }
@@ -625,7 +713,7 @@ int rrdc_update (const char *filename, i
 
   res = NULL;
   status = request (buffer, buffer_size, &res);
-  pthread_mutex_unlock (&lock);
+  mutex_unlock (&lock);
 
   if (status != 0)
     return (status);
@@ -638,7 +726,7 @@ int rrdc_update (const char *filename, i
 
 int rrdc_flush (const char *filename) /* {{{ */
 {
-  char buffer[4096];
+  char buffer[BUFFER_SIZE];
   char *buffer_ptr;
   size_t buffer_free;
   size_t buffer_size;
@@ -657,18 +745,18 @@ int rrdc_flush (const char *filename) /*
   if (status != 0)
     return (ENOBUFS);
 
-  pthread_mutex_lock (&lock);
+  mutex_lock (&lock);
   filename = get_path (filename, file_path);
   if (filename == NULL)
   {
-    pthread_mutex_unlock (&lock);
+    mutex_unlock (&lock);
     return (-1);
   }
 
   status = buffer_add_string (filename, &buffer_ptr, &buffer_free);
   if (status != 0)
   {
-    pthread_mutex_unlock (&lock);
+    mutex_unlock (&lock);
     return (ENOBUFS);
   }
 
@@ -679,7 +767,7 @@ int rrdc_flush (const char *filename) /*
 
   res = NULL;
   status = request (buffer, buffer_size, &res);
-  pthread_mutex_unlock (&lock);
+  mutex_unlock (&lock);
 
   if (status != 0)
     return (status);
@@ -745,9 +833,9 @@ int rrdc_stats_get (rrdc_stats_t **ret_s
    * }}} */
 
   res = NULL;
-  pthread_mutex_lock (&lock);
+  mutex_lock (&lock);
   status = request ("STATS\n", strlen ("STATS\n"), &res);
-  pthread_mutex_unlock (&lock);
+  mutex_unlock (&lock);
 
   if (status != 0)
     return (status);
@@ -843,23 +931,23 @@ int rrdc_stats_get (rrdc_stats_t **ret_s
 
 void rrdc_stats_free (rrdc_stats_t *ret_stats) /* {{{ */
 {
-  rrdc_stats_t *this;
+  rrdc_stats_t *stats;
 
-  this = ret_stats;
-  while (this != NULL)
+  stats = ret_stats;
+  while (stats != NULL)
   {
     rrdc_stats_t *next;
 
-    next = this->next;
+    next = stats->next;
 
-    if (this->name != NULL)
+    if (stats->name != NULL)
     {
-      free ((char *)this->name);
-      this->name = NULL;
+      free ((char *)stats->name);
+      stats->name = NULL;
     }
-    free (this);
+    free (stats);
 
-    this = next;
+    stats = next;
   } /* while (this != NULL) */
 } /* }}} void rrdc_stats_free */
 
--- src/rrd_client.h.orig	Thu May 23 08:55:08 2013
+++ src/rrd_client.h	Tue Oct  1 20:16:57 2013
@@ -58,9 +58,6 @@
 #define ENV_RRDCACHED_ADDRESS "RRDCACHED_ADDRESS"
 
 
-// Windows version has no daemon/client support
-
-#ifndef WIN32
 int rrdc_connect (const char *addr);
 int rrdc_is_connected(const char *daemon_addr);
 int rrdc_disconnect (void);
@@ -70,14 +67,6 @@ int rrdc_update (const char *filename, i
 
 int rrdc_flush (const char *filename);
 int rrdc_flush_if_daemon (const char *opt_daemon, const char *filename);
-
-#else
-#	define rrdc_flush_if_daemon(a,b) 0
-#	define rrdc_connect(a) 0
-#	define rrdc_is_connected(a) 0
-#	define rrdc_flush(a) 0
-#	define rrdc_update(a,b,c) 0
-#endif
 
 struct rrdc_stats_s
 {
--- src/rrd_create.c.orig	Tue Oct  1 18:25:55 2013
+++ src/rrd_create.c	Tue Oct  1 18:26:17 2013
@@ -12,7 +12,14 @@
 #include "rrd_rpncalc.h"
 #include "rrd_hw.h"
 #include "rrd_client.h"
+
+#if defined(_WIN32) && !defined(__CYGWIN__) && !defined(__CYGWIN32__)
+#include "../win32/config.h"
+#else
+#ifdef HAVE_CONFIG_H
 #include "../rrd_config.h"
+#endif
+#endif
 
 #include "rrd_is_thread_safe.h"
 static int opt_no_overwrite = 0;
--- src/rrd_flushcached.c.orig	Tue Oct  1 20:04:25 2013
+++ src/rrd_flushcached.c	Wed Oct  2 20:23:29 2013
@@ -78,9 +78,10 @@ int rrd_flushcached (int argc, char **ar
 
     if (! rrdc_is_connected(opt_daemon))
     {
-        rrd_set_error ("Daemon address unknown. Please use the \"--daemon\" "
+        rrd_set_error ("Daemon address \"%s\" unknown. Please use the \"--daemon\" "
                 "option to set an address on the command line or set the "
                 "\"%s\" environment variable.",
+                 opt_daemon,
                 ENV_RRDCACHED_ADDRESS);
         status = -1;
         goto out;
--- src/rrd_tool.c.orig	Thu May 23 08:55:08 2013
+++ src/rrd_tool.c	Wed Oct  2 20:26:19 2013
@@ -534,9 +534,6 @@ int HandleInputLine(
     DIR      *curdir;   /* to read current dir with ls */
     struct dirent *dent;
 #endif
-#if defined(HAVE_SYS_STAT_H)
-    struct stat st;
-#endif
 
     /* Reset errno to 0 before we start.
      */
@@ -548,7 +545,7 @@ int HandleInputLine(
             }
             exit(0);
         }
-#if defined(HAVE_OPENDIR) && defined(HAVE_READDIR) && defined(HAVE_CHDIR)
+#if defined(HAVE_OPENDIR) && defined(HAVE_READDIR) && defined(HAVE_CHDIR) && defined(HAVE_SYS_STAT_H)
         if (argc > 1 && strcmp("cd", argv[1]) == 0) {
             if (argc != 3) {
                 printf("ERROR: invalid parameter count for cd\n");
@@ -608,6 +605,7 @@ int HandleInputLine(
                 return (1);
             }
             if ((curdir = opendir(".")) != NULL) {
+                struct stat st;
                 while ((dent = readdir(curdir)) != NULL) {
                     if (!stat(dent->d_name, &st)) {
                         if (S_ISDIR(st.st_mode)) {
@@ -899,10 +897,8 @@ int HandleInputLine(
 #endif
     } else if (strcmp("tune", argv[1]) == 0)
         rrd_tune(argc - 1, &argv[1]);
-#ifndef WIN32
     else if (strcmp("flushcached", argv[1]) == 0)
         rrd_flushcached(argc - 1, &argv[1]);
-#endif
     else {
         rrd_set_error("unknown function '%s'", argv[1]);
     }
--- src/rrd_update.c.orig	Thu May 23 08:55:08 2013
+++ src/rrd_update.c	Tue Oct  1 22:55:51 2013
@@ -32,13 +32,6 @@
  */
 #include <sys/timeb.h>
 
-#ifndef __MINGW32__
-struct timeval {
-    time_t    tv_sec;   /* seconds */
-    long      tv_usec;  /* microseconds */
-};
-#endif
-
 struct __timezone {
     int       tz_minuteswest;   /* minutes W of Greenwich */
     int       tz_dsttime;   /* type of dst correction */
--- win32/config.h.orig	Tue Oct  1 18:31:10 2013
+++ win32/config.h	Tue Oct  1 23:58:16 2013
@@ -7,6 +7,7 @@
 #include <direct.h>
 #include <ctype.h>
 #include <stdlib.h>
+#include <WinSock.h>
 
 /* realloc does not support NULL as argument */
 
@@ -20,7 +21,6 @@
 #define HAVE_MEMMOVE 1
 #define HAVE_MALLOC_H 1
 #define HAVE_MKTIME 1
-#define HAVE_STRFTIME 1
 #define HAVE_STRING_H 1
 #define HAVE_STDLIB_H 1
 #define HAVE_VSNPRINTF 1
@@ -28,6 +28,60 @@
 #define HAVE_SYS_STAT_H 1
 #define HAVE_RRD_GRAPH 1
 
+/* VS2005 and later dafault size for time_t is 64-bit, unless */
+/* _USE_32BIT_TIME_T has been defined to use a 32-bit time_t. */
+#if defined(_MSC_VER) && (_MSC_VER >= 1400)
+# ifndef _USE_32BIT_TIME_T
+# define SIZEOF_TIME_T 8
+# else
+# define SIZEOF_TIME_T 4
+# endif
+#endif
+
+/*
+ * Windows Sockets errors redefined as regular Berkeley error constants.
+ * These are commented out in Windows NT to avoid conflicts with errno.h.
+ * Use the WSA constants instead.
+ */
+#define EWOULDBLOCK             WSAEWOULDBLOCK
+#define EINPROGRESS             WSAEINPROGRESS
+#define EALREADY                WSAEALREADY
+#define ENOTSOCK                WSAENOTSOCK
+#define EDESTADDRREQ            WSAEDESTADDRREQ
+#define EMSGSIZE                WSAEMSGSIZE
+#define EPROTOTYPE              WSAEPROTOTYPE
+#define ENOPROTOOPT             WSAENOPROTOOPT
+#define EPROTONOSUPPORT         WSAEPROTONOSUPPORT
+#define ESOCKTNOSUPPORT         WSAESOCKTNOSUPPORT
+#define EOPNOTSUPP              WSAEOPNOTSUPP
+#define EPFNOSUPPORT            WSAEPFNOSUPPORT
+#define EAFNOSUPPORT            WSAEAFNOSUPPORT
+#define EADDRINUSE              WSAEADDRINUSE
+#define EADDRNOTAVAIL           WSAEADDRNOTAVAIL
+#define ENETDOWN                WSAENETDOWN
+#define ENETUNREACH             WSAENETUNREACH
+#define ENETRESET               WSAENETRESET
+#define ECONNABORTED            WSAECONNABORTED
+#define ECONNRESET              WSAECONNRESET
+#define ENOBUFS                 WSAENOBUFS
+#define EISCONN                 WSAEISCONN
+#define ENOTCONN                WSAENOTCONN
+#define ESHUTDOWN               WSAESHUTDOWN
+#define ETOOMANYREFS            WSAETOOMANYREFS
+#define ETIMEDOUT               WSAETIMEDOUT
+#define ECONNREFUSED            WSAECONNREFUSED
+#define ELOOP                   WSAELOOP
+#define EHOSTDOWN               WSAEHOSTDOWN
+#define EHOSTUNREACH            WSAEHOSTUNREACH
+#define EPROCLIM                WSAEPROCLIM
+#define EUSERS                  WSAEUSERS
+#define EDQUOT                  WSAEDQUOT
+#define ESTALE                  WSAESTALE
+#define EREMOTE                 WSAEREMOTE
+
+/* Misc Missing Windows defines */
+#define PATH_MAX			1024
+
 /* Define to 1 if you have the ANSI C header files. */
 #define STDC_HEADERS 1
 
@@ -36,6 +90,7 @@
 #define PACKAGE_VERSION "1.4.5"
 #define PACKAGE_STRING PACKAGE_NAME " " PACKAGE_VERSION
 
+#define realpath(N,R) _fullpath((R),(N),_MAX_PATH)
 #define isinf(a) (_fpclass(a) == _FPCLASS_NINF || _fpclass(a) == _FPCLASS_PINF)
 #define isnan _isnan
 #define finite _finite
@@ -57,6 +112,7 @@
 
 /* #define DEBUG 1 */
 
+#pragma warning(disable: 4244)
 __inline int round(double a){int x = (a + 0.5); return x;}
 
 #endif                          /* CONFIG_H */
--- win32/rrdlib.vcproj.orig	Thu May 23 08:55:08 2013
+++ win32/rrdlib.vcproj	Tue Oct  1 23:58:42 2013
@@ -387,6 +387,10 @@
 				>
 			</File>
 			<File
+				RelativePath="..\src\mutex.c"
+				>
+			</File>
+			<File
 				RelativePath="..\src\plbasename.c"
 				>
 			</File>
@@ -395,6 +399,10 @@
 				>
 			</File>
 			<File
+				RelativePath="..\src\rrd_client.c"
+				>
+			</File>
+			<File
 				RelativePath="..\src\rrd_create.c"
 				>
 			</File>
@@ -419,6 +427,10 @@
 				>
 			</File>
 			<File
+				RelativePath="..\src\rrd_flushcached.c"
+				>
+			</File>
+			<File
 				RelativePath="..\src\rrd_format.c"
 				>
 			</File>
@@ -530,6 +542,10 @@
 			</File>
 			<File
 				RelativePath="..\src\fnv.h"
+				>
+			</File>
+			<File
+				RelativePath="..\src\mutex.h"
 				>
 			</File>
 			<File
--- win32/rrdtool.vcproj.orig	Thu May 23 08:55:08 2013
+++ win32/rrdtool.vcproj	Wed Oct  2 00:42:05 2013
@@ -62,9 +62,9 @@
 			/>
 			<Tool
 				Name="VCLinkerTool"
-				AdditionalDependencies="rrdlib.lib"
+				AdditionalDependencies="rrdlib.lib cairo.lib pango-1.0.lib pangocairo-1.0.lib libpng.lib zdll.lib glib-2.0.lib gobject-2.0.lib libxml2.lib Ws2_32.lib"
 				ShowProgress="2"
-				AdditionalLibraryDirectories="&quot;$(ConfigurationName)&quot;"
+				AdditionalLibraryDirectories="$(ConfigurationName); ../contrib/lib"
 				IgnoreDefaultLibraryNames="LIBCMTD.lib;LIBCMT.lib"
 				GenerateDebugInformation="true"
 				SubSystem="0"
@@ -140,7 +140,7 @@
 			/>
 			<Tool
 				Name="VCLinkerTool"
-				AdditionalDependencies="rrdlib.lib cairo.lib pango-1.0.lib pangocairo-1.0.lib libpng.lib zdll.lib glib-2.0.lib gobject-2.0.lib libxml2.lib"
+				AdditionalDependencies="rrdlib.lib cairo.lib pango-1.0.lib pangocairo-1.0.lib libpng.lib zdll.lib glib-2.0.lib gobject-2.0.lib libxml2.lib Ws2_32.lib"
 				AdditionalLibraryDirectories="$(ConfigurationName); ../contrib/lib"
 				GenerateDebugInformation="false"
 				OptimizeReferences="2"
@@ -253,6 +253,7 @@
 	<References>
 		<ProjectReference
 			ReferencedProjectIdentifier="{CC158E1D-1364-43CA-9B2D-4AF54225C7CA}"
+			RelativePathToProject=".\rrdlib.vcproj"
 		/>
 	</References>
 	<Files>
--- win32/rrdupdate.vcproj.orig	Thu May 23 08:55:08 2013
+++ win32/rrdupdate.vcproj	Wed Oct  2 00:42:05 2013
@@ -62,9 +62,9 @@
 			/>
 			<Tool
 				Name="VCLinkerTool"
-				AdditionalDependencies="rrdlib.lib"
+				AdditionalDependencies="rrdlib.lib cairo.lib pango-1.0.lib pangocairo-1.0.lib libpng.lib zdll.lib glib-2.0.lib gobject-2.0.lib libxml2.lib Ws2_32.lib"
 				ShowProgress="2"
-				AdditionalLibraryDirectories="&quot;$(ConfigurationName)&quot;"
+				AdditionalLibraryDirectories="$(ConfigurationName); ../contrib/lib"
 				IgnoreDefaultLibraryNames="LIBCMTD.lib;LIBCMT.lib"
 				GenerateDebugInformation="true"
 				SubSystem="0"
@@ -140,7 +140,7 @@
 			/>
 			<Tool
 				Name="VCLinkerTool"
-				AdditionalDependencies="rrdlib.lib cairo.lib pango-1.0.lib pangocairo-1.0.lib libpng.lib zdll.lib glib-2.0.lib gobject-2.0.lib libxml2.lib"
+				AdditionalDependencies="rrdlib.lib cairo.lib pango-1.0.lib pangocairo-1.0.lib libpng.lib zdll.lib glib-2.0.lib gobject-2.0.lib libxml2.lib Ws2_32.lib"
 				AdditionalLibraryDirectories="$(ConfigurationName); ../contrib/lib"
 				GenerateDebugInformation="true"
 				OptimizeReferences="2"
@@ -253,6 +253,7 @@
 	<References>
 		<ProjectReference
 			ReferencedProjectIdentifier="{CC158E1D-1364-43CA-9B2D-4AF54225C7CA}"
+			RelativePathToProject=".\rrdlib.vcproj"
 		/>
 	</References>
 	<Files>