diff --git a/LICENSE b/LICENSE
--- a/LICENSE
+++ b/LICENSE
@@ -1,4 +1,7 @@
-Copyright (c) 2007, Bjorn Bringert
+Copyright (c) 2007-2008, Björn Bringert
+Copyright (c) 2007-2009, Duncan Coutts
+Copyright (c) 2010-2011, Jacob Stanley
+Copyright (c)      2011, Bryan O'Sullivan
 All rights reserved.
 
 Redistribution and use in source and binary forms, with or without 
diff --git a/cbits/HsUname.c b/cbits/HsUname.c
--- a/cbits/HsUname.c
+++ b/cbits/HsUname.c
@@ -105,7 +105,7 @@
 # define VER_SUITE_WH_SERVER 0x00008000
 #endif
 
-int HsOSDisplayString(char *pszOS, size_t BUFSIZE)
+int unixcompat_os_display_string(char *pszOS, size_t BUFSIZE)
 {
     OSVERSIONINFOEX osvi;
     SYSTEM_INFO si;
@@ -121,213 +121,192 @@
     bOsVersionInfoEx = GetVersionEx((OSVERSIONINFO*) &osvi);
 
     if (bOsVersionInfoEx == 0)
-	return FALSE;
+        return FALSE;
 
     // Call GetNativeSystemInfo if supported or GetSystemInfo otherwise.
 
     pGNSI = (PGNSI) GetProcAddress(
-	GetModuleHandle(TEXT("kernel32.dll")), 
-	"GetNativeSystemInfo");
-    if(NULL != pGNSI)
-	pGNSI(&si);
-    else GetSystemInfo(&si);
-
-    if ( VER_PLATFORM_WIN32_NT==osvi.dwPlatformId && 
-	 osvi.dwMajorVersion > 4 )
-    {
-	StringCchCopy(pszOS, BUFSIZE, TEXT("Microsoft "));
+        GetModuleHandle(TEXT("kernel32.dll")),
+        "GetNativeSystemInfo");
+    if (NULL != pGNSI)
+        pGNSI(&si);
+    else
+        GetSystemInfo(&si);
 
-	// Test for the specific product.
+    if (VER_PLATFORM_WIN32_NT == osvi.dwPlatformId && osvi.dwMajorVersion > 4) {
+        StringCchCopy(pszOS, BUFSIZE, TEXT("Microsoft "));
 
-	if ( osvi.dwMajorVersion == 6 )
-	{
-	    if( osvi.dwMinorVersion == 0 )
-	    {
-		if( osvi.wProductType == VER_NT_WORKSTATION )
-		    StringCchCat(pszOS, BUFSIZE, TEXT("Windows Vista "));
-		else StringCchCat(pszOS, BUFSIZE, TEXT("Windows Server 2008 " ));
-	    }
+        // Test for the specific product.
+        if (osvi.dwMajorVersion == 6) {
+            if(osvi.dwMinorVersion == 0) {
+                if(osvi.wProductType == VER_NT_WORKSTATION)
+                    StringCchCat(pszOS, BUFSIZE, TEXT("Windows Vista "));
+                else
+                    StringCchCat(pszOS, BUFSIZE, TEXT("Windows Server 2008 "));
+            }
 
-	    if ( osvi.dwMinorVersion == 1 )
-	    {
-		if( osvi.wProductType == VER_NT_WORKSTATION )
-		    StringCchCat(pszOS, BUFSIZE, TEXT("Windows 7 "));
-		else StringCchCat(pszOS, BUFSIZE, TEXT("Windows Server 2008 R2 " ));
-	    }
-         
-	    pGPI = (PGPI) GetProcAddress(
-		GetModuleHandle(TEXT("kernel32.dll")), 
-		"GetProductInfo");
+            if (osvi.dwMinorVersion == 1) {
+                if (osvi.wProductType == VER_NT_WORKSTATION)
+                    StringCchCat(pszOS, BUFSIZE, TEXT("Windows 7 "));
+                else
+                    StringCchCat(pszOS, BUFSIZE, TEXT("Windows Server 2008 R2 "));
+            }
 
-	    pGPI( osvi.dwMajorVersion, osvi.dwMinorVersion, 0, 0, &dwType);
+            pGPI = (PGPI) GetProcAddress(
+                GetModuleHandle(TEXT("kernel32.dll")),
+                "GetProductInfo");
 
-	    switch( dwType )
-	    {
-            case PRODUCT_ULTIMATE:
-		StringCchCat(pszOS, BUFSIZE, TEXT("Ultimate Edition" ));
-		break;
-            case PRODUCT_PROFESSIONAL:
-		StringCchCat(pszOS, BUFSIZE, TEXT("Professional" ));
-		break;
-            case PRODUCT_HOME_PREMIUM:
-		StringCchCat(pszOS, BUFSIZE, TEXT("Home Premium Edition" ));
-		break;
-            case PRODUCT_HOME_BASIC:
-		StringCchCat(pszOS, BUFSIZE, TEXT("Home Basic Edition" ));
-		break;
-            case PRODUCT_ENTERPRISE:
-		StringCchCat(pszOS, BUFSIZE, TEXT("Enterprise Edition" ));
-		break;
-            case PRODUCT_BUSINESS:
-		StringCchCat(pszOS, BUFSIZE, TEXT("Business Edition" ));
-		break;
-            case PRODUCT_STARTER:
-		StringCchCat(pszOS, BUFSIZE, TEXT("Starter Edition" ));
-		break;
-            case PRODUCT_CLUSTER_SERVER:
-		StringCchCat(pszOS, BUFSIZE, TEXT("Cluster Server Edition" ));
-		break;
-            case PRODUCT_DATACENTER_SERVER:
-		StringCchCat(pszOS, BUFSIZE, TEXT("Datacenter Edition" ));
-		break;
-            case PRODUCT_DATACENTER_SERVER_CORE:
-		StringCchCat(pszOS, BUFSIZE, TEXT("Datacenter Edition (core installation)" ));
-		break;
-            case PRODUCT_ENTERPRISE_SERVER:
-		StringCchCat(pszOS, BUFSIZE, TEXT("Enterprise Edition" ));
-		break;
-            case PRODUCT_ENTERPRISE_SERVER_CORE:
-		StringCchCat(pszOS, BUFSIZE, TEXT("Enterprise Edition (core installation)" ));
-		break;
-            case PRODUCT_ENTERPRISE_SERVER_IA64:
-		StringCchCat(pszOS, BUFSIZE, TEXT("Enterprise Edition for Itanium-based Systems" ));
-		break;
-            case PRODUCT_SMALLBUSINESS_SERVER:
-		StringCchCat(pszOS, BUFSIZE, TEXT("Small Business Server" ));
-		break;
-            case PRODUCT_SMALLBUSINESS_SERVER_PREMIUM:
-		StringCchCat(pszOS, BUFSIZE, TEXT("Small Business Server Premium Edition" ));
-		break;
-            case PRODUCT_STANDARD_SERVER:
-		StringCchCat(pszOS, BUFSIZE, TEXT("Standard Edition" ));
-		break;
-            case PRODUCT_STANDARD_SERVER_CORE:
-		StringCchCat(pszOS, BUFSIZE, TEXT("Standard Edition (core installation)" ));
-		break;
-            case PRODUCT_WEB_SERVER:
-		StringCchCat(pszOS, BUFSIZE, TEXT("Web Server Edition" ));
-		break;
-	    }
-	}
+            pGPI(osvi.dwMajorVersion, osvi.dwMinorVersion, 0, 0, &dwType);
 
-	if ( osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 2 )
-	{
-	    if( GetSystemMetrics(SM_SERVERR2) )
-		StringCchCat(pszOS, BUFSIZE, TEXT( "Windows Server 2003 R2, "));
-	    else if ( osvi.wSuiteMask & VER_SUITE_STORAGE_SERVER )
-		StringCchCat(pszOS, BUFSIZE, TEXT( "Windows Storage Server 2003"));
-	    else if ( osvi.wSuiteMask & VER_SUITE_WH_SERVER )
-		StringCchCat(pszOS, BUFSIZE, TEXT( "Windows Home Server"));
-	    else if( osvi.wProductType == VER_NT_WORKSTATION &&
-		     si.wProcessorArchitecture==PROCESSOR_ARCHITECTURE_AMD64)
-	    {
-		StringCchCat(pszOS, BUFSIZE, TEXT( "Windows XP Professional x64 Edition"));
-	    }
-	    else StringCchCat(pszOS, BUFSIZE, TEXT("Windows Server 2003, "));
+            switch (dwType) {
+                case PRODUCT_ULTIMATE:
+                    StringCchCat(pszOS, BUFSIZE, TEXT("Ultimate Edition"));
+                    break;
+                case PRODUCT_PROFESSIONAL:
+                    StringCchCat(pszOS, BUFSIZE, TEXT("Professional"));
+                    break;
+                case PRODUCT_HOME_PREMIUM:
+                    StringCchCat(pszOS, BUFSIZE, TEXT("Home Premium Edition"));
+                    break;
+                case PRODUCT_HOME_BASIC:
+                    StringCchCat(pszOS, BUFSIZE, TEXT("Home Basic Edition"));
+                    break;
+                case PRODUCT_ENTERPRISE:
+                    StringCchCat(pszOS, BUFSIZE, TEXT("Enterprise Edition"));
+                    break;
+                case PRODUCT_BUSINESS:
+                    StringCchCat(pszOS, BUFSIZE, TEXT("Business Edition"));
+                    break;
+                case PRODUCT_STARTER:
+                    StringCchCat(pszOS, BUFSIZE, TEXT("Starter Edition"));
+                    break;
+                case PRODUCT_CLUSTER_SERVER:
+                    StringCchCat(pszOS, BUFSIZE, TEXT("Cluster Server Edition"));
+                    break;
+                case PRODUCT_DATACENTER_SERVER:
+                    StringCchCat(pszOS, BUFSIZE, TEXT("Datacenter Edition"));
+                    break;
+                case PRODUCT_DATACENTER_SERVER_CORE:
+                    StringCchCat(pszOS, BUFSIZE, TEXT("Datacenter Edition (core installation)"));
+                    break;
+                case PRODUCT_ENTERPRISE_SERVER:
+                    StringCchCat(pszOS, BUFSIZE, TEXT("Enterprise Edition"));
+                    break;
+                case PRODUCT_ENTERPRISE_SERVER_CORE:
+                    StringCchCat(pszOS, BUFSIZE, TEXT("Enterprise Edition (core installation)"));
+                    break;
+                case PRODUCT_ENTERPRISE_SERVER_IA64:
+                    StringCchCat(pszOS, BUFSIZE, TEXT("Enterprise Edition for Itanium-based Systems"));
+                    break;
+                case PRODUCT_SMALLBUSINESS_SERVER:
+                    StringCchCat(pszOS, BUFSIZE, TEXT("Small Business Server"));
+                    break;
+                case PRODUCT_SMALLBUSINESS_SERVER_PREMIUM:
+                    StringCchCat(pszOS, BUFSIZE, TEXT("Small Business Server Premium Edition"));
+                    break;
+                case PRODUCT_STANDARD_SERVER:
+                    StringCchCat(pszOS, BUFSIZE, TEXT("Standard Edition"));
+                    break;
+                case PRODUCT_STANDARD_SERVER_CORE:
+                    StringCchCat(pszOS, BUFSIZE, TEXT("Standard Edition (core installation)"));
+                    break;
+                case PRODUCT_WEB_SERVER:
+                    StringCchCat(pszOS, BUFSIZE, TEXT("Web Server Edition"));
+                    break;
+            }
+        }
 
-	    // Test for the server type.
-	    if ( osvi.wProductType != VER_NT_WORKSTATION )
-	    {
-		if ( si.wProcessorArchitecture==PROCESSOR_ARCHITECTURE_IA64 )
-		{
-		    if( osvi.wSuiteMask & VER_SUITE_DATACENTER )
-			StringCchCat(pszOS, BUFSIZE, TEXT( "Datacenter Edition for Itanium-based Systems" ));
-		    else if( osvi.wSuiteMask & VER_SUITE_ENTERPRISE )
-			StringCchCat(pszOS, BUFSIZE, TEXT( "Enterprise Edition for Itanium-based Systems" ));
-		}
+        if (osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 2) {
+            if (GetSystemMetrics(SM_SERVERR2))
+                StringCchCat(pszOS, BUFSIZE, TEXT("Windows Server 2003 R2, "));
+            else if (osvi.wSuiteMask & VER_SUITE_STORAGE_SERVER)
+                StringCchCat(pszOS, BUFSIZE, TEXT("Windows Storage Server 2003"));
+            else if (osvi.wSuiteMask & VER_SUITE_WH_SERVER)
+                StringCchCat(pszOS, BUFSIZE, TEXT("Windows Home Server"));
+            else if (osvi.wProductType == VER_NT_WORKSTATION &&
+                     si.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64)
+                StringCchCat(pszOS, BUFSIZE, TEXT("Windows XP Professional x64 Edition"));
+            else
+                StringCchCat(pszOS, BUFSIZE, TEXT("Windows Server 2003, "));
 
-		else if ( si.wProcessorArchitecture==PROCESSOR_ARCHITECTURE_AMD64 )
-		{
-		    if( osvi.wSuiteMask & VER_SUITE_DATACENTER )
-			StringCchCat(pszOS, BUFSIZE, TEXT( "Datacenter x64 Edition" ));
-		    else if( osvi.wSuiteMask & VER_SUITE_ENTERPRISE )
-			StringCchCat(pszOS, BUFSIZE, TEXT( "Enterprise x64 Edition" ));
-		    else StringCchCat(pszOS, BUFSIZE, TEXT( "Standard x64 Edition" ));
-		}
+            // Test for the server type.
 
-		else
-		{
-		    if ( osvi.wSuiteMask & VER_SUITE_COMPUTE_SERVER )
-			StringCchCat(pszOS, BUFSIZE, TEXT( "Compute Cluster Edition" ));
-		    else if( osvi.wSuiteMask & VER_SUITE_DATACENTER )
-			StringCchCat(pszOS, BUFSIZE, TEXT( "Datacenter Edition" ));
-		    else if( osvi.wSuiteMask & VER_SUITE_ENTERPRISE )
-			StringCchCat(pszOS, BUFSIZE, TEXT( "Enterprise Edition" ));
-		    else if ( osvi.wSuiteMask & VER_SUITE_BLADE )
-			StringCchCat(pszOS, BUFSIZE, TEXT( "Web Edition" ));
-		    else StringCchCat(pszOS, BUFSIZE, TEXT( "Standard Edition" ));
-		}
-	    }
-	}
+            if (osvi.wProductType != VER_NT_WORKSTATION) {
+                if (si.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_IA64) {
+                    if(osvi.wSuiteMask & VER_SUITE_DATACENTER)
+                        StringCchCat(pszOS, BUFSIZE, TEXT("Datacenter Edition for Itanium-based Systems"));
+                    else if(osvi.wSuiteMask & VER_SUITE_ENTERPRISE)
+                        StringCchCat(pszOS, BUFSIZE, TEXT("Enterprise Edition for Itanium-based Systems"));
+                } else if (si.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64) {
+                    if(osvi.wSuiteMask & VER_SUITE_DATACENTER)
+                        StringCchCat(pszOS, BUFSIZE, TEXT("Datacenter x64 Edition"));
+                    else if(osvi.wSuiteMask & VER_SUITE_ENTERPRISE)
+                        StringCchCat(pszOS, BUFSIZE, TEXT("Enterprise x64 Edition"));
+                    else StringCchCat(pszOS, BUFSIZE, TEXT("Standard x64 Edition"));
+                } else {
+                    if (osvi.wSuiteMask & VER_SUITE_COMPUTE_SERVER)
+                        StringCchCat(pszOS, BUFSIZE, TEXT("Compute Cluster Edition"));
+                    else if(osvi.wSuiteMask & VER_SUITE_DATACENTER)
+                        StringCchCat(pszOS, BUFSIZE, TEXT("Datacenter Edition"));
+                    else if(osvi.wSuiteMask & VER_SUITE_ENTERPRISE)
+                        StringCchCat(pszOS, BUFSIZE, TEXT("Enterprise Edition"));
+                    else if (osvi.wSuiteMask & VER_SUITE_BLADE)
+                        StringCchCat(pszOS, BUFSIZE, TEXT("Web Edition"));
+                    else StringCchCat(pszOS, BUFSIZE, TEXT("Standard Edition"));
+                }
+            }
+        }
 
-	if ( osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 1 )
-	{
-	    StringCchCat(pszOS, BUFSIZE, TEXT("Windows XP "));
-	    if( osvi.wSuiteMask & VER_SUITE_PERSONAL )
-		StringCchCat(pszOS, BUFSIZE, TEXT( "Home Edition" ));
-	    else StringCchCat(pszOS, BUFSIZE, TEXT( "Professional" ));
-	}
+        if (osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 1) {
+            StringCchCat(pszOS, BUFSIZE, TEXT("Windows XP "));
 
-	if ( osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 0 )
-	{
-	    StringCchCat(pszOS, BUFSIZE, TEXT("Windows 2000 "));
+            if (osvi.wSuiteMask & VER_SUITE_PERSONAL)
+                StringCchCat(pszOS, BUFSIZE, TEXT("Home Edition"));
+            else
+                StringCchCat(pszOS, BUFSIZE, TEXT("Professional"));
+        }
 
-	    if ( osvi.wProductType == VER_NT_WORKSTATION )
-	    {
-		StringCchCat(pszOS, BUFSIZE, TEXT( "Professional" ));
-	    }
-	    else 
-	    {
-		if( osvi.wSuiteMask & VER_SUITE_DATACENTER )
-		    StringCchCat(pszOS, BUFSIZE, TEXT( "Datacenter Server" ));
-		else if( osvi.wSuiteMask & VER_SUITE_ENTERPRISE )
-		    StringCchCat(pszOS, BUFSIZE, TEXT( "Advanced Server" ));
-		else StringCchCat(pszOS, BUFSIZE, TEXT( "Server" ));
-	    }
-	}
+        if (osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 0) {
+            StringCchCat(pszOS, BUFSIZE, TEXT("Windows 2000 "));
 
-	// Include service pack (if any) and build number.
+            if (osvi.wProductType == VER_NT_WORKSTATION) {
+                StringCchCat(pszOS, BUFSIZE, TEXT("Professional"));
+            } else {
+                if(osvi.wSuiteMask & VER_SUITE_DATACENTER)
+                    StringCchCat(pszOS, BUFSIZE, TEXT("Datacenter Server"));
+                else if(osvi.wSuiteMask & VER_SUITE_ENTERPRISE)
+                    StringCchCat(pszOS, BUFSIZE, TEXT("Advanced Server"));
+                else
+                    StringCchCat(pszOS, BUFSIZE, TEXT("Server"));
+            }
+        }
 
-	if( _tcslen(osvi.szCSDVersion) > 0 )
-	{
-	    StringCchCat(pszOS, BUFSIZE, TEXT(" ") );
-	    StringCchCat(pszOS, BUFSIZE, osvi.szCSDVersion);
-	}
+        // Include service pack (if any) and build number.
 
-	char buf[80];
+        if(_tcslen(osvi.szCSDVersion) > 0) {
+            StringCchCat(pszOS, BUFSIZE, TEXT(" "));
+            StringCchCat(pszOS, BUFSIZE, osvi.szCSDVersion);
+        }
 
-	StringCchPrintf( buf, 80, TEXT(" (build %d)"), osvi.dwBuildNumber);
-	StringCchCat(pszOS, BUFSIZE, buf);
+        char buf[80];
+        StringCchPrintf(buf, 80, TEXT(" (build %d)"), osvi.dwBuildNumber);
+        StringCchCat(pszOS, BUFSIZE, buf);
 
-	if ( osvi.dwMajorVersion >= 6 )
-	{
-	    if ( si.wProcessorArchitecture==PROCESSOR_ARCHITECTURE_AMD64 )
-		StringCchCat(pszOS, BUFSIZE, TEXT( ", 64-bit" ));
-	    else if (si.wProcessorArchitecture==PROCESSOR_ARCHITECTURE_INTEL )
-		StringCchCat(pszOS, BUFSIZE, TEXT(", 32-bit"));
-	}
-      
-	return TRUE;
-    }
+        if (osvi.dwMajorVersion >= 6) {
+            if (si.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64)
+                StringCchCat(pszOS, BUFSIZE, TEXT(", 64-bit"));
+            else if (si.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_INTEL)
+                StringCchCat(pszOS, BUFSIZE, TEXT(", 32-bit"));
+        }
 
-    else
-    {  
-	//printf( "This sample does not support this version of Windows.\n");
-	return FALSE;
+        return TRUE;
+    } else {
+        // This sample does not support this version of Windows.
+        return FALSE;
     }
 }
 
-int HsOSVersionString(char *ptr, size_t bufsize)
+int unixcompat_os_version_string(char *ptr, size_t bufsize)
 {
     OSVERSIONINFOEX osvi;
     BOOL bOsVersionInfoEx;
@@ -336,44 +315,44 @@
     ZeroMemory(&osvi, sizeof(OSVERSIONINFOEX));
     osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
     bOsVersionInfoEx = GetVersionEx((OSVERSIONINFO*) &osvi);
-    
+
     if (bOsVersionInfoEx == 0)
-	return FALSE;
+        return FALSE;
 
     if (strncmp(osvi.szCSDVersion, "Service Pack ", 13) == 0)
-	szServicePack = "0";
+        szServicePack = "0";
     else
-	szServicePack = osvi.szCSDVersion + 13;
+        szServicePack = osvi.szCSDVersion + 13;
 
     StringCchPrintf(ptr, bufsize, "%ld.%ld.%s.%ld",
-		    osvi.dwMajorVersion, osvi.dwMinorVersion, szServicePack,
-		    osvi.dwBuildNumber);
+                    osvi.dwMajorVersion, osvi.dwMinorVersion, szServicePack,
+                    osvi.dwBuildNumber);
 
     return TRUE;
 }
 
-int HsOSArchString(char *ptr, size_t bufsize)
+int unixcompat_os_arch_string(char *ptr, size_t bufsize)
 {
     SYSTEM_INFO sysInfo;
 
     GetSystemInfo(&sysInfo);
 
     switch (sysInfo.wProcessorArchitecture) {
-    case PROCESSOR_ARCHITECTURE_INTEL:
-	StringCchCopy(ptr, bufsize, "i386");
-	break;
-    case PROCESSOR_ARCHITECTURE_AMD64:
-	StringCchCopy(ptr, bufsize, "x86_64");
-	break;
-    default:
-	StringCchCopy(ptr, bufsize, "unknown");
-	break;
+        case PROCESSOR_ARCHITECTURE_INTEL:
+            StringCchCopy(ptr, bufsize, "i386");
+            break;
+        case PROCESSOR_ARCHITECTURE_AMD64:
+            StringCchCopy(ptr, bufsize, "x86_64");
+            break;
+        default:
+            StringCchCopy(ptr, bufsize, "unknown");
+            break;
     }
 
     return TRUE;
 }
 
-int HsOSNodeName(char *ptr, size_t bufsize)
+int unixcompat_os_node_name(char *ptr, size_t bufsize)
 {
     DWORD sLength;
 
diff --git a/cbits/HsUnixCompat.c b/cbits/HsUnixCompat.c
--- a/cbits/HsUnixCompat.c
+++ b/cbits/HsUnixCompat.c
@@ -4,15 +4,17 @@
 #include <sys/mkdev.h>
 #endif
 
-unsigned int unix_major(dev_t dev) {
-  return major(dev);
+unsigned int unix_major(dev_t dev)
+{
+    return major(dev);
 }
 
-unsigned int unix_minor(dev_t dev) {
-  return minor(dev);
+unsigned int unix_minor(dev_t dev)
+{
+    return minor(dev);
 }
 
-dev_t unix_makedev(unsigned int maj, unsigned int min) {
-  return makedev(maj, min);
+dev_t unix_makedev(unsigned int maj, unsigned int min)
+{
+    return makedev(maj, min);
 }
-
diff --git a/cbits/mktemp.c b/cbits/mktemp.c
new file mode 100644
--- /dev/null
+++ b/cbits/mktemp.c
@@ -0,0 +1,172 @@
+/*
+ * Modified version of 'mktemp.c' from FreeBSD
+ * http://www.freebsd.org/cgi/cvsweb.cgi/src/lib/libc/stdio/mktemp.c
+ *     ?rev=1.29.2.2.2.1;content-type=text%2Fplain
+ */
+
+/*
+ * 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.
+ */
+
+#include <sys/param.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <windows.h>
+#include <wincrypt.h>
+
+static int random(uint32_t *);
+static int _gettemp(char *, int *);
+
+static const unsigned char padchar[] =
+"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
+
+int unixcompat_mkstemp(char *path)
+{
+	int fd;
+
+	if (_gettemp(path, &fd))
+        return fd;
+
+    return -1;
+}
+
+static int _gettemp(char *path, int *doopen)
+{
+	char *start, *trv, *suffp, *carryp;
+	char *pad;
+	struct stat sbuf;
+	int rval;
+	uint32_t randidx, randval;
+	char carrybuf[MAXPATHLEN];
+
+	for (trv = path; *trv != '\0'; ++trv)
+		;
+	if (trv - path >= MAXPATHLEN) {
+		errno = ENAMETOOLONG;
+		return (0);
+	}
+	suffp = trv;
+	--trv;
+	if (trv < path || NULL != strchr(suffp, '/')) {
+		errno = EINVAL;
+		return (0);
+	}
+
+	/* Fill space with random characters */
+	while (trv >= path && *trv == 'X') {
+        if (!random(&randval)) {
+            /* this should never happen */
+            errno = EIO;
+            return 0;
+        }
+		randidx = randval % (sizeof(padchar) - 1);
+		*trv-- = padchar[randidx];
+	}
+	start = trv + 1;
+
+	/* save first combination of random characters */
+	memcpy(carrybuf, start, suffp - start);
+
+	/*
+	 * check the target directory.
+	 */
+	if (doopen != NULL) {
+		for (; trv > path; --trv) {
+			if (*trv == '/') {
+				*trv = '\0';
+				rval = stat(path, &sbuf);
+				*trv = '/';
+				if (rval != 0)
+					return (0);
+				if (!S_ISDIR(sbuf.st_mode)) {
+					errno = ENOTDIR;
+					return (0);
+				}
+				break;
+			}
+		}
+	}
+
+	for (;;) {
+		if (doopen) {
+			if ((*doopen =
+			    _open(path, O_CREAT|O_EXCL|O_RDWR, 0600)) >= 0)
+				return (1);
+			if (errno != EEXIST)
+				return (0);
+		} else if (stat(path, &sbuf))
+			return (errno == ENOENT);
+
+		/* If we have a collision, cycle through the space of filenames */
+		for (trv = start, carryp = carrybuf;;) {
+			/* have we tried all possible permutations? */
+			if (trv == suffp)
+				return (0); /* yes - exit with EEXIST */
+			pad = strchr(padchar, *trv);
+			if (pad == NULL) {
+				/* this should never happen */
+				errno = EIO;
+				return (0);
+			}
+			/* increment character */
+			*trv = (*++pad == '\0') ? padchar[0] : *pad;
+			/* carry to next position? */
+			if (*trv == *carryp) {
+				/* increment position and loop */
+				++trv;
+				++carryp;
+			} else {
+				/* try with new name */
+				break;
+			}
+		}
+	}
+	/*NOTREACHED*/
+}
+
+static int random(uint32_t *value)
+{
+    /* This handle is never released. Windows will clean up when the process
+     * exits. Python takes this approach when emulating /dev/urandom, and if
+     * it's good enough for them, then it's good enough for us. */
+    static HCRYPTPROV context = 0;
+
+    if (context == 0)
+        if (!CryptAcquireContext(
+                &context, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT))
+            return 0;
+
+    if (!CryptGenRandom(context, sizeof *value, (BYTE *)value))
+        return 0;
+
+    return 1;
+}
diff --git a/src/System/PosixCompat.hs b/src/System/PosixCompat.hs
--- a/src/System/PosixCompat.hs
+++ b/src/System/PosixCompat.hs
@@ -1,27 +1,33 @@
+{-# LANGUAGE CPP #-}
+
 {-|
 The @unix-compat@ package provides portable implementations of parts of the
 @unix@ package. On POSIX system it re-exports operations from the @unix@
 package, on other platforms it emulates the operations as far as possible.
 -}
 module System.PosixCompat (
-    module System.PosixCompat.Files,
-    module System.PosixCompat.Time,
-    module System.PosixCompat.Types,
-    module System.PosixCompat.User,
-    usingPortableImpl
-  ) where
+      module System.PosixCompat.Files
+    , module System.PosixCompat.Temp
+    , module System.PosixCompat.Time
+    , module System.PosixCompat.Types
+    , module System.PosixCompat.Unistd
+    , module System.PosixCompat.User
+    , usingPortableImpl
+    ) where
 
 import System.PosixCompat.Files
+import System.PosixCompat.Temp
 import System.PosixCompat.Time
 import System.PosixCompat.Types
+import System.PosixCompat.Unistd
 import System.PosixCompat.User
 
 -- | 'True' if unix-compat is using its portable implementation,
 --   or 'False' if the unix package is simply being re-exported.
 usingPortableImpl :: Bool
-#ifdef UNIX_IMPL
-usingPortableImpl = False
-#else
+#ifdef mingw32_HOST_OS
 usingPortableImpl = True
+#else
+usingPortableImpl = False
 #endif
 
diff --git a/src/System/PosixCompat/Extensions.hsc b/src/System/PosixCompat/Extensions.hsc
--- a/src/System/PosixCompat/Extensions.hsc
+++ b/src/System/PosixCompat/Extensions.hsc
@@ -1,12 +1,18 @@
+{-# LANGUAGE CPP #-}
+{-# LANGUAGE ForeignFunctionInterface #-}
+
 -- | This module provides some functions not present in the unix package.
 module System.PosixCompat.Extensions (
-         -- * Device IDs.
-         CMajor, CMinor,
-         deviceMajor, deviceMinor, makeDeviceID
-   ) where
+    -- * Device IDs.
+      CMajor
+    , CMinor
+    , deviceMajor
+    , deviceMinor
+    , makeDeviceID
+    ) where
 
 
-#ifdef UNIX_IMPL
+#ifndef mingw32_HOST_OS
 #include "HsUnixCompat.h"
 #endif
 
@@ -21,33 +27,32 @@
 --
 -- The portable implementation always returns @0@.
 deviceMajor :: DeviceID -> CMajor
-#ifdef UNIX_IMPL
+#ifdef mingw32_HOST_OS
+deviceMajor _ = 0
+#else
 deviceMajor dev = unix_major dev
 
 foreign import ccall unsafe "unix_major" unix_major :: CDev -> CUInt
-#else
-deviceMajor _ = 0
 #endif
 
 -- | Gets the minor number from a 'DeviceID' for a device file.
 --
 -- The portable implementation always returns @0@.
 deviceMinor :: DeviceID -> CMinor
-#ifdef UNIX_IMPL
+#ifdef mingw32_HOST_OS
+deviceMinor _ = 0
+#else
 deviceMinor dev = unix_minor dev
 
 foreign import ccall unsafe "unix_minor" unix_minor :: CDev -> CUInt
-#else
-deviceMinor _ = 0
 #endif
 
 -- | Creates a 'DeviceID' for a device file given a major and minor number.
 makeDeviceID :: CMajor -> CMinor -> DeviceID
-#ifdef UNIX_IMPL
+#ifdef mingw32_HOST_OS
+makeDeviceID _ _ = 0
+#else
 makeDeviceID ma mi = unix_makedev ma mi
 
 foreign import ccall unsafe "unix_makedev" unix_makedev :: CUInt -> CUInt -> CDev
-#else
-makeDeviceID _ _ = 0
 #endif
-
diff --git a/src/System/PosixCompat/Files.hsc b/src/System/PosixCompat/Files.hsc
--- a/src/System/PosixCompat/Files.hsc
+++ b/src/System/PosixCompat/Files.hsc
@@ -1,3 +1,5 @@
+{-# LANGUAGE CPP #-}
+
 {-|
 This module makes the operations exported by @System.Posix.Files@
 available on all platforms. On POSIX systems it re-exports operations from
@@ -10,59 +12,96 @@
 module System.PosixCompat.Files (
     -- * File modes
     -- FileMode exported by System.Posix.Types
-    unionFileModes, intersectFileModes,
-    nullFileMode,
-    ownerReadMode, ownerWriteMode, ownerExecuteMode, ownerModes,
-    groupReadMode, groupWriteMode, groupExecuteMode, groupModes,
-    otherReadMode, otherWriteMode, otherExecuteMode, otherModes,
-    setUserIDMode, setGroupIDMode,
-    stdFileMode,   accessModes,
+      unionFileModes
+    , intersectFileModes
+    , nullFileMode
+    , ownerReadMode
+    , ownerWriteMode
+    , ownerExecuteMode
+    , ownerModes
+    , groupReadMode
+    , groupWriteMode
+    , groupExecuteMode
+    , groupModes
+    , otherReadMode
+    , otherWriteMode
+    , otherExecuteMode
+    , otherModes
+    , setUserIDMode
+    , setGroupIDMode
+    , stdFileMode
+    , accessModes
 
     -- ** Setting file modes
-    setFileMode, setFdMode, setFileCreationMask,
+    , setFileMode
+    , setFdMode
+    , setFileCreationMask
 
     -- ** Checking file existence and permissions
-    fileAccess, fileExist,
+    , fileAccess
+    , fileExist
 
     -- * File status
-    FileStatus,
+    , FileStatus
     -- ** Obtaining file status
-    getFileStatus, getFdStatus, getSymbolicLinkStatus,
+    , getFileStatus
+    , getFdStatus
+    , getSymbolicLinkStatus
     -- ** Querying file status
-    deviceID, fileID, fileMode, linkCount, fileOwner, fileGroup,
-    specialDeviceID, fileSize, accessTime, modificationTime,
-    statusChangeTime,
-    isBlockDevice, isCharacterDevice, isNamedPipe, isRegularFile,
-    isDirectory, isSymbolicLink, isSocket,
+    , deviceID
+    , fileID
+    , fileMode
+    , linkCount
+    , fileOwner
+    , fileGroup
+    , specialDeviceID
+    , fileSize
+    , accessTime
+    , modificationTime
+    , statusChangeTime
+    , isBlockDevice
+    , isCharacterDevice
+    , isNamedPipe
+    , isRegularFile
+    , isDirectory
+    , isSymbolicLink
+    , isSocket
 
     -- * Creation
-    createNamedPipe,
-    createDevice,
+    , createNamedPipe
+    , createDevice
 
     -- * Hard links
-    createLink, removeLink,
+    , createLink
+    , removeLink
 
     -- * Symbolic links
-    createSymbolicLink, readSymbolicLink,
+    , createSymbolicLink
+    , readSymbolicLink
 
     -- * Renaming files
-    rename,
+    , rename
 
     -- * Changing file ownership
-    setOwnerAndGroup,  setFdOwnerAndGroup,
-    setSymbolicLinkOwnerAndGroup,
+    , setOwnerAndGroup
+    , setFdOwnerAndGroup
+    , setSymbolicLinkOwnerAndGroup
 
     -- * Changing file timestamps
-    setFileTimes, touchFile,
+    , setFileTimes
+    , touchFile
 
     -- * Setting file sizes
-    setFileSize, setFdSize,
+    , setFileSize
+    , setFdSize
 
     -- * Find system-specific limits for a file
-    PathVar(..), getPathVar, getFdPathVar,
- ) where
+    , PathVar(..)
+    , getPathVar
+    , getFdPathVar
+    ) where
 
-#ifdef UNIX_IMPL
+#ifndef mingw32_HOST_OS
 
 #include "HsUnixCompat.h"
 
diff --git a/src/System/PosixCompat/Temp.hs b/src/System/PosixCompat/Temp.hs
new file mode 100644
--- /dev/null
+++ b/src/System/PosixCompat/Temp.hs
@@ -0,0 +1,53 @@
+{-# LANGUAGE CPP #-}
+{-# LANGUAGE ForeignFunctionInterface #-}
+
+{-|
+This module makes the operations exported by @System.Posix.Temp@
+available on all platforms. On POSIX systems it re-exports operations from
+@System.Posix.Temp@, on other platforms it emulates the operations as far
+as possible.
+-}
+module System.PosixCompat.Temp (
+      mkstemp
+    ) where
+
+#ifndef mingw32_HOST_OS
+-- Re-export unix package
+
+import System.Posix.Temp
+
+#elif defined(__GLASGOW_HASKELL__)
+-- Windows w/ GHC, we have fdToHandle so we
+-- can use our own implementation of mkstemp.
+
+import System.IO (Handle)
+import Foreign.C (CInt, CString, withCString, peekCString, throwErrnoIfMinus1)
+import GHC.IO.Handle.FD (fdToHandle)
+
+-- | 'mkstemp' - make a unique filename and open it for
+-- reading\/writing.
+-- The returned 'FilePath' is the (possibly relative) path of
+-- the created file, which is padded with 6 random characters.
+mkstemp :: String -> IO (FilePath, Handle)
+mkstemp template = do
+  withCString template $ \ ptr -> do
+    fd <- throwErrnoIfMinus1 "mkstemp" (c_mkstemp ptr)
+    name <- peekCString ptr
+    h <- fdToHandle (fromIntegral fd)
+    return (name, h)
+
+foreign import ccall unsafe "unixcompat_mkstemp"
+    c_mkstemp :: CString -> IO CInt
+
+#else
+-- Windows w/o GHC, we don't have fdToHandle :(
+
+import System.IO (Handle)
+import System.IO.Error (mkIOError, illegalOperationErrorType)
+
+mkstemp :: String -> IO (FilePath, Handle)
+mkstemp _ = ioError $ mkIOError illegalOperationErrorType x Nothing Nothing
+  where
+    x = "System.PosixCompat.Temp.mkstemp: not supported"
+
+#endif
diff --git a/src/System/PosixCompat/Time.hs b/src/System/PosixCompat/Time.hs
--- a/src/System/PosixCompat/Time.hs
+++ b/src/System/PosixCompat/Time.hs
@@ -1,3 +1,5 @@
+{-# LANGUAGE CPP #-}
+
 {-|
 This module makes the operations exported by @System.Posix.Time@
 available on all platforms. On POSIX systems it re-exports operations from
@@ -5,10 +7,10 @@
 as possible.
 -}
 module System.PosixCompat.Time (
-    epochTime,
-  ) where
+      epochTime
+    ) where
 
-#ifdef UNIX_IMPL
+#ifndef mingw32_HOST_OS
 
 import System.Posix.Time
 
diff --git a/src/System/PosixCompat/Types.hs b/src/System/PosixCompat/Types.hs
--- a/src/System/PosixCompat/Types.hs
+++ b/src/System/PosixCompat/Types.hs
@@ -1,3 +1,6 @@
+{-# LANGUAGE CPP #-}
+{-# LANGUAGE GeneralizedNewtypeDeriving #-}
+
 {-|
 This module re-exports the types from @System.Posix.Types@ on all platforms.
 
@@ -5,15 +8,17 @@
 redefined by this module.
 -}
 module System.PosixCompat.Types (
-    module System.Posix.Types,
-#ifdef MISSING_POSIX_TYPES
-    UserID, GroupID, LinkCount
+      module System.Posix.Types
+#ifdef mingw32_HOST_OS
+    , UserID
+    , GroupID
+    , LinkCount
 #endif
-  ) where
+    ) where
 
 import System.Posix.Types
 
-#ifdef MISSING_POSIX_TYPES
+#ifdef mingw32_HOST_OS
 
 import Data.Word (Word32)
 
@@ -36,4 +41,3 @@
                                               | (x,s') <- readsPrec i s]
 
 #endif
-
diff --git a/src/System/PosixCompat/Unistd.hs b/src/System/PosixCompat/Unistd.hs
--- a/src/System/PosixCompat/Unistd.hs
+++ b/src/System/PosixCompat/Unistd.hs
@@ -1,3 +1,4 @@
+{-# LANGUAGE CPP #-}
 {-# LANGUAGE ForeignFunctionInterface #-}
 
 {-|
@@ -6,8 +7,7 @@
 @System.Posix.Unistd@, on other platforms it emulates the operations as far
 as possible.
 -}
-module System.PosixCompat.Unistd
-    (
+module System.PosixCompat.Unistd (
     -- * System environment
       SystemID(..)
     , getSystemID
@@ -17,7 +17,7 @@
     , nanosleep
     ) where
 
-#ifdef UNIX_IMPL
+#ifndef mingw32_HOST_OS
 
 import System.Posix.Unistd
 
@@ -40,21 +40,21 @@
 getSystemID = do
   let bufSize = 256
   let call f = allocaArray bufSize $ \buf -> do
-	ok <- f buf (fromIntegral bufSize)
-	if ok == 1
-	  then peekCString buf
-	  else return ""
-  display <- call c_HsOSDisplayString
-  vers <- call c_HsOSVersionString
-  arch <- call c_HsOSArchString
-  node <- call c_HsOSNodeName
+        ok <- f buf (fromIntegral bufSize)
+        if ok == 1
+          then peekCString buf
+          else return ""
+  display <- call c_os_display_string
+  vers <- call c_os_version_string
+  arch <- call c_os_arch_string
+  node <- call c_os_node_name
   return SystemID {
            systemName = "Windows"
-	 , nodeName = node
-	 , release = display
+         , nodeName = node
+         , release = display
          , version = vers
-	 , machine = arch
-	 }
+         , machine = arch
+         }
 
 -- | Sleep for the specified duration (in seconds). Returns the time
 -- remaining (if the sleep was interrupted by a signal, for example).
@@ -86,16 +86,16 @@
 nanosleep :: Integer -> IO ()
 nanosleep nsecs = threadDelay (round (fromIntegral nsecs / 1000 :: Double))
 
-foreign import ccall "HsOSDisplayString" c_HsOSDisplayString
-    :: CString -> CSize -> IO CInt
+foreign import ccall "unixcompat_os_display_string"
+    c_os_display_string :: CString -> CSize -> IO CInt
 
-foreign import ccall "HsOSVersionString" c_HsOSVersionString
-    :: CString -> CSize -> IO CInt
+foreign import ccall "unixcompat_os_version_string"
+    c_os_version_string :: CString -> CSize -> IO CInt
 
-foreign import ccall "HsOSArchString" c_HsOSArchString
-    :: CString -> CSize -> IO CInt
+foreign import ccall "unixcompat_os_arch_string"
+    c_os_arch_string :: CString -> CSize -> IO CInt
 
-foreign import ccall "HsOSNodeName" c_HsOSNodeName
-    :: CString -> CSize -> IO CInt
+foreign import ccall "unixcompat_os_node_name"
+    c_os_node_name :: CString -> CSize -> IO CInt
 
 #endif
diff --git a/src/System/PosixCompat/User.hsc b/src/System/PosixCompat/User.hsc
--- a/src/System/PosixCompat/User.hsc
+++ b/src/System/PosixCompat/User.hsc
@@ -1,3 +1,5 @@
+{-# LANGUAGE CPP #-}
+
 {-|
 This module makes the operations exported by @System.Posix.User@
 available on all platforms. On POSIX systems it re-exports operations from
@@ -6,32 +8,32 @@
 module System.PosixCompat.User (
     -- * User environment
     -- ** Querying the user environment
-    getRealUserID,
-    getRealGroupID,
-    getEffectiveUserID,
-    getEffectiveGroupID,
-    getGroups,
-    getLoginName,
-    getEffectiveUserName,
+      getRealUserID
+    , getRealGroupID
+    , getEffectiveUserID
+    , getEffectiveGroupID
+    , getGroups
+    , getLoginName
+    , getEffectiveUserName
 
     -- *** The group database
-    GroupEntry(..),
-    getGroupEntryForID,
-    getGroupEntryForName,
-    getAllGroupEntries,
+    , GroupEntry(..)
+    , getGroupEntryForID
+    , getGroupEntryForName
+    , getAllGroupEntries
 
     -- *** The user database
-    UserEntry(..),
-    getUserEntryForID,
-    getUserEntryForName,
-    getAllUserEntries,
+    , UserEntry(..)
+    , getUserEntryForID
+    , getUserEntryForName
+    , getAllUserEntries
 
     -- ** Modifying the user environment
-    setUserID,
-    setGroupID
-  ) where
+    , setUserID
+    , setGroupID
+    ) where
 
-#ifdef UNIX_IMPL
+#ifndef mingw32_HOST_OS
 
 #include "HsUnixCompat.h"
 
diff --git a/unix-compat.cabal b/unix-compat.cabal
--- a/unix-compat.cabal
+++ b/unix-compat.cabal
@@ -1,5 +1,5 @@
 name:           unix-compat
-version:        0.2.2.1
+version:        0.3
 synopsis:       Portable POSIX-compatibility layer.
 description:    This package provides portable implementations of parts
                 of the unix package. This package re-exports the unix
@@ -19,42 +19,34 @@
   type:     git
   location: git://github.com/jystic/unix-compat.git
 
-Flag portable
-  default: False
-  description: Force compiling in portable mode, useful for testing.
-
 Library
   hs-source-dirs: src
+  ghc-options: -Wall
+  build-depends: base == 4.*
 
   exposed-modules:
     System.PosixCompat
     System.PosixCompat.Extensions
     System.PosixCompat.Files
+    System.PosixCompat.Temp
     System.PosixCompat.Time
     System.PosixCompat.Types
     System.PosixCompat.Unistd
     System.PosixCompat.User
-  extensions: CPP
-  ghc-options: -Wall
-  build-depends: base == 4.*
 
-  if flag(portable) || os(windows)
+  if os(windows)
     build-depends: old-time == 1.0.*
-    extensions: GeneralizedNewtypeDeriving
+    c-sources:
+      cbits/HsUname.c
+      cbits/mktemp.c
 
     if impl(ghc < 7)
       build-depends: directory == 1.0.*
       cpp-options: -DDIRECTORY_1_0
     else
       build-depends: directory == 1.1.*
-
-    if os(windows)
-      cpp-options: -DMISSING_POSIX_TYPES
-      c-sources: cbits/HsUname.c
   else
     build-depends: unix >= 2.4 && < 2.6
-    extensions: ForeignFunctionInterface
-    cpp-options: -DUNIX_IMPL
     include-dirs: include
     includes: HsUnixCompat.h
     install-includes: HsUnixCompat.h
