rustc_data_structures/flock/
unix.rs

1use std::fs::{File, OpenOptions};
2use std::os::unix::prelude::*;
3use std::path::Path;
4use std::{io, mem};
5
6#[derive(Debug)]
7pub struct Lock {
8    file: File,
9}
10
11impl Lock {
12    pub fn new(p: &Path, wait: bool, create: bool, exclusive: bool) -> io::Result<Lock> {
13        let file = OpenOptions::new()
14            .read(true)
15            .write(true)
16            .create(create)
17            .mode(libc::S_IRWXU as u32)
18            .open(p)?;
19
20        let lock_type = if exclusive { libc::F_WRLCK } else { libc::F_RDLCK };
21
22        let mut flock: libc::flock = unsafe { mem::zeroed() };
23        #[cfg(not(all(target_os = "hurd", target_arch = "x86")))]
24        {
25            flock.l_type = lock_type as libc::c_short;
26            flock.l_whence = libc::SEEK_SET as libc::c_short;
27        }
28        #[cfg(all(target_os = "hurd", target_arch = "x86"))]
29        {
30            flock.l_type = lock_type as libc::c_int;
31            flock.l_whence = libc::SEEK_SET as libc::c_int;
32        }
33        flock.l_start = 0;
34        flock.l_len = 0;
35
36        let cmd = if wait { libc::F_SETLKW } else { libc::F_SETLK };
37        let ret = unsafe { libc::fcntl(file.as_raw_fd(), cmd, &flock) };
38        if ret == -1 { Err(io::Error::last_os_error()) } else { Ok(Lock { file }) }
39    }
40
41    pub fn error_unsupported(err: &io::Error) -> bool {
42        matches!(err.raw_os_error(), Some(libc::ENOTSUP) | Some(libc::ENOSYS))
43    }
44}
45
46impl Drop for Lock {
47    fn drop(&mut self) {
48        let mut flock: libc::flock = unsafe { mem::zeroed() };
49        #[cfg(not(all(target_os = "hurd", target_arch = "x86")))]
50        {
51            flock.l_type = libc::F_UNLCK as libc::c_short;
52            flock.l_whence = libc::SEEK_SET as libc::c_short;
53        }
54        #[cfg(all(target_os = "hurd", target_arch = "x86"))]
55        {
56            flock.l_type = libc::F_UNLCK as libc::c_int;
57            flock.l_whence = libc::SEEK_SET as libc::c_int;
58        }
59        flock.l_start = 0;
60        flock.l_len = 0;
61
62        unsafe {
63            libc::fcntl(self.file.as_raw_fd(), libc::F_SETLK, &flock);
64        }
65    }
66}