Skip to content

Commit fdd9da0

Browse files
authored
Merge pull request #31 from lucab/ups/syncfs
OpenatDirExt: add syncfs helper
2 parents dbed6cd + 41e813b commit fdd9da0

File tree

2 files changed

+28
-3
lines changed

2 files changed

+28
-3
lines changed

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ documentation = "http://docs.rs/openat-ext"
1515

1616
[dependencies]
1717
openat = "0.1.15"
18-
libc = "0.2.34"
18+
libc = "^0.2.94"
1919
nix = ">= 0.18, < 0.21"
2020
rand = "0.8.3"
2121

src/lib.rs

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,7 @@
1414
1515
#![deny(unused_results)]
1616
#![deny(missing_docs)]
17-
// We're just a wrapper around openat, shouldn't have any unsafe here.
18-
#![forbid(unsafe_code)]
17+
#![deny(unsafe_code)]
1918

2019
const TEMPFILE_ATTEMPTS: u32 = 100;
2120

@@ -78,6 +77,9 @@ pub trait OpenatDirExt {
7877
/// Remove all content at the target path, returns `true` if something existed there.
7978
fn remove_all<P: openat::AsPath>(&self, p: P) -> io::Result<bool>;
8079

80+
/// Synchronize to disk the filesystem containing this directory.
81+
fn syncfs(&self) -> io::Result<()>;
82+
8183
/// Copy a regular file. The semantics here are intended to match `std::fs::copy()`.
8284
/// If the target exists, it will be overwritten. The mode bits (permissions) will match, but
8385
/// owner/group will be derived from the current process. Extended attributes are not
@@ -292,6 +294,20 @@ impl OpenatDirExt for openat::Dir {
292294
impl_remove_all(self, p)
293295
}
294296

297+
#[allow(unsafe_code)]
298+
fn syncfs(&self) -> io::Result<()> {
299+
// syncfs(2) does not work with `O_PATH` FDs, so `self` cannot
300+
// be directly used. Thus we have to materialize a FD for the
301+
// directory first.
302+
let dirfd = self.open_file(".")?;
303+
let ret = unsafe { libc::syncfs(dirfd.as_raw_fd()) };
304+
if ret == 0 {
305+
Ok(())
306+
} else {
307+
Err(std::io::Error::last_os_error())
308+
}
309+
}
310+
295311
fn new_file_writer<'a>(&'a self, mode: libc::mode_t) -> io::Result<FileWriter> {
296312
let (tmpf, name) = if let Some(tmpf) = self.new_unnamed_file(mode).ok() {
297313
(tmpf, None)
@@ -753,6 +769,15 @@ mod tests {
753769
Ok(fallback)
754770
}
755771

772+
#[test]
773+
fn test_syncfs() {
774+
let td = tempfile::tempdir().unwrap();
775+
let d = openat::Dir::open(td.path()).unwrap();
776+
d.ensure_dir_all("foo/bar", 0o755).unwrap();
777+
d.syncfs().unwrap();
778+
assert_eq!(d.exists("foo/bar").unwrap(), true);
779+
}
780+
756781
#[test]
757782
fn copy_fallback() -> Result<()> {
758783
use std::io::Read;

0 commit comments

Comments
 (0)