[This patch has only the XML text; the usual scripts have
not been run on it yet.]

ISO C++ leaves concurrent use of std::filesystem operations
undefined. POSIX provides definitions for concurrent use. Here
we document POSIX (and sometimes GNU extension) operations used
to implement std::filesystem ops so that when run with libstdc++
hosted on POSIX, they are defined by the union of ISO C++ and
POSIX.

libstdc++/Changelog
        * doc/xml/manual/io.xml: Document POSIX usage in filesystem.
---
 libstdc++-v3/doc/xml/manual/io.xml | 285 +++++++++++++++++++++++++++++
 1 file changed, 285 insertions(+)

diff --git a/libstdc++-v3/doc/xml/manual/io.xml 
b/libstdc++-v3/doc/xml/manual/io.xml
index adc37cd8488..9be34ac7526 100644
--- a/libstdc++-v3/doc/xml/manual/io.xml
+++ b/libstdc++-v3/doc/xml/manual/io.xml
@@ -669,4 +669,289 @@
   </section>
 </section>
 
+<!-- Sect1 05 : Filesystem Operations -->
+<section xml:id="std.io.fs" xreflabel="Filesystem 
Operations"><info><title>Filesystem Operations</title></info>
+<?dbhtml filename="io_fs_intro.html"?>
+  <section xml:id="std.io.fs.intro" 
xreflabel="Introduction"><info><title>Introduction</title></info>
+    <para>
+      The ISO C++ Standard Library defines operations on a global,
+      shared filesystem that, called in parallel, may race.
+      Section <emphasis>[fs.race.behavior]</emphasis> of the
+      Standard identifies such races as <emphasis>undefined
+      behavior</emphasis>, "UB", so the behavior of programs
+      that do such filesystem operations in parallel may be
+      left undefined by the C++ Standard.
+      As Standard implementers are free to define what the Standard
+      does not, rehabilitating otherwise undefined programs on their
+      platform, this section provides definitions for many such
+      cases by relating Standard Library <type>filesystem</type>
+      operations implemented in libstdc++ to
+      corresponding ISO POSIX.1-2008 Standard or, in some cases,
+      GNU operations that have well-defined (if possibly surprising)
+      semantics under race conditions.
+    </para>
+    <para>
+      We begin by identifying C++ Standard objects with POSIX objects.
+      Trivially, an ISO C++ <emphasis>file</emphasis> is exactly an
+      ISO POSIX
+      <emphasis>file</emphasis>, and likewise for
+      <emphasis>directory</emphasis>,
+      <emphasis>link</emphasis>,
+      <emphasis>hard link</emphasis>, and
+      <emphasis>symbolic link</emphasis>.
+      All of these are identified by names represented in C++
+      with a string-like type <type>filesystem::path</type> defined
+      in <emphasis>[fs.class.path]</emphasis>.
+      The contents of <type>path</type> are identical to the
+      strings passed to and delivered from POSIX.
+    </para>
+    <para>
+      The C++ Standard defines file system operations via functions
+      that do not necessarily map one-to-one to those defined in
+      POSIX or GNU, taking arguments that do not necessarily match
+      those that must be passed to underlying library functions.
+      This section defines those mappings so that the effects of
+      <type>filesystem</type> operations may be deduced from those
+      of the POSIX operations in places the C++ Standard may leave
+      undefined.
+      POSIX defines the effect of some races as
+      <emphasis>unspecified</emphasis>, with a set of possible
+      outcomes;
+      corresponding operations in libstdc++ will
+      have the same set of possible outcomes.
+    </para>
+    <para>
+      <type>std::filesystem</type> operations on relative paths
+      rely on the process-global "current working directory"
+      which may be changed at any time by another thread.
+      Furthermore, the contents of a filesystem may be changed
+      at any time by operations in another thread or another
+      program.
+      Operations that involve checking the current contents
+      of the filesystem and choosing subsequent operations
+      according to the results may have surprising results
+      if the filesystem contents are changed in between,
+      often with serious consequences to security.
+    </para>
+    <para>
+      In other words, saying "results of concurrent filesystem
+      operations are well-defined" does not mean that they will
+      necessarily be what was intended, and it is very easy to
+      introduce security vulnerabilities if extreme care is not
+      taken.
+    </para>
+  </section>
+  <section xml:id="std.io.fs.dir_iter" xreflabel="Directory 
Iteration"><info><title>Directory Iteration</title></info>
+    <para>
+      This section addresses iteration through filesystem directories,
+      as defined in <emphasis>[fs.class.directory.iterator]</emphasis>
+      and <emphasis>[fs.class.rec.dir.itr]</emphasis> in the Standard,
+      both recursive and not.
+    </para>
+    <para>
+      Constructing a
+      <function>filesystem::directory_iterator</function> or
+      <function>recursive_directory_iterator</function> on a directory
+      <function>path</function> uses POSIX
+      <function>openat</function>, <function>fdopendir</function>, and
+      <function>fstat</function>.
+    </para>
+    <para>
+      Stepping into a subdirectory uses the same calls.
+    </para>
+    <para>
+      Incrementing an iterator uses POSIX <function>readdir</function> for
+      each entry.
+    </para>
+    <para>
+      Using any of the <function>directory_entry</function>
+      <emphasis>observer</emphasis> members, other than querying
+      <function>path</function>, <function>exists</function> or 
<function>is_</function>...
+      triggers an <function>fstat</function> operation on the first
+      such call.
+    </para>
+    <para>
+      Destroying one uses POSIX <function>close</close>
+    </para>
+  </section>
+  <section xml:id="std.io.fs.ops" xreflabel="Filesystem 
Operations"><info><title>Filesystem Operations</title></info>
+    <para>
+      Most subsections here correspond to a subheading under
+      <emphasis>[fs.ops.funcs]</emphasis> in the Standard, defining
+      operations implemented by calling POSIX filesystem functions.
+      The first two gather collections of such subheadings to share
+      a common description.
+    </para>
+    <section xml:id="std.io.fs.ops.lstats" xreflabel="Status 
Checks"><info><title>Status Checks</title></info>
+      <para>
+       All of
+       <function>filesystem::is_regular_file</function>,
+       <function>is_directory</function>,
+       <function>is_character_file</function>,
+       <function>is_block_file</function>
+       <function>is_fifo</function>,
+       <function>is_symlink</function>,
+       <function>is_socket</function>,
+       <function>file_size</function>,
+       <function>hard_link_count</function>,
+       <function>is_empty</function>,
+       <function>last_write_time</function>
+       <function>is_other</function>,
+       <function>status</function>, and
+       <function>symlink_status</function>
+       use POSIX <function>lstat</function>.
+      </para>
+    </section>
+    <section xml:id="std.io.fs.ops.paths" xreflabel="Filesystem Path 
Checks"><info><title>Filesystem Path Checks</title></info>
+      <para>
+       All of
+       <function>filesystem::canonical</function>,
+       <function>proximate</functiofunction>,
+       <function>relative</function>, and
+       <function>weakly_canonical</function> use POSIX
+       <function>realpath</function>, and may call
+       <function>fstat</function>, <function>lstat</function>, and
+       <function>readlink</function> on the argument
+       and its parent directories.
+      </para>
+    </section>
+    <section xml:id="std.io.fs.ops.copy" 
xreflabel="Copy"><info><title>Copy</title></info>
+      <para>
+       <function>filesystem::copy</function> uses POSIX
+       <function>fstat</function> and possibly
+       <function>readlink</function>, and
+       <function>symlink</function>, <function>link</function>,
+       <function>mkdir</function>, or operations listed under
+       <function>filesystem::copy_file</function>,
+       possibly repeatedly if the argument is a directory.
+      </para>
+    </section>
+    <section xml:id="std.io.fs.ops.copy_file" xreflabel="Copy 
File"><info><title>Copy File</title></info>
+      <para>
+       <function>filesystem::copy_file</function> uses POSIX
+       <function>lstat</function>, <function>open</function> on both
+       source and destination, and GNU
+       <function>copy_file_range</function> or
+       <function>send_file</function>
+       where available and applicable, or else POSIX
+       <function>read</function> and
+       <function>write</function> repeatedly, and then
+       <function>close</function> on both.
+      </para>
+    </section>
+    <section xml:id="std.io.fs.ops.copy_symlink" xreflabel="Copy 
Symlink"><info><title>Copy Symlink</title></info>
+      <para>
+       <function>filesystem::copy_symlink</function> uses POSIX
+       <function>lstat</function> and <function>symlink</function>.
+      </para>
+    </section>
+    <section xml:id="std.io.fs.ops.mkdirs" xreflabel="Create 
Directories"><info><title>Create Directories</title></info>
+      <para>
+       <function>filesystem::create_directories</function> uses POSIX
+       <function>fstat</function>, and then <function>mkdir</function>, 
possibly
+       repeatedly.
+      </para>
+    </section>
+    <section xml:id="std.io.fs.ops.mkdir" xreflabel="Create 
Directory"><info><title>Create Directory</title></info>
+      <para>
+       <function>filesystem::create_directory</function> uses POSIX
+       <function>mkdir</function>.
+      </para>
+    </section>
+    <section xml:id="std.io.fs.ops.mkdirsymlink" xreflabel="Create Directory 
Symlink"><info><title>Create Directory Symlink</title></info>
+      <para>
+       <function>filesystem::create_directory_symlink</function> uses POSIX
+       <function>symlink</function>.
+      </para>
+    </section>
+    <section xml:id="std.io.fs.ops.mklink" xreflabel="Create Hard 
Link"><info><title>Create Hard Link</title></info>
+      <para>
+       <function>filesystem::create_hard_link</function> uses POSIX
+       <function>link</function>.
+      </para>
+    </section>
+    <section xml:id="std.io.fs.ops.mksymlink" xreflabel="Create 
Symlink"><info><title>Create Symlink</title></info>
+      <para>
+       <function>filesystem::create_symlink</function> uses POSIX
+       <function>symlink</function>.
+      </para>
+    </section>
+    <section xml:id="std.io.fs.ops.cwd" xreflabel="Current 
Path"><info><title>Current Path</title></info>
+      <para>
+       <function>filesystem::current_path</function> uses POSIX
+       <function>getcwd</function>. This accesses process global
+       state, which may be changed at any time by another
+       thread.
+      </para>
+    </section>
+    <section xml:id="std.io.fs.ops.equiv" 
xreflabel="Equivalent"><info><title>Equivalent</title></info>
+      <para>
+       <function>filesystem::equivalent</function> uses a sequence
+       of calls to POSIX
+       <function>lstat</function> and, possibly,
+       <function>readlink</function>.
+      </para>
+    </section>
+    <section xml:id="std.io.fs.ops.perms" 
xreflabel="Permissions"><info><title>Permissions</title></info>
+      <para>
+       <function>filesystem::permissions</function> uses POSIX
+       <function>lstat</function>, and <function>fchmodat</function>.
+      </para>
+    </section>
+    <section xml:id="std.io.fs.ops.rdsym" xreflabel="Read 
Symlink"><info><title>Read Symlink</title></info>
+      <para>
+       <function>filesystem::read_symlink</function> uses POSIX
+       <function>lstat</function> and <function>readlink</function>.
+      </para>
+    </section>
+    <section xml:id="std.io.fs.ops.rm" 
xreflabel="Remove"><info><title>Remove</title></info>
+      <para>
+       <function>filesystem::remove</function> uses POSIX
+       <function>remove</function>.
+      </para>
+    </section>
+    <section xml:id="std.io.fs.ops.rmall" xreflabel="Remove 
All"><info><title>Remove All</title></info>
+      TODO
+    </section>
+    <section xml:id="std.io.fs.ops.mv" 
xreflabel="Rename"><info><title>Rename</title></info>
+      <para>
+       <function>filesystem::rename</function> uses POSIX
+       <function>rename</function>.
+      </para>
+    </section>
+    <section xml:id="std.io.fs.ops.resize" xreflabel="Resize 
File"><info><title>Resize File</title></info>
+      <para>
+       <function>filesystem::resize_file</function> uses POSIX
+       <function>truncate</function>.
+      </para>
+    </section>
+    <section xml:id="std.io.fs.ops.space" 
xreflabel="Space"><info><title>Space</title></info>
+      <para>
+       <function>filesystem::space</function> uses POSIX
+       <function>statvfs</function>.
+      </para>
+    </section>
+    <section xml:id="std.io.fs.ops.statknown" xreflabel="Status 
Known"><info><title>Status Known</title></info>
+    </section>
+      <para>
+       <function>filesystem::status_known</function> uses no POSIX operations.
+      </para>
+    </section>
+    <section xml:id="std.io.fs.ops.tmpdir" xreflabel="Temporary Directory 
Path"><info><title>Temporary Directory Path</title></info>
+      <para>
+       <function>filesystem::temp_directory_path</function> uses the
+       GNU extension <function>secure_getenv</function> if available,
+       or else POSIX <function>getenv</function> to check the process
+       environment sequentially for a definition of
+       <code>"TMPDIR"</code>,
+       <code>"TMP</code>,
+       <code>"TEMP"</code>, and
+       <code>"TEMPDIR"</code>, in that order, immediately
+       returning a path constructed from the first match.
+       These calls access process global state, which may be changed
+       at any time by another thread.
+      </para>
+    </section>
+  </section>
+</section>
 </chapter>
-- 
2.53.0

Reply via email to