fs4/unix/
sync_impl.rs

1macro_rules! allocate_size {
2    ($file:ty) => {
3        pub fn allocated_size(file: &$file) -> std::io::Result<u64> {
4            file.metadata().map(|m| m.blocks() * 512)
5        }
6    };
7}
8
9macro_rules! allocate {
10    ($file:ty) => {
11        #[cfg(any(
12            target_os = "linux",
13            target_os = "freebsd",
14            target_os = "android",
15            target_os = "emscripten",
16            target_os = "nacl",
17            target_os = "macos",
18            target_os = "ios",
19            target_os = "watchos",
20            target_os = "tvos"
21        ))]
22        pub fn allocate(file: &$file, len: u64) -> std::io::Result<()> {
23            use rustix::{
24                fd::BorrowedFd,
25                fs::{fallocate, FallocateFlags},
26            };
27            unsafe {
28                let borrowed_fd = BorrowedFd::borrow_raw(file.as_raw_fd());
29                match fallocate(borrowed_fd, FallocateFlags::empty(), 0, len) {
30                    Ok(_) => Ok(()),
31                    Err(e) => Err(std::io::Error::from_raw_os_error(e.raw_os_error())),
32                }
33            }
34        }
35
36        #[cfg(any(
37            target_os = "aix",
38            target_os = "openbsd",
39            target_os = "netbsd",
40            target_os = "dragonfly",
41            target_os = "solaris",
42            target_os = "illumos",
43            target_os = "haiku",
44            target_os = "hurd",
45        ))]
46        pub fn allocate(file: &$file, len: u64) -> std::io::Result<()> {
47            // No file allocation API available, just set the length if necessary.
48            if len > file.metadata()?.len() as u64 {
49                file.set_len(len)
50            } else {
51                Ok(())
52            }
53        }
54    };
55}
56
57macro_rules! test_mod {
58    ($($use_stmt:item)*) => {
59        #[cfg(test)]
60        mod test {
61          extern crate tempdir;
62
63          use crate::lock_contended_error;
64
65          $(
66              $use_stmt
67          )*
68
69          /// Tests that locking a file descriptor will replace any existing locks
70          /// held on the file descriptor.
71          #[test]
72          fn lock_replace() {
73              let tempdir = tempdir::TempDir::new("fs4").unwrap();
74              let path = tempdir.path().join("fs4");
75              let file1 = fs::OpenOptions::new()
76                  .write(true)
77                  .create(true)
78                  .truncate(true)
79                  .open(&path)
80                  .unwrap();
81              let file2 = fs::OpenOptions::new()
82                  .write(true)
83                  .truncate(true)
84                  .create(true)
85                  .open(&path)
86                  .unwrap();
87
88              // Creating a shared lock will drop an exclusive lock.
89              file1.lock_exclusive().unwrap();
90              file1.lock_shared().unwrap();
91              file2.lock_shared().unwrap();
92
93              // Attempting to replace a shared lock with an exclusive lock will fail
94              // with multiple lock holders, and remove the original shared lock.
95              assert_eq!(
96                  file2.try_lock_exclusive().unwrap_err().raw_os_error(),
97                  lock_contended_error().raw_os_error()
98              );
99              file1.lock_shared().unwrap();
100          }
101        }
102    };
103}
104
105cfg_sync! {
106    pub(crate) mod std_impl;
107}
108
109cfg_fs_err2! {
110    pub(crate) mod fs_err2_impl;
111}
112
113cfg_fs_err3! {
114    pub(crate) mod fs_err3_impl;
115}