9

I need to develop a C++ routine performing this apparently trivial task: create a file only if it does not exist, else do nothing/raise error.

As I need to avoid race conditions, I want to use the "ask forgiveness not permission" principle (i.e. attempting the intended operation and checking if it succeeded, as opposed to checking preconditions in advance), which, to my knowledge, is the only robust and portable method for this purpose [Wikipedia article][an example with getline].

Still, I could not find a way to implement it in my case. The best I could come up with is opening a fstream in app mode (or fopening with "a"), checking the output position with tellp (C++) or ftell (C) and aborting if such position is not zero. This has however two disadvantages, namely that if the file exists it gets locked (although for a short time) and its modification date is altered.

I checked other possible combinations of ios_base::openmode for fstream, as well as the mode strings of fopen but found no option that suited my needs. Further search in the C and C++ standard libraries, as well as Boost Filesystem, proved unfruitful.

Can someone point out a method to perform my task in a robust way (no collateral effects, no race conditions) without relying on OS-specific functions? My specific problem is in Windows, but portable solutions would be preferred.

EDIT: The answer by BitWhistler completely solves the problem for C programs. Still, I am amazed that no C++ idiomatic solution seems to exist. Either one uses open with the O_EXCL attribute as proposed by Andrew Henle, which is however OS-specific (in Windows the attribute seems to be called _O_EXCL with an additional underscore [MSDN]) or one separately compiles a C11 file and links it from the C++ code. Moreover, the file descriptor obtained cannot be converted to a stream except with nonstandard extensions (e.g. GCC's __gnu_cxx::stdio_filebuf). I hope a future version of C++ will implement the "x" subattribute and possibly also a corresponding ios:: modificator for file streams.

Community
  • 1
  • 1
Alberto M
  • 1,057
  • 8
  • 24
  • Do you want to avoid race conditions between several threads or several processes? – user2807083 Feb 29 '16 at 10:23
  • 3
    What's your OS? POSIX provides [`open( filename, O_CREAT | O_EXCL ... )`](http://pubs.opengroup.org/onlinepubs/009695399/functions/open.html) to do what you're looking to do. – Andrew Henle Feb 29 '16 at 10:24
  • 1
    Win32 API allows this. I know this for sure. – Kirill Kobelev Feb 29 '16 at 10:28
  • 2
    I never do what you seem to be proposing. If multiple threads need to write to one file, I queue the outputs to ONE thread that manages the file had performs all output. The races on the file system disappear, debugging becomes much easier and managing the output file,(eg. limiting its size, picking a new file every day), becomes trivial. – Martin James Feb 29 '16 at 10:28
  • Sorry for not clarifying: here the possible race condition is with an external process on which I have no control. I fully agree that I/O in an application should be performed by a single thread. – Alberto M Feb 29 '16 at 10:43
  • Question updated: O.S. is Windows (but I'd prefer a cross-platform solution) – Alberto M Feb 29 '16 at 10:46
  • Do you need to open the file once it is created or do you just want the file to be created? – Jabberwocky Feb 29 '16 at 11:03
  • i ran into a similar condition where two threads trying to open different file using ofstream or filbuf, gets into race condition and waits on something resulting in dead lock. Have you guys come across this kinda prblem? – Deepak Selvakumar Jun 25 '19 at 12:38

1 Answers1

3

The new C standard (C2011, which is not part of C++) adds a new standard subspecifier ("x"), that can be appended to any "w" specifier (to form "wx", "wbx", "w+x" or "w+bx"/"wb+x"). This subspecifier forces the function to fail if the file exists, instead of overwriting it.

source: http://www.cplusplus.com/reference/cstdio/fopen/

BitWhistler
  • 1,439
  • 8
  • 12