1//! Simple file-locking apis for each OS.
2//!
3//! This is not meant to be in the standard library, it does nothing with
4//! green/native threading. This is just a bare-bones enough solution for
5//! librustdoc, it is not production quality at all.
67use std::fs::{File, OpenOptions};
8use std::io;
9use std::path::Path;
1011#[derive(#[automatically_derived]
impl ::core::fmt::Debug for Lock {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
match self {
Lock::FdLocked { _file: __self_0 } =>
::core::fmt::Formatter::debug_struct_field1_finish(f,
"FdLocked", "_file", &__self_0),
Lock::Fallback(__self_0) =>
::core::fmt::Formatter::debug_tuple_field1_finish(f,
"Fallback", &__self_0),
}
}
}Debug)]
12pub enum Lock {
13/// A well behaved lock scoped to a single fd/handle and unlocked when closing it.
14#[doc(hidden)]
15FdLocked { _file: File },
16/// A fallback implementation which may for example be scoped to an entire process,
17 /// like legacy `fcntl(F_SETLK)` on Unix. This should only be used when `flock()`
18 /// or equivalent sane locking mechanism is unsupported by the OS.
19#[doc(hidden)]
20Fallback(fallback::Lock),
21}
2223impl Lock {
24pub fn new(p: &Path, wait: bool, create: bool, exclusive: bool) -> io::Result<Lock> {
25let mut open_options = OpenOptions::new();
26open_options.read(true).write(true).create(create);
27#[cfg(unix)]
28{
29use std::os::unix::fs::OpenOptionsExt;
30open_options.mode(0o600);
31 }
3233let file = open_options.open(p)?;
3435let res = match (wait, exclusive) {
36 (true, true) => file.lock(),
37 (true, false) => file.lock_shared(),
38 (false, true) => file.try_lock().map_err(io::Error::from),
39 (false, false) => file.try_lock_shared().map_err(io::Error::from),
40 };
4142match res {
43Ok(()) => Ok(Lock::FdLocked { _file: file }),
44Err(err) if #[allow(non_exhaustive_omitted_patterns)] match err.kind() {
io::ErrorKind::Unsupported => true,
_ => false,
}matches!(err.kind(), io::ErrorKind::Unsupported) => {
45Ok(Lock::Fallback(fallback::Lock::new(p, wait, create, exclusive)?))
46 }
47Err(err) => Err(err),
48 }
49 }
5051pub fn error_unsupported(err: &io::Error) -> bool {
52#[cfg(windows)]
53if err.raw_os_error() == Some(windows::Win32::Foundation::ERROR_INVALID_FUNCTION.0 as i32) {
54// Not mapped to ErrorKind::Unsupported by libstd
55return true;
56 }
5758#[allow(non_exhaustive_omitted_patterns)] match err.kind() {
io::ErrorKind::Unsupported => true,
_ => false,
}matches!(err.kind(), io::ErrorKind::Unsupported)59 }
60}
6162cfg_select! {
63 unix => {
64mod unix;
65use unixas fallback;
66 }
67_ => {
68mod unsupported;
69use unsupported as fallback;
70 }
71}