[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