rustdoc/html/render/write_shared/
flock.rs1use std::fs::{File, OpenOptions};
2use std::io;
3#[cfg(unix)]
4use std::os::unix::prelude::*;
5use std::path::Path;
6
7#[derive(Debug)]
8pub(super) enum Lock {
9 #[doc(hidden)]
11 FdLocked { _file: File },
12 #[doc(hidden)]
16 #[cfg(unix)]
17 FcntlFallback { _lock: FcntlLock },
18}
19
20impl Lock {
21 pub(super) fn new(p: &Path) -> io::Result<Lock> {
22 let mut open_options = OpenOptions::new();
23 open_options.read(true).write(true).create(true);
24 #[cfg(unix)]
25 {
26 use std::os::unix::fs::OpenOptionsExt;
27 open_options.mode(0o600);
28 }
29
30 let file = open_options.open(p)?;
31
32 match file.lock() {
33 Ok(()) => Ok(Lock::FdLocked { _file: file }),
34 #[cfg(unix)]
35 Err(err) if matches!(err.kind(), io::ErrorKind::Unsupported) => {
36 Ok(Lock::FcntlFallback { _lock: FcntlLock::new(file)? })
37 }
38 Err(err) => Err(err),
39 }
40 }
41}
42
43#[derive(Debug)]
44#[cfg(unix)]
45pub(super) struct FcntlLock {
46 file: File,
47}
48
49#[cfg(unix)]
50impl FcntlLock {
51 fn new(file: File) -> io::Result<FcntlLock> {
52 let mut flock: libc::flock = unsafe { std::mem::zeroed() };
53 #[cfg(not(all(target_os = "hurd", target_arch = "x86")))]
54 {
55 flock.l_type = libc::F_WRLCK as libc::c_short;
56 flock.l_whence = libc::SEEK_SET as libc::c_short;
57 }
58 #[cfg(all(target_os = "hurd", target_arch = "x86"))]
59 {
60 flock.l_type = libc::F_WRLCK as libc::c_int;
61 flock.l_whence = libc::SEEK_SET as libc::c_int;
62 }
63 flock.l_start = 0;
64 flock.l_len = 0;
65
66 let ret = unsafe { libc::fcntl(file.as_raw_fd(), libc::F_SETLKW, &flock) };
67 if ret == -1 { Err(io::Error::last_os_error()) } else { Ok(FcntlLock { file }) }
68 }
69}
70
71#[cfg(unix)]
72impl Drop for FcntlLock {
73 fn drop(&mut self) {
74 let mut flock: libc::flock = unsafe { std::mem::zeroed() };
75 #[cfg(not(all(target_os = "hurd", target_arch = "x86")))]
76 {
77 flock.l_type = libc::F_UNLCK as libc::c_short;
78 flock.l_whence = libc::SEEK_SET as libc::c_short;
79 }
80 #[cfg(all(target_os = "hurd", target_arch = "x86"))]
81 {
82 flock.l_type = libc::F_UNLCK as libc::c_int;
83 flock.l_whence = libc::SEEK_SET as libc::c_int;
84 }
85 flock.l_start = 0;
86 flock.l_len = 0;
87
88 unsafe {
89 libc::fcntl(self.file.as_raw_fd(), libc::F_SETLK, &flock);
90 }
91 }
92}