X-Git-Url: http://git.megacz.com/?a=blobdiff_plain;f=cbits%2FdirUtils.c;h=86b36579176d2adcc2e9bdb912d970333ba821f0;hb=dd70cacd4793c4497136829c50ef31f330163638;hp=316a689e7db3ac239b9288bbacd62187c2633a72;hpb=25955bc845f3680632b6230148f1a39d6a5c1e88;p=ghc-base.git diff --git a/cbits/dirUtils.c b/cbits/dirUtils.c index 316a689..86b3657 100644 --- a/cbits/dirUtils.c +++ b/cbits/dirUtils.c @@ -4,20 +4,54 @@ * Directory Runtime Support */ -#include "config.h" +#include "ghcconfig.h" // The following is required on Solaris to force the POSIX versions of // the various _r functions instead of the Solaris versions. -#ifdef solaris2_TARGET_OS +#ifdef solaris2_HOST_OS #define _POSIX_PTHREAD_SEMANTICS #endif #include "HsBase.h" -#if defined(mingw32_TARGET_OS) +#if defined(mingw32_HOST_OS) || defined(__MINGW32__) || defined(_MSC_VER) #include + +static +int +toErrno(DWORD rc) +{ + switch (rc) { + case ERROR_FILE_NOT_FOUND: return ENOENT; + case ERROR_PATH_NOT_FOUND: return ENOENT; + case ERROR_TOO_MANY_OPEN_FILES: return EMFILE; + case ERROR_ACCESS_DENIED: return EACCES; + case ERROR_INVALID_HANDLE: return EBADF; /* kinda sorta */ + case ERROR_NOT_ENOUGH_MEMORY: return ENOMEM; + case ERROR_INVALID_ACCESS: return EINVAL; + case ERROR_INVALID_DATA: return EINVAL; + case ERROR_OUTOFMEMORY: return ENOMEM; + case ERROR_SHARING_VIOLATION: return EACCES; + case ERROR_LOCK_VIOLATION: return EACCES; + case ERROR_ALREADY_EXISTS: return EEXIST; + case ERROR_BUSY: return EBUSY; + case ERROR_BROKEN_PIPE: return EPIPE; + case ERROR_PIPE_CONNECTED: return EBUSY; + case ERROR_PIPE_LISTENING: return EBUSY; + case ERROR_NOT_CONNECTED: return EINVAL; + + case ERROR_NOT_OWNER: return EPERM; + case ERROR_DIRECTORY: return ENOTDIR; + case ERROR_FILE_INVALID: return EACCES; + case ERROR_FILE_EXISTS: return EEXIST; + + default: + return rc; + } +} #endif + /* * read an entry from the directory stream; opt for the * re-entrant friendly way of doing this, if available. @@ -29,12 +63,12 @@ __hscore_readdir( HsAddr dirPtr, HsAddr pDirEnt ) #if HAVE_READDIR_R struct dirent* p; int res; - static unsigned int nm_max = -1; + static unsigned int nm_max = (unsigned int)-1; if (pDirE == NULL) { return -1; } - if (nm_max == -1) { + if (nm_max == (unsigned int)-1) { #ifdef NAME_MAX nm_max = NAME_MAX + 1; #else @@ -47,7 +81,11 @@ __hscore_readdir( HsAddr dirPtr, HsAddr pDirEnt ) if (p == NULL) return -1; res = readdir_r((DIR*)dirPtr, p, pDirE); if (res != 0) { - *pDirE = NULL; + *pDirE = NULL; + free(p); + } + else if (*pDirE == NULL) { + // end of stream free(p); } return res; @@ -79,21 +117,20 @@ HsInt __hscore_renameFile( HsAddr src, HsAddr dest) { -#if defined(_MSC_VER) || defined(_WIN32) +#if defined(mingw32_HOST_OS) || defined(__MINGW32__) || defined(_MSC_VER) static int forNT = -1; - DWORD rc; /* ToDo: propagate error codes back */ if (MoveFileA(src, dest)) { return 0; } else { - rc = GetLastError(); + ; } /* Failed...it could be because the target already existed. */ if ( !GetFileAttributes(dest) ) { /* No, it's not there - just fail. */ - errno = 0; + errno = toErrno(GetLastError()); return (-1); } @@ -101,7 +138,7 @@ __hscore_renameFile( HsAddr src, OSVERSIONINFO ovi; ovi.dwOSVersionInfoSize = sizeof(ovi); if ( !GetVersionEx(&ovi) ) { - errno = 0; + errno = toErrno(GetLastError()); return (-1); } forNT = ((ovi.dwPlatformId & VER_PLATFORM_WIN32_NT) != 0); @@ -112,7 +149,7 @@ __hscore_renameFile( HsAddr src, if ( MoveFileExA(src, dest, MOVEFILE_REPLACE_EXISTING) ) { return 0; } else { - errno = 0; + errno = toErrno(GetLastError()); return (-1); } } @@ -123,11 +160,11 @@ __hscore_renameFile( HsAddr src, if (MoveFileA(src,dest)) { return 0; } else { - errno = 0; + errno = toErrno(GetLastError()); return (-1); } } else { - errno = 0; + errno = toErrno(GetLastError()); return (-1); } #else @@ -135,3 +172,45 @@ __hscore_renameFile( HsAddr src, #endif } +/* + * Function: __hscore_getFolderPath() + * + * Late-bound version of SHGetFolderPath(), coping with OS versions + * that have shell32's lacking that particular API. + * + */ +#if defined(mingw32_HOST_OS) || defined(__MINGW32__) || defined(_MSC_VER) +typedef HRESULT (*HSCORE_GETAPPFOLDERFUNTY)(HWND,int,HANDLE,DWORD,char*); +int +__hscore_getFolderPath(HWND hwndOwner, + int nFolder, + HANDLE hToken, + DWORD dwFlags, + char* pszPath) +{ + static int loaded_dll = 0; + static HMODULE hMod = (HMODULE)NULL; + static HSCORE_GETAPPFOLDERFUNTY funcPtr = NULL; + + if (loaded_dll < 0) { + return (-1); + } else if (loaded_dll == 0) { + hMod = LoadLibrary("shell32.dll"); + if (hMod == NULL) { + loaded_dll = (-1); + return (-1); + } else { + funcPtr = (HSCORE_GETAPPFOLDERFUNTY)GetProcAddress(hMod, "SHGetFolderPathA"); + if (!funcPtr) { + loaded_dll = (-1); + return (-1); + } else { + loaded_dll = 1; + } + } + } + /* OK, if we got this far the function has been bound */ + return (int)funcPtr(hwndOwner,nFolder,hToken,dwFlags,pszPath); + /* ToDo: unload the DLL? */ +} +#endif