summaryrefslogtreecommitdiffstats
path: root/compiler/rustc_data_structures/src/flock/unix.rs
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/rustc_data_structures/src/flock/unix.rs')
-rw-r--r--compiler/rustc_data_structures/src/flock/unix.rs51
1 files changed, 51 insertions, 0 deletions
diff --git a/compiler/rustc_data_structures/src/flock/unix.rs b/compiler/rustc_data_structures/src/flock/unix.rs
new file mode 100644
index 000000000..4e5297d58
--- /dev/null
+++ b/compiler/rustc_data_structures/src/flock/unix.rs
@@ -0,0 +1,51 @@
+use std::fs::{File, OpenOptions};
+use std::io;
+use std::mem;
+use std::os::unix::prelude::*;
+use std::path::Path;
+
+#[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() };
+ flock.l_type = lock_type as libc::c_short;
+ flock.l_whence = libc::SEEK_SET as libc::c_short;
+ 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() };
+ flock.l_type = libc::F_UNLCK as libc::c_short;
+ flock.l_whence = libc::SEEK_SET as libc::c_short;
+ flock.l_start = 0;
+ flock.l_len = 0;
+
+ unsafe {
+ libc::fcntl(self.file.as_raw_fd(), libc::F_SETLK, &flock);
+ }
+ }
+}