1 //! Simple file-locking apis for each OS.
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.
7 #![allow(non_camel_case_types)]
8 #![allow(nonstandard_style)]
15 use std::ffi::{CString, OsStr};
17 use std::os::unix::prelude::*;
30 let os: &OsStr = p.as_ref();
31 let buf = CString::new(os.as_bytes()).unwrap();
32 let open_flags = if create {
33 libc::O_RDWR | libc::O_CREAT
39 libc::open(buf.as_ptr(), open_flags,
40 libc::S_IRWXU as libc::c_int)
44 return Err(io::Error::last_os_error());
47 let lock_type = if exclusive {
53 let mut flock: libc::flock = unsafe { mem::zeroed() };
54 flock.l_type = lock_type as libc::c_short;
55 flock.l_whence = libc::SEEK_SET as libc::c_short;
59 let cmd = if wait { libc::F_SETLKW } else { libc::F_SETLK };
61 libc::fcntl(fd, cmd, &flock)
64 let err = io::Error::last_os_error();
65 unsafe { libc::close(fd); }
75 let mut flock: libc::flock = unsafe { mem::zeroed() };
76 flock.l_type = libc::F_UNLCK as libc::c_short;
77 flock.l_whence = libc::SEEK_SET as libc::c_short;
82 libc::fcntl(self.fd, libc::F_SETLK, &flock);
87 } else if #[cfg(windows)] {
89 use std::os::windows::prelude::*;
90 use std::fs::{File, OpenOptions};
92 use winapi::um::minwinbase::{OVERLAPPED, LOCKFILE_FAIL_IMMEDIATELY, LOCKFILE_EXCLUSIVE_LOCK};
93 use winapi::um::fileapi::LockFileEx;
94 use winapi::um::winnt::{FILE_SHARE_DELETE, FILE_SHARE_READ, FILE_SHARE_WRITE};
106 -> io::Result<Lock> {
107 assert!(p.parent().unwrap().exists(),
108 "Parent directory of lock-file must exist: {}",
111 let share_mode = FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE;
113 let mut open_options = OpenOptions::new();
114 open_options.read(true)
115 .share_mode(share_mode);
118 open_options.create(true)
122 debug!("attempting to open lock file `{}`", p.display());
123 let file = match open_options.open(p) {
125 debug!("lock file opened successfully");
129 debug!("error opening lock file: {}", err);
135 let mut overlapped: OVERLAPPED = mem::zeroed();
139 dwFlags |= LOCKFILE_FAIL_IMMEDIATELY;
143 dwFlags |= LOCKFILE_EXCLUSIVE_LOCK;
146 debug!("attempting to acquire lock on lock file `{}`",
148 LockFileEx(file.as_raw_handle(),
156 let err = io::Error::last_os_error();
157 debug!("failed acquiring file lock: {}", err);
160 debug!("successfully acquired lock");
161 Ok(Lock { _file: file })
166 // Note that we don't need a Drop impl on the Windows: The file is unlocked
167 // automatically when it's closed.
173 pub fn new(_p: &Path, _wait: bool, _create: bool, _exclusive: bool)
176 let msg = "file locks not supported on this platform";
177 Err(io::Error::new(io::ErrorKind::Other, msg))