| use std::fs::{File, OpenOptions}; |
| use std::os::unix::prelude::*; |
| use std::path::Path; |
| use std::{io, mem}; |
| |
| #[derive(Debug)] |
| pub struct Lock { |
| file: File, |
| } |
| |
| impl Lock { |
| pub fn new(p: &Path, wait: bool, create: bool, exclusive: bool) -> io::Result<Lock> { |
| let file = OpenOptions::new() |
| .read(true) |
| .write(true) |
| .create(create) |
| .mode(libc::S_IRWXU as u32) |
| .open(p)?; |
| |
| let lock_type = if exclusive { libc::F_WRLCK } else { libc::F_RDLCK }; |
| |
| let mut flock: libc::flock = unsafe { mem::zeroed() }; |
| #[cfg(not(all(target_os = "hurd", target_arch = "x86")))] |
| { |
| flock.l_type = lock_type as libc::c_short; |
| flock.l_whence = libc::SEEK_SET as libc::c_short; |
| } |
| #[cfg(all(target_os = "hurd", target_arch = "x86"))] |
| { |
| flock.l_type = lock_type as libc::c_int; |
| flock.l_whence = libc::SEEK_SET as libc::c_int; |
| } |
| flock.l_start = 0; |
| flock.l_len = 0; |
| |
| let cmd = if wait { libc::F_SETLKW } else { libc::F_SETLK }; |
| let ret = unsafe { libc::fcntl(file.as_raw_fd(), cmd, &flock) }; |
| if ret == -1 { Err(io::Error::last_os_error()) } else { Ok(Lock { file }) } |
| } |
| |
| pub fn error_unsupported(err: &io::Error) -> bool { |
| matches!(err.raw_os_error(), Some(libc::ENOTSUP) | Some(libc::ENOSYS)) |
| } |
| } |
| |
| impl Drop for Lock { |
| fn drop(&mut self) { |
| let mut flock: libc::flock = unsafe { mem::zeroed() }; |
| #[cfg(not(all(target_os = "hurd", target_arch = "x86")))] |
| { |
| flock.l_type = libc::F_UNLCK as libc::c_short; |
| flock.l_whence = libc::SEEK_SET as libc::c_short; |
| } |
| #[cfg(all(target_os = "hurd", target_arch = "x86"))] |
| { |
| flock.l_type = libc::F_UNLCK as libc::c_int; |
| flock.l_whence = libc::SEEK_SET as libc::c_int; |
| } |
| flock.l_start = 0; |
| flock.l_len = 0; |
| |
| unsafe { |
| libc::fcntl(self.file.as_raw_fd(), libc::F_SETLK, &flock); |
| } |
| } |
| } |