Reputation: 878
The .net framework has GetTempFileName, which goes straight to the Windows API procedure of the same name, and as far as I know is a threadsafe way to create a temporary file with a name not previously in use. It's hilariously outdated and limited, but as far as I know it works, as long as you keep your temp directory from filling up.
But I don't see anything that'll work even that well for creating temporary folders. In a contentious parallel environment such as a web server, I don't see any way to avoid race conditions between testing whether a folder name is in use, and creating it. This could I suppose be doable with unmanaged API code, but there may be institutional resistance to such a solution. Is there a better way?
And if there is, can it be extended back to temp file creation, so I don't have to use GetTempFileName with its four hex digits of variation?
-- To those who think this is a duplicate: the linked other question did not really address thread safety. And I have to develop for a situation where thread safety is a very serious concern -- we could have 32 cores running with every one of them attempting to create batches of a hundred or a thousand temp files apiece.
-- UPDATE: the book Secure Programming with Static Analysis by Chess and West says that GetTempFileName “suffers from an inherent underlying race condition”. So maybe that ain't safe either.
Upvotes: 1
Views: 672
Reputation: 704
@paul-kienitz FWIW: according to the documentation of CreateDirectory(), the function returns ERROR_ALREADY_EXISTS
if the directory already existed, which gives you an atomic check for collisions. So you can safely create a new temp directory if you combine the random name approach (using CoCreateGuid()
) with a limited number of retries (e.g. 9 retries), after which you fail. The retries will exponentially lower the collision probability to a value which even satisfies paranoids.
Upvotes: 0
Reputation: 45789
If you want to create a unique temporary directory, a combination of Path.GetTempPath
and Guid.NewGuid
should do the trick quite nicely:
string GetUniqueTempPath()
{
var tempPath = Path.GetTempPath();
var uniqueDirectoryName = Guid.NewGuid().ToString();
var uniqueTempPath = Path.Combine(tempPath, uniqueDirectoryName);
return uniqueTempPath;
}
The fact that a GUID is being used as part of the path should eliminate any race condition as there's pretty much no chance that the composite directory name will exist so there's no (real) need to check prior to attempting to create it.
Upvotes: 4