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>(path: P) -> io::Result {

`

``

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>(&self, path: P) -> io::Result {

`

``

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

`///

`