So you wanna create a temporary file?
You’re in C, on Windows, and you want to create a temporary file. Ideally it would be:
- Cross-platform
- Guarantee a unique name
- Support SBCS/MBCS/Unicode
- Allow you to have some control over where the file goes
- Automatically delete itself when you close it or the process exits.
You wish. There are at least four primary ways of creating a temporary file (if you include the Secure CRT, Unicode, MBCS, and TCHAR versions then there are at least 12)! Each of these provides one or two of the ideal features above, with a few providing more when used in combination with other functions. None of them provides all of these features.
In this post we discuss what our basic options are when creating a temporary file on Windows in C. In Part 2 we’ll discuss which method I prefer and how I’ve implemented it.
So tell me, What are my Options?
tmpnam
Creates a unique filename for the current-working directory of the process
- Pros:
- Part of the ISO C Standard
- Cons
- No unicode support
- Potentially unsafe if the parameter is non-NULL and insufficiently sized
- Race condition 1 – If the str parameter NULL, the returned str points to an internal static buffer that will be overwritten by subsequent calls from the same process.
- Race condition 2 – The function only generates filenames which are unique when they are created. By the time the file is opened, it is possible that another process has already created a file with the same name.
_wtmpnam
Unicode version of tmpnam
Pros/Cons are the same as tmpnam, except it supports UNICODE instead of SBCS/MBCS and is Windows-only.
_ttmpnam
Generic-Text Routine Mapping. Used with TCHAR to map to tmpnam in MBCS builds and _wtmpnam in UNICODE builds.
Pros/Cons are the same as tmpnam/_wtmpnam except it can support either MBCS/UNICODE at build time and is Windows-only
tmpnam_s
Security-Enhanced CRT version of tmpnam
- Pros:
- Security enhancements (avoids buffer overflow and ensures null termination of string)
- Cons:
- Unique filenames in CWD only
- No unicode support
- Race condition 1 (see tmpnam above)
- Race condition 2 (see tmpnam above)
- Windows-only
_wtmpnam_s
Unicode version of tmpnam_s
Pros/Cons are the same as tmpnam_s, except it supports UNICODE instead of SBCS/MBCS.
_ttmpnam_s
Generic-Text Routine Mapping. Used with TCHAR to map to tempnam in MBCS builds and _wtempnam in UNICODE builds.
Pros/Cons are the same as _ttmpnam_s/_wtmpnam_s except it can support either MBCS/UNICODE at build time
_tempnam
From MSDN:
“_tempnam will generate a unique file name for a directory chosen by the following rules:
– If the TMP environment variable is defined and set to a valid directory name, unique file names will be generated for the directory specified by TMP.
– If the TMP environment variable is not defined or if it is set to the name of a directory that does not exist, _tempnam will use the dir parameter as the path for which it will generate unique names.
– If the TMP environment variable is not defined or if it is set to the name of a directory that does not exist, and if dir is either NULL or set to the name of a directory that does not exist, _tempnam will use the current working directory to generate unique names. Currently, if both TMP and dir specify names of directories that do not exist, the _tempnam function call will fail.The name returned by _tempnam will be a concatenation of prefix and a sequential number, which will combine to create a unique file name for the specified directory. _tempnam generates file names that have no extension. _tempnam uses malloc to allocate space for the filename; the program is responsible for freeing this space when it is no longer needed.”
- Pros:
- There is a way to use a directory other than the default
- Allocates memory for the return call so you don’t have to guess the size ahead of time
- Cons:
- Using a directory other than the default requires changing environment variables for the entire process
- Holy crap, did you see how complex the rules are just to get a stupid temporary file name?!
- Only creates a filename, not a file so Race Condition 2 applies again.
- No Unicode support
- Allocates memory that the caller has to remember to free (I like to keep my mallocs and frees matched as close together as possible)
- Windows-only
_wtempnam
Unicode version of _tempnam
Pros/Cons are the same as _tempnam, except it supports UNICODE instead of SBCS/MBCS
_ttempnam
Generic-Text Routine Mapping. Used with TCHAR to map to tempnam in MBCS builds and _wtempnam in UNICODE builds.
Pros/Cons are the same as tempnam/_wtempnam except it can support either MBCS/UNICODE at build time
tmpfile
Creates a temporary file
- Pros:
- Part of the ISO standard
- Creates a file (not a filename) and thus avoids Race Condition 2
- The temporary file is automatically deleted when the file is closed, the program terminates normally, or when _rmtmp is called (assuming that the CWD doesn’t change)
- Cons:
- Creates a temporary file in the root directory – WTH?! This of course, requires Admin privs on Vista and later.
tmpfile_s
Windows-only version of tmpfile with the Secure-CRT enhancements.
Pros/Cons are otherwise the same as tmpfile.
GetTempFileName
Creates a name for a temporary file. If a unique file name is generated, an empty file is created and the handle to it is released; otherwise, only a file name is generated.
MSDN has an article on “Creating and Using a Temporary File” that uses this function. Note that it uses CreateFile which returns a HANDLE not a FILE*.
- Pros:
- Supports both Unicode (via GetTempFileNameW macro resolution) and MBCS (via GetTempFileNameA macro resolution)
- Allows the caller to specify the path (yay!)
- Allows the caller to specify a filename prefix (up to three characters)
- Cons:
- Caller needs to make sure the out buffer is MAX_PATH chars to avoid buffer overflow
- While it can create the file, it releases the handle, which the caller has to reopen. This can create a security vulnerability where someone else can get to the file before the intented caller does.
- Windows-only