7

I'm writing a library. In one of my unit tests, I want to create a temporary file, make some library calls involving that file, and delete the file on exit (success, failure and exception - cleanup is important!).

Over 10 years ago, this was asked: How to create a temporary text file in C++? . But - the answers there are either non-portable, or not a proper complete solution (e.g. you get a file descriptor with no obvious way to get the name, so you can't access your file by name (std::tmpfile); you get a name (std::tmpnam) but can't be certain it's not already used; etc.) If that were resolved, I suppose my question would be answered by some RAII wrapper around some of these calls. But - I'm concerned with current reality.

My library must be usable with C++11, so I would prefer a C++11 solution if possible. Use of Boost is acceptable but not desirable.

einpoklum
  • 118,144
  • 57
  • 340
  • 684
  • Regarding your concern about `std::tmpname` possibly already being in use, it's description states *Creates a unique filename that does not name a currently existing file...* – Cory Kramer Oct 02 '20 at 17:27
  • Why not `fclose` the file pointer returned by `tmpfile` when you want to delete it? Why do you need its name? – cigien Oct 02 '20 at 17:31
  • 4
    "..., so you can't delete your file". According to cppreference, files created with `tmpfile` are automatically delete on `fclose()`, so that's not an issue. You can RAII that via `unique_ptr`. – sbabbi Oct 02 '20 at 17:32
  • @sbabbi: Thanks for that. Edited the question, since it still doesn't make `tmpfile()` into a proper solution. – einpoklum Oct 02 '20 at 17:41
  • @cigien: See edit. – einpoklum Oct 02 '20 at 17:42
  • @CoryKramer: "currently" is not when you use it, it's at some point during the execution of `tmpnam` - which is not so bad, but not perfect. That's what I do at the moment, since it's just a unit test. – einpoklum Oct 02 '20 at 17:43
  • Related: [How does `boost::filesystem::unique_path()` resolve the need in `mkstemp` analogue in C++?](https://stackoverflow.com/q/43946120/673852) Looks like Boost not only doesn't have any good solution, but its authors don't even appear to see the problem. – Ruslan Oct 02 '20 at 19:54
  • If you want a named file, then it is in principle impossible to guarantee that no one will want to use the same name at the same time as you. It is possible to guarantee that *in practice with good enough probability* though. `unique_path` does that by providing enough randomness in the name. It isn't however quite clear why you need a name. – n. m. could be an AI Oct 02 '20 at 22:02
  • @n.'pronouns'm.: A function could return both the file name and the wrapped file handle. – einpoklum Oct 02 '20 at 22:08
  • "A function could return both the file name and the wrapped file handle". Sure thing. What does this buy you exactly? A malicious oracle can still guess the file name and create a data race, despite you having the handle. If you don't believe in malicious oracles, then having just the name is enough, no one can ever guess it, you don't need the handle opened atomically. You are however still not saying why you need a name in the first place. – n. m. could be an AI Oct 02 '20 at 22:16
  • @n.'pronouns'm.: I think I'm not following you. If the file is opened with `O_CREAT | O_EXCL`, then mine will be the only process which opens the file. What do you mean by a "malicious oracle" in this context? – einpoklum Oct 02 '20 at 23:45
  • Other processes do not have to use O_EXCL. If they want to interfere with your file they still can. – n. m. could be an AI Oct 03 '20 at 06:00
  • @n.'pronouns'm. Won't they fail to open the file in that case? – einpoklum Oct 03 '20 at 07:45
  • 1
    It depends on the operating system. In the Unix world they will not fail. – n. m. could be an AI Oct 03 '20 at 07:50

0 Answers0