From Jason Turner

[filesystems]

Diff to HTML by rtfpessoa

Files changed (1) hide show
  1. tmp/tmpwnztb6_i/{from.md → to.md} +192 -109
tmp/tmpwnztb6_i/{from.md → to.md} RENAMED
@@ -326,26 +326,29 @@ namespace std::filesystem {
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
@@ -435,12 +438,12 @@ Pathnames are formatted according to the generic pathname format grammar
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 {
446
  public:
@@ -523,22 +526,24 @@ namespace std::filesystem {
523
 
524
  template<class EcharT, class traits = char_traits<EcharT>,
525
  class Allocator = allocator<EcharT>>
526
  basic_string<EcharT, traits, Allocator>
527
  string(const Allocator& a = Allocator()) const;
528
- std::string string() const;
 
529
  std::wstring wstring() const;
530
  std::u8string u8string() const;
531
  std::u16string u16string() const;
532
  std::u32string u32string() const;
533
 
534
  // [fs.path.generic.obs], generic format observers
535
  template<class EcharT, class traits = char_traits<EcharT>,
536
  class Allocator = allocator<EcharT>>
537
  basic_string<EcharT, traits, Allocator>
538
  generic_string(const Allocator& a = Allocator()) const;
539
- std::string generic_string() const;
 
540
  std::wstring generic_wstring() const;
541
  std::u8string generic_u8string() const;
542
  std::u16string generic_u16string() const;
543
  std::u32string generic_u32string() const;
544
 
@@ -557,11 +562,11 @@ namespace std::filesystem {
557
  path filename() const;
558
  path stem() const;
559
  path extension() const;
560
 
561
  // [fs.path.query], query
562
- [[nodiscard]] bool empty() const noexcept;
563
  bool has_root_name() const;
564
  bool has_root_directory() const;
565
  bool has_root_path() const;
566
  bool has_relative_path() const;
567
  bool has_parent_path() const;
@@ -751,12 +756,12 @@ 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*]
759
 
760
  Pathnames are converted as needed between the generic and native formats
761
  in an operating-system-dependent manner. Let *G(n)* and *N(g)* in a
762
  mathematical sense be the implementation’s functions that convert
@@ -842,16 +847,16 @@ named `Source` shall be one of:
842
  \[`source.begin()`, `source.end()`).
843
  - `basic_string_view<EcharT, traits>`. A function argument
844
  `const Source&` `source` shall have an effective range
845
  \[`source.begin()`, `source.end()`).
846
  - A type meeting the *Cpp17InputIterator* requirements that iterates
847
- over a NTCTS. The value type shall be an encoded character type. A
848
  function argument `const Source&` `source` shall have an effective
849
  range \[`source`, `end`) where `end` is the first iterator value with
850
  an element value equal to `iterator_traits<Source>::value_type()`.
851
  - A character array that after array-to-pointer decay results in a
852
- pointer to the start of a NTCTS. The value type shall be an encoded
853
  character type. A function argument `const Source&` `source` shall
854
  have an effective range \[`source`, `end`) where `end` is the first
855
  iterator value with an element value equal to
856
  `iterator_traits<decay_t<Source>>::value_type()`.
857
 
@@ -877,11 +882,11 @@ Arguments of type `Source` shall not be null pointers.
877
 
878
  ``` cpp
879
  path() noexcept;
880
  ```
881
 
882
- *Ensures:* `empty() == true`.
883
 
884
  ``` cpp
885
  path(const path& p);
886
  path(path&& p) noexcept;
887
  ```
@@ -1125,11 +1130,11 @@ template<class InputIterator>
1125
 
1126
  ``` cpp
1127
  void clear() noexcept;
1128
  ```
1129
 
1130
- *Ensures:* `empty() == true`.
1131
 
1132
  ``` cpp
1133
  path& make_preferred();
1134
  ```
1135
 
@@ -1254,24 +1259,22 @@ 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;
1263
  ```
1264
 
1265
  *Returns:* `native()`.
1266
 
1267
  *Remarks:* All memory allocation, including for the return value, shall
1268
  be performed by `a`. Conversion, if any, is specified by
1269
  [[fs.path.cvt]].
1270
 
1271
  ``` cpp
1272
- std::string string() const;
1273
  std::wstring wstring() const;
1274
  std::u8string u8string() const;
1275
  std::u16string u16string() const;
1276
  std::u32string u32string() const;
1277
  ```
@@ -1279,10 +1282,20 @@ std::u32string u32string() const;
1279
  *Returns:* `native()`.
1280
 
1281
  *Remarks:* Conversion, if any, is performed as specified by
1282
  [[fs.path.cvt]].
1283
 
 
 
 
 
 
 
 
 
 
 
1284
  ##### Generic format observers <a id="fs.path.generic.obs">[[fs.path.generic.obs]]</a>
1285
 
1286
  Generic format observer functions return strings formatted according to
1287
  the generic pathname format [[fs.path.generic]]. A single slash (`'/'`)
1288
  character is used as the *directory-separator*.
@@ -1298,34 +1311,42 @@ path("foo\\bar").generic_string()
1298
  returns `"foo/bar"`.
1299
 
1300
  — *end example*]
1301
 
1302
  ``` cpp
1303
- template<class EcharT, class traits = char_traits<EcharT>,
1304
- class Allocator = allocator<EcharT>>
1305
- basic_string<EcharT, traits, Allocator>
1306
- generic_string(const Allocator& a = Allocator()) const;
1307
  ```
1308
 
1309
  *Returns:* The pathname in the generic format.
1310
 
1311
  *Remarks:* All memory allocation, including for the return value, shall
1312
  be performed by `a`. Conversion, if any, is specified by
1313
  [[fs.path.cvt]].
1314
 
1315
  ``` cpp
1316
- std::string generic_string() const;
1317
  std::wstring generic_wstring() const;
1318
  std::u8string generic_u8string() const;
1319
  std::u16string generic_u16string() const;
1320
  std::u32string generic_u32string() const;
1321
  ```
1322
 
1323
  *Returns:* The pathname in the generic format.
1324
 
1325
  *Remarks:* Conversion, if any, is specified by  [[fs.path.cvt]].
1326
 
 
 
 
 
 
 
 
 
 
 
1327
  ##### Compare <a id="fs.path.compare">[[fs.path.compare]]</a>
1328
 
1329
  ``` cpp
1330
  int compare(const path& p) const noexcept;
1331
  ```
@@ -1456,22 +1477,22 @@ path(".bar").extension(); // yields "" and stem() is ".bar"
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;
1473
  ```
1474
 
1475
  *Returns:* `true` if the pathname in the generic format is empty,
1476
  otherwise `false`.
1477
 
@@ -1575,11 +1596,11 @@ path lexically_relative(const path& base) const;
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
@@ -1618,28 +1639,28 @@ The above assertions will succeed. On Windows, the returned path’s
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
 
@@ -1657,13 +1678,13 @@ iterators referring to elements of that object.
1657
 
1658
  For the elements of the pathname in the generic format, the forward
1659
  traversal order is as follows:
1660
 
1661
  - The *root-name* element, if present.
1662
- - The *root-directory* element, if present. \[*Note 1*: The generic
1663
- format is required to ensure lexicographical comparison works
1664
- correctly. — *end note*]
1665
  - Each successive *filename* element, if present.
1666
  - An empty element, if a trailing non-root *directory-separator* is
1667
  present.
1668
 
1669
  The backward traversal order is the reverse of forward traversal.
@@ -1758,10 +1779,79 @@ friend strong_ordering operator<=>(const path& lhs, const path& rhs) noexcept;
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
  ```
@@ -1804,25 +1894,27 @@ with an error.
1804
  filesystem_error(const string& what_arg, error_code ec);
1805
  ```
1806
 
1807
  *Ensures:*
1808
 
1809
- - `code() == ec`,
1810
- - `path1().empty() == true`,
1811
- - `path2().empty() == true`, and
1812
- - `string_view(what()).find(what_arg.c_str())` `!= string_view::npos`.
 
1813
 
1814
  ``` cpp
1815
  filesystem_error(const string& what_arg, const path& p1, error_code ec);
1816
  ```
1817
 
1818
  *Ensures:*
1819
 
1820
- - `code() == ec`,
1821
  - `path1()` returns a reference to the stored copy of `p1`,
1822
- - `path2().empty() == true`, and
1823
- - `string_view(what()).find(what_arg.c_str())` `!= string_view::npos`.
 
1824
 
1825
  ``` cpp
1826
  filesystem_error(const string& what_arg, const path& p1, const path& p2, error_code ec);
1827
  ```
1828
 
@@ -1879,11 +1971,11 @@ 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 |
@@ -1906,11 +1998,11 @@ exposition; implementations shall provide only a single definition.
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} |
@@ -1928,11 +2020,11 @@ specifies bitmask constants used to identify file permissions, with the
1928
  meanings listed in [[fs.enum.perms]].
1929
 
1930
  **Table: Enum class `perms`** <a id="fs.enum.perms">[fs.enum.perms]</a>
1931
 
1932
  | Name | Value (octal) | POSIX macro | Definition or notes |
1933
- | -------------- | ------------- | ----------- | ---------------------------------------------------------------------------------------------------------------- |
1934
  | `none` | `0` | | There are no permissions set for the file. |
1935
  | `owner_read` | `0400` | `S_IRUSR` | Read permission, owner |
1936
  | `owner_write` | `0200` | `S_IWUSR` | Write permission, owner |
1937
  | `owner_exec` | `0100` | `S_IXUSR` | Execute/search permission, owner |
1938
  | `owner_all` | `0700` | `S_IRWXU` | Read, write, execute/search by owner;<br> `owner_read | owner_write | owner_exec` |
@@ -1962,11 +2054,11 @@ permissions operations, with the meanings listed in
1962
  `permissions`.
1963
 
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
 
@@ -1980,11 +2072,11 @@ directory traversal options, with the meanings listed in
1980
  every other constant in the table represents a distinct bitmask element.
1981
 
1982
  **Table: Enum class `directory_options`** <a id="fs.enum.dir.opts">[fs.enum.dir.opts]</a>
1983
 
1984
  | Name | Meaning |
1985
- | -------------------------- | ------------------------------------------------------------------ |
1986
  | `none` | (Default) Skip directory symlinks, permission denied is an error. |
1987
  | `follow_directory_symlink` | Follow rather than skip directory symlinks. |
1988
  | `skip_permission_denied` | Skip directories that would otherwise result in permission denied. |
1989
 
1990
 
@@ -2129,12 +2221,11 @@ namespace std::filesystem {
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
  }
2138
  ```
2139
 
2140
  A `directory_entry` object stores a `path` object and may store
@@ -2145,16 +2236,13 @@ Implementations should store such additional file attributes during
2145
  directory iteration if their values are available and storing the values
2146
  would allow the implementation to eliminate file system accesses by
2147
  `directory_entry` observer functions [[fs.op.funcs]]. Such stored file
2148
  attribute values are said to be *cached*.
2149
 
2150
- [*Note 1*: For purposes of exposition, class `directory_iterator`
2151
- [[fs.class.directory.iterator]] is shown above as a friend of class
2152
- `directory_entry`. Friendship allows the `directory_iterator`
2153
- implementation to cache already available attribute values directly into
2154
- a `directory_entry` object without the cost of an unneeded call to
2155
- `refresh()`. — *end note*]
2156
 
2157
  [*Example 1*:
2158
 
2159
  ``` cpp
2160
  using namespace std::filesystem;
@@ -2203,22 +2291,22 @@ directory_entry(const filesystem::path& p, error_code& ec);
2203
  ``` cpp
2204
  void assign(const filesystem::path& p);
2205
  void assign(const filesystem::path& p, error_code& ec);
2206
  ```
2207
 
2208
- *Effects:* Equivalent to `pathobject = p`, then `refresh()` or
2209
  `refresh(ec)`, respectively. If an error occurs, the values of any
2210
  cached attributes are unspecified.
2211
 
2212
  *Throws:* As specified in  [[fs.err.report]].
2213
 
2214
  ``` cpp
2215
  void replace_filename(const filesystem::path& p);
2216
  void replace_filename(const filesystem::path& p, error_code& ec);
2217
  ```
2218
 
2219
- *Effects:* Equivalent to `pathobject.replace_filename(p)`, then
2220
  `refresh()` or `refresh(ec)`, respectively. If an error occurs, the
2221
  values of any cached attributes are unspecified.
2222
 
2223
  *Throws:* As specified in  [[fs.err.report]].
2224
 
@@ -2248,11 +2336,11 @@ Unqualified function names in the *Returns:* elements of the
2248
  ``` cpp
2249
  const filesystem::path& path() const noexcept;
2250
  operator const filesystem::path&() const noexcept;
2251
  ```
2252
 
2253
- *Returns:* `pathobject`.
2254
 
2255
  ``` cpp
2256
  bool exists() const;
2257
  bool exists(error_code& ec) const noexcept;
2258
  ```
@@ -2396,17 +2484,17 @@ file_status symlink_status(error_code& ec) const noexcept;
2396
 
2397
  ``` cpp
2398
  bool operator==(const directory_entry& rhs) const noexcept;
2399
  ```
2400
 
2401
- *Returns:* `pathobject == rhs.pathobject`.
2402
 
2403
  ``` cpp
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>
@@ -2497,13 +2585,11 @@ the values of any cached attributes [[fs.class.directory.entry]] in the
2497
  `directory_entry` element returned by `operator*()`.
2498
  `directory_iterator` member functions shall not directly or indirectly
2499
  call any `directory_entry` `refresh` function.
2500
 
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
@@ -2835,11 +2921,11 @@ required to be dereferenceable nor to be in the domain of `==`.
2835
  void disable_recursion_pending();
2836
  ```
2837
 
2838
  *Ensures:* `recursion_pending() == false`.
2839
 
2840
- [*Note 4*: `disable_recursion_pending``()` is used to prevent unwanted
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
@@ -2965,11 +3051,11 @@ group [[fs.enum.copy.opts]] is set in `options`.
2965
  Effects are then as follows:
2966
 
2967
  - If `f.type()` or `t.type()` is an implementation-defined file
2968
  type [[fs.enum.file.type]], then the effects are
2969
  *implementation-defined*.
2970
- - Otherwise, an error is reported as specified in  [[fs.err.report]] if:
2971
  - `exists(f)` is `false`, or
2972
  - `equivalent(from, to)` is `true`, or
2973
  - `is_other(f) || is_other(t)` is `true`, or
2974
  - `is_directory(f) && is_regular_file(t)` is `true`.
2975
  - Otherwise, if `is_symlink(f)`, then:
@@ -3032,21 +3118,21 @@ applicable.
3032
 
3033
  [*Example 1*:
3034
 
3035
  Given this directory structure:
3036
 
3037
- ``` cpp
3038
  /dir1
3039
  file1
3040
  file2
3041
  dir2
3042
  file3
3043
  ```
3044
 
3045
  Calling `copy("/dir1", "/dir3")` would result in:
3046
 
3047
- ``` cpp
3048
  /dir1
3049
  file1
3050
  file2
3051
  dir2
3052
  file3
@@ -3056,11 +3142,11 @@ Calling `copy("/dir1", "/dir3")` would result in:
3056
  ```
3057
 
3058
  Alternatively, calling `copy("/dir1", "/dir3", copy_options::recursive)`
3059
  would result in:
3060
 
3061
- ``` cpp
3062
  /dir1
3063
  file1
3064
  file2
3065
  dir2
3066
  file3
@@ -3094,22 +3180,22 @@ bool filesystem::copy_file(const path& from, const path& to, copy_options option
3094
  *Preconditions:* At most one element from each option
3095
  group [[fs.enum.copy.opts]] is set in `options`.
3096
 
3097
  *Effects:* As follows:
3098
 
3099
- - Report an error as specified in  [[fs.err.report]] if:
3100
  - `is_regular_file(from)` is `false`, or
3101
  - `exists(to)` is `true` and `is_regular_file(to)` is `false`, or
3102
  - `exists(to)` is `true` and `equivalent(from, to)` is `true`, or
3103
  - `exists(to)` is `true` and
3104
  ``` cpp
3105
  (options & (copy_options::skip_existing |
3106
  copy_options::overwrite_existing |
3107
  copy_options::update_existing)) == copy_options::none
3108
  ```
3109
  - Otherwise, copy the contents and attributes of the file `from`
3110
- resolves to, to the file `to` resolves to, if:
3111
  - `exists(to)` is `false`, or
3112
  - `(options & copy_options::overwrite_existing) != copy_options::none`,
3113
  or
3114
  - `(options & copy_options::update_existing) `` `` != copy_options::none`
3115
  and `from` is more recent than `to`, determined as if by use of the
@@ -3144,11 +3230,11 @@ respectively, where in each case *`function`* is `create_symlink` or
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
 
3152
  *Returns:* `true` if a new directory was created for the directory `p`
3153
  resolves to, otherwise `false`.
3154
 
@@ -3201,21 +3287,21 @@ from directory `existing_p`, otherwise `false`.
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
 
3208
  *Ensures:* `new_symlink` resolves to a symbolic link file that contains
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*]
@@ -3226,11 +3312,11 @@ operating system. — *end note*]
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
 
3233
  *Ensures:*
3234
 
3235
  - `exists(to) && exists(new_hard_link) && equivalent(to, new_hard_link)`
3236
  - The contents of the file or directory `to` resolves to are unchanged.
@@ -3249,11 +3335,11 @@ file. — *end note*]
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
 
3256
  *Ensures:* `new_symlink` resolves to a symbolic link file that contains
3257
  an unspecified representation of `to`.
3258
 
3259
  *Throws:* As specified in  [[fs.err.report]].
@@ -3269,39 +3355,35 @@ operating system. — *end note*]
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.
3276
 
3277
  *Throws:* As specified in  [[fs.err.report]].
3278
 
3279
  *Remarks:* The current working directory is the directory, associated
3280
  with the process, that is used as the starting location in pathname
3281
  resolution for relative paths.
3282
 
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
 
@@ -3312,11 +3394,11 @@ bool filesystem::equivalent(const path& p1, const path& p2, error_code& ec) noex
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.
@@ -3360,11 +3442,11 @@ reported [[fs.err.report]].
3360
 
3361
  *Returns:*
3362
 
3363
  - If `is_regular_file(p)`, the size in bytes of the file `p` resolves
3364
  to, determined as if by the value of the POSIX `stat` class member
3365
- `st_size` obtained as if by POSIX `stat()`.
3366
  - Otherwise, the result is *implementation-defined*.
3367
 
3368
  The signature with argument `ec` returns `static_cast<uintmax_t>(-1)` if
3369
  an error occurs.
3370
 
@@ -3581,11 +3663,11 @@ 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
@@ -3593,11 +3675,11 @@ 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
@@ -3615,11 +3697,11 @@ void filesystem::permissions(const path& p, perms prms, perm_options opts, error
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]].
@@ -3712,19 +3794,20 @@ or `path()` at the first error occurrence, if any.
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
 
3719
  [*Note 1*: A symbolic link is itself removed, rather than the file it
3720
  resolves to. — *end note*]
3721
 
3722
  *Ensures:* `exists(symlink_status(p))` is `false`.
3723
 
3724
- *Returns:* `false` if `p` did not exist, otherwise `true`. The signature
3725
- with argument `ec` returns `false` if an error occurs.
 
3726
 
3727
  *Throws:* As specified in  [[fs.err.report]].
3728
 
3729
  #### Remove all <a id="fs.op.remove.all">[[fs.op.remove.all]]</a>
3730
 
@@ -3732,11 +3815,11 @@ with argument `ec` returns `false` if an error occurs.
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
 
3739
  [*Note 1*: A symbolic link is itself removed, rather than the file it
3740
  resolves to. — *end note*]
3741
 
3742
  *Ensures:* `exists(symlink_status(p))` is `false`.
@@ -3751,11 +3834,11 @@ returns `static_cast< uintmax_t>(-1)` if an error occurs.
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.
@@ -3778,11 +3861,11 @@ A symbolic link is itself renamed, rather than the file it resolves to.
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
 
@@ -3811,11 +3894,11 @@ system dependent.
3811
 
3812
  ``` cpp
3813
  file_status filesystem::status(const path& p);
3814
  ```
3815
 
3816
- *Effects:* As if:
3817
 
3818
  ``` cpp
3819
  error_code ec;
3820
  file_status result = status(p, ec);
3821
  if (result.type() == file_type::none)
@@ -3834,17 +3917,17 @@ cause an exception to be thrown. — *end note*]
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
3841
  system API reports an error, sets `ec` to indicate the specific error
3842
  reported. Otherwise, `ec.clear()`.
3843
 
3844
  [*Note 2*: This allows users to inspect the specifics of underlying API
3845
- errors even when the value returned by `status()` is not
3846
  `file_status(file_type::none)`. — *end note*]
3847
 
3848
  Let `prms` denote the result of `(m & perms::mask)`, where `m` is
3849
  determined as if by converting the `st_mode` member of the obtained
3850
  `struct stat` to the type `perms`.
@@ -3907,19 +3990,19 @@ bool filesystem::status_known(file_status s) noexcept;
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`.
3915
 
3916
  Let `prms` denote the result of `(m & perms::mask)`, where `m` is
3917
  determined as if by converting the `st_mode` member of the obtained
3918
  `struct stat` to the type `perms`.
3919
 
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]].
@@ -3957,16 +4040,16 @@ 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
3965
- called without an `error_code` argument. For the second form,
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]].
 
326
 
327
  path weakly_canonical(const path& p);
328
  path weakly_canonical(const path& p, error_code& ec);
329
  }
330
 
331
+ namespace std {
332
+ // [fs.path.fmtr], formatting support
333
+ template<class charT> struct formatter<filesystem::path, charT>;
334
+
335
  // [fs.path.hash], hash support
 
336
  template<class T> struct hash;
337
  template<> struct hash<filesystem::path>;
338
  }
339
 
340
  namespace std::ranges {
341
  template<>
342
+ inline constexpr bool \libspec{enable_borrowed_range}{directory_iterator}<filesystem::directory_iterator> = true;
343
  template<>
344
+ inline constexpr bool \libspec{enable_borrowed_range}{recursive_directory_iterator}<filesystem::recursive_directory_iterator> = true;
345
 
346
  template<>
347
+ inline constexpr bool \libspec{enable_view}{directory_iterator}<filesystem::directory_iterator> = true;
348
  template<>
349
+ inline constexpr bool \libspec{enable_view}{recursive_directory_iterator}<filesystem::recursive_directory_iterator> = true;
350
  }
351
  ```
352
 
353
  Implementations should ensure that the resolution and range of
354
  `file_time_type` reflect the operating system dependent resolution and
 
438
 
439
  *Pathname resolution* is the operating system dependent mechanism for
440
  resolving a pathname to a particular file in a file hierarchy. There may
441
  be multiple pathnames that resolve to the same file.
442
 
443
+ [*Example 1*: For POSIX-based operating systems, this mechanism is
444
+ specified in POSIX, section 4.12, Pathname resolution. — *end example*]
445
 
446
  ``` cpp
447
  namespace std::filesystem {
448
  class path {
449
  public:
 
526
 
527
  template<class EcharT, class traits = char_traits<EcharT>,
528
  class Allocator = allocator<EcharT>>
529
  basic_string<EcharT, traits, Allocator>
530
  string(const Allocator& a = Allocator()) const;
531
+ std::string display_string() const;
532
+ std::string system_encoded_string() const;
533
  std::wstring wstring() const;
534
  std::u8string u8string() const;
535
  std::u16string u16string() const;
536
  std::u32string u32string() const;
537
 
538
  // [fs.path.generic.obs], generic format observers
539
  template<class EcharT, class traits = char_traits<EcharT>,
540
  class Allocator = allocator<EcharT>>
541
  basic_string<EcharT, traits, Allocator>
542
  generic_string(const Allocator& a = Allocator()) const;
543
+ std::string generic_display_string() const;
544
+ std::string generic_system_encoded_string() const;
545
  std::wstring generic_wstring() const;
546
  std::u8string generic_u8string() const;
547
  std::u16string generic_u16string() const;
548
  std::u32string generic_u32string() const;
549
 
 
562
  path filename() const;
563
  path stem() const;
564
  path extension() const;
565
 
566
  // [fs.path.query], query
567
+ bool empty() const noexcept;
568
  bool has_root_name() const;
569
  bool has_root_directory() const;
570
  bool has_root_path() const;
571
  bool has_relative_path() const;
572
  bool has_parent_path() const;
 
756
  path.
757
 
758
  [*Note 2*: Some operating systems have no unambiguous way to
759
  distinguish between native format and generic format arguments. This is
760
  by design as it simplifies use for operating systems that do not require
761
+ disambiguation. It is possible that an implementation for an operating
762
+ system where disambiguation is needed distinguishes between the
763
  formats. — *end note*]
764
 
765
  Pathnames are converted as needed between the generic and native formats
766
  in an operating-system-dependent manner. Let *G(n)* and *N(g)* in a
767
  mathematical sense be the implementation’s functions that convert
 
847
  \[`source.begin()`, `source.end()`).
848
  - `basic_string_view<EcharT, traits>`. A function argument
849
  `const Source&` `source` shall have an effective range
850
  \[`source.begin()`, `source.end()`).
851
  - A type meeting the *Cpp17InputIterator* requirements that iterates
852
+ over an NTCTS. The value type shall be an encoded character type. A
853
  function argument `const Source&` `source` shall have an effective
854
  range \[`source`, `end`) where `end` is the first iterator value with
855
  an element value equal to `iterator_traits<Source>::value_type()`.
856
  - A character array that after array-to-pointer decay results in a
857
+ pointer to the start of an NTCTS. The value type shall be an encoded
858
  character type. A function argument `const Source&` `source` shall
859
  have an effective range \[`source`, `end`) where `end` is the first
860
  iterator value with an element value equal to
861
  `iterator_traits<decay_t<Source>>::value_type()`.
862
 
 
882
 
883
  ``` cpp
884
  path() noexcept;
885
  ```
886
 
887
+ *Ensures:* `empty()` is `true`.
888
 
889
  ``` cpp
890
  path(const path& p);
891
  path(path&& p) noexcept;
892
  ```
 
1130
 
1131
  ``` cpp
1132
  void clear() noexcept;
1133
  ```
1134
 
1135
+ *Ensures:* `empty()` is `true`.
1136
 
1137
  ``` cpp
1138
  path& make_preferred();
1139
  ```
1140
 
 
1259
  ```
1260
 
1261
  *Returns:* `native()`.
1262
 
1263
  ``` cpp
1264
+ template<class EcharT, class traits = char_traits<EcharT>, class Allocator = allocator<EcharT>>
1265
+ basic_string<EcharT, traits, Allocator> string(const Allocator& a = Allocator()) const;
 
 
1266
  ```
1267
 
1268
  *Returns:* `native()`.
1269
 
1270
  *Remarks:* All memory allocation, including for the return value, shall
1271
  be performed by `a`. Conversion, if any, is specified by
1272
  [[fs.path.cvt]].
1273
 
1274
  ``` cpp
1275
+ std::string system_encoded_string() const;
1276
  std::wstring wstring() const;
1277
  std::u8string u8string() const;
1278
  std::u16string u16string() const;
1279
  std::u32string u32string() const;
1280
  ```
 
1282
  *Returns:* `native()`.
1283
 
1284
  *Remarks:* Conversion, if any, is performed as specified by
1285
  [[fs.path.cvt]].
1286
 
1287
+ ``` cpp
1288
+ std::string display_string() const;
1289
+ ```
1290
+
1291
+ *Returns:* `std::format("{}", *this)`.
1292
+
1293
+ [*Note 3*: The returned string is suitable for use with
1294
+ formatting [[format.functions]] and print
1295
+ functions [[print.fun]]. — *end note*]
1296
+
1297
  ##### Generic format observers <a id="fs.path.generic.obs">[[fs.path.generic.obs]]</a>
1298
 
1299
  Generic format observer functions return strings formatted according to
1300
  the generic pathname format [[fs.path.generic]]. A single slash (`'/'`)
1301
  character is used as the *directory-separator*.
 
1311
  returns `"foo/bar"`.
1312
 
1313
  — *end example*]
1314
 
1315
  ``` cpp
1316
+ template<class EcharT, class traits = char_traits<EcharT>, class Allocator = allocator<EcharT>>
1317
+ basic_string<EcharT, traits, Allocator> generic_string(const Allocator& a = Allocator()) const;
 
 
1318
  ```
1319
 
1320
  *Returns:* The pathname in the generic format.
1321
 
1322
  *Remarks:* All memory allocation, including for the return value, shall
1323
  be performed by `a`. Conversion, if any, is specified by
1324
  [[fs.path.cvt]].
1325
 
1326
  ``` cpp
1327
+ std::string generic_system_encoded_string() const;
1328
  std::wstring generic_wstring() const;
1329
  std::u8string generic_u8string() const;
1330
  std::u16string generic_u16string() const;
1331
  std::u32string generic_u32string() const;
1332
  ```
1333
 
1334
  *Returns:* The pathname in the generic format.
1335
 
1336
  *Remarks:* Conversion, if any, is specified by  [[fs.path.cvt]].
1337
 
1338
+ ``` cpp
1339
+ std::string generic_display_string() const;
1340
+ ```
1341
+
1342
+ *Returns:* `std::format("{:g}", *this)`.
1343
+
1344
+ [*Note 4*: The returned string is suitable for use with
1345
+ formatting [[format.functions]] and print
1346
+ functions [[print.fun]]. — *end note*]
1347
+
1348
  ##### Compare <a id="fs.path.compare">[[fs.path.compare]]</a>
1349
 
1350
  ``` cpp
1351
  int compare(const path& p) const noexcept;
1352
  ```
 
1477
  path("..bar").extension(); // yields ".bar" and stem() is "."
1478
  ```
1479
 
1480
  — *end example*]
1481
 
1482
+ [*Note 5*: The period is included in the return value so that it is
1483
  possible to distinguish between no extension and an empty
1484
  extension. — *end note*]
1485
 
1486
+ [*Note 6*: On non-POSIX operating systems, for a path `p`, it is
1487
  possible that `p.stem() + p.extension() == p.filename()` is `false`,
1488
  even though the generic format pathnames are the same. — *end note*]
1489
 
1490
  ##### Query <a id="fs.path.query">[[fs.path.query]]</a>
1491
 
1492
  ``` cpp
1493
+ bool empty() const noexcept;
1494
  ```
1495
 
1496
  *Returns:* `true` if the pathname in the generic format is empty,
1497
  otherwise `false`.
1498
 
 
1596
  - any *filename* in `relative_path()` or `base.relative_path()` can be
1597
  interpreted as a *root-name*,
1598
 
1599
  returns `path()`.
1600
 
1601
+ [*Note 7*: On a POSIX implementation, no *filename* in a
1602
  *relative-path* is acceptable as a *root-name*. — *end note*]
1603
 
1604
  Determines the first mismatched element of `*this` and `base` as if by:
1605
 
1606
  ``` cpp
 
1639
  *directory-separator* characters will be backslashes rather than
1640
  slashes, but that does not affect `path` equality.
1641
 
1642
  — *end example*]
1643
 
1644
+ [*Note 8*: If symlink following semantics are desired, use the
1645
  operational function `relative()`. — *end note*]
1646
 
1647
+ [*Note 9*: If normalization [[fs.path.generic]] is needed to ensure
1648
  consistent matching of elements, apply `lexically_normal()` to `*this`,
1649
  `base`, or both. — *end note*]
1650
 
1651
  ``` cpp
1652
  path lexically_proximate(const path& base) const;
1653
  ```
1654
 
1655
  *Returns:* If the value of `lexically_relative(base)` is not an empty
1656
  path, return it. Otherwise return `*this`.
1657
 
1658
+ [*Note 10*: If symlink following semantics are desired, use the
1659
  operational function `proximate()`. — *end note*]
1660
 
1661
+ [*Note 11*: If normalization [[fs.path.generic]] is needed to ensure
1662
  consistent matching of elements, apply `lexically_normal()` to `*this`,
1663
  `base`, or both. — *end note*]
1664
 
1665
  #### Iterators <a id="fs.path.itr">[[fs.path.itr]]</a>
1666
 
 
1678
 
1679
  For the elements of the pathname in the generic format, the forward
1680
  traversal order is as follows:
1681
 
1682
  - The *root-name* element, if present.
1683
+ - The *root-directory* element, if present. \[*Note 1*: It is possible
1684
+ that the use of the generic format is needed to ensure correct
1685
+ lexicographical comparison. — *end note*]
1686
  - Each successive *filename* element, if present.
1687
  - An empty element, if a trailing non-root *directory-separator* is
1688
  present.
1689
 
1690
  The backward traversal order is the reverse of forward traversal.
 
1779
  friend path operator/(const path& lhs, const path& rhs);
1780
  ```
1781
 
1782
  *Effects:* Equivalent to: `return path(lhs) /= rhs;`
1783
 
1784
+ #### Formatting support <a id="fs.path.fmtr">[[fs.path.fmtr]]</a>
1785
+
1786
+ ##### Formatting support overview <a id="fs.path.fmtr.general">[[fs.path.fmtr.general]]</a>
1787
+
1788
+ ``` cpp
1789
+ namespace std {
1790
+ template<class charT> struct formatter<filesystem::path, charT> {
1791
+ constexpr void set_debug_format();
1792
+
1793
+ constexpr typename basic_format_parse_context<charT>::iterator
1794
+ parse(basic_format_parse_context<charT>& ctx);
1795
+
1796
+ template<class FormatContext>
1797
+ typename FormatContext::iterator
1798
+ format(const filesystem::path& path, FormatContext& ctx) const;
1799
+ };
1800
+ }
1801
+ ```
1802
+
1803
+ ##### Formatting support functions <a id="fs.path.fmtr.funcs">[[fs.path.fmtr.funcs]]</a>
1804
+
1805
+ Formatting of paths uses formatting specifiers of the form
1806
+
1807
+ ``` bnf
1808
+ path-format-spec:
1809
+ fill-and-alignₒₚₜ widthₒₚₜ '?'ₒₚₜ 'g'ₒₚₜ
1810
+ ```
1811
+
1812
+ where the productions *fill-and-align* and *width* are described in
1813
+ [[format.string]]. If the `?` option is used then the path is formatted
1814
+ as an escaped string [[format.string.escaped]].
1815
+
1816
+ ``` cpp
1817
+ constexpr void set_debug_format();
1818
+ ```
1819
+
1820
+ *Effects:* Modifies the state of the `formatter` to be as if the
1821
+ *path-format-spec* parsed by the last call to `parse` contained the `?`
1822
+ option.
1823
+
1824
+ ``` cpp
1825
+ constexpr typename basic_format_parse_context<charT>::iterator
1826
+ parse(basic_format_parse_context<charT>& ctx);
1827
+ ```
1828
+
1829
+ *Effects:* Parses the format specifier as a *path-format-spec* and
1830
+ stores the parsed specifiers in `*this`.
1831
+
1832
+ *Returns:* An iterator past the end of the *path-format-spec*.
1833
+
1834
+ ``` cpp
1835
+ template<class FormatContext>
1836
+ typename FormatContext::iterator
1837
+ format(const filesystem::path& p, FormatContext& ctx) const;
1838
+ ```
1839
+
1840
+ *Effects:* Let `s` be `p.generic_string<filesystem::path::value_type>()`
1841
+ if the `g` option is used, otherwise `p.native()`. Writes `s` into
1842
+ `ctx.out()`, adjusted according to the *path-format-spec*. If `charT` is
1843
+ `char`, `path::value_type` is `wchar_t`, and the literal encoding is
1844
+ UTF-8, then the escaped path is transcoded from the native encoding for
1845
+ wide character strings to UTF-8 with maximal subparts of ill-formed
1846
+ subsequences substituted with ‘U+fffd‘ replacement character per the
1847
+ Unicode Standard, Chapter 3.9 ‘U+fffd‘ Substitution in Conversion. If
1848
+ `charT` and `path::value_type` are the same then no transcoding is
1849
+ performed. Otherwise, transcoding is *implementation-defined*.
1850
+
1851
+ *Returns:* An iterator past the end of the output range.
1852
+
1853
  #### Hash support <a id="fs.path.hash">[[fs.path.hash]]</a>
1854
 
1855
  ``` cpp
1856
  template<> struct hash<filesystem::path>;
1857
  ```
 
1894
  filesystem_error(const string& what_arg, error_code ec);
1895
  ```
1896
 
1897
  *Ensures:*
1898
 
1899
+ - `code() == ec` is `true`,
1900
+ - `path1().empty()` is `true`,
1901
+ - `path2().empty()` is `true`, and
1902
+ - `string_view(what()).find(what_arg.c_str())` `!= string_view::npos` is
1903
+ `true`.
1904
 
1905
  ``` cpp
1906
  filesystem_error(const string& what_arg, const path& p1, error_code ec);
1907
  ```
1908
 
1909
  *Ensures:*
1910
 
1911
+ - `code() == ec` is `true`,
1912
  - `path1()` returns a reference to the stored copy of `p1`,
1913
+ - `path2().empty()` is `true`, and
1914
+ - `string_view(what()).find(what_arg.c_str())` `!= string_view::npos` is
1915
+ `true`.
1916
 
1917
  ``` cpp
1918
  filesystem_error(const string& what_arg, const path& p1, const path& p2, error_code ec);
1919
  ```
1920
 
 
1971
  constants are distinct.
1972
 
1973
  **Table: Enum class `file_type`** <a id="fs.enum.file.type">[fs.enum.file.type]</a>
1974
 
1975
  | Constant | Meaning |
1976
+ | ---------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
1977
  | `none` | The type of the file has not been determined or an error occurred while trying to determine the type. |
1978
  | `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.* |
1979
  | `regular` | Regular file |
1980
  | `directory` | Directory file |
1981
  | `symlink` | Symbolic link file |
 
1998
  Every other constant in the table represents a distinct bitmask element.
1999
 
2000
  **Table: Enum class `copy_options`** <a id="fs.enum.copy.opts">[fs.enum.copy.opts]</a>
2001
 
2002
  | Constant | Meaning |
2003
+ | ---------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------- |
2004
  | `none` | (Default) Error; file already exists. |
2005
  | `skip_existing` | Do not overwrite existing file, do not report an error. |
2006
  | `overwrite_existing` | Overwrite the existing file. |
2007
  | `update_existing` | Overwrite the existing file if it is older than the replacement file. \ohdrx{2}{Option group controlling `copy` function effects for subdirectories} |
2008
  | `recursive` | Recursively copy subdirectories and their contents. \ohdrx{2}{Option group controlling `copy` function effects for symbolic links} |
 
2020
  meanings listed in [[fs.enum.perms]].
2021
 
2022
  **Table: Enum class `perms`** <a id="fs.enum.perms">[fs.enum.perms]</a>
2023
 
2024
  | Name | Value (octal) | POSIX macro | Definition or notes |
2025
+ | --------------------------------- | ------------- | ----------- | ---------------------------------------------------------------------------------------------------------------- |
2026
  | `none` | `0` | | There are no permissions set for the file. |
2027
  | `owner_read` | `0400` | `S_IRUSR` | Read permission, owner |
2028
  | `owner_write` | `0200` | `S_IWUSR` | Write permission, owner |
2029
  | `owner_exec` | `0100` | `S_IXUSR` | Execute/search permission, owner |
2030
  | `owner_all` | `0700` | `S_IRWXU` | Read, write, execute/search by owner;<br> `owner_read | owner_write | owner_exec` |
 
2054
  `permissions`.
2055
 
2056
  **Table: Enum class `perm_options`** <a id="fs.enum.perm.opts">[fs.enum.perm.opts]</a>
2057
 
2058
  | Name | Meaning |
2059
+ | ------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------- |
2060
  | `replace` | `permissions` shall replace the file's permission bits with `perm` |
2061
  | `add` | `permissions` shall replace the file's permission bits with the bitwise \logop{or} of `perm` and the file's current permission bits. |
2062
  | `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. |
2063
  | `nofollow` | `permissions` shall change the permissions of a symbolic link itself rather than the permissions of the file the link resolves to. |
2064
 
 
2072
  every other constant in the table represents a distinct bitmask element.
2073
 
2074
  **Table: Enum class `directory_options`** <a id="fs.enum.dir.opts">[fs.enum.dir.opts]</a>
2075
 
2076
  | Name | Meaning |
2077
+ | --------------------------------------------------------- | ------------------------------------------------------------------ |
2078
  | `none` | (Default) Skip directory symlinks, permission denied is an error. |
2079
  | `follow_directory_symlink` | Follow rather than skip directory symlinks. |
2080
  | `skip_permission_denied` | Skip directories that would otherwise result in permission denied. |
2081
 
2082
 
 
2221
  template<class charT, class traits>
2222
  friend basic_ostream<charT, traits>&
2223
  operator<<(basic_ostream<charT, traits>& os, const directory_entry& d);
2224
 
2225
  private:
2226
+ filesystem::path path-object; // exposition only
 
2227
  };
2228
  }
2229
  ```
2230
 
2231
  A `directory_entry` object stores a `path` object and may store
 
2236
  directory iteration if their values are available and storing the values
2237
  would allow the implementation to eliminate file system accesses by
2238
  `directory_entry` observer functions [[fs.op.funcs]]. Such stored file
2239
  attribute values are said to be *cached*.
2240
 
2241
+ [*Note 1*: `directory_iterator` can cache already available attribute
2242
+ values directly into a `directory_entry` object without the cost of a
2243
+ call to `refresh()`. *end note*]
 
 
 
2244
 
2245
  [*Example 1*:
2246
 
2247
  ``` cpp
2248
  using namespace std::filesystem;
 
2291
  ``` cpp
2292
  void assign(const filesystem::path& p);
2293
  void assign(const filesystem::path& p, error_code& ec);
2294
  ```
2295
 
2296
+ *Effects:* Equivalent to *`path-object`*` = p`, then `refresh()` or
2297
  `refresh(ec)`, respectively. If an error occurs, the values of any
2298
  cached attributes are unspecified.
2299
 
2300
  *Throws:* As specified in  [[fs.err.report]].
2301
 
2302
  ``` cpp
2303
  void replace_filename(const filesystem::path& p);
2304
  void replace_filename(const filesystem::path& p, error_code& ec);
2305
  ```
2306
 
2307
+ *Effects:* Equivalent to *`path-object`*`.replace_filename(p)`, then
2308
  `refresh()` or `refresh(ec)`, respectively. If an error occurs, the
2309
  values of any cached attributes are unspecified.
2310
 
2311
  *Throws:* As specified in  [[fs.err.report]].
2312
 
 
2336
  ``` cpp
2337
  const filesystem::path& path() const noexcept;
2338
  operator const filesystem::path&() const noexcept;
2339
  ```
2340
 
2341
+ *Returns:* *path-object*.
2342
 
2343
  ``` cpp
2344
  bool exists() const;
2345
  bool exists(error_code& ec) const noexcept;
2346
  ```
 
2484
 
2485
  ``` cpp
2486
  bool operator==(const directory_entry& rhs) const noexcept;
2487
  ```
2488
 
2489
+ *Returns:* *`path-object`*` == rhs.`*`path-object`*.
2490
 
2491
  ``` cpp
2492
  strong_ordering operator<=>(const directory_entry& rhs) const noexcept;
2493
  ```
2494
 
2495
+ *Returns:* *`path-object`*` <=> rhs.`*`path-object`*.
2496
 
2497
  #### Inserter <a id="fs.dir.entry.io">[[fs.dir.entry.io]]</a>
2498
 
2499
  ``` cpp
2500
  template<class charT, class traits>
 
2585
  `directory_entry` element returned by `operator*()`.
2586
  `directory_iterator` member functions shall not directly or indirectly
2587
  call any `directory_entry` `refresh` function.
2588
 
2589
  [*Note 2*: The exact mechanism for storing cached attribute values is
2590
+ not exposed to users. *end note*]
 
 
2591
 
2592
  [*Note 3*: A path obtained by dereferencing a directory iterator might
2593
  not actually exist; it could be a symbolic link to a non-existent file.
2594
  Recursively walking directory trees for purposes of removing and
2595
  renaming entries might invalidate symbolic links that are being
 
2921
  void disable_recursion_pending();
2922
  ```
2923
 
2924
  *Ensures:* `recursion_pending() == false`.
2925
 
2926
+ [*Note 4*: `disable_recursion_pending()` is used to prevent unwanted
2927
  recursion into a directory. — *end note*]
2928
 
2929
  #### Non-member functions <a id="fs.rec.dir.itr.nonmembers">[[fs.rec.dir.itr.nonmembers]]</a>
2930
 
2931
  These functions enable use of `recursive_directory_iterator` with
 
3051
  Effects are then as follows:
3052
 
3053
  - If `f.type()` or `t.type()` is an implementation-defined file
3054
  type [[fs.enum.file.type]], then the effects are
3055
  *implementation-defined*.
3056
+ - Otherwise, an error is reported as specified in  [[fs.err.report]] if
3057
  - `exists(f)` is `false`, or
3058
  - `equivalent(from, to)` is `true`, or
3059
  - `is_other(f) || is_other(t)` is `true`, or
3060
  - `is_directory(f) && is_regular_file(t)` is `true`.
3061
  - Otherwise, if `is_symlink(f)`, then:
 
3118
 
3119
  [*Example 1*:
3120
 
3121
  Given this directory structure:
3122
 
3123
+ ``` text
3124
  /dir1
3125
  file1
3126
  file2
3127
  dir2
3128
  file3
3129
  ```
3130
 
3131
  Calling `copy("/dir1", "/dir3")` would result in:
3132
 
3133
+ ``` text
3134
  /dir1
3135
  file1
3136
  file2
3137
  dir2
3138
  file3
 
3142
  ```
3143
 
3144
  Alternatively, calling `copy("/dir1", "/dir3", copy_options::recursive)`
3145
  would result in:
3146
 
3147
+ ``` text
3148
  /dir1
3149
  file1
3150
  file2
3151
  dir2
3152
  file3
 
3180
  *Preconditions:* At most one element from each option
3181
  group [[fs.enum.copy.opts]] is set in `options`.
3182
 
3183
  *Effects:* As follows:
3184
 
3185
+ - Report an error as specified in  [[fs.err.report]] if
3186
  - `is_regular_file(from)` is `false`, or
3187
  - `exists(to)` is `true` and `is_regular_file(to)` is `false`, or
3188
  - `exists(to)` is `true` and `equivalent(from, to)` is `true`, or
3189
  - `exists(to)` is `true` and
3190
  ``` cpp
3191
  (options & (copy_options::skip_existing |
3192
  copy_options::overwrite_existing |
3193
  copy_options::update_existing)) == copy_options::none
3194
  ```
3195
  - Otherwise, copy the contents and attributes of the file `from`
3196
+ resolves to, to the file `to` resolves to, if
3197
  - `exists(to)` is `false`, or
3198
  - `(options & copy_options::overwrite_existing) != copy_options::none`,
3199
  or
3200
  - `(options & copy_options::update_existing) `` `` != copy_options::none`
3201
  and `from` is more recent than `to`, determined as if by use of the
 
3230
  ``` cpp
3231
  bool filesystem::create_directories(const path& p);
3232
  bool filesystem::create_directories(const path& p, error_code& ec);
3233
  ```
3234
 
3235
+ *Effects:* Calls `create_directory` for each element of `p` that does
3236
  not exist.
3237
 
3238
  *Returns:* `true` if a new directory was created for the directory `p`
3239
  resolves to, otherwise `false`.
3240
 
 
3287
  void filesystem::create_directory_symlink(const path& to, const path& new_symlink);
3288
  void filesystem::create_directory_symlink(const path& to, const path& new_symlink,
3289
  error_code& ec) noexcept;
3290
  ```
3291
 
3292
+ *Effects:* Establishes the postcondition, as if by POSIX `symlink`.
3293
 
3294
  *Ensures:* `new_symlink` resolves to a symbolic link file that contains
3295
  an unspecified representation of `to`.
3296
 
3297
  *Throws:* As specified in  [[fs.err.report]].
3298
 
3299
  [*Note 1*: Some operating systems require symlink creation to identify
3300
+ that the link is to a directory. Thus, `create_symlink` (instead of
3301
+ `create_directory_symlink`) cannot be used reliably to create directory
3302
+ symlinks. — *end note*]
3303
 
3304
  [*Note 2*: Some operating systems do not support symbolic links at all
3305
  or support them only for regular files. Some file systems (such as the
3306
  FAT file system) do not support symbolic links regardless of the
3307
  operating system. — *end note*]
 
3312
  void filesystem::create_hard_link(const path& to, const path& new_hard_link);
3313
  void filesystem::create_hard_link(const path& to, const path& new_hard_link,
3314
  error_code& ec) noexcept;
3315
  ```
3316
 
3317
+ *Effects:* Establishes the postcondition, as if by POSIX `link`.
3318
 
3319
  *Ensures:*
3320
 
3321
  - `exists(to) && exists(new_hard_link) && equivalent(to, new_hard_link)`
3322
  - The contents of the file or directory `to` resolves to are unchanged.
 
3335
  void filesystem::create_symlink(const path& to, const path& new_symlink);
3336
  void filesystem::create_symlink(const path& to, const path& new_symlink,
3337
  error_code& ec) noexcept;
3338
  ```
3339
 
3340
+ *Effects:* Establishes the postcondition, as if by POSIX `symlink`.
3341
 
3342
  *Ensures:* `new_symlink` resolves to a symbolic link file that contains
3343
  an unspecified representation of `to`.
3344
 
3345
  *Throws:* As specified in  [[fs.err.report]].
 
3355
  path filesystem::current_path();
3356
  path filesystem::current_path(error_code& ec);
3357
  ```
3358
 
3359
  *Returns:* The absolute path of the current working directory, whose
3360
+ pathname in the native format is obtained as if by POSIX `getcwd`. The
3361
  signature with argument `ec` returns `path()` if an error occurs.
3362
 
3363
  *Throws:* As specified in  [[fs.err.report]].
3364
 
3365
  *Remarks:* The current working directory is the directory, associated
3366
  with the process, that is used as the starting location in pathname
3367
  resolution for relative paths.
3368
 
3369
+ [*Note 1*: The current path as returned by many operating systems is a
 
 
 
 
3370
  dangerous global variable and can be changed unexpectedly by third-party
3371
  or system library functions, or by another thread. — *end note*]
3372
 
3373
  ``` cpp
3374
  void filesystem::current_path(const path& p);
3375
  void filesystem::current_path(const path& p, error_code& ec) noexcept;
3376
  ```
3377
 
3378
+ *Effects:* Establishes the postcondition, as if by POSIX `chdir`.
3379
 
3380
  *Ensures:* `equivalent(p, current_path())`.
3381
 
3382
  *Throws:* As specified in  [[fs.err.report]].
3383
 
3384
+ [*Note 2*: The current path for many operating systems is a dangerous
3385
  global state and can be changed unexpectedly by third-party or system
3386
  library functions, or by another thread. — *end note*]
3387
 
3388
  #### Equivalent <a id="fs.op.equivalent">[[fs.op.equivalent]]</a>
3389
 
 
3394
 
3395
  Two paths are considered to resolve to the same file system entity if
3396
  two candidate entities reside on the same device at the same location.
3397
 
3398
  [*Note 1*: On POSIX platforms, this is determined as if by the values
3399
+ of the POSIX `stat` class, obtained as if by `stat` for the two paths,
3400
  having equal `st_dev` values and equal `st_ino` values. — *end note*]
3401
 
3402
  *Returns:* `true`, if `p1` and `p2` resolve to the same file system
3403
  entity, otherwise `false`. The signature with argument `ec` returns
3404
  `false` if an error occurs.
 
3442
 
3443
  *Returns:*
3444
 
3445
  - If `is_regular_file(p)`, the size in bytes of the file `p` resolves
3446
  to, determined as if by the value of the POSIX `stat` class member
3447
+ `st_size` obtained as if by POSIX `stat`.
3448
  - Otherwise, the result is *implementation-defined*.
3449
 
3450
  The signature with argument `ec` returns `static_cast<uintmax_t>(-1)` if
3451
  an error occurs.
3452
 
 
3663
  file_time_type filesystem::last_write_time(const path& p, error_code& ec) noexcept;
3664
  ```
3665
 
3666
  *Returns:* The time of last data modification of `p`, determined as if
3667
  by the value of the POSIX `stat` class member `st_mtime` obtained as if
3668
+ by POSIX `stat`. The signature with argument `ec` returns
3669
  `file_time_type::min()` if an error occurs.
3670
 
3671
  *Throws:* As specified in  [[fs.err.report]].
3672
 
3673
  ``` cpp
 
3675
  void filesystem::last_write_time(const path& p, file_time_type new_time,
3676
  error_code& ec) noexcept;
3677
  ```
3678
 
3679
  *Effects:* Sets the time of last data modification of the file resolved
3680
+ to by `p` to `new_time`, as if by POSIX `futimens`.
3681
 
3682
  *Throws:* As specified in  [[fs.err.report]].
3683
 
3684
  [*Note 1*: A postcondition of `last_write_time(p) == new_time` is not
3685
  specified because it does not necessarily hold for file systems with
 
3697
  `add`, or `remove` is present in `opts`.
3698
 
3699
  *Effects:* Applies the action specified by `opts` to the file `p`
3700
  resolves to, or to file `p` itself if `p` is a symbolic link and
3701
  `perm_options::nofollow` is set in `opts`. The action is applied as if
3702
+ by POSIX `fchmodat`.
3703
 
3704
  [*Note 1*: Conceptually permissions are viewed as bits, but the actual
3705
  implementation can use some other mechanism. — *end note*]
3706
 
3707
  *Throws:* As specified in  [[fs.err.report]].
 
3794
  bool filesystem::remove(const path& p);
3795
  bool filesystem::remove(const path& p, error_code& ec) noexcept;
3796
  ```
3797
 
3798
  *Effects:* If `exists(symlink_status(p, ec))`, the file `p` is removed
3799
+ as if by POSIX `remove`.
3800
 
3801
  [*Note 1*: A symbolic link is itself removed, rather than the file it
3802
  resolves to. — *end note*]
3803
 
3804
  *Ensures:* `exists(symlink_status(p))` is `false`.
3805
 
3806
+ *Returns:* `true` if a file `p` has been removed and `false` otherwise.
3807
+
3808
+ [*Note 2*: Absence of a file `p` is not an error. — *end note*]
3809
 
3810
  *Throws:* As specified in  [[fs.err.report]].
3811
 
3812
  #### Remove all <a id="fs.op.remove.all">[[fs.op.remove.all]]</a>
3813
 
 
3815
  uintmax_t filesystem::remove_all(const path& p);
3816
  uintmax_t filesystem::remove_all(const path& p, error_code& ec);
3817
  ```
3818
 
3819
  *Effects:* Recursively deletes the contents of `p` if it exists, then
3820
+ deletes file `p` itself, as if by POSIX `remove`.
3821
 
3822
  [*Note 1*: A symbolic link is itself removed, rather than the file it
3823
  resolves to. — *end note*]
3824
 
3825
  *Ensures:* `exists(symlink_status(p))` is `false`.
 
3834
  ``` cpp
3835
  void filesystem::rename(const path& old_p, const path& new_p);
3836
  void filesystem::rename(const path& old_p, const path& new_p, error_code& ec) noexcept;
3837
  ```
3838
 
3839
+ *Effects:* Renames `old_p` to `new_p`, as if by POSIX `rename`.
3840
 
3841
  [*Note 1*:
3842
 
3843
  - If `old_p` and `new_p` resolve to the same existing file, no action is
3844
  taken.
 
3861
  void filesystem::resize_file(const path& p, uintmax_t new_size);
3862
  void filesystem::resize_file(const path& p, uintmax_t new_size, error_code& ec) noexcept;
3863
  ```
3864
 
3865
  *Effects:* Causes the size that would be returned by `file_size(p)` to
3866
+ be equal to `new_size`, as if by POSIX `truncate`.
3867
 
3868
  *Throws:* As specified in  [[fs.err.report]].
3869
 
3870
  #### Space <a id="fs.op.space">[[fs.op.space]]</a>
3871
 
 
3894
 
3895
  ``` cpp
3896
  file_status filesystem::status(const path& p);
3897
  ```
3898
 
3899
+ *Effects:* As if by:
3900
 
3901
  ``` cpp
3902
  error_code ec;
3903
  file_status result = status(p, ec);
3904
  if (result.type() == file_type::none)
 
3917
  ``` cpp
3918
  file_status filesystem::status(const path& p, error_code& ec) noexcept;
3919
  ```
3920
 
3921
  *Effects:* If possible, determines the attributes of the file `p`
3922
+ resolves to, as if by using POSIX `stat` to obtain a POSIX
3923
  `struct stat`. If, during attribute determination, the underlying file
3924
  system API reports an error, sets `ec` to indicate the specific error
3925
  reported. Otherwise, `ec.clear()`.
3926
 
3927
  [*Note 2*: This allows users to inspect the specifics of underlying API
3928
+ errors even when the value returned by `status` is not
3929
  `file_status(file_type::none)`. — *end note*]
3930
 
3931
  Let `prms` denote the result of `(m & perms::mask)`, where `m` is
3932
  determined as if by converting the `st_mode` member of the obtained
3933
  `struct stat` to the type `perms`.
 
3990
  ``` cpp
3991
  file_status filesystem::symlink_status(const path& p);
3992
  file_status filesystem::symlink_status(const path& p, error_code& ec) noexcept;
3993
  ```
3994
 
3995
+ *Effects:* Same as `status`, above, except that the attributes of `p`
3996
+ are determined as if by using POSIX `lstat` to obtain a POSIX
3997
  `struct stat`.
3998
 
3999
  Let `prms` denote the result of `(m & perms::mask)`, where `m` is
4000
  determined as if by converting the `st_mode` member of the obtained
4001
  `struct stat` to the type `perms`.
4002
 
4003
+ *Returns:* Same as `status`, above, except that if the attributes
4004
  indicate a symbolic link, as if by POSIX `S_ISLNK`, returns
4005
  `file_status(file_type::symlink, prms)`. The signature with argument
4006
  `ec` returns `file_status(file_type::none)` if an error occurs.
4007
 
4008
  *Throws:* As specified in  [[fs.err.report]].
 
4040
  path filesystem::weakly_canonical(const path& p, error_code& ec);
4041
  ```
4042
 
4043
  *Effects:* Using `status(p)` or `status(p, ec)`, respectively, to
4044
  determine existence, return a path composed by `operator/=` from the
4045
+ result of calling `canonical` with a path argument composed of the
4046
  leading elements of `p` that exist, if any, followed by the elements of
4047
+ `p` that do not exist, if any. For the first form, `canonical` is called
4048
+ without an `error_code` argument. For the second form, `canonical` is
4049
+ called with `ec` as an `error_code` argument, and `path()` is returned
4050
+ at the first error occurrence, if any.
4051
 
4052
  *Ensures:* The returned path is in normal form [[fs.path.generic]].
4053
 
4054
  *Returns:* `p` with symlinks resolved and the result
4055
  normalized [[fs.path.generic]].