If you want to remove the file as soon as your application closes, use std::tmpfile(). It is safe, you can open a few thousand file per process (see TMP_MAX value) and platform independent.
It will create an empty file, and delete it as soon as it is closed.
#include <cstdio> int main() { std::FILE* temp_file = std::tmpfile(); // create file if(temp_file == nullptr) { // error, temp file cannot be created return -1; } std::fprintf(temp_file, "Some temporary text"); // use the file (write and read content) std::fclose(temp_file); // file removed from disk return 0; }
Note if your program exits abnormally, it is implementation defined whether the file gets deleted or not.
To get the path of the file, we could use the following (linux implementation is from cppreference, for more details on windows implementation see the last paragraph of my other answer):
#ifdef WIN32 #include <windows.h> #include <io.h> std::string get_path_from_FILE(FILE* file) { int fd = _fileno(file); if (fd == -1) return ""; HANDLE h = (HANDLE)_get_osfhandle(fd); if (h == INVALID_HANDLE_VALUE) return ""; char path[MAX_PATH]; DWORD ret = GetFinalPathNameByHandleA(h, path, MAX_PATH, FILE_NAME_NORMALIZED); if (ret == 0 || ret >= MAX_PATH) return ""; return std::string(path+4); // it starts with "\\?\C:\...." this is why we need +4 } #elif defined __unix__ std::string get_path_from_FILE(FILE* file) { // Linux-specific method to display the tmpfile name char fname[FILENAME_MAX], link[FILENAME_MAX] = {0}; sprintf(fname, "/proc/self/fd/%d", fileno(tmpf)); if (readlink(fname, link, sizeof link - 1) > 0) { return fname; } return ""; } #endif
If you stick with linux and C style creation, use open() with O_TMPFILE flag. In this case, the file won't be written to disk, unless a name is given to it.
#include <fcntl.h> #include <unistd.h> int main() { int temp_file = open("/tmp/", O_TMPFILE|O_RDWR, 0); if(temp_file == -1) { return -1; // error, temp file cannot be created } const char* my_temporary_content = "It is temporary"; write(temp_file, my_temporary_content, 15); // 15 is length of the const char above close(temp_file); return 0; }
Here, the open's first parameter is a directory. Since c++17, we can use temp_directory_path() to determine the temporary directory path.
What is the danger of tmpnam()?
It gives a name that was unique in the time of calling the function, not when creating the file. Therefore, someone (e.g. an attacker, or another process) can create the file after the tmpnam() call, but before the open() call.
This is why one should use the O_EXCL flag to make sure the file is created by us (and handle error properly).
In this case, the file won't be removed after the process finished
#include <stdio.h> #include <fcntl.h> #include <unistd.h> int main() { int temp_file = -1; while(temp_file == -1){ const char* temp_name = tmpnam(nullptr); // this is the dangerous part temp_file = open(temp_name, O_CREAT|O_EXCL|O_RDWR, S_IRUSR | S_IWUSR); // it is left to the reader to prevent infinite loop } const char* my_temporary_content = "It is temporary"; write(temp_file, my_temporary_content, 15); // 15 is length of the const char above close(temp_file); return 0; }