15
15
//! librustdoc, it is not production quality at all.
16
16
17
17
#![ allow( non_camel_case_types) ]
18
+ use std:: path:: Path ;
18
19
19
20
pub use self :: imp:: Lock ;
20
21
@@ -41,6 +42,7 @@ mod imp {
41
42
pub l_sysid : libc:: c_int ,
42
43
}
43
44
45
+ pub const F_RDLCK : libc:: c_short = 0 ;
44
46
pub const F_WRLCK : libc:: c_short = 1 ;
45
47
pub const F_UNLCK : libc:: c_short = 2 ;
46
48
pub const F_SETLK : libc:: c_int = 6 ;
@@ -60,6 +62,7 @@ mod imp {
60
62
pub l_sysid : libc:: c_int ,
61
63
}
62
64
65
+ pub const F_RDLCK : libc:: c_short = 1 ;
63
66
pub const F_UNLCK : libc:: c_short = 2 ;
64
67
pub const F_WRLCK : libc:: c_short = 3 ;
65
68
pub const F_SETLK : libc:: c_int = 12 ;
@@ -84,6 +87,7 @@ mod imp {
84
87
pub l_sysid : libc:: c_int ,
85
88
}
86
89
90
+ pub const F_RDLCK : libc:: c_short = 1 ;
87
91
pub const F_UNLCK : libc:: c_short = 2 ;
88
92
pub const F_WRLCK : libc:: c_short = 3 ;
89
93
pub const F_SETLK : libc:: c_int = 8 ;
@@ -105,6 +109,7 @@ mod imp {
105
109
pub l_sysid : libc:: c_int ,
106
110
}
107
111
112
+ pub const F_RDLCK : libc:: c_short = 1 ;
108
113
pub const F_UNLCK : libc:: c_short = 2 ;
109
114
pub const F_WRLCK : libc:: c_short = 3 ;
110
115
pub const F_SETLK : libc:: c_int = 8 ;
@@ -124,6 +129,7 @@ mod imp {
124
129
pub l_pid : libc:: pid_t ,
125
130
}
126
131
132
+ pub const F_RDLCK : libc:: c_short = 1 ;
127
133
pub const F_WRLCK : libc:: c_short = 2 ;
128
134
pub const F_UNLCK : libc:: c_short = 3 ;
129
135
pub const F_SETLK : libc:: c_int = 6 ;
@@ -135,32 +141,53 @@ mod imp {
135
141
}
136
142
137
143
impl Lock {
138
- pub fn new ( p : & Path ) -> Lock {
144
+ pub fn new ( p : & Path ,
145
+ wait : bool ,
146
+ create : bool ,
147
+ exclusive : bool )
148
+ -> io:: Result < Lock > {
139
149
let os: & OsStr = p. as_ref ( ) ;
140
150
let buf = CString :: new ( os. as_bytes ( ) ) . unwrap ( ) ;
151
+ let open_flags = if create {
152
+ libc:: O_RDWR | libc:: O_CREAT
153
+ } else {
154
+ libc:: O_RDWR
155
+ } ;
156
+
141
157
let fd = unsafe {
142
- libc:: open ( buf. as_ptr ( ) , libc :: O_RDWR | libc :: O_CREAT ,
158
+ libc:: open ( buf. as_ptr ( ) , open_flags ,
143
159
libc:: S_IRWXU as libc:: c_int )
144
160
} ;
145
- assert ! ( fd > 0 , "failed to open lockfile: {}" ,
146
- io:: Error :: last_os_error( ) ) ;
161
+
162
+ if fd < 0 {
163
+ return Err ( io:: Error :: last_os_error ( ) ) ;
164
+ }
165
+
166
+ let lock_type = if exclusive {
167
+ os:: F_WRLCK
168
+ } else {
169
+ os:: F_RDLCK
170
+ } ;
171
+
147
172
let flock = os:: flock {
148
173
l_start : 0 ,
149
174
l_len : 0 ,
150
175
l_pid : 0 ,
151
176
l_whence : libc:: SEEK_SET as libc:: c_short ,
152
- l_type : os :: F_WRLCK ,
177
+ l_type : lock_type ,
153
178
l_sysid : 0 ,
154
179
} ;
180
+ let cmd = if wait { os:: F_SETLKW } else { os:: F_SETLK } ;
155
181
let ret = unsafe {
156
- libc:: fcntl ( fd, os :: F_SETLKW , & flock)
182
+ libc:: fcntl ( fd, cmd , & flock)
157
183
} ;
158
184
if ret == -1 {
159
185
let err = io:: Error :: last_os_error ( ) ;
160
186
unsafe { libc:: close ( fd) ; }
161
- panic ! ( "could not lock `{}`: {}" , p. display( ) , err) ;
187
+ Err ( err)
188
+ } else {
189
+ Ok ( Lock { fd : fd } )
162
190
}
163
- Lock { fd : fd }
164
191
}
165
192
}
166
193
@@ -191,18 +218,28 @@ mod imp {
191
218
use std:: os:: windows:: raw:: HANDLE ;
192
219
use std:: path:: Path ;
193
220
use std:: fs:: { File , OpenOptions } ;
221
+ use std:: os:: raw:: { c_ulong, c_ulonglong, c_int} ;
222
+ use std:: os:: windows:: fs:: OpenOptionsExt ;
223
+
224
+ pub type DWORD = c_ulong ;
225
+ pub type BOOL = c_int ;
226
+ pub type ULONG_PTR = c_ulonglong ;
194
227
195
- type DWORD = u32 ;
196
228
type LPOVERLAPPED = * mut OVERLAPPED ;
197
- type BOOL = i32 ;
198
229
const LOCKFILE_EXCLUSIVE_LOCK : DWORD = 0x00000002 ;
230
+ const LOCKFILE_FAIL_IMMEDIATELY : DWORD = 0x00000001 ;
231
+
232
+ pub const FILE_SHARE_DELETE : DWORD = 0x4 ;
233
+ pub const FILE_SHARE_READ : DWORD = 0x1 ;
234
+ pub const FILE_SHARE_WRITE : DWORD = 0x2 ;
199
235
200
236
#[ repr( C ) ]
201
237
struct OVERLAPPED {
202
- Internal : usize ,
203
- InternalHigh : usize ,
204
- Pointer : * mut u8 ,
205
- hEvent : * mut u8 ,
238
+ Internal : ULONG_PTR ,
239
+ InternalHigh : ULONG_PTR ,
240
+ Offset : DWORD ,
241
+ OffsetHigh : DWORD ,
242
+ hEvent : HANDLE ,
206
243
}
207
244
208
245
extern "system" {
@@ -219,19 +256,66 @@ mod imp {
219
256
}
220
257
221
258
impl Lock {
222
- pub fn new ( p : & Path ) -> Lock {
223
- let f = OpenOptions :: new ( ) . read ( true ) . write ( true ) . create ( true )
224
- . open ( p) . unwrap ( ) ;
259
+ pub fn new ( p : & Path ,
260
+ wait : bool ,
261
+ create : bool ,
262
+ exclusive : bool )
263
+ -> io:: Result < Lock > {
264
+
265
+ let share_mode = FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE ;
266
+
267
+ let f = {
268
+ let mut open_options = OpenOptions :: new ( ) . read ( true )
269
+ . share_mode ( share_mode) ;
270
+ if create {
271
+ open_options. create ( true ) ;
272
+ }
273
+
274
+ match open_options. open ( p) {
275
+ Ok ( file) => file,
276
+ Err ( err) => return Err ( err) ,
277
+ }
278
+ } ;
279
+
225
280
let ret = unsafe {
226
281
let mut overlapped: OVERLAPPED = mem:: zeroed ( ) ;
227
- LockFileEx ( f. as_raw_handle ( ) , LOCKFILE_EXCLUSIVE_LOCK , 0 , 100 , 0 ,
282
+
283
+ let mut dwFlags = 0 ;
284
+ if !wait {
285
+ dwFlags |= LOCKFILE_FAIL_IMMEDIATELY ;
286
+ }
287
+
288
+ if exclusive {
289
+ dwFlags |= LOCKFILE_EXCLUSIVE_LOCK ;
290
+ }
291
+
292
+ LockFileEx ( f. as_raw_handle ( ) ,
293
+ dwFlags,
294
+ 0 ,
295
+ 0xFFFF_FFFF ,
296
+ 0xFFFF_FFFF ,
228
297
& mut overlapped)
229
298
} ;
230
299
if ret == 0 {
231
- let err = io:: Error :: last_os_error ( ) ;
232
- panic ! ( "could not lock `{}`: {}" , p. display( ) , err) ;
300
+ Err ( io:: Error :: last_os_error ( ) )
301
+ } else {
302
+ Ok ( Lock { _file : f } )
233
303
}
234
- Lock { _file : f }
235
304
}
236
305
}
306
+
307
+ // Note that we don't need a Drop impl on the Windows: The file is unlocked
308
+ // automatically when it's closed.
309
+ }
310
+
311
+ impl imp:: Lock {
312
+ pub fn panicking_new ( p : & Path ,
313
+ wait : bool ,
314
+ create : bool ,
315
+ exclusive : bool )
316
+ -> Lock {
317
+ Lock :: new ( p, wait, create, exclusive) . unwrap_or_else ( |err| {
318
+ panic ! ( "could not lock `{}`: {}" , p. display( ) , err) ;
319
+ } )
320
+ }
237
321
}
0 commit comments