diff options
author | Tamar Christina <tamar@zhox.com> | 2018-01-02 16:02:49 -0500 |
---|---|---|
committer | Ben Gamari <ben@smart-cactus.org> | 2018-01-02 17:33:04 -0500 |
commit | 46287af0911f7cb446c62850630f85af567ac512 (patch) | |
tree | 6447e46470669753746a2da83391347781e77eae /libraries/base/cbits | |
parent | 27b7b4db9af99aeb88dce7ef0e85131199bbf2ff (diff) | |
download | haskell-46287af0911f7cb446c62850630f85af567ac512.tar.gz |
Make System.IO.openTempFile thread-safe on Windows
This calls out to the Win32 API `GetTempFileName` to generate
a temporary file. Using `uUnique = 0` guarantees that the file
we get back is unique and the file is "reserved" by creating it.
Test Plan:
./validate
I can't think of any sensible tests that shouldn't run for a while
to verify. So the example in #10731 was ran for a while and no
collisions in new code
Reviewers: hvr, bgamari, erikd
Reviewed By: bgamari
Subscribers: RyanGlScott, rwbarton, thomie, carter
GHC Trac Issues: #10731
Differential Revision: https://phabricator.haskell.org/D4278
Diffstat (limited to 'libraries/base/cbits')
-rw-r--r-- | libraries/base/cbits/Win32Utils.c | 45 |
1 files changed, 44 insertions, 1 deletions
diff --git a/libraries/base/cbits/Win32Utils.c b/libraries/base/cbits/Win32Utils.c index 965adc2902..ce7ce97fc0 100644 --- a/libraries/base/cbits/Win32Utils.c +++ b/libraries/base/cbits/Win32Utils.c @@ -1,12 +1,16 @@ /* ---------------------------------------------------------------------------- (c) The University of Glasgow 2006 - + Useful Win32 bits ------------------------------------------------------------------------- */ #if defined(_WIN32) #include "HsBase.h" +#include <stdbool.h> +#include <stdint.h> +#include <wchar.h> +#include <windows.h> /* This is the error table that defines the mapping between OS error codes and errno values */ @@ -148,4 +152,43 @@ BOOL file_exists(LPCTSTR path) return r != INVALID_FILE_ATTRIBUTES; } +bool getTempFileNameErrorNo (wchar_t* pathName, wchar_t* prefix, + wchar_t* suffix, uint32_t uUnique, + wchar_t* tempFileName) +{ + if (!GetTempFileNameW(pathName, prefix, uUnique, tempFileName)) + { + maperrno(); + return false; + } + + wchar_t* drive = malloc (sizeof(wchar_t) * _MAX_DRIVE); + wchar_t* dir = malloc (sizeof(wchar_t) * _MAX_DIR); + wchar_t* fname = malloc (sizeof(wchar_t) * _MAX_FNAME); + bool success = true; + if (_wsplitpath_s (tempFileName, drive, _MAX_DRIVE, dir, _MAX_DIR, + fname, _MAX_FNAME, NULL, 0) != 0) + { + success = false; + maperrno (); + } + else + { + wchar_t* temp = _wcsdup (tempFileName); + if (wcsnlen(drive, _MAX_DRIVE) == 0) + swprintf_s(tempFileName, MAX_PATH, L"%s\%s%s", + dir, fname, suffix); + else + swprintf_s(tempFileName, MAX_PATH, L"%s\%s\%s%s", + drive, dir, fname, suffix); + MoveFileW(temp, tempFileName); + free(temp); + } + + free(drive); + free(dir); + free(fname); + + return success; +} #endif |