Auto merge of #146341 - Qelxiros:dirfd-minimum, r= · rust-lang/rust@b34b92d (original) (raw)
`@@ -153,6 +153,43 @@ pub enum TryLockError {
`
153
153
`WouldBlock,
`
154
154
`}
`
155
155
``
``
156
`+
/// An object providing access to a directory on the filesystem.
`
``
157
`+
///
`
``
158
`+
/// Directories are automatically closed when they go out of scope. Errors detected
`
``
159
`` +
/// on closing are ignored by the implementation of Drop.
``
``
160
`+
///
`
``
161
`+
/// # Platform-specific behavior
`
``
162
`+
///
`
``
163
`+
/// On supported systems (including Windows and some UNIX-based OSes), this function acquires a
`
``
164
`` +
/// handle/file descriptor for the directory. This allows functions like [Dir::open_file] to
``
``
165
`+
/// avoid [TOCTOU] errors when the directory itself is being moved.
`
``
166
`+
///
`
``
167
`` +
/// On other systems, it stores an absolute path (see [canonicalize()]). In the latter case, no
``
``
168
`+
/// [TOCTOU] guarantees are made.
`
``
169
`+
///
`
``
170
`+
/// # Examples
`
``
171
`+
///
`
``
172
`+
/// Opens a directory and then a file inside it.
`
``
173
`+
///
`
``
174
/// ```no_run
``
175
`+
/// #![feature(dirfd)]
`
``
176
`+
/// use std::{fs::Dir, io};
`
``
177
`+
///
`
``
178
`+
/// fn main() -> std::io::Result<()> {
`
``
179
`+
/// let dir = Dir::open("foo")?;
`
``
180
`+
/// let mut file = dir.open_file("bar.txt")?;
`
``
181
`+
/// let contents = io::read_to_string(file)?;
`
``
182
`+
/// assert_eq!(contents, "Hello, world!");
`
``
183
`+
/// Ok(())
`
``
184
`+
/// }
`
``
185
/// ```
``
186
`+
///
`
``
187
`+
/// [TOCTOU]: self#time-of-check-to-time-of-use-toctou
`
``
188
`+
#[unstable(feature = "dirfd", issue = "120426")]
`
``
189
`+
pub struct Dir {
`
``
190
`+
inner: fs_imp::Dir,
`
``
191
`+
}
`
``
192
+
156
193
`/// Metadata information about a file.
`
157
194
`///
`
158
195
`` /// This structure is returned from the [metadata] or
``
`@@ -1555,6 +1592,87 @@ impl Seek for Arc {
`
1555
1592
`}
`
1556
1593
`}
`
1557
1594
``
``
1595
`+
impl Dir {
`
``
1596
`` +
/// Attempts to open a directory at path in read-only mode.
``
``
1597
`+
///
`
``
1598
`+
/// # Errors
`
``
1599
`+
///
`
``
1600
`` +
/// This function will return an error if path does not point to an existing directory.
``
``
1601
`` +
/// Other errors may also be returned according to [OpenOptions::open].
``
``
1602
`+
///
`
``
1603
`+
/// # Examples
`
``
1604
`+
///
`
``
1605
/// ```no_run
``
1606
`+
/// #![feature(dirfd)]
`
``
1607
`+
/// use std::{fs::Dir, io};
`
``
1608
`+
///
`
``
1609
`+
/// fn main() -> std::io::Result<()> {
`
``
1610
`+
/// let dir = Dir::open("foo")?;
`
``
1611
`+
/// let mut f = dir.open_file("bar.txt")?;
`
``
1612
`+
/// let contents = io::read_to_string(f)?;
`
``
1613
`+
/// assert_eq!(contents, "Hello, world!");
`
``
1614
`+
/// Ok(())
`
``
1615
`+
/// }
`
``
1616
/// ```
``
1617
`+
#[unstable(feature = "dirfd", issue = "120426")]
`
``
1618
`+
pub fn open<P: AsRef
`
``
1619
`+
fs_imp::Dir::open(path.as_ref(), &OpenOptions::new().read(true).0)
`
``
1620
`+
.map(|inner| Self { inner })
`
``
1621
`+
}
`
``
1622
+
``
1623
`+
/// Attempts to open a file in read-only mode relative to this directory.
`
``
1624
`+
///
`
``
1625
`+
/// # Errors
`
``
1626
`+
///
`
``
1627
`` +
/// This function will return an error if path does not point to an existing file.
``
``
1628
`` +
/// Other errors may also be returned according to [OpenOptions::open].
``
``
1629
`+
///
`
``
1630
`+
/// # Examples
`
``
1631
`+
///
`
``
1632
/// ```no_run
``
1633
`+
/// #![feature(dirfd)]
`
``
1634
`+
/// use std::{fs::Dir, io};
`
``
1635
`+
///
`
``
1636
`+
/// fn main() -> std::io::Result<()> {
`
``
1637
`+
/// let dir = Dir::open("foo")?;
`
``
1638
`+
/// let mut f = dir.open_file("bar.txt")?;
`
``
1639
`+
/// let contents = io::read_to_string(f)?;
`
``
1640
`+
/// assert_eq!(contents, "Hello, world!");
`
``
1641
`+
/// Ok(())
`
``
1642
`+
/// }
`
``
1643
/// ```
``
1644
`+
#[unstable(feature = "dirfd", issue = "120426")]
`
``
1645
`+
pub fn open_file<P: AsRef
`
``
1646
`+
self.inner
`
``
1647
`+
.open_file(path.as_ref(), &OpenOptions::new().read(true).0)
`
``
1648
`+
.map(|f| File { inner: f })
`
``
1649
`+
}
`
``
1650
`+
}
`
``
1651
+
``
1652
`+
impl AsInner<fs_imp::Dir> for Dir {
`
``
1653
`+
#[inline]
`
``
1654
`+
fn as_inner(&self) -> &fs_imp::Dir {
`
``
1655
`+
&self.inner
`
``
1656
`+
}
`
``
1657
`+
}
`
``
1658
`+
impl FromInner<fs_imp::Dir> for Dir {
`
``
1659
`+
fn from_inner(f: fs_imp::Dir) -> Dir {
`
``
1660
`+
Dir { inner: f }
`
``
1661
`+
}
`
``
1662
`+
}
`
``
1663
`+
impl IntoInner<fs_imp::Dir> for Dir {
`
``
1664
`+
fn into_inner(self) -> fs_imp::Dir {
`
``
1665
`+
self.inner
`
``
1666
`+
}
`
``
1667
`+
}
`
``
1668
+
``
1669
`+
#[unstable(feature = "dirfd", issue = "120426")]
`
``
1670
`+
impl fmt::Debug for Dir {
`
``
1671
`+
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
`
``
1672
`+
self.inner.fmt(f)
`
``
1673
`+
}
`
``
1674
`+
}
`
``
1675
+
1558
1676
`impl OpenOptions {
`
1559
1677
`/// Creates a blank new set of options ready for configuration.
`
1560
1678
`///
`