From Jason Turner

[filesystems]

Diff to HTML by rtfpessoa

Files changed (1) hide show
  1. tmp/tmp5as575t4/{from.md → to.md} +279 -216
tmp/tmp5as575t4/{from.md → to.md} RENAMED
@@ -40,18 +40,20 @@ can be thought of as a raw pointer to a file. If the file pointed to
40
  does not exist, the symbolic link is said to be a “dangling” symbolic
41
  link. — *end note*]
42
 
43
  ### Conformance <a id="fs.conformance">[[fs.conformance]]</a>
44
 
 
 
45
  Conformance is specified in terms of behavior. Ideal behavior is not
46
  always implementable, so the conformance subclauses take that into
47
  account.
48
 
49
  #### POSIX conformance <a id="fs.conform.9945">[[fs.conform.9945]]</a>
50
 
51
- Some behavior is specified by reference to POSIX [[fs.norm.ref]]. How
52
- such behavior is actually implemented is unspecified.
53
 
54
  [*Note 1*: This constitutes an “as if” rule allowing implementations to
55
  call native operating system or other APIs. — *end note*]
56
 
57
  Implementations should provide such behavior as it is defined by POSIX.
@@ -90,26 +92,20 @@ system.
90
  #### File system race behavior <a id="fs.race.behavior">[[fs.race.behavior]]</a>
91
 
92
  A *file system race* is the condition that occurs when multiple threads,
93
  processes, or computers interleave access and modification of the same
94
  object within a file system. Behavior is undefined if calls to functions
95
- provided by subclause  [[fs.race.behavior]] introduce a file system
96
- race.
97
 
98
  If the possibility of a file system race would make it unreliable for a
99
  program to test for a precondition before calling a function described
100
  herein, *Preconditions:* is not specified for the function.
101
 
102
  [*Note 1*: As a design practice, preconditions are not specified when
103
  it is unreasonable for a program to detect them prior to calling the
104
  function. — *end note*]
105
 
106
- ### Normative references <a id="fs.norm.ref">[[fs.norm.ref]]</a>
107
-
108
- Subclause  [[filesystems]] mentions commercially available operating
109
- systems for purposes of exposition.[^41]
110
-
111
  ### Requirements <a id="fs.req">[[fs.req]]</a>
112
 
113
  Throughout subclause  [[filesystems]], `char`, `wchar_t`, `char8_t`,
114
  `char16_t`, and `char32_t` are collectively called *encoded character
115
  types*.
@@ -126,17 +122,11 @@ value type that is one of the encoded character types.
126
  character set and encoding. Since `signed char` and `unsigned char` have
127
  no implied character set and encoding, they are not included as
128
  permitted types. — *end note*]
129
 
130
  Template parameters named `Allocator` shall meet the *Cpp17Allocator*
131
- requirements ([[cpp17.allocator]]).
132
-
133
- #### Namespaces and headers <a id="fs.req.namespace">[[fs.req.namespace]]</a>
134
-
135
- Unless otherwise specified, references to entities described in
136
- subclause  [[filesystems]] are assumed to be qualified with
137
- `::std::filesystem::`.
138
 
139
  ### Header `<filesystem>` synopsis <a id="fs.filesystem.syn">[[fs.filesystem.syn]]</a>
140
 
141
  ``` cpp
142
  #include <compare> // see [compare.syn]
@@ -158,18 +148,18 @@ namespace std::filesystem {
158
  // [fs.class.directory.iterator], directory iterators
159
  class directory_iterator;
160
 
161
  // [fs.dir.itr.nonmembers], range access for directory iterators
162
  directory_iterator begin(directory_iterator iter) noexcept;
163
- directory_iterator end(const directory_iterator&) noexcept;
164
 
165
  // [fs.class.rec.dir.itr], recursive directory iterators
166
  class recursive_directory_iterator;
167
 
168
  // [fs.rec.dir.itr.nonmembers], range access for recursive directory iterators
169
  recursive_directory_iterator begin(recursive_directory_iterator iter) noexcept;
170
- recursive_directory_iterator end(const recursive_directory_iterator&) noexcept;
171
 
172
  // [fs.class.file.status], file status
173
  class file_status;
174
 
175
  struct space_info {
@@ -335,10 +325,28 @@ namespace std::filesystem {
335
  path temp_directory_path(error_code& ec);
336
 
337
  path weakly_canonical(const path& p);
338
  path weakly_canonical(const path& p, error_code& ec);
339
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
340
  ```
341
 
342
  Implementations should ensure that the resolution and range of
343
  `file_time_type` reflect the operating system dependent resolution and
344
  range of file time values.
@@ -389,10 +397,12 @@ follows, unless otherwise specified:
389
  appropriate for the specific operating system dependent error.
390
  Otherwise, `clear()` is called on the `error_code&` argument.
391
 
392
  ### Class `path` <a id="fs.class.path">[[fs.class.path]]</a>
393
 
 
 
394
  An object of class `path` represents a path and contains a pathname.
395
  Such an object is concerned only with the lexical and syntactic aspects
396
  of a path. The path does not necessarily exist in external storage, and
397
  the pathname is not necessarily valid for the current operating system
398
  or for a particular file system.
@@ -414,22 +424,22 @@ elements of a path that determine if it is absolute are operating system
414
  dependent. A *relative path* is a path that is not absolute, and as
415
  such, only unambiguously identifies the location of a file when resolved
416
  relative to an implied starting location. The elements of a path that
417
  determine if it is relative are operating system dependent.
418
 
419
- [*Note 2*: Pathnames “.” and “..” are relative paths. — *end note*]
420
 
421
  A *pathname* is a character string that represents the name of a path.
422
  Pathnames are formatted according to the generic pathname format grammar
423
  [[fs.path.generic]] or according to an operating system dependent
424
  *native pathname format* accepted by the host operating system.
425
 
426
  *Pathname resolution* is the operating system dependent mechanism for
427
  resolving a pathname to a particular file in a file hierarchy. There may
428
  be multiple pathnames that resolve to the same file.
429
 
430
- [*Example 1*: POSIX specifies the mechanism in section 4.11, Pathname
431
  resolution. — *end example*]
432
 
433
  ``` cpp
434
  namespace std::filesystem {
435
  class path {
@@ -647,13 +657,13 @@ consisting solely of one and two period characters respectively, have
647
  special meaning. The following characteristics of filenames are
648
  operating system dependent:
649
 
650
  - The permitted characters. \[*Example 1*: Some operating systems
651
  prohibit the ASCII control characters (0x00 – 0x1F) in
652
- filenames. — *end example*] \[*Note 1*: For wide portability, users
653
- may wish to limit *filename* characters to the POSIX Portable Filename
654
- Character Set:
655
  `A B C D E F G H I J K L M N O P Q R S T U V W X Y Z`
656
  `a b c d e f g h i j k l m n o p q r s t u v w x y z`
657
  `0 1 2 3 4 5 6 7 8 9 . _ -` — *end note*]
658
  - The maximum permitted length.
659
  - Filenames that are not permitted.
@@ -678,11 +688,11 @@ A *root-name* identifies the starting location for pathname resolution
678
  required.
679
 
680
  [*Note 2*: Many operating systems define a name beginning with two
681
  *directory-separator* characters as a *root-name* that identifies
682
  network or other resource locations. Some operating systems define a
683
- single letter followed by a colon as a drive specifier a *root-name*
684
  identifying a specific device such as a disk drive. — *end note*]
685
 
686
  If a *root-name* is otherwise ambiguous, the possibility with the
687
  longest sequence of characters is chosen.
688
 
@@ -694,11 +704,11 @@ longest sequence of characters is chosen.
694
 
695
  1. If the path is empty, stop.
696
  2. Replace each slash character in the *root-name* with a
697
  *preferred-separator*.
698
  3. Replace each *directory-separator* with a *preferred-separator*.
699
- \[*Note 4*: The generic pathname grammar [[fs.path.generic]] defines
700
  *directory-separator* as one or more slashes and
701
  *preferred-separator*s. — *end note*]
702
  4. Remove each dot filename and any immediately following
703
  *directory-separator*.
704
  5. As long as any appear, remove a non-dot-dot filename immediately
@@ -738,11 +748,11 @@ path using either a pathname in the generic format [[fs.path.generic]]
738
  or a pathname in the native format [[fs.class.path]]. Such an argument
739
  is taken to be in the generic format if and only if it matches the
740
  generic format and is not acceptable to the operating system as a native
741
  path.
742
 
743
- [*Note 2*: Some operating systems may have no unambiguous way to
744
  distinguish between native format and generic format arguments. This is
745
  by design as it simplifies use for operating systems that do not require
746
  disambiguation. An implementation for an operating system where
747
  disambiguation is required is permitted to distinguish between the
748
  formats. — *end note*]
@@ -761,11 +771,11 @@ differently from paths for directories, the path shall be treated as a
761
  directory path if its last element is a *directory-separator*, otherwise
762
  it shall be treated as a path to a regular file.
763
 
764
  [*Note 4*: A path stores a native format pathname
765
  [[fs.path.native.obs]] and acts as if it also stores a generic format
766
- pathname, related as given below. The implementation may generate the
767
  generic format pathname based on the native format pathname (and
768
  possibly other information) when requested. — *end note*]
769
 
770
  When a path is constructed from or is assigned a single representation
771
  separate from any path, the other representation is selected by the
@@ -783,11 +793,11 @@ the result of converting *p*. — *end note*]
783
 
784
  The *native encoding* of an ordinary character string is the operating
785
  system dependent current encoding for pathnames [[fs.class.path]]. The
786
  *native encoding* for wide character strings is the
787
  implementation-defined execution wide-character set encoding
788
- [[lex.charset]].
789
 
790
  For member function arguments that take character sequences representing
791
  paths and for member functions returning strings, value type and
792
  encoding conversion is performed if the value type of the argument or
793
  return value differs from `path::value_type`. For the argument or return
@@ -801,12 +811,12 @@ determined by its value type:
801
  return values is performed. For Windows-based operating systems, the
802
  native ordinary encoding is determined by calling a Windows API
803
  function. — *end note*] \[*Note 7*: This results in behavior
804
  identical to other C and C++ standard library functions that perform
805
  file operations using ordinary character strings to identify paths.
806
- Changing this behavior would be surprising and error
807
- prone. — *end note*]
808
  - `wchar_t`: The encoding is the native wide encoding. The method of
809
  conversion is unspecified. \[*Note 8*: For Windows-based operating
810
  systems `path::value_type` is `wchar_t` so no conversion from
811
  `wchar_t` value type arguments or to `wchar_t` value type return
812
  values is performed. — *end note*]
@@ -850,11 +860,11 @@ participate in overload resolution unless `Source` denotes a type other
850
  than `path`, and either
851
 
852
  - `Source` is a specialization of `basic_string` or `basic_string_view`,
853
  or
854
  - the *qualified-id* `iterator_traits<decay_t<Source>>::value_type` is
855
- valid and denotes a possibly `const` encoded character type
856
  [[temp.deduct]].
857
 
858
  [*Note 1*: See path conversions [[fs.path.cvt]] for how the value types
859
  above and their encodings convert to `path::value_type` and its
860
  encoding. — *end note*]
@@ -1089,12 +1099,12 @@ template<class Source>
1089
  ```
1090
 
1091
  *Effects:* Appends `path(x).native()` to the pathname in the native
1092
  format.
1093
 
1094
- [*Note 2*: This directly manipulates the value of `native()` and may
1095
- not be portable between operating systems. — *end note*]
1096
 
1097
  *Returns:* `*this`.
1098
 
1099
  ``` cpp
1100
  path& operator+=(value_type x);
@@ -1243,14 +1253,10 @@ const value_type* c_str() const noexcept;
1243
  operator string_type() const;
1244
  ```
1245
 
1246
  *Returns:* `native()`.
1247
 
1248
- [*Note 3*: Conversion to `string_type` is provided so that an object of
1249
- class `path` can be given as an argument to existing standard library
1250
- file stream constructors and open functions. — *end note*]
1251
-
1252
  ``` cpp
1253
  template<class EcharT, class traits = char_traits<EcharT>,
1254
  class Allocator = allocator<EcharT>>
1255
  basic_string<EcharT, traits, Allocator>
1256
  string(const Allocator& a = Allocator()) const;
@@ -1450,17 +1456,17 @@ path(".bar").extension(); // yields "" and stem() is ".bar"
1450
  path("..bar").extension(); // yields ".bar" and stem() is "."
1451
  ```
1452
 
1453
  — *end example*]
1454
 
1455
- [*Note 4*: The period is included in the return value so that it is
1456
  possible to distinguish between no extension and an empty
1457
  extension. — *end note*]
1458
 
1459
- [*Note 5*: On non-POSIX operating systems, for a path `p`, it may not
1460
- be the case that `p.stem() + p.extension() == p.filename()`, even though
1461
- the generic format pathnames are the same. — *end note*]
1462
 
1463
  ##### Query <a id="fs.path.query">[[fs.path.query]]</a>
1464
 
1465
  ``` cpp
1466
  [[nodiscard]] bool empty() const noexcept;
@@ -1559,25 +1565,21 @@ slashes, but that does not affect `path` equality.
1559
 
1560
  ``` cpp
1561
  path lexically_relative(const path& base) const;
1562
  ```
1563
 
1564
- *Returns:* `*this` made relative to `base`. Does not
1565
- resolve [[fs.class.path]] symlinks. Does not first
1566
- normalize [[fs.path.generic]] `*this` or `base`.
1567
-
1568
  *Effects:* If:
1569
 
1570
  - `root_name() != base.root_name()` is `true`, or
1571
  - `is_absolute() != base.is_absolute()` is `true`, or
1572
  - `!has_root_directory() && base.has_root_directory()` is `true`, or
1573
  - any *filename* in `relative_path()` or `base.relative_path()` can be
1574
  interpreted as a *root-name*,
1575
 
1576
  returns `path()`.
1577
 
1578
- [*Note 6*: On a POSIX implementation, no *filename* in a
1579
  *relative-path* is acceptable as a *root-name*. — *end note*]
1580
 
1581
  Determines the first mismatched element of `*this` and `base` as if by:
1582
 
1583
  ``` cpp
@@ -1595,10 +1597,14 @@ Then,
1595
  - returns an object of class `path` that is default-constructed,
1596
  followed by
1597
  - application of `operator/=(path(".."))` `n` times, and then
1598
  - application of `operator/=` for each element in \[`a`, `end()`).
1599
 
 
 
 
 
1600
  [*Example 11*:
1601
 
1602
  ``` cpp
1603
  assert(path("/a/d").lexically_relative("/a/b/c") == "../../d");
1604
  assert(path("/a/b/c").lexically_relative("/a/d") == "../b/c");
@@ -1612,28 +1618,28 @@ The above assertions will succeed. On Windows, the returned path’s
1612
  *directory-separator* characters will be backslashes rather than
1613
  slashes, but that does not affect `path` equality.
1614
 
1615
  — *end example*]
1616
 
1617
- [*Note 7*: If symlink following semantics are desired, use the
1618
  operational function `relative()`. — *end note*]
1619
 
1620
- [*Note 8*: If normalization [[fs.path.generic]] is needed to ensure
1621
  consistent matching of elements, apply `lexically_normal()` to `*this`,
1622
  `base`, or both. — *end note*]
1623
 
1624
  ``` cpp
1625
  path lexically_proximate(const path& base) const;
1626
  ```
1627
 
1628
  *Returns:* If the value of `lexically_relative(base)` is not an empty
1629
  path, return it. Otherwise return `*this`.
1630
 
1631
- [*Note 9*: If symlink following semantics are desired, use the
1632
  operational function `proximate()`. — *end note*]
1633
 
1634
- [*Note 10*: If normalization [[fs.path.generic]] is needed to ensure
1635
  consistent matching of elements, apply `lexically_normal()` to `*this`,
1636
  `base`, or both. — *end note*]
1637
 
1638
  #### Iterators <a id="fs.path.itr">[[fs.path.itr]]</a>
1639
 
@@ -1738,14 +1744,10 @@ Path equality and path equivalence have different semantics.
1738
  - Equivalence is determined by the `equivalent()` non-member function,
1739
  which determines if two paths resolve [[fs.class.path]] to the same
1740
  file system entity. \[*Example 2*: `equivalent("foo", "bar")` will be
1741
  `true` when both paths resolve to the same file. — *end example*]
1742
 
1743
- Programmers wishing to determine if two paths are “the same” must decide
1744
- if “the same” means “the same representation” or “resolve to the same
1745
- actual file”, and choose the appropriate function accordingly.
1746
-
1747
  — *end note*]
1748
 
1749
  ``` cpp
1750
  friend strong_ordering operator<=>(const path& lhs, const path& rhs) noexcept;
1751
  ```
@@ -1756,12 +1758,24 @@ friend strong_ordering operator<=>(const path& lhs, const path& rhs) noexcept;
1756
  friend path operator/(const path& lhs, const path& rhs);
1757
  ```
1758
 
1759
  *Effects:* Equivalent to: `return path(lhs) /= rhs;`
1760
 
 
 
 
 
 
 
 
 
 
 
1761
  ### Class `filesystem_error` <a id="fs.class.filesystem.error">[[fs.class.filesystem.error]]</a>
1762
 
 
 
1763
  ``` cpp
1764
  namespace std::filesystem {
1765
  class filesystem_error : public system_error {
1766
  public:
1767
  filesystem_error(const string& what_arg, error_code ec);
@@ -1847,22 +1861,41 @@ and `path2` in the native format in the returned string.
1847
  #### Enum `path::format` <a id="fs.enum.path.format">[[fs.enum.path.format]]</a>
1848
 
1849
  This enum specifies constants used to identify the format of the
1850
  character sequence, with the meanings listed in [[fs.enum.path.format]].
1851
 
1852
- [*Note 1*: For POSIX-based systems, native and generic formats are
1853
- equivalent and the character sequence should always be interpreted in
1854
- the same way. — *end note*]
 
 
 
 
 
1855
 
1856
  #### Enum class `file_type` <a id="fs.enum.file.type">[[fs.enum.file.type]]</a>
1857
 
1858
  This enum class specifies constants used to identify file types, with
1859
  the meanings listed in [[fs.enum.file.type]]. The values of the
1860
  constants are distinct.
1861
 
1862
- [*Note 1*: The file not being found is not considered an error while
1863
- determining the type of a file. — *end note*]
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1864
 
1865
  #### Enum class `copy_options` <a id="fs.enum.copy.opts">[[fs.enum.copy.opts]]</a>
1866
 
1867
  The `enum class` type `copy_options` is a bitmask type [[bitmask.types]]
1868
  that specifies bitmask constants used to control the semantics of copy
@@ -1873,16 +1906,16 @@ exposition; implementations shall provide only a single definition.
1873
  Every other constant in the table represents a distinct bitmask element.
1874
 
1875
  **Table: Enum class `copy_options`** <a id="fs.enum.copy.opts">[fs.enum.copy.opts]</a>
1876
 
1877
  | Constant | Meaning |
1878
- | -------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------- |
1879
  | `none` | (Default) Error; file already exists. |
1880
  | `skip_existing` | Do not overwrite existing file, do not report an error. |
1881
  | `overwrite_existing` | Overwrite the existing file. |
1882
- | `update_existing` | Overwrite the existing file if it is older than the replacement file. \ohdrx{2}{Option group controlling `copy` function effects for sub-directories} |
1883
- | `recursive` | Recursively copy sub-directories and their contents. \ohdrx{2}{Option group controlling `copy` function effects for symbolic links} |
1884
  | `copy_symlinks` | Copy symbolic links as symbolic links rather than copying the files that they point to. |
1885
  | `skip_symlinks` | Ignore symbolic links. \ohdrx{2}{Option group controlling `copy` function effects for choosing the form of copying} |
1886
  | `directories_only` | Copy directory structure only, do not copy non-directory files. |
1887
  | `create_symlinks` | Make symbolic links instead of copies of files. The source path shall be an absolute path unless the destination path is in the current directory. |
1888
  | `create_hard_links` | Make hard links instead of copies of files. |
@@ -1931,12 +1964,12 @@ permissions operations, with the meanings listed in
1931
  **Table: Enum class `perm_options`** <a id="fs.enum.perm.opts">[fs.enum.perm.opts]</a>
1932
 
1933
  | Name | Meaning |
1934
  | ---------- | ------------------------------------------------------------------------------------------------------------------------------------------------------- |
1935
  | `replace` | `permissions` shall replace the file's permission bits with `perm` |
1936
- | `add` | `permissions` shall replace the file's permission bits with the bitwise \logop{OR} of `perm` and the file's current permission bits. |
1937
- | `remove` | `permissions` shall replace the file's permission bits with the bitwise \logop{AND} of the complement of `perm` and the file's current permission bits. |
1938
  | `nofollow` | `permissions` shall change the permissions of a symbolic link itself rather than the permissions of the file the link resolves to. |
1939
 
1940
 
1941
  #### Enum class `directory_options` <a id="fs.enum.dir.opts">[[fs.enum.dir.opts]]</a>
1942
 
@@ -1955,10 +1988,12 @@ every other constant in the table represents a distinct bitmask element.
1955
  | `skip_permission_denied` | Skip directories that would otherwise result in permission denied. |
1956
 
1957
 
1958
  ### Class `file_status` <a id="fs.class.file.status">[[fs.class.file.status]]</a>
1959
 
 
 
1960
  ``` cpp
1961
  namespace std::filesystem {
1962
  class file_status {
1963
  public:
1964
  // [fs.file.status.cons], constructors and destructor
@@ -2027,10 +2062,12 @@ void permissions(perms prms) noexcept;
2027
 
2028
  *Ensures:* `permissions() == prms`.
2029
 
2030
  ### Class `directory_entry` <a id="fs.class.directory.entry">[[fs.class.directory.entry]]</a>
2031
 
 
 
2032
  ``` cpp
2033
  namespace std::filesystem {
2034
  class directory_entry {
2035
  public:
2036
  // [fs.dir.entry.cons], constructors and destructor
@@ -2086,10 +2123,15 @@ namespace std::filesystem {
2086
  file_status symlink_status(error_code& ec) const noexcept;
2087
 
2088
  bool operator==(const directory_entry& rhs) const noexcept;
2089
  strong_ordering operator<=>(const directory_entry& rhs) const noexcept;
2090
 
 
 
 
 
 
2091
  private:
2092
  filesystem::path pathobject; // exposition only
2093
  friend class directory_iterator; // exposition only
2094
  };
2095
  }
@@ -2192,13 +2234,12 @@ unspecified.
2192
 
2193
  *Throws:* As specified in  [[fs.err.report]].
2194
 
2195
  [*Note 1*: Implementations of `directory_iterator`
2196
  [[fs.class.directory.iterator]] are prohibited from directly or
2197
- indirectly calling the `refresh` function since it must access the
2198
- external file system, and the objective of caching is to avoid
2199
- unnecessary file system accesses. — *end note*]
2200
 
2201
  #### Observers <a id="fs.dir.entry.obs">[[fs.dir.entry.obs]]</a>
2202
 
2203
  Unqualified function names in the *Returns:* elements of the
2204
  `directory_entry` observers described below refer to members of the
@@ -2363,18 +2404,30 @@ bool operator==(const directory_entry& rhs) const noexcept;
2363
  strong_ordering operator<=>(const directory_entry& rhs) const noexcept;
2364
  ```
2365
 
2366
  *Returns:* `pathobject <=> rhs.pathobject`.
2367
 
 
 
 
 
 
 
 
 
 
 
2368
  ### Class `directory_iterator` <a id="fs.class.directory.iterator">[[fs.class.directory.iterator]]</a>
2369
 
 
 
2370
  An object of type `directory_iterator` provides an iterator for a
2371
  sequence of `directory_entry` elements representing the path and any
2372
  cached attribute values [[fs.class.directory.entry]] for each file in a
2373
  directory or in an *implementation-defined* directory-like file type.
2374
 
2375
- [*Note 1*: For iteration into sub-directories, see class
2376
  `recursive_directory_iterator` [[fs.class.rec.dir.itr]]. — *end note*]
2377
 
2378
  ``` cpp
2379
  namespace std::filesystem {
2380
  class directory_iterator {
@@ -2402,10 +2455,14 @@ namespace std::filesystem {
2402
  const directory_entry& operator*() const;
2403
  const directory_entry* operator->() const;
2404
  directory_iterator& operator++();
2405
  directory_iterator& increment(error_code& ec);
2406
 
 
 
 
 
2407
  // other members as required by [input.iterators], input iterators
2408
  };
2409
  }
2410
  ```
2411
 
@@ -2424,12 +2481,12 @@ Two end iterators are always equal. An end iterator shall not be equal
2424
  to a non-end iterator.
2425
 
2426
  The result of calling the `path()` member of the `directory_entry`
2427
  object obtained by dereferencing a `directory_iterator` is a reference
2428
  to a `path` object composed of the directory argument from which the
2429
- iterator was constructed with filename of the directory entry appended
2430
- as if by `operator/=`.
2431
 
2432
  Directory iteration shall not yield directory entries for the current
2433
  (dot) and parent (dot-dot) directories.
2434
 
2435
  The order of directory entries obtained by dereferencing successive
@@ -2444,21 +2501,21 @@ call any `directory_entry` `refresh` function.
2444
  [*Note 2*: The exact mechanism for storing cached attribute values is
2445
  not exposed to users. For exposition, class `directory_iterator` is
2446
  shown in [[fs.class.directory.entry]] as a friend of class
2447
  `directory_entry`. — *end note*]
2448
 
2449
- [*Note 3*: Programs performing directory iteration may wish to test if
2450
- the path obtained by dereferencing a directory iterator actually exists.
2451
- It could be a symbolic link to a non-existent file. Programs recursively
2452
- walking directory trees for purposes of removing and renaming entries
2453
- may wish to avoid following symbolic links. — *end note*]
2454
 
2455
  [*Note 4*: If a file is removed from or added to a directory after the
2456
  construction of a `directory_iterator` for the directory, it is
2457
  unspecified whether or not subsequently incrementing the iterator will
2458
  ever result in an iterator referencing the removed or added directory
2459
- entry. See POSIX `readdir_r`. — *end note*]
2460
 
2461
  #### Members <a id="fs.dir.itr.members">[[fs.dir.itr.members]]</a>
2462
 
2463
  ``` cpp
2464
  directory_iterator() noexcept;
@@ -2532,21 +2589,23 @@ directory_iterator begin(directory_iterator iter) noexcept;
2532
  ```
2533
 
2534
  *Returns:* `iter`.
2535
 
2536
  ``` cpp
2537
- directory_iterator end(const directory_iterator&) noexcept;
2538
  ```
2539
 
2540
  *Returns:* `directory_iterator()`.
2541
 
2542
  ### Class `recursive_directory_iterator` <a id="fs.class.rec.dir.itr">[[fs.class.rec.dir.itr]]</a>
2543
 
 
 
2544
  An object of type `recursive_directory_iterator` provides an iterator
2545
  for a sequence of `directory_entry` elements representing the files in a
2546
  directory or in an *implementation-defined* directory-like file type,
2547
- and its sub-directories.
2548
 
2549
  ``` cpp
2550
  namespace std::filesystem {
2551
  class recursive_directory_iterator {
2552
  public:
@@ -2586,10 +2645,14 @@ namespace std::filesystem {
2586
 
2587
  void pop();
2588
  void pop(error_code& ec);
2589
  void disable_recursion_pending();
2590
 
 
 
 
 
2591
  // other members as required by [input.iterators], input iterators
2592
  };
2593
  }
2594
  ```
2595
 
@@ -2599,11 +2662,12 @@ results in undefined behavior.
2599
 
2600
  The behavior of a `recursive_directory_iterator` is the same as a
2601
  `directory_iterator` unless otherwise specified.
2602
 
2603
  [*Note 1*: If the directory structure being iterated over contains
2604
- cycles then the end iterator may be unreachable. — *end note*]
 
2605
 
2606
  #### Members <a id="fs.rec.dir.itr.members">[[fs.rec.dir.itr.members]]</a>
2607
 
2608
  ``` cpp
2609
  recursive_directory_iterator() noexcept;
@@ -2634,13 +2698,13 @@ error.
2634
  `directory_options` argument, otherwise
2635
  `options() == directory_options::none`.
2636
 
2637
  *Throws:* As specified in  [[fs.err.report]].
2638
 
2639
- [*Note 1*: To iterate over the current directory, use
2640
- `recursive_directory_iterator(".")` rather than
2641
- `recursive_directory_iterator("")`. — *end note*]
2642
 
2643
  [*Note 2*: By default, `recursive_directory_iterator` does not follow
2644
  directory symlinks. To follow directory symlinks, specify `options` as
2645
  `directory_options::follow_directory_symlink`. — *end note*]
2646
 
@@ -2777,40 +2841,42 @@ void disable_recursion_pending();
2777
  recursion into a directory. — *end note*]
2778
 
2779
  #### Non-member functions <a id="fs.rec.dir.itr.nonmembers">[[fs.rec.dir.itr.nonmembers]]</a>
2780
 
2781
  These functions enable use of `recursive_directory_iterator` with
2782
- range-based for statements.
2783
 
2784
  ``` cpp
2785
  recursive_directory_iterator begin(recursive_directory_iterator iter) noexcept;
2786
  ```
2787
 
2788
  *Returns:* `iter`.
2789
 
2790
  ``` cpp
2791
- recursive_directory_iterator end(const recursive_directory_iterator&) noexcept;
2792
  ```
2793
 
2794
  *Returns:* `recursive_directory_iterator()`.
2795
 
2796
  ### Filesystem operation functions <a id="fs.op.funcs">[[fs.op.funcs]]</a>
2797
 
 
 
2798
  Filesystem operation functions query or modify files, including
2799
  directories, in external storage.
2800
 
2801
  [*Note 1*: Because hardware failures, network failures, file system
2802
  races [[fs.race.behavior]], and many other kinds of errors occur
2803
- frequently in file system operations, users should be aware that any
2804
- filesystem operation function, no matter how apparently innocuous, may
2805
- encounter an error; see  [[fs.err.report]]. — *end note*]
2806
 
2807
  #### Absolute <a id="fs.op.absolute">[[fs.op.absolute]]</a>
2808
 
2809
  ``` cpp
2810
- path absolute(const path& p);
2811
- path absolute(const path& p, error_code& ec);
2812
  ```
2813
 
2814
  *Effects:* Composes an absolute path referencing the same file system
2815
  location as `p` according to the operating system [[fs.conform.os]].
2816
 
@@ -2820,12 +2886,12 @@ location as `p` according to the operating system [[fs.conform.os]].
2820
  [*Note 1*: For the returned path, `rp`, `rp.is_absolute()` is `true`
2821
  unless an error occurs. — *end note*]
2822
 
2823
  *Throws:* As specified in  [[fs.err.report]].
2824
 
2825
- [*Note 2*: To resolve symlinks, or perform other sanitization which
2826
- might require queries to secondary storage, such as hard disks, consider
2827
  `canonical` [[fs.op.canonical]]. — *end note*]
2828
 
2829
  [*Note 3*: Implementations are strongly encouraged to not query
2830
  secondary storage, and not consider `!exists(p)` an
2831
  error. — *end note*]
@@ -2836,12 +2902,12 @@ simply `current_path()/p`. For Windows-based operating systems,
2836
  `GetFullPathNameW`. — *end example*]
2837
 
2838
  #### Canonical <a id="fs.op.canonical">[[fs.op.canonical]]</a>
2839
 
2840
  ``` cpp
2841
- path canonical(const path& p);
2842
- path canonical(const path& p, error_code& ec);
2843
  ```
2844
 
2845
  *Effects:* Converts `p` to an absolute path that has no symbolic link,
2846
  dot, or dot-dot elements in its pathname in the generic format.
2847
 
@@ -2854,24 +2920,24 @@ error occurs.
2854
  *Remarks:* `!exists(p)` is an error.
2855
 
2856
  #### Copy <a id="fs.op.copy">[[fs.op.copy]]</a>
2857
 
2858
  ``` cpp
2859
- void copy(const path& from, const path& to);
2860
  ```
2861
 
2862
  *Effects:* Equivalent to `copy(from, to, copy_options::none)`.
2863
 
2864
  ``` cpp
2865
- void copy(const path& from, const path& to, error_code& ec);
2866
  ```
2867
 
2868
  *Effects:* Equivalent to `copy(from, to, copy_options::none, ec)`.
2869
 
2870
  ``` cpp
2871
- void copy(const path& from, const path& to, copy_options options);
2872
- void copy(const path& from, const path& to, copy_options options,
2873
  error_code& ec);
2874
  ```
2875
 
2876
  *Preconditions:* At most one element from each option
2877
  group [[fs.enum.copy.opts]] is set in `options`.
@@ -3008,22 +3074,22 @@ would result in:
3008
  — *end example*]
3009
 
3010
  #### Copy file <a id="fs.op.copy.file">[[fs.op.copy.file]]</a>
3011
 
3012
  ``` cpp
3013
- bool copy_file(const path& from, const path& to);
3014
- bool copy_file(const path& from, const path& to, error_code& ec);
3015
  ```
3016
 
3017
  *Returns:* `copy_file(from, to, copy_options::none)` or
3018
  `copy_file(from, to, copy_options::none, ec)`, respectively.
3019
 
3020
  *Throws:* As specified in  [[fs.err.report]].
3021
 
3022
  ``` cpp
3023
- bool copy_file(const path& from, const path& to, copy_options options);
3024
- bool copy_file(const path& from, const path& to, copy_options options,
3025
  error_code& ec);
3026
  ```
3027
 
3028
  *Preconditions:* At most one element from each option
3029
  group [[fs.enum.copy.opts]] is set in `options`.
@@ -3058,12 +3124,12 @@ signature with argument `ec` returns `false` if an error occurs.
3058
  *Complexity:* At most one direct or indirect invocation of `status(to)`.
3059
 
3060
  #### Copy symlink <a id="fs.op.copy.symlink">[[fs.op.copy.symlink]]</a>
3061
 
3062
  ``` cpp
3063
- void copy_symlink(const path& existing_symlink, const path& new_symlink);
3064
- void copy_symlink(const path& existing_symlink, const path& new_symlink,
3065
  error_code& ec) noexcept;
3066
  ```
3067
 
3068
  *Effects:* Equivalent to
3069
  *`function`*`(read_symlink(existing_symlink), new_symlink)` or
@@ -3074,12 +3140,12 @@ respectively, where in each case *`function`* is `create_symlink` or
3074
  *Throws:* As specified in  [[fs.err.report]].
3075
 
3076
  #### Create directories <a id="fs.op.create.directories">[[fs.op.create.directories]]</a>
3077
 
3078
  ``` cpp
3079
- bool create_directories(const path& p);
3080
- bool create_directories(const path& p, error_code& ec);
3081
  ```
3082
 
3083
  *Effects:* Calls `create_directory()` for each element of `p` that does
3084
  not exist.
3085
 
@@ -3091,12 +3157,12 @@ resolves to, otherwise `false`.
3091
  *Complexity:* 𝑂(n) where *n* is the number of elements of `p`.
3092
 
3093
  #### Create directory <a id="fs.op.create.directory">[[fs.op.create.directory]]</a>
3094
 
3095
  ``` cpp
3096
- bool create_directory(const path& p);
3097
- bool create_directory(const path& p, error_code& ec) noexcept;
3098
  ```
3099
 
3100
  *Effects:* Creates the directory `p` resolves to, as if by POSIX `mkdir`
3101
  with a second argument of `static_cast<int>(perms::all)`. If `mkdir`
3102
  fails because `p` resolves to an existing directory, no error is
@@ -3105,12 +3171,12 @@ reported. Otherwise on failure an error is reported.
3105
  *Returns:* `true` if a new directory was created, otherwise `false`.
3106
 
3107
  *Throws:* As specified in  [[fs.err.report]].
3108
 
3109
  ``` cpp
3110
- bool create_directory(const path& p, const path& existing_p);
3111
- bool create_directory(const path& p, const path& existing_p, error_code& ec) noexcept;
3112
  ```
3113
 
3114
  *Effects:* Creates the directory `p` resolves to, with attributes copied
3115
  from directory `existing_p`. The set of attributes copied is operating
3116
  system dependent. If `mkdir` fails because `p` resolves to an existing
@@ -3130,12 +3196,12 @@ from directory `existing_p`, otherwise `false`.
3130
  *Throws:* As specified in  [[fs.err.report]].
3131
 
3132
  #### Create directory symlink <a id="fs.op.create.dir.symlk">[[fs.op.create.dir.symlk]]</a>
3133
 
3134
  ``` cpp
3135
- void create_directory_symlink(const path& to, const path& new_symlink);
3136
- void create_directory_symlink(const path& to, const path& new_symlink,
3137
  error_code& ec) noexcept;
3138
  ```
3139
 
3140
  *Effects:* Establishes the postcondition, as if by POSIX `symlink()`.
3141
 
@@ -3143,24 +3209,24 @@ void create_directory_symlink(const path& to, const path& new_symlink,
3143
  an unspecified representation of `to`.
3144
 
3145
  *Throws:* As specified in  [[fs.err.report]].
3146
 
3147
  [*Note 1*: Some operating systems require symlink creation to identify
3148
- that the link is to a directory. Portable code should use
3149
- `create_directory_symlink()` to create directory symlinks rather than
3150
- `create_symlink()` — *end note*]
3151
 
3152
  [*Note 2*: Some operating systems do not support symbolic links at all
3153
  or support them only for regular files. Some file systems (such as the
3154
  FAT file system) do not support symbolic links regardless of the
3155
  operating system. — *end note*]
3156
 
3157
  #### Create hard link <a id="fs.op.create.hard.lk">[[fs.op.create.hard.lk]]</a>
3158
 
3159
  ``` cpp
3160
- void create_hard_link(const path& to, const path& new_hard_link);
3161
- void create_hard_link(const path& to, const path& new_hard_link,
3162
  error_code& ec) noexcept;
3163
  ```
3164
 
3165
  *Effects:* Establishes the postcondition, as if by POSIX `link()`.
3166
 
@@ -3178,12 +3244,12 @@ system. Some file systems limit the number of links per
3178
  file. — *end note*]
3179
 
3180
  #### Create symlink <a id="fs.op.create.symlink">[[fs.op.create.symlink]]</a>
3181
 
3182
  ``` cpp
3183
- void create_symlink(const path& to, const path& new_symlink);
3184
- void create_symlink(const path& to, const path& new_symlink,
3185
  error_code& ec) noexcept;
3186
  ```
3187
 
3188
  *Effects:* Establishes the postcondition, as if by POSIX `symlink()`.
3189
 
@@ -3198,12 +3264,12 @@ FAT file system) do not support symbolic links regardless of the
3198
  operating system. — *end note*]
3199
 
3200
  #### Current path <a id="fs.op.current.path">[[fs.op.current.path]]</a>
3201
 
3202
  ``` cpp
3203
- path current_path();
3204
- path current_path(error_code& ec);
3205
  ```
3206
 
3207
  *Returns:* The absolute path of the current working directory, whose
3208
  pathname in the native format is obtained as if by POSIX `getcwd()`. The
3209
  signature with argument `ec` returns `path()` if an error occurs.
@@ -3217,61 +3283,61 @@ resolution for relative paths.
3217
  [*Note 1*: The `current_path()` name was chosen to emphasize that the
3218
  returned value is a path, not just a single directory
3219
  name. — *end note*]
3220
 
3221
  [*Note 2*: The current path as returned by many operating systems is a
3222
- dangerous global variable. It may be changed unexpectedly by third-party
3223
  or system library functions, or by another thread. — *end note*]
3224
 
3225
  ``` cpp
3226
- void current_path(const path& p);
3227
- void current_path(const path& p, error_code& ec) noexcept;
3228
  ```
3229
 
3230
  *Effects:* Establishes the postcondition, as if by POSIX `chdir()`.
3231
 
3232
  *Ensures:* `equivalent(p, current_path())`.
3233
 
3234
  *Throws:* As specified in  [[fs.err.report]].
3235
 
3236
  [*Note 3*: The current path for many operating systems is a dangerous
3237
- global state. It may be changed unexpectedly by a third-party or system
3238
  library functions, or by another thread. — *end note*]
3239
 
3240
  #### Equivalent <a id="fs.op.equivalent">[[fs.op.equivalent]]</a>
3241
 
3242
  ``` cpp
3243
- bool equivalent(const path& p1, const path& p2);
3244
- bool equivalent(const path& p1, const path& p2, error_code& ec) noexcept;
3245
  ```
3246
 
3247
- *Returns:* `true`, if `p1` and `p2` resolve to the same file system
3248
- entity, otherwise `false`. The signature with argument `ec` returns
3249
- `false` if an error occurs.
3250
-
3251
  Two paths are considered to resolve to the same file system entity if
3252
  two candidate entities reside on the same device at the same location.
3253
 
3254
  [*Note 1*: On POSIX platforms, this is determined as if by the values
3255
  of the POSIX `stat` class, obtained as if by `stat()` for the two paths,
3256
  having equal `st_dev` values and equal `st_ino` values. — *end note*]
3257
 
 
 
 
 
 
 
3258
  *Remarks:* `!exists(p1) || !exists(p2)` is an error.
3259
 
3260
- *Throws:* As specified in  [[fs.err.report]].
3261
-
3262
  #### Exists <a id="fs.op.exists">[[fs.op.exists]]</a>
3263
 
3264
  ``` cpp
3265
- bool exists(file_status s) noexcept;
3266
  ```
3267
 
3268
  *Returns:* `status_known(s) && s.type() != file_type::not_found`.
3269
 
3270
  ``` cpp
3271
- bool exists(const path& p);
3272
- bool exists(const path& p, error_code& ec) noexcept;
3273
  ```
3274
 
3275
  Let `s` be a `file_status`, determined as if by `status(p)` or
3276
  `status(p, ec)`, respectively.
3277
 
@@ -3283,12 +3349,12 @@ Let `s` be a `file_status`, determined as if by `status(p)` or
3283
  *Throws:* As specified in  [[fs.err.report]].
3284
 
3285
  #### File size <a id="fs.op.file.size">[[fs.op.file.size]]</a>
3286
 
3287
  ``` cpp
3288
- uintmax_t file_size(const path& p);
3289
- uintmax_t file_size(const path& p, error_code& ec) noexcept;
3290
  ```
3291
 
3292
  *Effects:* If `exists(p)` is `false`, an error is
3293
  reported [[fs.err.report]].
3294
 
@@ -3305,30 +3371,30 @@ an error occurs.
3305
  *Throws:* As specified in  [[fs.err.report]].
3306
 
3307
  #### Hard link count <a id="fs.op.hard.lk.ct">[[fs.op.hard.lk.ct]]</a>
3308
 
3309
  ``` cpp
3310
- uintmax_t hard_link_count(const path& p);
3311
- uintmax_t hard_link_count(const path& p, error_code& ec) noexcept;
3312
  ```
3313
 
3314
  *Returns:* The number of hard links for `p`. The signature with argument
3315
  `ec` returns `static_cast<uintmax_t>(-1)` if an error occurs.
3316
 
3317
  *Throws:* As specified in  [[fs.err.report]].
3318
 
3319
  #### Is block file <a id="fs.op.is.block.file">[[fs.op.is.block.file]]</a>
3320
 
3321
  ``` cpp
3322
- bool is_block_file(file_status s) noexcept;
3323
  ```
3324
 
3325
  *Returns:* `s.type() == file_type::block`.
3326
 
3327
  ``` cpp
3328
- bool is_block_file(const path& p);
3329
- bool is_block_file(const path& p, error_code& ec) noexcept;
3330
  ```
3331
 
3332
  *Returns:* `is_block_file(status(p))` or `is_block_file(status(p, ec))`,
3333
  respectively. The signature with argument `ec` returns `false` if an
3334
  error occurs.
@@ -3336,18 +3402,18 @@ error occurs.
3336
  *Throws:* As specified in  [[fs.err.report]].
3337
 
3338
  #### Is character file <a id="fs.op.is.char.file">[[fs.op.is.char.file]]</a>
3339
 
3340
  ``` cpp
3341
- bool is_character_file(file_status s) noexcept;
3342
  ```
3343
 
3344
  *Returns:* `s.type() == file_type::character`.
3345
 
3346
  ``` cpp
3347
- bool is_character_file(const path& p);
3348
- bool is_character_file(const path& p, error_code& ec) noexcept;
3349
  ```
3350
 
3351
  *Returns:* `is_character_file(status(p))` or
3352
  `is_character_file(status(p, ec))`, respectively.
3353
  The signature with argument `ec` returns `false` if an error occurs.
@@ -3355,18 +3421,18 @@ The signature with argument `ec` returns `false` if an error occurs.
3355
  *Throws:* As specified in  [[fs.err.report]].
3356
 
3357
  #### Is directory <a id="fs.op.is.directory">[[fs.op.is.directory]]</a>
3358
 
3359
  ``` cpp
3360
- bool is_directory(file_status s) noexcept;
3361
  ```
3362
 
3363
  *Returns:* `s.type() == file_type::directory`.
3364
 
3365
  ``` cpp
3366
- bool is_directory(const path& p);
3367
- bool is_directory(const path& p, error_code& ec) noexcept;
3368
  ```
3369
 
3370
  *Returns:* `is_directory(status(p))` or `is_directory(status(p, ec))`,
3371
  respectively. The signature with argument `ec` returns `false` if an
3372
  error occurs.
@@ -3374,12 +3440,12 @@ error occurs.
3374
  *Throws:* As specified in  [[fs.err.report]].
3375
 
3376
  #### Is empty <a id="fs.op.is.empty">[[fs.op.is.empty]]</a>
3377
 
3378
  ``` cpp
3379
- bool is_empty(const path& p);
3380
- bool is_empty(const path& p, error_code& ec);
3381
  ```
3382
 
3383
  *Effects:*
3384
 
3385
  - Determine `file_status s`, as if by `status(p)` or `status(p, ec)`,
@@ -3402,18 +3468,18 @@ bool is_empty(const path& p, error_code& ec);
3402
  *Throws:* As specified in  [[fs.err.report]].
3403
 
3404
  #### Is fifo <a id="fs.op.is.fifo">[[fs.op.is.fifo]]</a>
3405
 
3406
  ``` cpp
3407
- bool is_fifo(file_status s) noexcept;
3408
  ```
3409
 
3410
  *Returns:* `s.type() == file_type::fifo`.
3411
 
3412
  ``` cpp
3413
- bool is_fifo(const path& p);
3414
- bool is_fifo(const path& p, error_code& ec) noexcept;
3415
  ```
3416
 
3417
  *Returns:* `is_fifo(status(p))` or `is_fifo(status(p, ec))`,
3418
  respectively. The signature with argument `ec` returns `false` if an
3419
  error occurs.
@@ -3421,19 +3487,19 @@ error occurs.
3421
  *Throws:* As specified in  [[fs.err.report]].
3422
 
3423
  #### Is other <a id="fs.op.is.other">[[fs.op.is.other]]</a>
3424
 
3425
  ``` cpp
3426
- bool is_other(file_status s) noexcept;
3427
  ```
3428
 
3429
  *Returns:*
3430
  `exists(s) && !is_regular_file(s) && !is_directory(s) && !is_symlink(s)`.
3431
 
3432
  ``` cpp
3433
- bool is_other(const path& p);
3434
- bool is_other(const path& p, error_code& ec) noexcept;
3435
  ```
3436
 
3437
  *Returns:* `is_other(status(p))` or `is_other(status(p, ec))`,
3438
  respectively. The signature with argument `ec` returns `false` if an
3439
  error occurs.
@@ -3441,26 +3507,26 @@ error occurs.
3441
  *Throws:* As specified in  [[fs.err.report]].
3442
 
3443
  #### Is regular file <a id="fs.op.is.regular.file">[[fs.op.is.regular.file]]</a>
3444
 
3445
  ``` cpp
3446
- bool is_regular_file(file_status s) noexcept;
3447
  ```
3448
 
3449
  *Returns:* `s.type() == file_type::regular`.
3450
 
3451
  ``` cpp
3452
- bool is_regular_file(const path& p);
3453
  ```
3454
 
3455
  *Returns:* `is_regular_file(status(p))`.
3456
 
3457
  *Throws:* `filesystem_error` if `status(p)` would throw
3458
  `filesystem_error`.
3459
 
3460
  ``` cpp
3461
- bool is_regular_file(const path& p, error_code& ec) noexcept;
3462
  ```
3463
 
3464
  *Effects:* Sets `ec` as if by `status(p, ec)`.
3465
 
3466
  [*Note 1*: `file_type::none`, `file_type::not_found` and
@@ -3471,18 +3537,18 @@ between cases, call the `status` function directly. — *end note*]
3471
  occurs.
3472
 
3473
  #### Is socket <a id="fs.op.is.socket">[[fs.op.is.socket]]</a>
3474
 
3475
  ``` cpp
3476
- bool is_socket(file_status s) noexcept;
3477
  ```
3478
 
3479
  *Returns:* `s.type() == file_type::socket`.
3480
 
3481
  ``` cpp
3482
- bool is_socket(const path& p);
3483
- bool is_socket(const path& p, error_code& ec) noexcept;
3484
  ```
3485
 
3486
  *Returns:* `is_socket(status(p))` or `is_socket(status(p, ec))`,
3487
  respectively. The signature with argument `ec` returns `false` if an
3488
  error occurs.
@@ -3490,18 +3556,18 @@ error occurs.
3490
  *Throws:* As specified in  [[fs.err.report]].
3491
 
3492
  #### Is symlink <a id="fs.op.is.symlink">[[fs.op.is.symlink]]</a>
3493
 
3494
  ``` cpp
3495
- bool is_symlink(file_status s) noexcept;
3496
  ```
3497
 
3498
  *Returns:* `s.type() == file_type::symlink`.
3499
 
3500
  ``` cpp
3501
- bool is_symlink(const path& p);
3502
- bool is_symlink(const path& p, error_code& ec) noexcept;
3503
  ```
3504
 
3505
  *Returns:* `is_symlink(symlink_status(p))` or
3506
  `is_symlink(symlink_status(p, ec))`, respectively. The signature with
3507
  argument `ec` returns `false` if an error occurs.
@@ -3509,74 +3575,74 @@ argument `ec` returns `false` if an error occurs.
3509
  *Throws:* As specified in  [[fs.err.report]].
3510
 
3511
  #### Last write time <a id="fs.op.last.write.time">[[fs.op.last.write.time]]</a>
3512
 
3513
  ``` cpp
3514
- file_time_type last_write_time(const path& p);
3515
- file_time_type last_write_time(const path& p, error_code& ec) noexcept;
3516
  ```
3517
 
3518
  *Returns:* The time of last data modification of `p`, determined as if
3519
  by the value of the POSIX `stat` class member `st_mtime` obtained as if
3520
  by POSIX `stat()`. The signature with argument `ec` returns
3521
  `file_time_type::min()` if an error occurs.
3522
 
3523
  *Throws:* As specified in  [[fs.err.report]].
3524
 
3525
  ``` cpp
3526
- void last_write_time(const path& p, file_time_type new_time);
3527
- void last_write_time(const path& p, file_time_type new_time,
3528
  error_code& ec) noexcept;
3529
  ```
3530
 
3531
  *Effects:* Sets the time of last data modification of the file resolved
3532
  to by `p` to `new_time`, as if by POSIX `futimens()`.
3533
 
3534
  *Throws:* As specified in  [[fs.err.report]].
3535
 
3536
  [*Note 1*: A postcondition of `last_write_time(p) == new_time` is not
3537
- specified since it might not hold for file systems with coarse time
3538
- granularity. — *end note*]
3539
 
3540
  #### Permissions <a id="fs.op.permissions">[[fs.op.permissions]]</a>
3541
 
3542
  ``` cpp
3543
- void permissions(const path& p, perms prms, perm_options opts=perm_options::replace);
3544
- void permissions(const path& p, perms prms, error_code& ec) noexcept;
3545
- void permissions(const path& p, perms prms, perm_options opts, error_code& ec);
3546
  ```
3547
 
3548
  *Preconditions:* Exactly one of the `perm_options` constants `replace`,
3549
  `add`, or `remove` is present in `opts`.
3550
 
3551
- *Remarks:* The second signature behaves as if it had an additional
3552
- parameter `perm_options` `opts` with an argument of
3553
- `perm_options::replace`.
3554
-
3555
  *Effects:* Applies the action specified by `opts` to the file `p`
3556
  resolves to, or to file `p` itself if `p` is a symbolic link and
3557
  `perm_options::nofollow` is set in `opts`. The action is applied as if
3558
  by POSIX `fchmodat()`.
3559
 
3560
  [*Note 1*: Conceptually permissions are viewed as bits, but the actual
3561
- implementation may use some other mechanism. — *end note*]
3562
 
3563
  *Throws:* As specified in  [[fs.err.report]].
3564
 
 
 
 
 
3565
  #### Proximate <a id="fs.op.proximate">[[fs.op.proximate]]</a>
3566
 
3567
  ``` cpp
3568
- path proximate(const path& p, error_code& ec);
3569
  ```
3570
 
3571
  *Returns:* `proximate(p, current_path(), ec)`.
3572
 
3573
  *Throws:* As specified in  [[fs.err.report]].
3574
 
3575
  ``` cpp
3576
- path proximate(const path& p, const path& base = current_path());
3577
- path proximate(const path& p, const path& base, error_code& ec);
3578
  ```
3579
 
3580
  *Returns:* For the first form:
3581
 
3582
  ``` cpp
@@ -3594,12 +3660,12 @@ or `path()` at the first error occurrence, if any.
3594
  *Throws:* As specified in  [[fs.err.report]].
3595
 
3596
  #### Read symlink <a id="fs.op.read.symlink">[[fs.op.read.symlink]]</a>
3597
 
3598
  ``` cpp
3599
- path read_symlink(const path& p);
3600
- path read_symlink(const path& p, error_code& ec);
3601
  ```
3602
 
3603
  *Returns:* If `p` resolves to a symbolic link, a `path` object
3604
  containing the contents of that symbolic link. The signature with
3605
  argument `ec` returns `path()` if an error occurs.
@@ -3610,20 +3676,20 @@ argument `ec` returns `path()` if an error occurs.
3610
  link. — *end note*]
3611
 
3612
  #### Relative <a id="fs.op.relative">[[fs.op.relative]]</a>
3613
 
3614
  ``` cpp
3615
- path relative(const path& p, error_code& ec);
3616
  ```
3617
 
3618
  *Returns:* `relative(p, current_path(), ec)`.
3619
 
3620
  *Throws:* As specified in  [[fs.err.report]].
3621
 
3622
  ``` cpp
3623
- path relative(const path& p, const path& base = current_path());
3624
- path relative(const path& p, const path& base, error_code& ec);
3625
  ```
3626
 
3627
  *Returns:* For the first form:
3628
 
3629
  ``` cpp
@@ -3641,12 +3707,12 @@ or `path()` at the first error occurrence, if any.
3641
  *Throws:* As specified in  [[fs.err.report]].
3642
 
3643
  #### Remove <a id="fs.op.remove">[[fs.op.remove]]</a>
3644
 
3645
  ``` cpp
3646
- bool remove(const path& p);
3647
- bool remove(const path& p, error_code& ec) noexcept;
3648
  ```
3649
 
3650
  *Effects:* If `exists(symlink_status(p, ec))`, the file `p` is removed
3651
  as if by POSIX `remove()`.
3652
 
@@ -3661,12 +3727,12 @@ with argument `ec` returns `false` if an error occurs.
3661
  *Throws:* As specified in  [[fs.err.report]].
3662
 
3663
  #### Remove all <a id="fs.op.remove.all">[[fs.op.remove.all]]</a>
3664
 
3665
  ``` cpp
3666
- uintmax_t remove_all(const path& p);
3667
- uintmax_t remove_all(const path& p, error_code& ec);
3668
  ```
3669
 
3670
  *Effects:* Recursively deletes the contents of `p` if it exists, then
3671
  deletes file `p` itself, as if by POSIX `remove()`.
3672
 
@@ -3681,25 +3747,25 @@ returns `static_cast< uintmax_t>(-1)` if an error occurs.
3681
  *Throws:* As specified in  [[fs.err.report]].
3682
 
3683
  #### Rename <a id="fs.op.rename">[[fs.op.rename]]</a>
3684
 
3685
  ``` cpp
3686
- void rename(const path& old_p, const path& new_p);
3687
- void rename(const path& old_p, const path& new_p, error_code& ec) noexcept;
3688
  ```
3689
 
3690
  *Effects:* Renames `old_p` to `new_p`, as if by POSIX `rename()`.
3691
 
3692
  [*Note 1*:
3693
 
3694
  - If `old_p` and `new_p` resolve to the same existing file, no action is
3695
  taken.
3696
- - Otherwise, the rename may include the following effects:
3697
  - if `new_p` resolves to an existing non-directory file, `new_p` is
3698
  removed; otherwise,
3699
  - if `new_p` resolves to an existing directory, `new_p` is removed if
3700
- empty on POSIX compliant operating systems but may be an error on
3701
  other operating systems.
3702
 
3703
  A symbolic link is itself renamed, rather than the file it resolves to.
3704
 
3705
  — *end note*]
@@ -3707,24 +3773,24 @@ A symbolic link is itself renamed, rather than the file it resolves to.
3707
  *Throws:* As specified in  [[fs.err.report]].
3708
 
3709
  #### Resize file <a id="fs.op.resize.file">[[fs.op.resize.file]]</a>
3710
 
3711
  ``` cpp
3712
- void resize_file(const path& p, uintmax_t new_size);
3713
- void resize_file(const path& p, uintmax_t new_size, error_code& ec) noexcept;
3714
  ```
3715
 
3716
  *Effects:* Causes the size that would be returned by `file_size(p)` to
3717
  be equal to `new_size`, as if by POSIX `truncate()`.
3718
 
3719
  *Throws:* As specified in  [[fs.err.report]].
3720
 
3721
  #### Space <a id="fs.op.space">[[fs.op.space]]</a>
3722
 
3723
  ``` cpp
3724
- space_info space(const path& p);
3725
- space_info space(const path& p, error_code& ec) noexcept;
3726
  ```
3727
 
3728
  *Returns:* An object of type `space_info`. The value of the `space_info`
3729
  object is determined as if by using POSIX `statvfs` to obtain a POSIX
3730
  `struct statvfs`, and then multiplying its `f_blocks`, `f_bfree`, and
@@ -3737,16 +3803,16 @@ members are set to `static_cast<uintmax_t>(-1)` if an error occurs.
3737
  *Throws:* As specified in  [[fs.err.report]].
3738
 
3739
  *Remarks:* The value of member `space_info::available` is operating
3740
  system dependent.
3741
 
3742
- [*Note 1*: `available` may be less than `free`. — *end note*]
3743
 
3744
  #### Status <a id="fs.op.status">[[fs.op.status]]</a>
3745
 
3746
  ``` cpp
3747
- file_status status(const path& p);
3748
  ```
3749
 
3750
  *Effects:* As if:
3751
 
3752
  ``` cpp
@@ -3764,11 +3830,11 @@ return result;
3764
  [*Note 1*: `result` values of `file_status(file_type::not_found)` and
3765
  `file_status(file_type::unknown)` are not considered failures and do not
3766
  cause an exception to be thrown. — *end note*]
3767
 
3768
  ``` cpp
3769
- file_status status(const path& p, error_code& ec) noexcept;
3770
  ```
3771
 
3772
  *Effects:* If possible, determines the attributes of the file `p`
3773
  resolves to, as if by using POSIX `stat()` to obtain a POSIX
3774
  `struct stat`. If, during attribute determination, the underlying file
@@ -3829,20 +3895,20 @@ determined as if by converting the `st_mode` member of the obtained
3829
  pathname resolution continues using the contents of the symbolic link.
3830
 
3831
  #### Status known <a id="fs.op.status.known">[[fs.op.status.known]]</a>
3832
 
3833
  ``` cpp
3834
- bool status_known(file_status s) noexcept;
3835
  ```
3836
 
3837
  *Returns:* `s.type() != file_type::none`.
3838
 
3839
  #### Symlink status <a id="fs.op.symlink.status">[[fs.op.symlink.status]]</a>
3840
 
3841
  ``` cpp
3842
- file_status symlink_status(const path& p);
3843
- file_status symlink_status(const path& p, error_code& ec) noexcept;
3844
  ```
3845
 
3846
  *Effects:* Same as `status()`, above, except that the attributes of `p`
3847
  are determined as if by using POSIX `lstat()` to obtain a POSIX
3848
  `struct stat`.
@@ -3854,19 +3920,19 @@ determined as if by converting the `st_mode` member of the obtained
3854
  *Returns:* Same as `status()`, above, except that if the attributes
3855
  indicate a symbolic link, as if by POSIX `S_ISLNK`, returns
3856
  `file_status(file_type::symlink, prms)`. The signature with argument
3857
  `ec` returns `file_status(file_type::none)` if an error occurs.
3858
 
 
 
3859
  *Remarks:* Pathname resolution terminates if `p` names a symbolic link.
3860
 
3861
- *Throws:* As specified in  [[fs.err.report]].
3862
-
3863
  #### Temporary directory path <a id="fs.op.temp.dir.path">[[fs.op.temp.dir.path]]</a>
3864
 
3865
  ``` cpp
3866
- path temp_directory_path();
3867
- path temp_directory_path(error_code& ec);
3868
  ```
3869
 
3870
  Let `p` be an unspecified directory path suitable for temporary files.
3871
 
3872
  *Effects:* If `exists(p)` is `false` or `is_directory(p)` is `false`, an
@@ -3885,17 +3951,14 @@ return the path reported by the Windows `GetTempPath` API
3885
  function. — *end example*]
3886
 
3887
  #### Weakly canonical <a id="fs.op.weakly.canonical">[[fs.op.weakly.canonical]]</a>
3888
 
3889
  ``` cpp
3890
- path weakly_canonical(const path& p);
3891
- path weakly_canonical(const path& p, error_code& ec);
3892
  ```
3893
 
3894
- *Returns:* `p` with symlinks resolved and the result
3895
- normalized [[fs.path.generic]].
3896
-
3897
  *Effects:* Using `status(p)` or `status(p, ec)`, respectively, to
3898
  determine existence, return a path composed by `operator/=` from the
3899
  result of calling `canonical()` with a path argument composed of the
3900
  leading elements of `p` that exist, if any, followed by the elements of
3901
  `p` that do not exist, if any. For the first form, `canonical()` is
@@ -3903,10 +3966,10 @@ called without an `error_code` argument. For the second form,
3903
  `canonical()` is called with `ec` as an `error_code` argument, and
3904
  `path()` is returned at the first error occurrence, if any.
3905
 
3906
  *Ensures:* The returned path is in normal form [[fs.path.generic]].
3907
 
3908
- *Remarks:* Implementations should avoid unnecessary normalization such
3909
- as when `canonical` has already been called on the entirety of `p`.
3910
 
3911
  *Throws:* As specified in  [[fs.err.report]].
3912
 
 
40
  does not exist, the symbolic link is said to be a “dangling” symbolic
41
  link. — *end note*]
42
 
43
  ### Conformance <a id="fs.conformance">[[fs.conformance]]</a>
44
 
45
+ #### General <a id="fs.conformance.general">[[fs.conformance.general]]</a>
46
+
47
  Conformance is specified in terms of behavior. Ideal behavior is not
48
  always implementable, so the conformance subclauses take that into
49
  account.
50
 
51
  #### POSIX conformance <a id="fs.conform.9945">[[fs.conform.9945]]</a>
52
 
53
+ Some behavior is specified by reference to POSIX. How such behavior is
54
+ actually implemented is unspecified.
55
 
56
  [*Note 1*: This constitutes an “as if” rule allowing implementations to
57
  call native operating system or other APIs. — *end note*]
58
 
59
  Implementations should provide such behavior as it is defined by POSIX.
 
92
  #### File system race behavior <a id="fs.race.behavior">[[fs.race.behavior]]</a>
93
 
94
  A *file system race* is the condition that occurs when multiple threads,
95
  processes, or computers interleave access and modification of the same
96
  object within a file system. Behavior is undefined if calls to functions
97
+ provided by subclause  [[filesystems]] introduce a file system race.
 
98
 
99
  If the possibility of a file system race would make it unreliable for a
100
  program to test for a precondition before calling a function described
101
  herein, *Preconditions:* is not specified for the function.
102
 
103
  [*Note 1*: As a design practice, preconditions are not specified when
104
  it is unreasonable for a program to detect them prior to calling the
105
  function. — *end note*]
106
 
 
 
 
 
 
107
  ### Requirements <a id="fs.req">[[fs.req]]</a>
108
 
109
  Throughout subclause  [[filesystems]], `char`, `wchar_t`, `char8_t`,
110
  `char16_t`, and `char32_t` are collectively called *encoded character
111
  types*.
 
122
  character set and encoding. Since `signed char` and `unsigned char` have
123
  no implied character set and encoding, they are not included as
124
  permitted types. — *end note*]
125
 
126
  Template parameters named `Allocator` shall meet the *Cpp17Allocator*
127
+ requirements [[allocator.requirements.general]].
 
 
 
 
 
 
128
 
129
  ### Header `<filesystem>` synopsis <a id="fs.filesystem.syn">[[fs.filesystem.syn]]</a>
130
 
131
  ``` cpp
132
  #include <compare> // see [compare.syn]
 
148
  // [fs.class.directory.iterator], directory iterators
149
  class directory_iterator;
150
 
151
  // [fs.dir.itr.nonmembers], range access for directory iterators
152
  directory_iterator begin(directory_iterator iter) noexcept;
153
+ directory_iterator end(directory_iterator) noexcept;
154
 
155
  // [fs.class.rec.dir.itr], recursive directory iterators
156
  class recursive_directory_iterator;
157
 
158
  // [fs.rec.dir.itr.nonmembers], range access for recursive directory iterators
159
  recursive_directory_iterator begin(recursive_directory_iterator iter) noexcept;
160
+ recursive_directory_iterator end(recursive_directory_iterator) noexcept;
161
 
162
  // [fs.class.file.status], file status
163
  class file_status;
164
 
165
  struct space_info {
 
325
  path temp_directory_path(error_code& ec);
326
 
327
  path weakly_canonical(const path& p);
328
  path weakly_canonical(const path& p, error_code& ec);
329
  }
330
+
331
+ // [fs.path.hash], hash support
332
+ namespace std {
333
+ template<class T> struct hash;
334
+ template<> struct hash<filesystem::path>;
335
+ }
336
+
337
+ namespace std::ranges {
338
+ template<>
339
+ inline constexpr bool enable_borrowed_range<filesystem::directory_iterator> = true;
340
+ template<>
341
+ inline constexpr bool enable_borrowed_range<filesystem::recursive_directory_iterator> = true;
342
+
343
+ template<>
344
+ inline constexpr bool enable_view<filesystem::directory_iterator> = true;
345
+ template<>
346
+ inline constexpr bool enable_view<filesystem::recursive_directory_iterator> = true;
347
+ }
348
  ```
349
 
350
  Implementations should ensure that the resolution and range of
351
  `file_time_type` reflect the operating system dependent resolution and
352
  range of file time values.
 
397
  appropriate for the specific operating system dependent error.
398
  Otherwise, `clear()` is called on the `error_code&` argument.
399
 
400
  ### Class `path` <a id="fs.class.path">[[fs.class.path]]</a>
401
 
402
+ #### General <a id="fs.class.path.general">[[fs.class.path.general]]</a>
403
+
404
  An object of class `path` represents a path and contains a pathname.
405
  Such an object is concerned only with the lexical and syntactic aspects
406
  of a path. The path does not necessarily exist in external storage, and
407
  the pathname is not necessarily valid for the current operating system
408
  or for a particular file system.
 
424
  dependent. A *relative path* is a path that is not absolute, and as
425
  such, only unambiguously identifies the location of a file when resolved
426
  relative to an implied starting location. The elements of a path that
427
  determine if it is relative are operating system dependent.
428
 
429
+ [*Note 2*: Pathnames “.” and “..” are relative paths. — *end note*]
430
 
431
  A *pathname* is a character string that represents the name of a path.
432
  Pathnames are formatted according to the generic pathname format grammar
433
  [[fs.path.generic]] or according to an operating system dependent
434
  *native pathname format* accepted by the host operating system.
435
 
436
  *Pathname resolution* is the operating system dependent mechanism for
437
  resolving a pathname to a particular file in a file hierarchy. There may
438
  be multiple pathnames that resolve to the same file.
439
 
440
+ [*Example 1*: POSIX specifies the mechanism in section 4.12, Pathname
441
  resolution. — *end example*]
442
 
443
  ``` cpp
444
  namespace std::filesystem {
445
  class path {
 
657
  special meaning. The following characteristics of filenames are
658
  operating system dependent:
659
 
660
  - The permitted characters. \[*Example 1*: Some operating systems
661
  prohibit the ASCII control characters (0x00 – 0x1F) in
662
+ filenames. — *end example*] \[*Note 1*: Wider portability can be
663
+ achieved by limiting *filename* characters to the POSIX Portable
664
+ Filename Character Set:
665
  `A B C D E F G H I J K L M N O P Q R S T U V W X Y Z`
666
  `a b c d e f g h i j k l m n o p q r s t u v w x y z`
667
  `0 1 2 3 4 5 6 7 8 9 . _ -` — *end note*]
668
  - The maximum permitted length.
669
  - Filenames that are not permitted.
 
688
  required.
689
 
690
  [*Note 2*: Many operating systems define a name beginning with two
691
  *directory-separator* characters as a *root-name* that identifies
692
  network or other resource locations. Some operating systems define a
693
+ single letter followed by a colon as a drive specifier a *root-name*
694
  identifying a specific device such as a disk drive. — *end note*]
695
 
696
  If a *root-name* is otherwise ambiguous, the possibility with the
697
  longest sequence of characters is chosen.
698
 
 
704
 
705
  1. If the path is empty, stop.
706
  2. Replace each slash character in the *root-name* with a
707
  *preferred-separator*.
708
  3. Replace each *directory-separator* with a *preferred-separator*.
709
+ \[*Note 4*: The generic pathname grammar defines
710
  *directory-separator* as one or more slashes and
711
  *preferred-separator*s. — *end note*]
712
  4. Remove each dot filename and any immediately following
713
  *directory-separator*.
714
  5. As long as any appear, remove a non-dot-dot filename immediately
 
748
  or a pathname in the native format [[fs.class.path]]. Such an argument
749
  is taken to be in the generic format if and only if it matches the
750
  generic format and is not acceptable to the operating system as a native
751
  path.
752
 
753
+ [*Note 2*: Some operating systems have no unambiguous way to
754
  distinguish between native format and generic format arguments. This is
755
  by design as it simplifies use for operating systems that do not require
756
  disambiguation. An implementation for an operating system where
757
  disambiguation is required is permitted to distinguish between the
758
  formats. — *end note*]
 
771
  directory path if its last element is a *directory-separator*, otherwise
772
  it shall be treated as a path to a regular file.
773
 
774
  [*Note 4*: A path stores a native format pathname
775
  [[fs.path.native.obs]] and acts as if it also stores a generic format
776
+ pathname, related as given below. The implementation can generate the
777
  generic format pathname based on the native format pathname (and
778
  possibly other information) when requested. — *end note*]
779
 
780
  When a path is constructed from or is assigned a single representation
781
  separate from any path, the other representation is selected by the
 
793
 
794
  The *native encoding* of an ordinary character string is the operating
795
  system dependent current encoding for pathnames [[fs.class.path]]. The
796
  *native encoding* for wide character strings is the
797
  implementation-defined execution wide-character set encoding
798
+ [[character.seq]].
799
 
800
  For member function arguments that take character sequences representing
801
  paths and for member functions returning strings, value type and
802
  encoding conversion is performed if the value type of the argument or
803
  return value differs from `path::value_type`. For the argument or return
 
811
  return values is performed. For Windows-based operating systems, the
812
  native ordinary encoding is determined by calling a Windows API
813
  function. — *end note*] \[*Note 7*: This results in behavior
814
  identical to other C and C++ standard library functions that perform
815
  file operations using ordinary character strings to identify paths.
816
+ Changing this behavior would be surprising and
817
+ error-prone. — *end note*]
818
  - `wchar_t`: The encoding is the native wide encoding. The method of
819
  conversion is unspecified. \[*Note 8*: For Windows-based operating
820
  systems `path::value_type` is `wchar_t` so no conversion from
821
  `wchar_t` value type arguments or to `wchar_t` value type return
822
  values is performed. — *end note*]
 
860
  than `path`, and either
861
 
862
  - `Source` is a specialization of `basic_string` or `basic_string_view`,
863
  or
864
  - the *qualified-id* `iterator_traits<decay_t<Source>>::value_type` is
865
+ valid and denotes a possibly const encoded character type
866
  [[temp.deduct]].
867
 
868
  [*Note 1*: See path conversions [[fs.path.cvt]] for how the value types
869
  above and their encodings convert to `path::value_type` and its
870
  encoding. — *end note*]
 
1099
  ```
1100
 
1101
  *Effects:* Appends `path(x).native()` to the pathname in the native
1102
  format.
1103
 
1104
+ [*Note 2*: This directly manipulates the value of `native()`, which is
1105
+ not necessarily portable between operating systems. — *end note*]
1106
 
1107
  *Returns:* `*this`.
1108
 
1109
  ``` cpp
1110
  path& operator+=(value_type x);
 
1253
  operator string_type() const;
1254
  ```
1255
 
1256
  *Returns:* `native()`.
1257
 
 
 
 
 
1258
  ``` cpp
1259
  template<class EcharT, class traits = char_traits<EcharT>,
1260
  class Allocator = allocator<EcharT>>
1261
  basic_string<EcharT, traits, Allocator>
1262
  string(const Allocator& a = Allocator()) const;
 
1456
  path("..bar").extension(); // yields ".bar" and stem() is "."
1457
  ```
1458
 
1459
  — *end example*]
1460
 
1461
+ [*Note 3*: The period is included in the return value so that it is
1462
  possible to distinguish between no extension and an empty
1463
  extension. — *end note*]
1464
 
1465
+ [*Note 4*: On non-POSIX operating systems, for a path `p`, it is
1466
+ possible that `p.stem() + p.extension() == p.filename()` is `false`,
1467
+ even though the generic format pathnames are the same. — *end note*]
1468
 
1469
  ##### Query <a id="fs.path.query">[[fs.path.query]]</a>
1470
 
1471
  ``` cpp
1472
  [[nodiscard]] bool empty() const noexcept;
 
1565
 
1566
  ``` cpp
1567
  path lexically_relative(const path& base) const;
1568
  ```
1569
 
 
 
 
 
1570
  *Effects:* If:
1571
 
1572
  - `root_name() != base.root_name()` is `true`, or
1573
  - `is_absolute() != base.is_absolute()` is `true`, or
1574
  - `!has_root_directory() && base.has_root_directory()` is `true`, or
1575
  - any *filename* in `relative_path()` or `base.relative_path()` can be
1576
  interpreted as a *root-name*,
1577
 
1578
  returns `path()`.
1579
 
1580
+ [*Note 5*: On a POSIX implementation, no *filename* in a
1581
  *relative-path* is acceptable as a *root-name*. — *end note*]
1582
 
1583
  Determines the first mismatched element of `*this` and `base` as if by:
1584
 
1585
  ``` cpp
 
1597
  - returns an object of class `path` that is default-constructed,
1598
  followed by
1599
  - application of `operator/=(path(".."))` `n` times, and then
1600
  - application of `operator/=` for each element in \[`a`, `end()`).
1601
 
1602
+ *Returns:* `*this` made relative to `base`. Does not
1603
+ resolve [[fs.class.path]] symlinks. Does not first
1604
+ normalize [[fs.path.generic]] `*this` or `base`.
1605
+
1606
  [*Example 11*:
1607
 
1608
  ``` cpp
1609
  assert(path("/a/d").lexically_relative("/a/b/c") == "../../d");
1610
  assert(path("/a/b/c").lexically_relative("/a/d") == "../b/c");
 
1618
  *directory-separator* characters will be backslashes rather than
1619
  slashes, but that does not affect `path` equality.
1620
 
1621
  — *end example*]
1622
 
1623
+ [*Note 6*: If symlink following semantics are desired, use the
1624
  operational function `relative()`. — *end note*]
1625
 
1626
+ [*Note 7*: If normalization [[fs.path.generic]] is needed to ensure
1627
  consistent matching of elements, apply `lexically_normal()` to `*this`,
1628
  `base`, or both. — *end note*]
1629
 
1630
  ``` cpp
1631
  path lexically_proximate(const path& base) const;
1632
  ```
1633
 
1634
  *Returns:* If the value of `lexically_relative(base)` is not an empty
1635
  path, return it. Otherwise return `*this`.
1636
 
1637
+ [*Note 8*: If symlink following semantics are desired, use the
1638
  operational function `proximate()`. — *end note*]
1639
 
1640
+ [*Note 9*: If normalization [[fs.path.generic]] is needed to ensure
1641
  consistent matching of elements, apply `lexically_normal()` to `*this`,
1642
  `base`, or both. — *end note*]
1643
 
1644
  #### Iterators <a id="fs.path.itr">[[fs.path.itr]]</a>
1645
 
 
1744
  - Equivalence is determined by the `equivalent()` non-member function,
1745
  which determines if two paths resolve [[fs.class.path]] to the same
1746
  file system entity. \[*Example 2*: `equivalent("foo", "bar")` will be
1747
  `true` when both paths resolve to the same file. — *end example*]
1748
 
 
 
 
 
1749
  — *end note*]
1750
 
1751
  ``` cpp
1752
  friend strong_ordering operator<=>(const path& lhs, const path& rhs) noexcept;
1753
  ```
 
1758
  friend path operator/(const path& lhs, const path& rhs);
1759
  ```
1760
 
1761
  *Effects:* Equivalent to: `return path(lhs) /= rhs;`
1762
 
1763
+ #### Hash support <a id="fs.path.hash">[[fs.path.hash]]</a>
1764
+
1765
+ ``` cpp
1766
+ template<> struct hash<filesystem::path>;
1767
+ ```
1768
+
1769
+ For an object `p` of type `filesystem::path`,
1770
+ `hash<filesystem::path>()(p)` evaluates to the same result as
1771
+ `filesystem::hash_value(p)`.
1772
+
1773
  ### Class `filesystem_error` <a id="fs.class.filesystem.error">[[fs.class.filesystem.error]]</a>
1774
 
1775
+ #### General <a id="fs.class.filesystem.error.general">[[fs.class.filesystem.error.general]]</a>
1776
+
1777
  ``` cpp
1778
  namespace std::filesystem {
1779
  class filesystem_error : public system_error {
1780
  public:
1781
  filesystem_error(const string& what_arg, error_code ec);
 
1861
  #### Enum `path::format` <a id="fs.enum.path.format">[[fs.enum.path.format]]</a>
1862
 
1863
  This enum specifies constants used to identify the format of the
1864
  character sequence, with the meanings listed in [[fs.enum.path.format]].
1865
 
1866
+ **Table: Enum `path::format`** <a id="fs.enum.path.format">[fs.enum.path.format]</a>
1867
+
1868
+ | Name | Meaning |
1869
+ | ---------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
1870
+ | `native_format` | The native pathname format. |
1871
+ | `generic_format` | The generic pathname format. |
1872
+ | `auto_format` | The interpretation of the format of the character sequence is implementation-defined. The implementation may inspect the content of the character sequence to determine the format. Recommended practice: For POSIX-based systems, native and generic formats are equivalent and the character sequence should always be interpreted in the same way. |
1873
+
1874
 
1875
  #### Enum class `file_type` <a id="fs.enum.file.type">[[fs.enum.file.type]]</a>
1876
 
1877
  This enum class specifies constants used to identify file types, with
1878
  the meanings listed in [[fs.enum.file.type]]. The values of the
1879
  constants are distinct.
1880
 
1881
+ **Table: Enum class `file_type`** <a id="fs.enum.file.type">[fs.enum.file.type]</a>
1882
+
1883
+ | Constant | Meaning |
1884
+ | ------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
1885
+ | `none` | The type of the file has not been determined or an error occurred while trying to determine the type. |
1886
+ | `not_found` | Pseudo-type indicating the file was not found. *The file not being found is not considered an error while determining the type of a file.* |
1887
+ | `regular` | Regular file |
1888
+ | `directory` | Directory file |
1889
+ | `symlink` | Symbolic link file |
1890
+ | `block` | Block special file |
1891
+ | `character` | Character special file |
1892
+ | `fifo` | FIFO or pipe file |
1893
+ | `socket` | Socket file |
1894
+ | `implementation-defined` | Implementations that support file systems having file types in addition to the above `file_type` types shall supply implementation-defined `file_type` constants to separately identify each of those additional file types |
1895
+ | `unknown` | The file exists but the type cannot be determined |
1896
+
1897
 
1898
  #### Enum class `copy_options` <a id="fs.enum.copy.opts">[[fs.enum.copy.opts]]</a>
1899
 
1900
  The `enum class` type `copy_options` is a bitmask type [[bitmask.types]]
1901
  that specifies bitmask constants used to control the semantics of copy
 
1906
  Every other constant in the table represents a distinct bitmask element.
1907
 
1908
  **Table: Enum class `copy_options`** <a id="fs.enum.copy.opts">[fs.enum.copy.opts]</a>
1909
 
1910
  | Constant | Meaning |
1911
+ | -------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------- |
1912
  | `none` | (Default) Error; file already exists. |
1913
  | `skip_existing` | Do not overwrite existing file, do not report an error. |
1914
  | `overwrite_existing` | Overwrite the existing file. |
1915
+ | `update_existing` | Overwrite the existing file if it is older than the replacement file. \ohdrx{2}{Option group controlling `copy` function effects for subdirectories} |
1916
+ | `recursive` | Recursively copy subdirectories and their contents. \ohdrx{2}{Option group controlling `copy` function effects for symbolic links} |
1917
  | `copy_symlinks` | Copy symbolic links as symbolic links rather than copying the files that they point to. |
1918
  | `skip_symlinks` | Ignore symbolic links. \ohdrx{2}{Option group controlling `copy` function effects for choosing the form of copying} |
1919
  | `directories_only` | Copy directory structure only, do not copy non-directory files. |
1920
  | `create_symlinks` | Make symbolic links instead of copies of files. The source path shall be an absolute path unless the destination path is in the current directory. |
1921
  | `create_hard_links` | Make hard links instead of copies of files. |
 
1964
  **Table: Enum class `perm_options`** <a id="fs.enum.perm.opts">[fs.enum.perm.opts]</a>
1965
 
1966
  | Name | Meaning |
1967
  | ---------- | ------------------------------------------------------------------------------------------------------------------------------------------------------- |
1968
  | `replace` | `permissions` shall replace the file's permission bits with `perm` |
1969
+ | `add` | `permissions` shall replace the file's permission bits with the bitwise \logop{or} of `perm` and the file's current permission bits. |
1970
+ | `remove` | `permissions` shall replace the file's permission bits with the bitwise \logop{and} of the complement of `perm` and the file's current permission bits. |
1971
  | `nofollow` | `permissions` shall change the permissions of a symbolic link itself rather than the permissions of the file the link resolves to. |
1972
 
1973
 
1974
  #### Enum class `directory_options` <a id="fs.enum.dir.opts">[[fs.enum.dir.opts]]</a>
1975
 
 
1988
  | `skip_permission_denied` | Skip directories that would otherwise result in permission denied. |
1989
 
1990
 
1991
  ### Class `file_status` <a id="fs.class.file.status">[[fs.class.file.status]]</a>
1992
 
1993
+ #### General <a id="fs.class.file.status.general">[[fs.class.file.status.general]]</a>
1994
+
1995
  ``` cpp
1996
  namespace std::filesystem {
1997
  class file_status {
1998
  public:
1999
  // [fs.file.status.cons], constructors and destructor
 
2062
 
2063
  *Ensures:* `permissions() == prms`.
2064
 
2065
  ### Class `directory_entry` <a id="fs.class.directory.entry">[[fs.class.directory.entry]]</a>
2066
 
2067
+ #### General <a id="fs.class.directory.entry.general">[[fs.class.directory.entry.general]]</a>
2068
+
2069
  ``` cpp
2070
  namespace std::filesystem {
2071
  class directory_entry {
2072
  public:
2073
  // [fs.dir.entry.cons], constructors and destructor
 
2123
  file_status symlink_status(error_code& ec) const noexcept;
2124
 
2125
  bool operator==(const directory_entry& rhs) const noexcept;
2126
  strong_ordering operator<=>(const directory_entry& rhs) const noexcept;
2127
 
2128
+ // [fs.dir.entry.io], inserter
2129
+ template<class charT, class traits>
2130
+ friend basic_ostream<charT, traits>&
2131
+ operator<<(basic_ostream<charT, traits>& os, const directory_entry& d);
2132
+
2133
  private:
2134
  filesystem::path pathobject; // exposition only
2135
  friend class directory_iterator; // exposition only
2136
  };
2137
  }
 
2234
 
2235
  *Throws:* As specified in  [[fs.err.report]].
2236
 
2237
  [*Note 1*: Implementations of `directory_iterator`
2238
  [[fs.class.directory.iterator]] are prohibited from directly or
2239
+ indirectly calling the `refresh` function as described in
2240
+ [[fs.class.directory.iterator.general]]. *end note*]
 
2241
 
2242
  #### Observers <a id="fs.dir.entry.obs">[[fs.dir.entry.obs]]</a>
2243
 
2244
  Unqualified function names in the *Returns:* elements of the
2245
  `directory_entry` observers described below refer to members of the
 
2404
  strong_ordering operator<=>(const directory_entry& rhs) const noexcept;
2405
  ```
2406
 
2407
  *Returns:* `pathobject <=> rhs.pathobject`.
2408
 
2409
+ #### Inserter <a id="fs.dir.entry.io">[[fs.dir.entry.io]]</a>
2410
+
2411
+ ``` cpp
2412
+ template<class charT, class traits>
2413
+ friend basic_ostream<charT, traits>&
2414
+ operator<<(basic_ostream<charT, traits>& os, const directory_entry& d);
2415
+ ```
2416
+
2417
+ *Effects:* Equivalent to: `return os << d.path();`
2418
+
2419
  ### Class `directory_iterator` <a id="fs.class.directory.iterator">[[fs.class.directory.iterator]]</a>
2420
 
2421
+ #### General <a id="fs.class.directory.iterator.general">[[fs.class.directory.iterator.general]]</a>
2422
+
2423
  An object of type `directory_iterator` provides an iterator for a
2424
  sequence of `directory_entry` elements representing the path and any
2425
  cached attribute values [[fs.class.directory.entry]] for each file in a
2426
  directory or in an *implementation-defined* directory-like file type.
2427
 
2428
+ [*Note 1*: For iteration into subdirectories, see class
2429
  `recursive_directory_iterator` [[fs.class.rec.dir.itr]]. — *end note*]
2430
 
2431
  ``` cpp
2432
  namespace std::filesystem {
2433
  class directory_iterator {
 
2455
  const directory_entry& operator*() const;
2456
  const directory_entry* operator->() const;
2457
  directory_iterator& operator++();
2458
  directory_iterator& increment(error_code& ec);
2459
 
2460
+ bool operator==(default_sentinel_t) const noexcept {
2461
+ return *this == directory_iterator();
2462
+ }
2463
+
2464
  // other members as required by [input.iterators], input iterators
2465
  };
2466
  }
2467
  ```
2468
 
 
2481
  to a non-end iterator.
2482
 
2483
  The result of calling the `path()` member of the `directory_entry`
2484
  object obtained by dereferencing a `directory_iterator` is a reference
2485
  to a `path` object composed of the directory argument from which the
2486
+ iterator was constructed with the filename of the directory entry
2487
+ appended as if by `operator/=`.
2488
 
2489
  Directory iteration shall not yield directory entries for the current
2490
  (dot) and parent (dot-dot) directories.
2491
 
2492
  The order of directory entries obtained by dereferencing successive
 
2501
  [*Note 2*: The exact mechanism for storing cached attribute values is
2502
  not exposed to users. For exposition, class `directory_iterator` is
2503
  shown in [[fs.class.directory.entry]] as a friend of class
2504
  `directory_entry`. — *end note*]
2505
 
2506
+ [*Note 3*: A path obtained by dereferencing a directory iterator might
2507
+ not actually exist; it could be a symbolic link to a non-existent file.
2508
+ Recursively walking directory trees for purposes of removing and
2509
+ renaming entries might invalidate symbolic links that are being
2510
+ followed. — *end note*]
2511
 
2512
  [*Note 4*: If a file is removed from or added to a directory after the
2513
  construction of a `directory_iterator` for the directory, it is
2514
  unspecified whether or not subsequently incrementing the iterator will
2515
  ever result in an iterator referencing the removed or added directory
2516
+ entry. See POSIX `readdir`. — *end note*]
2517
 
2518
  #### Members <a id="fs.dir.itr.members">[[fs.dir.itr.members]]</a>
2519
 
2520
  ``` cpp
2521
  directory_iterator() noexcept;
 
2589
  ```
2590
 
2591
  *Returns:* `iter`.
2592
 
2593
  ``` cpp
2594
+ directory_iterator end(directory_iterator) noexcept;
2595
  ```
2596
 
2597
  *Returns:* `directory_iterator()`.
2598
 
2599
  ### Class `recursive_directory_iterator` <a id="fs.class.rec.dir.itr">[[fs.class.rec.dir.itr]]</a>
2600
 
2601
+ #### General <a id="fs.class.rec.dir.itr.general">[[fs.class.rec.dir.itr.general]]</a>
2602
+
2603
  An object of type `recursive_directory_iterator` provides an iterator
2604
  for a sequence of `directory_entry` elements representing the files in a
2605
  directory or in an *implementation-defined* directory-like file type,
2606
+ and its subdirectories.
2607
 
2608
  ``` cpp
2609
  namespace std::filesystem {
2610
  class recursive_directory_iterator {
2611
  public:
 
2645
 
2646
  void pop();
2647
  void pop(error_code& ec);
2648
  void disable_recursion_pending();
2649
 
2650
+ bool operator==(default_sentinel_t) const noexcept {
2651
+ return *this == recursive_directory_iterator();
2652
+ }
2653
+
2654
  // other members as required by [input.iterators], input iterators
2655
  };
2656
  }
2657
  ```
2658
 
 
2662
 
2663
  The behavior of a `recursive_directory_iterator` is the same as a
2664
  `directory_iterator` unless otherwise specified.
2665
 
2666
  [*Note 1*: If the directory structure being iterated over contains
2667
+ cycles then it is possible that the end iterator is
2668
+ unreachable. — *end note*]
2669
 
2670
  #### Members <a id="fs.rec.dir.itr.members">[[fs.rec.dir.itr.members]]</a>
2671
 
2672
  ``` cpp
2673
  recursive_directory_iterator() noexcept;
 
2698
  `directory_options` argument, otherwise
2699
  `options() == directory_options::none`.
2700
 
2701
  *Throws:* As specified in  [[fs.err.report]].
2702
 
2703
+ [*Note 1*: Use `recursive_directory_iterator(".")` rather than
2704
+ `recursive_directory_iterator("")` to iterate over the current
2705
+ directory. — *end note*]
2706
 
2707
  [*Note 2*: By default, `recursive_directory_iterator` does not follow
2708
  directory symlinks. To follow directory symlinks, specify `options` as
2709
  `directory_options::follow_directory_symlink`. — *end note*]
2710
 
 
2841
  recursion into a directory. — *end note*]
2842
 
2843
  #### Non-member functions <a id="fs.rec.dir.itr.nonmembers">[[fs.rec.dir.itr.nonmembers]]</a>
2844
 
2845
  These functions enable use of `recursive_directory_iterator` with
2846
+ range-based `for` statements.
2847
 
2848
  ``` cpp
2849
  recursive_directory_iterator begin(recursive_directory_iterator iter) noexcept;
2850
  ```
2851
 
2852
  *Returns:* `iter`.
2853
 
2854
  ``` cpp
2855
+ recursive_directory_iterator end(recursive_directory_iterator) noexcept;
2856
  ```
2857
 
2858
  *Returns:* `recursive_directory_iterator()`.
2859
 
2860
  ### Filesystem operation functions <a id="fs.op.funcs">[[fs.op.funcs]]</a>
2861
 
2862
+ #### General <a id="fs.op.funcs.general">[[fs.op.funcs.general]]</a>
2863
+
2864
  Filesystem operation functions query or modify files, including
2865
  directories, in external storage.
2866
 
2867
  [*Note 1*: Because hardware failures, network failures, file system
2868
  races [[fs.race.behavior]], and many other kinds of errors occur
2869
+ frequently in file system operations, any filesystem operation function,
2870
+ no matter how apparently innocuous, can encounter an error; see 
2871
+ [[fs.err.report]]. — *end note*]
2872
 
2873
  #### Absolute <a id="fs.op.absolute">[[fs.op.absolute]]</a>
2874
 
2875
  ``` cpp
2876
+ path filesystem::absolute(const path& p);
2877
+ path filesystem::absolute(const path& p, error_code& ec);
2878
  ```
2879
 
2880
  *Effects:* Composes an absolute path referencing the same file system
2881
  location as `p` according to the operating system [[fs.conform.os]].
2882
 
 
2886
  [*Note 1*: For the returned path, `rp`, `rp.is_absolute()` is `true`
2887
  unless an error occurs. — *end note*]
2888
 
2889
  *Throws:* As specified in  [[fs.err.report]].
2890
 
2891
+ [*Note 2*: To resolve symlinks or perform other sanitization that can
2892
+ involve queries to secondary storage, such as hard disks, consider
2893
  `canonical` [[fs.op.canonical]]. — *end note*]
2894
 
2895
  [*Note 3*: Implementations are strongly encouraged to not query
2896
  secondary storage, and not consider `!exists(p)` an
2897
  error. — *end note*]
 
2902
  `GetFullPathNameW`. — *end example*]
2903
 
2904
  #### Canonical <a id="fs.op.canonical">[[fs.op.canonical]]</a>
2905
 
2906
  ``` cpp
2907
+ path filesystem::canonical(const path& p);
2908
+ path filesystem::canonical(const path& p, error_code& ec);
2909
  ```
2910
 
2911
  *Effects:* Converts `p` to an absolute path that has no symbolic link,
2912
  dot, or dot-dot elements in its pathname in the generic format.
2913
 
 
2920
  *Remarks:* `!exists(p)` is an error.
2921
 
2922
  #### Copy <a id="fs.op.copy">[[fs.op.copy]]</a>
2923
 
2924
  ``` cpp
2925
+ void filesystem::copy(const path& from, const path& to);
2926
  ```
2927
 
2928
  *Effects:* Equivalent to `copy(from, to, copy_options::none)`.
2929
 
2930
  ``` cpp
2931
+ void filesystem::copy(const path& from, const path& to, error_code& ec);
2932
  ```
2933
 
2934
  *Effects:* Equivalent to `copy(from, to, copy_options::none, ec)`.
2935
 
2936
  ``` cpp
2937
+ void filesystem::copy(const path& from, const path& to, copy_options options);
2938
+ void filesystem::copy(const path& from, const path& to, copy_options options,
2939
  error_code& ec);
2940
  ```
2941
 
2942
  *Preconditions:* At most one element from each option
2943
  group [[fs.enum.copy.opts]] is set in `options`.
 
3074
  — *end example*]
3075
 
3076
  #### Copy file <a id="fs.op.copy.file">[[fs.op.copy.file]]</a>
3077
 
3078
  ``` cpp
3079
+ bool filesystem::copy_file(const path& from, const path& to);
3080
+ bool filesystem::copy_file(const path& from, const path& to, error_code& ec);
3081
  ```
3082
 
3083
  *Returns:* `copy_file(from, to, copy_options::none)` or
3084
  `copy_file(from, to, copy_options::none, ec)`, respectively.
3085
 
3086
  *Throws:* As specified in  [[fs.err.report]].
3087
 
3088
  ``` cpp
3089
+ bool filesystem::copy_file(const path& from, const path& to, copy_options options);
3090
+ bool filesystem::copy_file(const path& from, const path& to, copy_options options,
3091
  error_code& ec);
3092
  ```
3093
 
3094
  *Preconditions:* At most one element from each option
3095
  group [[fs.enum.copy.opts]] is set in `options`.
 
3124
  *Complexity:* At most one direct or indirect invocation of `status(to)`.
3125
 
3126
  #### Copy symlink <a id="fs.op.copy.symlink">[[fs.op.copy.symlink]]</a>
3127
 
3128
  ``` cpp
3129
+ void filesystem::copy_symlink(const path& existing_symlink, const path& new_symlink);
3130
+ void filesystem::copy_symlink(const path& existing_symlink, const path& new_symlink,
3131
  error_code& ec) noexcept;
3132
  ```
3133
 
3134
  *Effects:* Equivalent to
3135
  *`function`*`(read_symlink(existing_symlink), new_symlink)` or
 
3140
  *Throws:* As specified in  [[fs.err.report]].
3141
 
3142
  #### Create directories <a id="fs.op.create.directories">[[fs.op.create.directories]]</a>
3143
 
3144
  ``` cpp
3145
+ bool filesystem::create_directories(const path& p);
3146
+ bool filesystem::create_directories(const path& p, error_code& ec);
3147
  ```
3148
 
3149
  *Effects:* Calls `create_directory()` for each element of `p` that does
3150
  not exist.
3151
 
 
3157
  *Complexity:* 𝑂(n) where *n* is the number of elements of `p`.
3158
 
3159
  #### Create directory <a id="fs.op.create.directory">[[fs.op.create.directory]]</a>
3160
 
3161
  ``` cpp
3162
+ bool filesystem::create_directory(const path& p);
3163
+ bool filesystem::create_directory(const path& p, error_code& ec) noexcept;
3164
  ```
3165
 
3166
  *Effects:* Creates the directory `p` resolves to, as if by POSIX `mkdir`
3167
  with a second argument of `static_cast<int>(perms::all)`. If `mkdir`
3168
  fails because `p` resolves to an existing directory, no error is
 
3171
  *Returns:* `true` if a new directory was created, otherwise `false`.
3172
 
3173
  *Throws:* As specified in  [[fs.err.report]].
3174
 
3175
  ``` cpp
3176
+ bool filesystem::create_directory(const path& p, const path& existing_p);
3177
+ bool filesystem::create_directory(const path& p, const path& existing_p, error_code& ec) noexcept;
3178
  ```
3179
 
3180
  *Effects:* Creates the directory `p` resolves to, with attributes copied
3181
  from directory `existing_p`. The set of attributes copied is operating
3182
  system dependent. If `mkdir` fails because `p` resolves to an existing
 
3196
  *Throws:* As specified in  [[fs.err.report]].
3197
 
3198
  #### Create directory symlink <a id="fs.op.create.dir.symlk">[[fs.op.create.dir.symlk]]</a>
3199
 
3200
  ``` cpp
3201
+ void filesystem::create_directory_symlink(const path& to, const path& new_symlink);
3202
+ void filesystem::create_directory_symlink(const path& to, const path& new_symlink,
3203
  error_code& ec) noexcept;
3204
  ```
3205
 
3206
  *Effects:* Establishes the postcondition, as if by POSIX `symlink()`.
3207
 
 
3209
  an unspecified representation of `to`.
3210
 
3211
  *Throws:* As specified in  [[fs.err.report]].
3212
 
3213
  [*Note 1*: Some operating systems require symlink creation to identify
3214
+ that the link is to a directory. Thus, `create_symlink()` (instead of
3215
+ `create_directory_symlink()`) cannot be used reliably to create
3216
+ directory symlinks. — *end note*]
3217
 
3218
  [*Note 2*: Some operating systems do not support symbolic links at all
3219
  or support them only for regular files. Some file systems (such as the
3220
  FAT file system) do not support symbolic links regardless of the
3221
  operating system. — *end note*]
3222
 
3223
  #### Create hard link <a id="fs.op.create.hard.lk">[[fs.op.create.hard.lk]]</a>
3224
 
3225
  ``` cpp
3226
+ void filesystem::create_hard_link(const path& to, const path& new_hard_link);
3227
+ void filesystem::create_hard_link(const path& to, const path& new_hard_link,
3228
  error_code& ec) noexcept;
3229
  ```
3230
 
3231
  *Effects:* Establishes the postcondition, as if by POSIX `link()`.
3232
 
 
3244
  file. — *end note*]
3245
 
3246
  #### Create symlink <a id="fs.op.create.symlink">[[fs.op.create.symlink]]</a>
3247
 
3248
  ``` cpp
3249
+ void filesystem::create_symlink(const path& to, const path& new_symlink);
3250
+ void filesystem::create_symlink(const path& to, const path& new_symlink,
3251
  error_code& ec) noexcept;
3252
  ```
3253
 
3254
  *Effects:* Establishes the postcondition, as if by POSIX `symlink()`.
3255
 
 
3264
  operating system. — *end note*]
3265
 
3266
  #### Current path <a id="fs.op.current.path">[[fs.op.current.path]]</a>
3267
 
3268
  ``` cpp
3269
+ path filesystem::current_path();
3270
+ path filesystem::current_path(error_code& ec);
3271
  ```
3272
 
3273
  *Returns:* The absolute path of the current working directory, whose
3274
  pathname in the native format is obtained as if by POSIX `getcwd()`. The
3275
  signature with argument `ec` returns `path()` if an error occurs.
 
3283
  [*Note 1*: The `current_path()` name was chosen to emphasize that the
3284
  returned value is a path, not just a single directory
3285
  name. — *end note*]
3286
 
3287
  [*Note 2*: The current path as returned by many operating systems is a
3288
+ dangerous global variable and can be changed unexpectedly by third-party
3289
  or system library functions, or by another thread. — *end note*]
3290
 
3291
  ``` cpp
3292
+ void filesystem::current_path(const path& p);
3293
+ void filesystem::current_path(const path& p, error_code& ec) noexcept;
3294
  ```
3295
 
3296
  *Effects:* Establishes the postcondition, as if by POSIX `chdir()`.
3297
 
3298
  *Ensures:* `equivalent(p, current_path())`.
3299
 
3300
  *Throws:* As specified in  [[fs.err.report]].
3301
 
3302
  [*Note 3*: The current path for many operating systems is a dangerous
3303
+ global state and can be changed unexpectedly by third-party or system
3304
  library functions, or by another thread. — *end note*]
3305
 
3306
  #### Equivalent <a id="fs.op.equivalent">[[fs.op.equivalent]]</a>
3307
 
3308
  ``` cpp
3309
+ bool filesystem::equivalent(const path& p1, const path& p2);
3310
+ bool filesystem::equivalent(const path& p1, const path& p2, error_code& ec) noexcept;
3311
  ```
3312
 
 
 
 
 
3313
  Two paths are considered to resolve to the same file system entity if
3314
  two candidate entities reside on the same device at the same location.
3315
 
3316
  [*Note 1*: On POSIX platforms, this is determined as if by the values
3317
  of the POSIX `stat` class, obtained as if by `stat()` for the two paths,
3318
  having equal `st_dev` values and equal `st_ino` values. — *end note*]
3319
 
3320
+ *Returns:* `true`, if `p1` and `p2` resolve to the same file system
3321
+ entity, otherwise `false`. The signature with argument `ec` returns
3322
+ `false` if an error occurs.
3323
+
3324
+ *Throws:* As specified in  [[fs.err.report]].
3325
+
3326
  *Remarks:* `!exists(p1) || !exists(p2)` is an error.
3327
 
 
 
3328
  #### Exists <a id="fs.op.exists">[[fs.op.exists]]</a>
3329
 
3330
  ``` cpp
3331
+ bool filesystem::exists(file_status s) noexcept;
3332
  ```
3333
 
3334
  *Returns:* `status_known(s) && s.type() != file_type::not_found`.
3335
 
3336
  ``` cpp
3337
+ bool filesystem::exists(const path& p);
3338
+ bool filesystem::exists(const path& p, error_code& ec) noexcept;
3339
  ```
3340
 
3341
  Let `s` be a `file_status`, determined as if by `status(p)` or
3342
  `status(p, ec)`, respectively.
3343
 
 
3349
  *Throws:* As specified in  [[fs.err.report]].
3350
 
3351
  #### File size <a id="fs.op.file.size">[[fs.op.file.size]]</a>
3352
 
3353
  ``` cpp
3354
+ uintmax_t filesystem::file_size(const path& p);
3355
+ uintmax_t filesystem::file_size(const path& p, error_code& ec) noexcept;
3356
  ```
3357
 
3358
  *Effects:* If `exists(p)` is `false`, an error is
3359
  reported [[fs.err.report]].
3360
 
 
3371
  *Throws:* As specified in  [[fs.err.report]].
3372
 
3373
  #### Hard link count <a id="fs.op.hard.lk.ct">[[fs.op.hard.lk.ct]]</a>
3374
 
3375
  ``` cpp
3376
+ uintmax_t filesystem::hard_link_count(const path& p);
3377
+ uintmax_t filesystem::hard_link_count(const path& p, error_code& ec) noexcept;
3378
  ```
3379
 
3380
  *Returns:* The number of hard links for `p`. The signature with argument
3381
  `ec` returns `static_cast<uintmax_t>(-1)` if an error occurs.
3382
 
3383
  *Throws:* As specified in  [[fs.err.report]].
3384
 
3385
  #### Is block file <a id="fs.op.is.block.file">[[fs.op.is.block.file]]</a>
3386
 
3387
  ``` cpp
3388
+ bool filesystem::is_block_file(file_status s) noexcept;
3389
  ```
3390
 
3391
  *Returns:* `s.type() == file_type::block`.
3392
 
3393
  ``` cpp
3394
+ bool filesystem::is_block_file(const path& p);
3395
+ bool filesystem::is_block_file(const path& p, error_code& ec) noexcept;
3396
  ```
3397
 
3398
  *Returns:* `is_block_file(status(p))` or `is_block_file(status(p, ec))`,
3399
  respectively. The signature with argument `ec` returns `false` if an
3400
  error occurs.
 
3402
  *Throws:* As specified in  [[fs.err.report]].
3403
 
3404
  #### Is character file <a id="fs.op.is.char.file">[[fs.op.is.char.file]]</a>
3405
 
3406
  ``` cpp
3407
+ bool filesystem::is_character_file(file_status s) noexcept;
3408
  ```
3409
 
3410
  *Returns:* `s.type() == file_type::character`.
3411
 
3412
  ``` cpp
3413
+ bool filesystem::is_character_file(const path& p);
3414
+ bool filesystem::is_character_file(const path& p, error_code& ec) noexcept;
3415
  ```
3416
 
3417
  *Returns:* `is_character_file(status(p))` or
3418
  `is_character_file(status(p, ec))`, respectively.
3419
  The signature with argument `ec` returns `false` if an error occurs.
 
3421
  *Throws:* As specified in  [[fs.err.report]].
3422
 
3423
  #### Is directory <a id="fs.op.is.directory">[[fs.op.is.directory]]</a>
3424
 
3425
  ``` cpp
3426
+ bool filesystem::is_directory(file_status s) noexcept;
3427
  ```
3428
 
3429
  *Returns:* `s.type() == file_type::directory`.
3430
 
3431
  ``` cpp
3432
+ bool filesystem::is_directory(const path& p);
3433
+ bool filesystem::is_directory(const path& p, error_code& ec) noexcept;
3434
  ```
3435
 
3436
  *Returns:* `is_directory(status(p))` or `is_directory(status(p, ec))`,
3437
  respectively. The signature with argument `ec` returns `false` if an
3438
  error occurs.
 
3440
  *Throws:* As specified in  [[fs.err.report]].
3441
 
3442
  #### Is empty <a id="fs.op.is.empty">[[fs.op.is.empty]]</a>
3443
 
3444
  ``` cpp
3445
+ bool filesystem::is_empty(const path& p);
3446
+ bool filesystem::is_empty(const path& p, error_code& ec);
3447
  ```
3448
 
3449
  *Effects:*
3450
 
3451
  - Determine `file_status s`, as if by `status(p)` or `status(p, ec)`,
 
3468
  *Throws:* As specified in  [[fs.err.report]].
3469
 
3470
  #### Is fifo <a id="fs.op.is.fifo">[[fs.op.is.fifo]]</a>
3471
 
3472
  ``` cpp
3473
+ bool filesystem::is_fifo(file_status s) noexcept;
3474
  ```
3475
 
3476
  *Returns:* `s.type() == file_type::fifo`.
3477
 
3478
  ``` cpp
3479
+ bool filesystem::is_fifo(const path& p);
3480
+ bool filesystem::is_fifo(const path& p, error_code& ec) noexcept;
3481
  ```
3482
 
3483
  *Returns:* `is_fifo(status(p))` or `is_fifo(status(p, ec))`,
3484
  respectively. The signature with argument `ec` returns `false` if an
3485
  error occurs.
 
3487
  *Throws:* As specified in  [[fs.err.report]].
3488
 
3489
  #### Is other <a id="fs.op.is.other">[[fs.op.is.other]]</a>
3490
 
3491
  ``` cpp
3492
+ bool filesystem::is_other(file_status s) noexcept;
3493
  ```
3494
 
3495
  *Returns:*
3496
  `exists(s) && !is_regular_file(s) && !is_directory(s) && !is_symlink(s)`.
3497
 
3498
  ``` cpp
3499
+ bool filesystem::is_other(const path& p);
3500
+ bool filesystem::is_other(const path& p, error_code& ec) noexcept;
3501
  ```
3502
 
3503
  *Returns:* `is_other(status(p))` or `is_other(status(p, ec))`,
3504
  respectively. The signature with argument `ec` returns `false` if an
3505
  error occurs.
 
3507
  *Throws:* As specified in  [[fs.err.report]].
3508
 
3509
  #### Is regular file <a id="fs.op.is.regular.file">[[fs.op.is.regular.file]]</a>
3510
 
3511
  ``` cpp
3512
+ bool filesystem::is_regular_file(file_status s) noexcept;
3513
  ```
3514
 
3515
  *Returns:* `s.type() == file_type::regular`.
3516
 
3517
  ``` cpp
3518
+ bool filesystem::is_regular_file(const path& p);
3519
  ```
3520
 
3521
  *Returns:* `is_regular_file(status(p))`.
3522
 
3523
  *Throws:* `filesystem_error` if `status(p)` would throw
3524
  `filesystem_error`.
3525
 
3526
  ``` cpp
3527
+ bool filesystem::is_regular_file(const path& p, error_code& ec) noexcept;
3528
  ```
3529
 
3530
  *Effects:* Sets `ec` as if by `status(p, ec)`.
3531
 
3532
  [*Note 1*: `file_type::none`, `file_type::not_found` and
 
3537
  occurs.
3538
 
3539
  #### Is socket <a id="fs.op.is.socket">[[fs.op.is.socket]]</a>
3540
 
3541
  ``` cpp
3542
+ bool filesystem::is_socket(file_status s) noexcept;
3543
  ```
3544
 
3545
  *Returns:* `s.type() == file_type::socket`.
3546
 
3547
  ``` cpp
3548
+ bool filesystem::is_socket(const path& p);
3549
+ bool filesystem::is_socket(const path& p, error_code& ec) noexcept;
3550
  ```
3551
 
3552
  *Returns:* `is_socket(status(p))` or `is_socket(status(p, ec))`,
3553
  respectively. The signature with argument `ec` returns `false` if an
3554
  error occurs.
 
3556
  *Throws:* As specified in  [[fs.err.report]].
3557
 
3558
  #### Is symlink <a id="fs.op.is.symlink">[[fs.op.is.symlink]]</a>
3559
 
3560
  ``` cpp
3561
+ bool filesystem::is_symlink(file_status s) noexcept;
3562
  ```
3563
 
3564
  *Returns:* `s.type() == file_type::symlink`.
3565
 
3566
  ``` cpp
3567
+ bool filesystem::is_symlink(const path& p);
3568
+ bool filesystem::is_symlink(const path& p, error_code& ec) noexcept;
3569
  ```
3570
 
3571
  *Returns:* `is_symlink(symlink_status(p))` or
3572
  `is_symlink(symlink_status(p, ec))`, respectively. The signature with
3573
  argument `ec` returns `false` if an error occurs.
 
3575
  *Throws:* As specified in  [[fs.err.report]].
3576
 
3577
  #### Last write time <a id="fs.op.last.write.time">[[fs.op.last.write.time]]</a>
3578
 
3579
  ``` cpp
3580
+ file_time_type filesystem::last_write_time(const path& p);
3581
+ file_time_type filesystem::last_write_time(const path& p, error_code& ec) noexcept;
3582
  ```
3583
 
3584
  *Returns:* The time of last data modification of `p`, determined as if
3585
  by the value of the POSIX `stat` class member `st_mtime` obtained as if
3586
  by POSIX `stat()`. The signature with argument `ec` returns
3587
  `file_time_type::min()` if an error occurs.
3588
 
3589
  *Throws:* As specified in  [[fs.err.report]].
3590
 
3591
  ``` cpp
3592
+ void filesystem::last_write_time(const path& p, file_time_type new_time);
3593
+ void filesystem::last_write_time(const path& p, file_time_type new_time,
3594
  error_code& ec) noexcept;
3595
  ```
3596
 
3597
  *Effects:* Sets the time of last data modification of the file resolved
3598
  to by `p` to `new_time`, as if by POSIX `futimens()`.
3599
 
3600
  *Throws:* As specified in  [[fs.err.report]].
3601
 
3602
  [*Note 1*: A postcondition of `last_write_time(p) == new_time` is not
3603
+ specified because it does not necessarily hold for file systems with
3604
+ coarse time granularity. — *end note*]
3605
 
3606
  #### Permissions <a id="fs.op.permissions">[[fs.op.permissions]]</a>
3607
 
3608
  ``` cpp
3609
+ void filesystem::permissions(const path& p, perms prms, perm_options opts=perm_options::replace);
3610
+ void filesystem::permissions(const path& p, perms prms, error_code& ec) noexcept;
3611
+ void filesystem::permissions(const path& p, perms prms, perm_options opts, error_code& ec);
3612
  ```
3613
 
3614
  *Preconditions:* Exactly one of the `perm_options` constants `replace`,
3615
  `add`, or `remove` is present in `opts`.
3616
 
 
 
 
 
3617
  *Effects:* Applies the action specified by `opts` to the file `p`
3618
  resolves to, or to file `p` itself if `p` is a symbolic link and
3619
  `perm_options::nofollow` is set in `opts`. The action is applied as if
3620
  by POSIX `fchmodat()`.
3621
 
3622
  [*Note 1*: Conceptually permissions are viewed as bits, but the actual
3623
+ implementation can use some other mechanism. — *end note*]
3624
 
3625
  *Throws:* As specified in  [[fs.err.report]].
3626
 
3627
+ *Remarks:* The second signature behaves as if it had an additional
3628
+ parameter `perm_options` `opts` with an argument of
3629
+ `perm_options::replace`.
3630
+
3631
  #### Proximate <a id="fs.op.proximate">[[fs.op.proximate]]</a>
3632
 
3633
  ``` cpp
3634
+ path filesystem::proximate(const path& p, error_code& ec);
3635
  ```
3636
 
3637
  *Returns:* `proximate(p, current_path(), ec)`.
3638
 
3639
  *Throws:* As specified in  [[fs.err.report]].
3640
 
3641
  ``` cpp
3642
+ path filesystem::proximate(const path& p, const path& base = current_path());
3643
+ path filesystem::proximate(const path& p, const path& base, error_code& ec);
3644
  ```
3645
 
3646
  *Returns:* For the first form:
3647
 
3648
  ``` cpp
 
3660
  *Throws:* As specified in  [[fs.err.report]].
3661
 
3662
  #### Read symlink <a id="fs.op.read.symlink">[[fs.op.read.symlink]]</a>
3663
 
3664
  ``` cpp
3665
+ path filesystem::read_symlink(const path& p);
3666
+ path filesystem::read_symlink(const path& p, error_code& ec);
3667
  ```
3668
 
3669
  *Returns:* If `p` resolves to a symbolic link, a `path` object
3670
  containing the contents of that symbolic link. The signature with
3671
  argument `ec` returns `path()` if an error occurs.
 
3676
  link. — *end note*]
3677
 
3678
  #### Relative <a id="fs.op.relative">[[fs.op.relative]]</a>
3679
 
3680
  ``` cpp
3681
+ path filesystem::relative(const path& p, error_code& ec);
3682
  ```
3683
 
3684
  *Returns:* `relative(p, current_path(), ec)`.
3685
 
3686
  *Throws:* As specified in  [[fs.err.report]].
3687
 
3688
  ``` cpp
3689
+ path filesystem::relative(const path& p, const path& base = current_path());
3690
+ path filesystem::relative(const path& p, const path& base, error_code& ec);
3691
  ```
3692
 
3693
  *Returns:* For the first form:
3694
 
3695
  ``` cpp
 
3707
  *Throws:* As specified in  [[fs.err.report]].
3708
 
3709
  #### Remove <a id="fs.op.remove">[[fs.op.remove]]</a>
3710
 
3711
  ``` cpp
3712
+ bool filesystem::remove(const path& p);
3713
+ bool filesystem::remove(const path& p, error_code& ec) noexcept;
3714
  ```
3715
 
3716
  *Effects:* If `exists(symlink_status(p, ec))`, the file `p` is removed
3717
  as if by POSIX `remove()`.
3718
 
 
3727
  *Throws:* As specified in  [[fs.err.report]].
3728
 
3729
  #### Remove all <a id="fs.op.remove.all">[[fs.op.remove.all]]</a>
3730
 
3731
  ``` cpp
3732
+ uintmax_t filesystem::remove_all(const path& p);
3733
+ uintmax_t filesystem::remove_all(const path& p, error_code& ec);
3734
  ```
3735
 
3736
  *Effects:* Recursively deletes the contents of `p` if it exists, then
3737
  deletes file `p` itself, as if by POSIX `remove()`.
3738
 
 
3747
  *Throws:* As specified in  [[fs.err.report]].
3748
 
3749
  #### Rename <a id="fs.op.rename">[[fs.op.rename]]</a>
3750
 
3751
  ``` cpp
3752
+ void filesystem::rename(const path& old_p, const path& new_p);
3753
+ void filesystem::rename(const path& old_p, const path& new_p, error_code& ec) noexcept;
3754
  ```
3755
 
3756
  *Effects:* Renames `old_p` to `new_p`, as if by POSIX `rename()`.
3757
 
3758
  [*Note 1*:
3759
 
3760
  - If `old_p` and `new_p` resolve to the same existing file, no action is
3761
  taken.
3762
+ - Otherwise, the rename can include the following effects:
3763
  - if `new_p` resolves to an existing non-directory file, `new_p` is
3764
  removed; otherwise,
3765
  - if `new_p` resolves to an existing directory, `new_p` is removed if
3766
+ empty on POSIX compliant operating systems but might be an error on
3767
  other operating systems.
3768
 
3769
  A symbolic link is itself renamed, rather than the file it resolves to.
3770
 
3771
  — *end note*]
 
3773
  *Throws:* As specified in  [[fs.err.report]].
3774
 
3775
  #### Resize file <a id="fs.op.resize.file">[[fs.op.resize.file]]</a>
3776
 
3777
  ``` cpp
3778
+ void filesystem::resize_file(const path& p, uintmax_t new_size);
3779
+ void filesystem::resize_file(const path& p, uintmax_t new_size, error_code& ec) noexcept;
3780
  ```
3781
 
3782
  *Effects:* Causes the size that would be returned by `file_size(p)` to
3783
  be equal to `new_size`, as if by POSIX `truncate()`.
3784
 
3785
  *Throws:* As specified in  [[fs.err.report]].
3786
 
3787
  #### Space <a id="fs.op.space">[[fs.op.space]]</a>
3788
 
3789
  ``` cpp
3790
+ space_info filesystem::space(const path& p);
3791
+ space_info filesystem::space(const path& p, error_code& ec) noexcept;
3792
  ```
3793
 
3794
  *Returns:* An object of type `space_info`. The value of the `space_info`
3795
  object is determined as if by using POSIX `statvfs` to obtain a POSIX
3796
  `struct statvfs`, and then multiplying its `f_blocks`, `f_bfree`, and
 
3803
  *Throws:* As specified in  [[fs.err.report]].
3804
 
3805
  *Remarks:* The value of member `space_info::available` is operating
3806
  system dependent.
3807
 
3808
+ [*Note 1*: `available` might be less than `free`. — *end note*]
3809
 
3810
  #### Status <a id="fs.op.status">[[fs.op.status]]</a>
3811
 
3812
  ``` cpp
3813
+ file_status filesystem::status(const path& p);
3814
  ```
3815
 
3816
  *Effects:* As if:
3817
 
3818
  ``` cpp
 
3830
  [*Note 1*: `result` values of `file_status(file_type::not_found)` and
3831
  `file_status(file_type::unknown)` are not considered failures and do not
3832
  cause an exception to be thrown. — *end note*]
3833
 
3834
  ``` cpp
3835
+ file_status filesystem::status(const path& p, error_code& ec) noexcept;
3836
  ```
3837
 
3838
  *Effects:* If possible, determines the attributes of the file `p`
3839
  resolves to, as if by using POSIX `stat()` to obtain a POSIX
3840
  `struct stat`. If, during attribute determination, the underlying file
 
3895
  pathname resolution continues using the contents of the symbolic link.
3896
 
3897
  #### Status known <a id="fs.op.status.known">[[fs.op.status.known]]</a>
3898
 
3899
  ``` cpp
3900
+ bool filesystem::status_known(file_status s) noexcept;
3901
  ```
3902
 
3903
  *Returns:* `s.type() != file_type::none`.
3904
 
3905
  #### Symlink status <a id="fs.op.symlink.status">[[fs.op.symlink.status]]</a>
3906
 
3907
  ``` cpp
3908
+ file_status filesystem::symlink_status(const path& p);
3909
+ file_status filesystem::symlink_status(const path& p, error_code& ec) noexcept;
3910
  ```
3911
 
3912
  *Effects:* Same as `status()`, above, except that the attributes of `p`
3913
  are determined as if by using POSIX `lstat()` to obtain a POSIX
3914
  `struct stat`.
 
3920
  *Returns:* Same as `status()`, above, except that if the attributes
3921
  indicate a symbolic link, as if by POSIX `S_ISLNK`, returns
3922
  `file_status(file_type::symlink, prms)`. The signature with argument
3923
  `ec` returns `file_status(file_type::none)` if an error occurs.
3924
 
3925
+ *Throws:* As specified in  [[fs.err.report]].
3926
+
3927
  *Remarks:* Pathname resolution terminates if `p` names a symbolic link.
3928
 
 
 
3929
  #### Temporary directory path <a id="fs.op.temp.dir.path">[[fs.op.temp.dir.path]]</a>
3930
 
3931
  ``` cpp
3932
+ path filesystem::temp_directory_path();
3933
+ path filesystem::temp_directory_path(error_code& ec);
3934
  ```
3935
 
3936
  Let `p` be an unspecified directory path suitable for temporary files.
3937
 
3938
  *Effects:* If `exists(p)` is `false` or `is_directory(p)` is `false`, an
 
3951
  function. — *end example*]
3952
 
3953
  #### Weakly canonical <a id="fs.op.weakly.canonical">[[fs.op.weakly.canonical]]</a>
3954
 
3955
  ``` cpp
3956
+ path filesystem::weakly_canonical(const path& p);
3957
+ path filesystem::weakly_canonical(const path& p, error_code& ec);
3958
  ```
3959
 
 
 
 
3960
  *Effects:* Using `status(p)` or `status(p, ec)`, respectively, to
3961
  determine existence, return a path composed by `operator/=` from the
3962
  result of calling `canonical()` with a path argument composed of the
3963
  leading elements of `p` that exist, if any, followed by the elements of
3964
  `p` that do not exist, if any. For the first form, `canonical()` is
 
3966
  `canonical()` is called with `ec` as an `error_code` argument, and
3967
  `path()` is returned at the first error occurrence, if any.
3968
 
3969
  *Ensures:* The returned path is in normal form [[fs.path.generic]].
3970
 
3971
+ *Returns:* `p` with symlinks resolved and the result
3972
+ normalized [[fs.path.generic]].
3973
 
3974
  *Throws:* As specified in  [[fs.err.report]].
3975