summaryrefslogtreecommitdiff
path: root/libraries/base/cbits
diff options
context:
space:
mode:
authorTamar Christina <tamar@zhox.com>2018-01-02 16:02:49 -0500
committerBen Gamari <ben@smart-cactus.org>2018-01-02 17:33:04 -0500
commit46287af0911f7cb446c62850630f85af567ac512 (patch)
tree6447e46470669753746a2da83391347781e77eae /libraries/base/cbits
parent27b7b4db9af99aeb88dce7ef0e85131199bbf2ff (diff)
downloadhaskell-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.c45
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