Skip to content

Commit 219d81f

Browse files
committed
separate flock implementations into separate modules
1 parent e7575f9 commit 219d81f

File tree

5 files changed

+194
-215
lines changed

5 files changed

+194
-215
lines changed

compiler/rustc_data_structures/src/flock.rs

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

10-
use std::fs::{File, OpenOptions};
11-
use std::io;
12-
use std::path::Path;
13-
1410
cfg_if! {
15-
// We use `flock` rather than `fcntl` on Linux, because WSL1 does not support
16-
// `fcntl`-style advisory locks properly (rust-lang/rust#72157).
17-
//
18-
// For other Unix targets we still use `fcntl` because it's more portable than
19-
// `flock`.
2011
if #[cfg(target_os = "linux")] {
21-
use std::os::unix::prelude::*;
22-
23-
#[derive(Debug)]
24-
pub struct Lock {
25-
_file: File,
26-
}
27-
28-
impl Lock {
29-
pub fn new(p: &Path,
30-
wait: bool,
31-
create: bool,
32-
exclusive: bool)
33-
-> io::Result<Lock> {
34-
let file = OpenOptions::new()
35-
.read(true)
36-
.write(true)
37-
.create(create)
38-
.mode(libc::S_IRWXU as u32)
39-
.open(p)?;
40-
41-
let mut operation = if exclusive {
42-
libc::LOCK_EX
43-
} else {
44-
libc::LOCK_SH
45-
};
46-
if !wait {
47-
operation |= libc::LOCK_NB
48-
}
49-
50-
let ret = unsafe { libc::flock(file.as_raw_fd(), operation) };
51-
if ret == -1 {
52-
Err(io::Error::last_os_error())
53-
} else {
54-
Ok(Lock { _file: file })
55-
}
56-
}
57-
58-
pub fn error_unsupported(err: &io::Error) -> bool {
59-
matches!(err.raw_os_error(), Some(libc::ENOTSUP) | Some(libc::ENOSYS))
60-
}
61-
}
62-
63-
// Note that we don't need a Drop impl to execute `flock(fd, LOCK_UN)`. Lock acquired by
64-
// `flock` is associated with the file descriptor and closing the file release it
65-
// automatically.
12+
mod linux;
13+
use linux as imp;
6614
} else if #[cfg(unix)] {
67-
use std::mem;
68-
use std::os::unix::prelude::*;
69-
70-
#[derive(Debug)]
71-
pub struct Lock {
72-
file: File,
73-
}
74-
75-
impl Lock {
76-
pub fn new(p: &Path,
77-
wait: bool,
78-
create: bool,
79-
exclusive: bool)
80-
-> io::Result<Lock> {
81-
let file = OpenOptions::new()
82-
.read(true)
83-
.write(true)
84-
.create(create)
85-
.mode(libc::S_IRWXU as u32)
86-
.open(p)?;
87-
88-
let lock_type = if exclusive {
89-
libc::F_WRLCK
90-
} else {
91-
libc::F_RDLCK
92-
};
93-
94-
let mut flock: libc::flock = unsafe { mem::zeroed() };
95-
flock.l_type = lock_type as libc::c_short;
96-
flock.l_whence = libc::SEEK_SET as libc::c_short;
97-
flock.l_start = 0;
98-
flock.l_len = 0;
99-
100-
let cmd = if wait { libc::F_SETLKW } else { libc::F_SETLK };
101-
let ret = unsafe {
102-
libc::fcntl(file.as_raw_fd(), cmd, &flock)
103-
};
104-
if ret == -1 {
105-
Err(io::Error::last_os_error())
106-
} else {
107-
Ok(Lock { file })
108-
}
109-
}
110-
111-
pub fn error_unsupported(err: &io::Error) -> bool {
112-
matches!(err.raw_os_error(), Some(libc::ENOTSUP) | Some(libc::ENOSYS))
113-
}
114-
}
115-
116-
impl Drop for Lock {
117-
fn drop(&mut self) {
118-
let mut flock: libc::flock = unsafe { mem::zeroed() };
119-
flock.l_type = libc::F_UNLCK as libc::c_short;
120-
flock.l_whence = libc::SEEK_SET as libc::c_short;
121-
flock.l_start = 0;
122-
flock.l_len = 0;
123-
124-
unsafe {
125-
libc::fcntl(self.file.as_raw_fd(), libc::F_SETLK, &flock);
126-
}
127-
}
128-
}
15+
mod unix;
16+
use unix as imp;
12917
} else if #[cfg(windows)] {
130-
use std::mem;
131-
use std::os::windows::prelude::*;
132-
133-
use winapi::shared::winerror::ERROR_INVALID_FUNCTION;
134-
use winapi::um::minwinbase::{OVERLAPPED, LOCKFILE_FAIL_IMMEDIATELY, LOCKFILE_EXCLUSIVE_LOCK};
135-
use winapi::um::fileapi::LockFileEx;
136-
use winapi::um::winnt::{FILE_SHARE_DELETE, FILE_SHARE_READ, FILE_SHARE_WRITE};
137-
138-
#[derive(Debug)]
139-
pub struct Lock {
140-
_file: File,
141-
}
142-
143-
impl Lock {
144-
pub fn new(p: &Path,
145-
wait: bool,
146-
create: bool,
147-
exclusive: bool)
148-
-> io::Result<Lock> {
149-
assert!(p.parent().unwrap().exists(),
150-
"Parent directory of lock-file must exist: {}",
151-
p.display());
152-
153-
let share_mode = FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE;
154-
155-
let mut open_options = OpenOptions::new();
156-
open_options.read(true)
157-
.share_mode(share_mode);
158-
159-
if create {
160-
open_options.create(true)
161-
.write(true);
162-
}
163-
164-
debug!("attempting to open lock file `{}`", p.display());
165-
let file = match open_options.open(p) {
166-
Ok(file) => {
167-
debug!("lock file opened successfully");
168-
file
169-
}
170-
Err(err) => {
171-
debug!("error opening lock file: {}", err);
172-
return Err(err)
173-
}
174-
};
175-
176-
let ret = unsafe {
177-
let mut overlapped: OVERLAPPED = mem::zeroed();
178-
179-
let mut dwFlags = 0;
180-
if !wait {
181-
dwFlags |= LOCKFILE_FAIL_IMMEDIATELY;
182-
}
183-
184-
if exclusive {
185-
dwFlags |= LOCKFILE_EXCLUSIVE_LOCK;
186-
}
187-
188-
debug!("attempting to acquire lock on lock file `{}`",
189-
p.display());
190-
LockFileEx(file.as_raw_handle(),
191-
dwFlags,
192-
0,
193-
0xFFFF_FFFF,
194-
0xFFFF_FFFF,
195-
&mut overlapped)
196-
};
197-
if ret == 0 {
198-
let err = io::Error::last_os_error();
199-
debug!("failed acquiring file lock: {}", err);
200-
Err(err)
201-
} else {
202-
debug!("successfully acquired lock");
203-
Ok(Lock { _file: file })
204-
}
205-
}
206-
207-
pub fn error_unsupported(err: &io::Error) -> bool {
208-
err.raw_os_error() == Some(ERROR_INVALID_FUNCTION as i32)
209-
}
210-
}
211-
212-
// Note that we don't need a Drop impl on the Windows: The file is unlocked
213-
// automatically when it's closed.
18+
mod windows;
19+
use windows as imp;
21420
} else {
215-
#[derive(Debug)]
216-
pub struct Lock(());
217-
218-
impl Lock {
219-
pub fn new(_p: &Path, _wait: bool, _create: bool, _exclusive: bool)
220-
-> io::Result<Lock>
221-
{
222-
let msg = "file locks not supported on this platform";
223-
Err(io::Error::new(io::ErrorKind::Other, msg))
224-
}
225-
226-
pub fn error_unsupported(_err: &io::Error) -> bool {
227-
true
228-
}
229-
}
21+
mod unsupported;
22+
use unsupported as imp;
23023
}
23124
}
25+
26+
pub use imp::Lock;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
//! We use `flock` rather than `fcntl` on Linux, because WSL1 does not support
2+
//! `fcntl`-style advisory locks properly (rust-lang/rust#72157). For other Unix
3+
//! targets we still use `fcntl` because it's more portable than `flock`.
4+
5+
use std::fs::{File, OpenOptions};
6+
use std::io;
7+
use std::os::unix::prelude::*;
8+
use std::path::Path;
9+
10+
#[derive(Debug)]
11+
pub struct Lock {
12+
_file: File,
13+
}
14+
15+
impl Lock {
16+
pub fn new(p: &Path, wait: bool, create: bool, exclusive: bool) -> io::Result<Lock> {
17+
let file = OpenOptions::new()
18+
.read(true)
19+
.write(true)
20+
.create(create)
21+
.mode(libc::S_IRWXU as u32)
22+
.open(p)?;
23+
24+
let mut operation = if exclusive { libc::LOCK_EX } else { libc::LOCK_SH };
25+
if !wait {
26+
operation |= libc::LOCK_NB
27+
}
28+
29+
let ret = unsafe { libc::flock(file.as_raw_fd(), operation) };
30+
if ret == -1 { Err(io::Error::last_os_error()) } else { Ok(Lock { _file: file }) }
31+
}
32+
33+
pub fn error_unsupported(err: &io::Error) -> bool {
34+
matches!(err.raw_os_error(), Some(libc::ENOTSUP) | Some(libc::ENOSYS))
35+
}
36+
}
37+
38+
// Note that we don't need a Drop impl to execute `flock(fd, LOCK_UN)`. A lock acquired by
39+
// `flock` is associated with the file descriptor and closing the file releases it
40+
// automatically.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
use std::fs::{File, OpenOptions};
2+
use std::io;
3+
use std::mem;
4+
use std::os::unix::prelude::*;
5+
use std::path::Path;
6+
7+
#[derive(Debug)]
8+
pub struct Lock {
9+
file: File,
10+
}
11+
12+
impl Lock {
13+
pub fn new(p: &Path, wait: bool, create: bool, exclusive: bool) -> io::Result<Lock> {
14+
let file = OpenOptions::new()
15+
.read(true)
16+
.write(true)
17+
.create(create)
18+
.mode(libc::S_IRWXU as u32)
19+
.open(p)?;
20+
21+
let lock_type = if exclusive { libc::F_WRLCK } else { libc::F_RDLCK };
22+
23+
let mut flock: libc::flock = unsafe { mem::zeroed() };
24+
flock.l_type = lock_type as libc::c_short;
25+
flock.l_whence = libc::SEEK_SET as libc::c_short;
26+
flock.l_start = 0;
27+
flock.l_len = 0;
28+
29+
let cmd = if wait { libc::F_SETLKW } else { libc::F_SETLK };
30+
let ret = unsafe { libc::fcntl(file.as_raw_fd(), cmd, &flock) };
31+
if ret == -1 { Err(io::Error::last_os_error()) } else { Ok(Lock { file }) }
32+
}
33+
34+
pub fn error_unsupported(err: &io::Error) -> bool {
35+
matches!(err.raw_os_error(), Some(libc::ENOTSUP) | Some(libc::ENOSYS))
36+
}
37+
}
38+
39+
impl Drop for Lock {
40+
fn drop(&mut self) {
41+
let mut flock: libc::flock = unsafe { mem::zeroed() };
42+
flock.l_type = libc::F_UNLCK as libc::c_short;
43+
flock.l_whence = libc::SEEK_SET as libc::c_short;
44+
flock.l_start = 0;
45+
flock.l_len = 0;
46+
47+
unsafe {
48+
libc::fcntl(self.file.as_raw_fd(), libc::F_SETLK, &flock);
49+
}
50+
}
51+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
use std::io;
2+
use std::path::Path;
3+
4+
#[derive(Debug)]
5+
pub struct Lock(());
6+
7+
impl Lock {
8+
pub fn new(_p: &Path, _wait: bool, _create: bool, _exclusive: bool) -> io::Result<Lock> {
9+
let msg = "file locks not supported on this platform";
10+
Err(io::Error::new(io::ErrorKind::Other, msg))
11+
}
12+
13+
pub fn error_unsupported(_err: &io::Error) -> bool {
14+
true
15+
}
16+
}

0 commit comments

Comments
 (0)