Skip to content

Commit 564ebbb

Browse files
committed
Use fcntl-based file lock for non-Linux unix
1 parent a23dd0d commit 564ebbb

File tree

1 file changed

+67
-10
lines changed

1 file changed

+67
-10
lines changed

src/librustc_data_structures/flock.rs

+67-10
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,13 @@
77
#![allow(non_camel_case_types)]
88
#![allow(nonstandard_style)]
99

10+
use std::fs::{File, OpenOptions};
1011
use std::io;
1112
use std::path::Path;
1213

1314
cfg_if! {
14-
if #[cfg(unix)] {
15+
if #[cfg(target_os = "linux")] {
1516
use std::os::unix::prelude::*;
16-
use std::fs::{File, OpenOptions};
1717

1818
#[derive(Debug)]
1919
pub struct Lock {
@@ -27,11 +27,11 @@ cfg_if! {
2727
exclusive: bool)
2828
-> io::Result<Lock> {
2929
let file = OpenOptions::new()
30-
.read(true)
31-
.write(true)
32-
.create(create)
33-
.mode(libc::S_IRWXU as u32)
34-
.open(p)?;
30+
.read(true)
31+
.write(true)
32+
.create(create)
33+
.mode(libc::S_IRWXU as u32)
34+
.open(p)?;
3535

3636
let mut operation = if exclusive {
3737
libc::LOCK_EX
@@ -44,8 +44,7 @@ cfg_if! {
4444

4545
let ret = unsafe { libc::flock(file.as_raw_fd(), operation) };
4646
if ret == -1 {
47-
let err = io::Error::last_os_error();
48-
Err(err)
47+
Err(io::Error::last_os_error())
4948
} else {
5049
Ok(Lock { _file: file })
5150
}
@@ -55,10 +54,68 @@ cfg_if! {
5554
// Note that we don't need a Drop impl to execute `flock(fd, LOCK_UN)`. Lock acquired by
5655
// `flock` is associated with the file descriptor and closing the file release it
5756
// automatically.
57+
} else if #[cfg(unix)] {
58+
use std::mem;
59+
use std::os::unix::prelude::*;
60+
61+
#[derive(Debug)]
62+
pub struct Lock {
63+
file: File,
64+
}
65+
66+
impl Lock {
67+
pub fn new(p: &Path,
68+
wait: bool,
69+
create: bool,
70+
exclusive: bool)
71+
-> io::Result<Lock> {
72+
let file = OpenOptions::new()
73+
.read(true)
74+
.write(true)
75+
.create(create)
76+
.mode(libc::S_IRWXU as u32)
77+
.open(p)?;
78+
79+
let lock_type = if exclusive {
80+
libc::F_WRLCK
81+
} else {
82+
libc::F_RDLCK
83+
};
84+
85+
let mut flock: libc::flock = unsafe { mem::zeroed() };
86+
flock.l_type = lock_type as libc::c_short;
87+
flock.l_whence = libc::SEEK_SET as libc::c_short;
88+
flock.l_start = 0;
89+
flock.l_len = 0;
90+
91+
let cmd = if wait { libc::F_SETLKW } else { libc::F_SETLK };
92+
let ret = unsafe {
93+
libc::fcntl(file.as_raw_fd(), cmd, &flock)
94+
};
95+
if ret == -1 {
96+
Err(io::Error::last_os_error())
97+
} else {
98+
Ok(Lock { file })
99+
}
100+
}
101+
}
102+
103+
impl Drop for Lock {
104+
fn drop(&mut self) {
105+
let mut flock: libc::flock = unsafe { mem::zeroed() };
106+
flock.l_type = libc::F_UNLCK as libc::c_short;
107+
flock.l_whence = libc::SEEK_SET as libc::c_short;
108+
flock.l_start = 0;
109+
flock.l_len = 0;
110+
111+
unsafe {
112+
libc::fcntl(self.file.as_raw_fd(), libc::F_SETLK, &flock);
113+
}
114+
}
115+
}
58116
} else if #[cfg(windows)] {
59117
use std::mem;
60118
use std::os::windows::prelude::*;
61-
use std::fs::{File, OpenOptions};
62119

63120
use winapi::um::minwinbase::{OVERLAPPED, LOCKFILE_FAIL_IMMEDIATELY, LOCKFILE_EXCLUSIVE_LOCK};
64121
use winapi::um::fileapi::LockFileEx;

0 commit comments

Comments
 (0)