possum/sys/flock/
mod.rs

1use super::*;
2
3cfg_if! {
4    if #[cfg(windows)] {
5        mod windows;
6        pub use self::windows::*;
7    } else if #[cfg(target_os = "freebsd")] {
8        mod freebsd;
9    } else {
10        mod ofd;
11    }
12}
13
14cfg_if! {
15    if #[cfg(unix)] {
16        mod unix;
17        pub use self::unix::*;
18    }
19}
20
21pub trait FileLocking {
22    /// Returns Ok(false) if the lock could not be moved (you should assume the file is busted at
23    /// this point).
24    fn trim_exclusive_lock_left(&self, old_left: u64, new_left: u64) -> io::Result<bool>;
25    fn lock_segment(&self, arg: FlockArg, len: Option<u64>, offset: u64) -> io::Result<bool>;
26    /// Locks a segment that spans the maximum possible range of offsets.
27    fn lock_max_segment(&self, arg: FlockArg) -> io::Result<bool> {
28        self.lock_segment(arg, None, 0)
29    }
30}
31
32#[cfg(test)]
33mod tests {
34    use tempfile::NamedTempFile;
35
36    use super::*;
37    use crate::test;
38
39    #[test]
40    #[cfg(not(miri))]
41    fn open_locked_file() -> anyhow::Result<()> {
42        let file1_named = NamedTempFile::new()?;
43        let file1_ref = file1_named.as_file();
44        let file_reopen = file1_named.reopen()?;
45        assert!(file1_ref.lock_segment(LockExclusiveNonblock, None, 1)?);
46        // Trying to exclusively lock from another file handle fails immediately.
47        assert!(!file_reopen.lock_segment(LockExclusiveNonblock, None, 2)?);
48        let file_reader = OpenOptions::new().read(true).open(file1_named.path())?;
49        // This won't work with flock, because the entire file is exclusively locked, not just a
50        // different segment.
51        if !flocking() {
52            assert!(file_reader.lock_segment(LockSharedNonblock, Some(1), 0,)?);
53        }
54        Ok(())
55    }
56}