unix-compat 0.2.2.1 → 0.3
raw patch · 13 files changed
+586/−327 lines, 13 filesPVP ok
version bump matches the API change (PVP)
API changes (from Hackage documentation)
+ System.PosixCompat.Temp: mkstemp :: String -> IO (FilePath, Handle)
Files
- LICENSE +4/−1
- cbits/HsUname.c +179/−200
- cbits/HsUnixCompat.c +9/−7
- cbits/mktemp.c +172/−0
- src/System/PosixCompat.hs +15/−9
- src/System/PosixCompat/Extensions.hsc +20/−15
- src/System/PosixCompat/Files.hsc +67/−28
- src/System/PosixCompat/Temp.hs +53/−0
- src/System/PosixCompat/Time.hs +5/−3
- src/System/PosixCompat/Types.hs +10/−6
- src/System/PosixCompat/Unistd.hs +23/−23
- src/System/PosixCompat/User.hsc +21/−19
- unix-compat.cabal +8/−16
LICENSE view
@@ -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
cbits/HsUname.c view
@@ -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;
cbits/HsUnixCompat.c view
@@ -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); }-
+ cbits/mktemp.c view
@@ -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;+}
src/System/PosixCompat.hs view
@@ -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
src/System/PosixCompat/Extensions.hsc view
@@ -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-
src/System/PosixCompat/Files.hsc view
@@ -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"
+ src/System/PosixCompat/Temp.hs view
@@ -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
src/System/PosixCompat/Time.hs view
@@ -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
src/System/PosixCompat/Types.hs view
@@ -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-
src/System/PosixCompat/Unistd.hs view
@@ -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
src/System/PosixCompat/User.hsc view
@@ -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"
unix-compat.cabal view
@@ -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