<html><head><meta charset="UTF-8">
<title>Support exclusive mode for fstreams</title>
  <style type='text/css'>
  body {font-variant-ligatures: none;}
  p {text-align:justify}
  li {text-align:justify}
  blockquote.note, div.note
  {
          background-color:#E0E0E0;
          padding-left: 15px;
          padding-right: 15px;
          padding-top: 1px;
          padding-bottom: 1px;
  }
  p code {color:navy}
  ins p code {color:#00A000}
  p ins code {color:#00A000}
  p del code {color:#A00000}
  ins {color:#00A000}
  del {color:#A00000}
  table#boilerplate { border:0 }
  table#boilerplate td { padding-left: 2em }
  table.bordered, table.bordered th, table.bordered td {
    border: 1px solid;
    text-align: center;
  }
  ins.block {color:#00A000; text-decoration: none}
  del.block {color:#A00000; text-decoration: none}
  #hidedel:checked ~ * del, #hidedel:checked ~ * del * { display:none; visibility:hidden }
  </style>
</head><body>
<table id="boilerplate">
<tr><td>Document number</td><td>P2467R1</td></tr>
<tr><td>Date</td><td>2022-01-28</td></tr>
<tr><td>Audience</td><td>LWG</td></tr>
<tr><td>Reply-to</td><td>Jonathan Wakely &lt;cxx&#x40;kayari.org&gt;</td></tr>
</table><hr>
<h1>Support exclusive mode for fstreams</h1>
<ul>
 <li>
 <ul>
  <li><a href="#Revision-History">Revision History</a></li>
  <li><a href="#Introduction">Introduction</a></li>
  <li><a href="#Background">Background</a></li>
  <li><a href="#Design-Considerations">Design Considerations</a></li>
  <li><a href="#Proposed-wording">Proposed wording</a></li>
 </ul>
 </li>
</ul>
<a name="Revision-History"></a>
<h2>Revision History</h2>

<p>Changes since R0</p>

<ul>
<li>Preserve alphabetical ordering when adding <code>noreplace</code> to existing lists.</li>
<li>Fix markup for '+' in binary column of new rows.</li>
</ul>


<a name="Introduction"></a>
<h2>Introduction</h2>

<p>Historically, C++ iostreams libraries had a <code>noreplace</code> open mode that
corresponded to the <code>O_EXCL</code> flag for POSIX
<a href="https://pubs.opengroup.org/onlinepubs/9699919799/functions/open.html"><code>open</code></a>.
That mode was not included in the C++98 standard,
presumably for portability reasons, because it wasn't in ISO C90.</p>

<p>Since then, ISO C added support for "exclusive" mode to <code>fopen</code>,
so now C++'s <code>&lt;fstream&gt;</code> is missing a feature that is present in both
ISO C and POSIX. We should fix this for C++23.</p>

<a name="Background"></a>
<h2>Background</h2>

<p>C11 added an 'x' modifier to the <code>fopen</code> flags for files opened in write mode.
This opens the file in "exclusive" mode, meaning the <code>fopen</code> call fails if the
file already exists.
This is quite an important feature for certain use cases.
As the
<a href="http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1339.pdf">WG14 N1339</a>
proposal explained,
"This is necessary to eliminate
a time-of-creation to time-of-use race condition vulnerability. [...]
fopen() does not indicate if an existing file has been opened for writing
or a new file has been created.
This may lead to a program overwriting or accessing an unintended file."
See N1339 for additional rationale.</p>

<p>C++ already incorporates the C11 changes to <code>fopen</code> by reference,
but <code>std::fstream</code> has no way to achieve the same thing.
To avoid the time-of-creation to time-of-use (TOCTTOU) problem
it's necessary to use <code>fopen</code> and <code>FILE*</code>
(or non-standard APIs to hand an existing file handle or file descriptor
to an fstream).</p>

<p>The 'x' modifier is widely supported. It was already supported as an extension by Glibc's
<a href="http://www.gnu.org/software/libc/manual/html_node/Opening-Streams.html"><code>fopen</code></a>
(since at least version 2.4 from 2006),
and is in the draft for the next revision of POSIX
(because it's rebasing on C11).</p>

<p>Support for opening an ofstream in exclusive mode isn't even a new idea,
pre-ISO iostreams provided it. References to a <code>noreplace</code> flag can be
found in texts such as:</p>

<ul>
<li><a href="https://www.oreilly.com/library/view/object-oriented-programming/9789332503663/xhtml/head-0660.xhtml">Object Oriented Programming with C++, 2nd Edition</a>
(presumably not corrected from the 1st edition published in 1999),</li>
<li><a href="https://www.ibm.com/docs/en/zos/2.1.0?topic=scciezcp-migration-from-unix-system-laboratories-io-stream-library-standard-c-io-stream-library">Migration from UNIX System Laboratories I/O Stream Library to Standard C++ I/O Stream Library</a></li>
</ul>


<p>The flag is still present in the MSVC library, as <code>ios_base::_Noreplace</code>,
and in the Apache stdcxx implementation, as
<a href="https://stdcxx.apache.org/doc/stdlibref/ios-base.html"><code>ios_base::noreplace</code></a>.</p>

<a name="Design-Considerations"></a>
<h2>Design Considerations</h2>

<p>The historical name was "noreplace" but we could consider something like
<code>ios_base::excl</code> to correspond more closely with POSIX and C. I originally
preferred that, but have since decided that it's better to be consistent
with the historical <code>noreplace</code> name, which is still present as
<code>ios_base::_Noreplace</code> in MSVC. I think that the meaning of "noreplace"
is a bit more intuitable than "exclusive". If you don't already know what
POSIX or C means by "exclusive mode" then the name doesn't help you.</p>

<p>We could also consider not using an <code>ios_base::openmode</code> for this,
but just add new constructors to <code>basic_filebuf</code>, <code>basic_ofstream</code> etc.
to request the file be opened in exclusive mode. This would be novel,
as all existing options for opening files (such as binary mode) are done
via <code>openmode</code> flags. There was no interest in doing it any differently when
the idea was discussed on the LEWG reflector.</p>

<p>Niall Douglas raised a concern related to the ISO C specification for <code>fopen</code>,
which is vague about what "exclusive" mode means, and allows it to be ignored.
I feel we should not deviate from C, so any fixes should be done "upstream"
in the C standard. That makes it simpler to implement the C++ feature in terms
of <code>fopen</code>, rather than having to do use OS-specific APIs.</p>

<a name="Proposed-wording"></a>
<h2>Proposed wording</h2>

<p>This is relative to the
<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2021/n4901.pdf">N4901</a>
working draft.</p>

<p>Add a feature test macro to [version.syn]:</p>

<pre><code>      <ins>#define __cpp_lib_ios_noreplace    YYYYDDL // also in &lt;ios&gt;</ins>
</code></pre>

<p>Add a new <code>openmode</code> constant to the <code>ios_base</code> synopsis in [ios.base.general]
as indicated:</p>

<pre><code>      // [ios.openmode], openmode
      using openmode = T3;
      static constexpr openmode app = unspecified;
      static constexpr openmode ate = unspecified;
      static constexpr openmode binary = unspecified;
      static constexpr openmode in = unspecified;
      <ins>static constexpr openmode noreplace = unspecified;</ins>
      static constexpr openmode out = unspecified;
      static constexpr openmode trunc = unspecified;
</code></pre>

<p>Add a new row to Table 123 [tag:ios.openmode]:</p>

<blockquote><table>
<thead>
<tr>
<th>Element </th>
<th> Effect(s) if set</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>app</code> </td>
<td> seek to end before each write</td>
</tr>
<tr>
<td><code>ate</code> </td>
<td> open and seek to end immediately after opening</td>
</tr>
<tr>
<td><code>binary</code> </td>
<td> perform input and output in binary mode (as opposed to text mode)</td>
</tr>
<tr>
<td><code>in</code> </td>
<td> open for input</td>
</tr>
<tr>
<td><ins><code>noreplace</code></ins> </td>
<td> <ins>open in exclusive mode</ins></td>
</tr>
<tr>
<td><code>out</code> </td>
<td> open for output</td>
</tr>
<tr>
<td><code>trunc</code> </td>
<td>  truncate an existing stream when opening</td>
</tr>
</tbody>
</table>
</blockquote>

<p>Add a new column and several new rows to Table 130 [tab:filebuf.open.modes],
as indicated:</p>

<blockquote><table>
<thead>
<tr>
<th style="text-align:center;"><code>binary</code> </th>
<th style="text-align:center;"> <code>in</code> </th>
<th style="text-align:center;"> <code>out</code>   </th>
<th style="text-align:center;"> <code>trunc</code> </th>
<th style="text-align:center;"> <code>app</code> </th>
<th style="text-align:center;"> <ins><code>noreplace</code></ins> </th>
<th>  &nbsp;</th>
</tr>
</thead>
<tbody>
<tr>
<td style="text-align:center;"></td>
<td style="text-align:center;">         </td>
<td style="text-align:center;">   +     </td>
<td style="text-align:center;">         </td>
<td style="text-align:center;">       </td>
<td style="text-align:center;">                   </td>
<td> "w"</td>
</tr>
<tr>
<td style="text-align:center;"></td>
<td style="text-align:center;">         </td>
<td style="text-align:center;"> <ins>+</ins> </td>
<td style="text-align:center;">         </td>
<td style="text-align:center;">       </td>
<td style="text-align:center;">     <ins>+</ins>       </td>
<td> <ins>"wx"</ins></td>
</tr>
<tr>
<td style="text-align:center;"></td>
<td style="text-align:center;">         </td>
<td style="text-align:center;">   +     </td>
<td style="text-align:center;">    +    </td>
<td style="text-align:center;">       </td>
<td style="text-align:center;">                   </td>
<td> "w"</td>
</tr>
<tr>
<td style="text-align:center;"></td>
<td style="text-align:center;">         </td>
<td style="text-align:center;"> <ins>+</ins> </td>
<td style="text-align:center;"> <ins>+</ins> </td>
<td style="text-align:center;">       </td>
<td style="text-align:center;">     <ins>+</ins>       </td>
<td> <ins>"wx"</ins></td>
</tr>
<tr>
<td style="text-align:center;"></td>
<td style="text-align:center;">         </td>
<td style="text-align:center;">   +     </td>
<td style="text-align:center;">         </td>
<td style="text-align:center;">   +   </td>
<td style="text-align:center;">                   </td>
<td> "a"</td>
</tr>
<tr>
<td style="text-align:center;"></td>
<td style="text-align:center;">         </td>
<td style="text-align:center;">         </td>
<td style="text-align:center;">         </td>
<td style="text-align:center;">   +   </td>
<td style="text-align:center;">                   </td>
<td> "a"</td>
</tr>
<tr>
<td style="text-align:center;"></td>
<td style="text-align:center;">     +   </td>
<td style="text-align:center;">         </td>
<td style="text-align:center;">         </td>
<td style="text-align:center;">       </td>
<td style="text-align:center;">                   </td>
<td> "r"</td>
</tr>
<tr>
<td style="text-align:center;"></td>
<td style="text-align:center;">     +   </td>
<td style="text-align:center;">   +     </td>
<td style="text-align:center;">         </td>
<td style="text-align:center;">       </td>
<td style="text-align:center;">                   </td>
<td> "r+"</td>
</tr>
<tr>
<td style="text-align:center;"></td>
<td style="text-align:center;">     +   </td>
<td style="text-align:center;">   +     </td>
<td style="text-align:center;">    +    </td>
<td style="text-align:center;">       </td>
<td style="text-align:center;">                   </td>
<td> "w+"</td>
</tr>
<tr>
<td style="text-align:center;"></td>
<td style="text-align:center;"> <ins>+</ins> </td>
<td style="text-align:center;"> <ins>+</ins> </td>
<td style="text-align:center;"> <ins>+</ins> </td>
<td style="text-align:center;">       </td>
<td style="text-align:center;">    <ins>+</ins>        </td>
<td> <ins>"w+x"</ins></td>
</tr>
<tr>
<td style="text-align:center;"></td>
<td style="text-align:center;">     +   </td>
<td style="text-align:center;">   +     </td>
<td style="text-align:center;">         </td>
<td style="text-align:center;">  +    </td>
<td style="text-align:center;">                   </td>
<td> "a+"</td>
</tr>
<tr>
<td style="text-align:center;"></td>
<td style="text-align:center;">     +   </td>
<td style="text-align:center;">         </td>
<td style="text-align:center;">         </td>
<td style="text-align:center;">  +    </td>
<td style="text-align:center;">                   </td>
<td> "a+"</td>
</tr>
<tr>
<td style="text-align:center;">+   </td>
<td style="text-align:center;">         </td>
<td style="text-align:center;">   +     </td>
<td style="text-align:center;">         </td>
<td style="text-align:center;">       </td>
<td style="text-align:center;">                   </td>
<td> "wb"</td>
</tr>
<tr>
<td style="text-align:center;"><ins>+</ins> </td>
<td style="text-align:center;">         </td>
<td style="text-align:center;"> <ins>+</ins> </td>
<td style="text-align:center;">         </td>
<td style="text-align:center;">       </td>
<td style="text-align:center;">     <ins>+</ins>       </td>
<td> <ins>"wbx"</ins></td>
</tr>
<tr>
<td style="text-align:center;">+   </td>
<td style="text-align:center;">         </td>
<td style="text-align:center;">   +     </td>
<td style="text-align:center;">    +    </td>
<td style="text-align:center;">       </td>
<td style="text-align:center;">                   </td>
<td> "wb"</td>
</tr>
<tr>
<td style="text-align:center;"><ins>+</ins> </td>
<td style="text-align:center;">         </td>
<td style="text-align:center;"> <ins>+</ins> </td>
<td style="text-align:center;"> <ins>+</ins> </td>
<td style="text-align:center;">       </td>
<td style="text-align:center;">     <ins>+</ins>       </td>
<td> <ins>"wbx"</ins></td>
</tr>
<tr>
<td style="text-align:center;">+   </td>
<td style="text-align:center;">         </td>
<td style="text-align:center;">   +     </td>
<td style="text-align:center;">         </td>
<td style="text-align:center;">   +   </td>
<td style="text-align:center;">                   </td>
<td> "ab"</td>
</tr>
<tr>
<td style="text-align:center;">+   </td>
<td style="text-align:center;">         </td>
<td style="text-align:center;">         </td>
<td style="text-align:center;">         </td>
<td style="text-align:center;">   +   </td>
<td style="text-align:center;">                   </td>
<td> "ab"</td>
</tr>
<tr>
<td style="text-align:center;">+   </td>
<td style="text-align:center;">     +   </td>
<td style="text-align:center;">         </td>
<td style="text-align:center;">         </td>
<td style="text-align:center;">       </td>
<td style="text-align:center;">                   </td>
<td> "rb"</td>
</tr>
<tr>
<td style="text-align:center;">+   </td>
<td style="text-align:center;">     +   </td>
<td style="text-align:center;">   +     </td>
<td style="text-align:center;">         </td>
<td style="text-align:center;">       </td>
<td style="text-align:center;">                   </td>
<td> "r+b"</td>
</tr>
<tr>
<td style="text-align:center;">+   </td>
<td style="text-align:center;">     +   </td>
<td style="text-align:center;">   +     </td>
<td style="text-align:center;">    +    </td>
<td style="text-align:center;">       </td>
<td style="text-align:center;">                   </td>
<td> "w+b"</td>
</tr>
<tr>
<td style="text-align:center;"><ins>+</ins> </td>
<td style="text-align:center;"> <ins>+</ins> </td>
<td style="text-align:center;"> <ins>+</ins> </td>
<td style="text-align:center;"> <ins>+</ins> </td>
<td style="text-align:center;">     </td>
<td style="text-align:center;">    <ins>+</ins>        </td>
<td> <ins>"w+bx"</ins></td>
</tr>
<tr>
<td style="text-align:center;">+   </td>
<td style="text-align:center;">     +   </td>
<td style="text-align:center;">   +     </td>
<td style="text-align:center;">         </td>
<td style="text-align:center;">  +    </td>
<td style="text-align:center;">                   </td>
<td> "a+b"</td>
</tr>
<tr>
<td style="text-align:center;">+   </td>
<td style="text-align:center;">     +   </td>
<td style="text-align:center;">         </td>
<td style="text-align:center;">         </td>
<td style="text-align:center;">  +    </td>
<td style="text-align:center;">                   </td>
<td> "a+b"</td>
</tr>
</tbody>
</table>
</blockquote>
</body></html>
