rustc_data_structures/flock/
unix.rs1use 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}