Add some features to flock.
This commit is contained in:
parent
6ef8198406
commit
206e7b6fc7
2 changed files with 106 additions and 22 deletions
|
@ -15,6 +15,7 @@
|
|||
//! librustdoc, it is not production quality at all.
|
||||
|
||||
#![allow(non_camel_case_types)]
|
||||
use std::path::Path;
|
||||
|
||||
pub use self::imp::Lock;
|
||||
|
||||
|
@ -41,6 +42,7 @@ mod imp {
|
|||
pub l_sysid: libc::c_int,
|
||||
}
|
||||
|
||||
pub const F_RDLCK: libc::c_short = 0;
|
||||
pub const F_WRLCK: libc::c_short = 1;
|
||||
pub const F_UNLCK: libc::c_short = 2;
|
||||
pub const F_SETLK: libc::c_int = 6;
|
||||
|
@ -60,6 +62,7 @@ mod imp {
|
|||
pub l_sysid: libc::c_int,
|
||||
}
|
||||
|
||||
pub const F_RDLCK: libc::c_short = 1;
|
||||
pub const F_UNLCK: libc::c_short = 2;
|
||||
pub const F_WRLCK: libc::c_short = 3;
|
||||
pub const F_SETLK: libc::c_int = 12;
|
||||
|
@ -84,6 +87,7 @@ mod imp {
|
|||
pub l_sysid: libc::c_int,
|
||||
}
|
||||
|
||||
pub const F_RDLCK: libc::c_short = 1;
|
||||
pub const F_UNLCK: libc::c_short = 2;
|
||||
pub const F_WRLCK: libc::c_short = 3;
|
||||
pub const F_SETLK: libc::c_int = 8;
|
||||
|
@ -105,6 +109,7 @@ mod imp {
|
|||
pub l_sysid: libc::c_int,
|
||||
}
|
||||
|
||||
pub const F_RDLCK: libc::c_short = 1;
|
||||
pub const F_UNLCK: libc::c_short = 2;
|
||||
pub const F_WRLCK: libc::c_short = 3;
|
||||
pub const F_SETLK: libc::c_int = 8;
|
||||
|
@ -124,6 +129,7 @@ mod imp {
|
|||
pub l_pid: libc::pid_t,
|
||||
}
|
||||
|
||||
pub const F_RDLCK: libc::c_short = 1;
|
||||
pub const F_WRLCK: libc::c_short = 2;
|
||||
pub const F_UNLCK: libc::c_short = 3;
|
||||
pub const F_SETLK: libc::c_int = 6;
|
||||
|
@ -135,32 +141,53 @@ mod imp {
|
|||
}
|
||||
|
||||
impl Lock {
|
||||
pub fn new(p: &Path) -> Lock {
|
||||
pub fn new(p: &Path,
|
||||
wait: bool,
|
||||
create: bool,
|
||||
exclusive: bool)
|
||||
-> io::Result<Lock> {
|
||||
let os: &OsStr = p.as_ref();
|
||||
let buf = CString::new(os.as_bytes()).unwrap();
|
||||
let open_flags = if create {
|
||||
libc::O_RDWR | libc::O_CREAT
|
||||
} else {
|
||||
libc::O_RDWR
|
||||
};
|
||||
|
||||
let fd = unsafe {
|
||||
libc::open(buf.as_ptr(), libc::O_RDWR | libc::O_CREAT,
|
||||
libc::open(buf.as_ptr(), open_flags,
|
||||
libc::S_IRWXU as libc::c_int)
|
||||
};
|
||||
assert!(fd > 0, "failed to open lockfile: {}",
|
||||
io::Error::last_os_error());
|
||||
|
||||
if fd < 0 {
|
||||
return Err(io::Error::last_os_error());
|
||||
}
|
||||
|
||||
let lock_type = if exclusive {
|
||||
os::F_WRLCK
|
||||
} else {
|
||||
os::F_RDLCK
|
||||
};
|
||||
|
||||
let flock = os::flock {
|
||||
l_start: 0,
|
||||
l_len: 0,
|
||||
l_pid: 0,
|
||||
l_whence: libc::SEEK_SET as libc::c_short,
|
||||
l_type: os::F_WRLCK,
|
||||
l_type: lock_type,
|
||||
l_sysid: 0,
|
||||
};
|
||||
let cmd = if wait { os::F_SETLKW } else { os::F_SETLK };
|
||||
let ret = unsafe {
|
||||
libc::fcntl(fd, os::F_SETLKW, &flock)
|
||||
libc::fcntl(fd, cmd, &flock)
|
||||
};
|
||||
if ret == -1 {
|
||||
let err = io::Error::last_os_error();
|
||||
unsafe { libc::close(fd); }
|
||||
panic!("could not lock `{}`: {}", p.display(), err);
|
||||
Err(err)
|
||||
} else {
|
||||
Ok(Lock { fd: fd })
|
||||
}
|
||||
Lock { fd: fd }
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -191,18 +218,28 @@ mod imp {
|
|||
use std::os::windows::raw::HANDLE;
|
||||
use std::path::Path;
|
||||
use std::fs::{File, OpenOptions};
|
||||
use std::os::raw::{c_ulong, c_ulonglong, c_int};
|
||||
use std::os::windows::fs::OpenOptionsExt;
|
||||
|
||||
pub type DWORD = c_ulong;
|
||||
pub type BOOL = c_int;
|
||||
pub type ULONG_PTR = c_ulonglong;
|
||||
|
||||
type DWORD = u32;
|
||||
type LPOVERLAPPED = *mut OVERLAPPED;
|
||||
type BOOL = i32;
|
||||
const LOCKFILE_EXCLUSIVE_LOCK: DWORD = 0x00000002;
|
||||
const LOCKFILE_FAIL_IMMEDIATELY: DWORD = 0x00000001;
|
||||
|
||||
pub const FILE_SHARE_DELETE: DWORD = 0x4;
|
||||
pub const FILE_SHARE_READ: DWORD = 0x1;
|
||||
pub const FILE_SHARE_WRITE: DWORD = 0x2;
|
||||
|
||||
#[repr(C)]
|
||||
struct OVERLAPPED {
|
||||
Internal: usize,
|
||||
InternalHigh: usize,
|
||||
Pointer: *mut u8,
|
||||
hEvent: *mut u8,
|
||||
Internal: ULONG_PTR,
|
||||
InternalHigh: ULONG_PTR,
|
||||
Offset: DWORD,
|
||||
OffsetHigh: DWORD,
|
||||
hEvent: HANDLE,
|
||||
}
|
||||
|
||||
extern "system" {
|
||||
|
@ -219,19 +256,66 @@ mod imp {
|
|||
}
|
||||
|
||||
impl Lock {
|
||||
pub fn new(p: &Path) -> Lock {
|
||||
let f = OpenOptions::new().read(true).write(true).create(true)
|
||||
.open(p).unwrap();
|
||||
pub fn new(p: &Path,
|
||||
wait: bool,
|
||||
create: bool,
|
||||
exclusive: bool)
|
||||
-> io::Result<Lock> {
|
||||
|
||||
let share_mode = FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE;
|
||||
|
||||
let f = {
|
||||
let mut open_options = OpenOptions::new().read(true)
|
||||
.share_mode(share_mode);
|
||||
if create {
|
||||
open_options.create(true);
|
||||
}
|
||||
|
||||
match open_options.open(p) {
|
||||
Ok(file) => file,
|
||||
Err(err) => return Err(err),
|
||||
}
|
||||
};
|
||||
|
||||
let ret = unsafe {
|
||||
let mut overlapped: OVERLAPPED = mem::zeroed();
|
||||
LockFileEx(f.as_raw_handle(), LOCKFILE_EXCLUSIVE_LOCK, 0, 100, 0,
|
||||
|
||||
let mut dwFlags = 0;
|
||||
if !wait {
|
||||
dwFlags |= LOCKFILE_FAIL_IMMEDIATELY;
|
||||
}
|
||||
|
||||
if exclusive {
|
||||
dwFlags |= LOCKFILE_EXCLUSIVE_LOCK;
|
||||
}
|
||||
|
||||
LockFileEx(f.as_raw_handle(),
|
||||
dwFlags,
|
||||
0,
|
||||
0xFFFF_FFFF,
|
||||
0xFFFF_FFFF,
|
||||
&mut overlapped)
|
||||
};
|
||||
if ret == 0 {
|
||||
let err = io::Error::last_os_error();
|
||||
Err(io::Error::last_os_error())
|
||||
} else {
|
||||
Ok(Lock { _file: f })
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Note that we don't need a Drop impl on the Windows: The file is unlocked
|
||||
// automatically when it's closed.
|
||||
}
|
||||
|
||||
impl imp::Lock {
|
||||
pub fn panicking_new(p: &Path,
|
||||
wait: bool,
|
||||
create: bool,
|
||||
exclusive: bool)
|
||||
-> Lock {
|
||||
Lock::new(p, wait, create, exclusive).unwrap_or_else(|err| {
|
||||
panic!("could not lock `{}`: {}", p.display(), err);
|
||||
}
|
||||
Lock { _file: f }
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
@ -652,7 +652,7 @@ fn write_shared(cx: &Context,
|
|||
// docs placed in the output directory, so this needs to be a synchronized
|
||||
// operation with respect to all other rustdocs running around.
|
||||
try_err!(mkdir(&cx.dst), &cx.dst);
|
||||
let _lock = flock::Lock::new(&cx.dst.join(".lock"));
|
||||
let _lock = flock::Lock::panicking_new(&cx.dst.join(".lock"), true, true, true);
|
||||
|
||||
// Add all the static files. These may already exist, but we just
|
||||
// overwrite them anyway to make sure that they're fresh and up-to-date.
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue