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::os::windows::raw::HANDLE;
91 use std::fs::{File, OpenOptions};
92 use std::os::raw::{c_ulong, c_int};
96 type ULONG_PTR = usize;
98 type LPOVERLAPPED = *mut OVERLAPPED;
99 const LOCKFILE_EXCLUSIVE_LOCK: DWORD = 0x0000_0002;
100 const LOCKFILE_FAIL_IMMEDIATELY: DWORD = 0x0000_0001;
102 const FILE_SHARE_DELETE: DWORD = 0x4;
103 const FILE_SHARE_READ: DWORD = 0x1;
104 const FILE_SHARE_WRITE: DWORD = 0x2;
109 InternalHigh: ULONG_PTR,
116 fn LockFileEx(hFile: HANDLE,
119 nNumberOfBytesToLockLow: DWORD,
120 nNumberOfBytesToLockHigh: DWORD,
121 lpOverlapped: LPOVERLAPPED) -> BOOL;
134 -> io::Result<Lock> {
135 assert!(p.parent().unwrap().exists(),
136 "Parent directory of lock-file must exist: {}",
139 let share_mode = FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE;
141 let mut open_options = OpenOptions::new();
142 open_options.read(true)
143 .share_mode(share_mode);
146 open_options.create(true)
150 debug!("attempting to open lock file `{}`", p.display());
151 let file = match open_options.open(p) {
153 debug!("lock file opened successfully");
157 debug!("error opening lock file: {}", err);
163 let mut overlapped: OVERLAPPED = mem::zeroed();
167 dwFlags |= LOCKFILE_FAIL_IMMEDIATELY;
171 dwFlags |= LOCKFILE_EXCLUSIVE_LOCK;
174 debug!("attempting to acquire lock on lock file `{}`",
176 LockFileEx(file.as_raw_handle(),
184 let err = io::Error::last_os_error();
185 debug!("failed acquiring file lock: {}", err);
188 debug!("successfully acquired lock");
189 Ok(Lock { _file: file })
194 // Note that we don't need a Drop impl on the Windows: The file is unlocked
195 // automatically when it's closed.
201 pub fn new(_p: &Path, _wait: bool, _create: bool, _exclusive: bool)
204 let msg = "file locks not supported on this platform";
205 Err(io::Error::new(io::ErrorKind::Other, msg))