Skip to content

Commit 4f3007e

Browse files
authored
Merge pull request #65 from cgwalters/dir-reopen-file
dirext: Add reopen_as_ownedfd helper
2 parents 9192399 + b1a0271 commit 4f3007e

File tree

2 files changed

+31
-0
lines changed

2 files changed

+31
-0
lines changed

src/dirext.rs

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ use std::ffi::OsStr;
1515
use std::io::Result;
1616
use std::io::{self, Write};
1717
use std::ops::Deref;
18+
use std::os::fd::OwnedFd;
1819
use std::path::Path;
1920

2021
#[cfg(feature = "fs_utf8")]
@@ -125,6 +126,14 @@ pub trait CapStdExtDirExt {
125126
perms: cap_std::fs::Permissions,
126127
) -> Result<()>;
127128

129+
/// By default, cap-std `Dir` instances are opened using `O_PATH`.
130+
/// There are some operations such as `fsync` and `fsetxattr` that
131+
/// cannot be performed on `O_PATH` file descriptors. Use this
132+
/// function to create a non-`O_PATH` copy of the directory
133+
/// file descriptor.
134+
#[cfg(unix)]
135+
fn reopen_as_ownedfd(&self) -> Result<OwnedFd>;
136+
128137
#[cfg(any(target_os = "android", target_os = "linux"))]
129138
/// Returns `Some(true)` if the target is known to be a mountpoint, or
130139
/// `Some(false)` if the target is definitively known not to be a mountpoint.
@@ -532,6 +541,19 @@ impl CapStdExtDirExt for Dir {
532541
})
533542
}
534543

544+
#[cfg(unix)]
545+
fn reopen_as_ownedfd(&self) -> Result<OwnedFd> {
546+
use rustix::fs::{Mode, OFlags};
547+
use std::os::fd::AsFd;
548+
rustix::fs::openat(
549+
self.as_fd(),
550+
".",
551+
OFlags::CLOEXEC | OFlags::DIRECTORY | OFlags::RDONLY,
552+
Mode::empty(),
553+
)
554+
.map_err(Into::into)
555+
}
556+
535557
fn is_mountpoint(&self, path: impl AsRef<Path>) -> Result<Option<bool>> {
536558
is_mountpoint_impl_statx(self, path.as_ref()).map_err(Into::into)
537559
}

tests/it/main.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -393,6 +393,15 @@ fn test_mountpoint() -> Result<()> {
393393
Ok(())
394394
}
395395

396+
#[test]
397+
#[cfg(unix)]
398+
fn test_reopen_as_ownedfd() -> Result<()> {
399+
let td = &cap_tempfile::TempDir::new(cap_std::ambient_authority())?;
400+
let fd = td.reopen_as_ownedfd()?;
401+
rustix::fs::fsync(fd)?;
402+
Ok(())
403+
}
404+
396405
#[test]
397406
#[cfg(any(target_os = "android", target_os = "linux"))]
398407
fn test_open_noxdev() -> Result<()> {

0 commit comments

Comments
 (0)