Skip to content

Commit d4043c9

Browse files
authored
0.13.0 (#36)
- Make `try_lock_*` returns `std::io::Result<bool>`, which is compatible with the incoming `std::fs::File::try_lock*` in std liberary.
1 parent 0be8a38 commit d4043c9

File tree

13 files changed

+161
-102
lines changed

13 files changed

+161
-102
lines changed

.github/workflows/ci.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ on:
2121
- '**.md'
2222
- '**.txt'
2323
workflow_dispatch:
24+
schedule: [cron: "0 1 */7 * *"]
2425

2526
env:
2627
CARGO_TERM_COLOR: always

CHANGELOG.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
# Releases
2+
3+
## 0.13.0
4+
5+
### Breakage
6+
7+
- Make `try_lock_*` returns `std::io::Result<bool>`, which is compatible with the incoming `std::fs::File::try_lock*` in std liberary.

Cargo.toml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
[package]
22
name = "fs4"
33
# NB: When modifying, also modify html_root_url in lib.rs
4-
version = "0.12.0"
4+
version = "0.13.0"
55
rust-version = "1.75.0"
66
authors = ["Dan Burkert <[email protected]>", "Al Liu <[email protected]>"]
77
license = "MIT OR Apache-2.0"
@@ -28,7 +28,7 @@ fs-err3-tokio = ["fs-err3", "fs-err3/tokio"]
2828
rustix = { version = "0.38", features = ["fs"] }
2929

3030
[target.'cfg(windows)'.dependencies.windows-sys]
31-
version = "0.52"
31+
version = "0.59"
3232
features = ["Win32_Foundation", "Win32_Storage_FileSystem", "Win32_System_IO"]
3333

3434
[dependencies]

README.md

Lines changed: 18 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -20,52 +20,61 @@ This is a fork of the [fs2-rs](https://github.com/danburkert/fs2-rs) crate, the
2020
</div>
2121

2222
## Installation
23+
2324
- std
25+
2426
```toml
2527
[dependencies]
26-
fs4 = { version = "0.12", features = ["sync"] }
28+
fs4 = { version = "0.13", features = ["sync"] }
2729
```
2830

2931
- [async-std runtime](https://crates.io/crates/async-std)
32+
3033
```toml
3134
[dependencies]
32-
fs4 = { version = "0.12", features = ["async-std"] }
35+
fs4 = { version = "0.13", features = ["async-std"] }
3336
```
3437

3538
- [fs-err v2](https://crates.io/crates/fs-err)
39+
3640
```toml
3741
[dependencies]
38-
fs4 = { version = "0.12", features = ["fs-err2"] }
42+
fs4 = { version = "0.13", features = ["fs-err2"] }
3943
```
4044

4145
- [fs-err-tokio v2](https://crates.io/crates/fs-err)
46+
4247
```toml
4348
[dependencies]
44-
fs4 = { version = "0.12", features = ["fs-err2-tokio"] }
49+
fs4 = { version = "0.13", features = ["fs-err2-tokio"] }
4550
```
4651

4752
- [fs-err v3](https://crates.io/crates/fs-err)
53+
4854
```toml
4955
[dependencies]
50-
fs4 = { version = "0.12", features = ["fs-err3"] }
56+
fs4 = { version = "0.13", features = ["fs-err3"] }
5157
```
5258

5359
- [fs-err-tokio v3](https://crates.io/crates/fs-err)
60+
5461
```toml
5562
[dependencies]
56-
fs4 = { version = "0.12", features = ["fs-err3-tokio"] }
63+
fs4 = { version = "0.13", features = ["fs-err3-tokio"] }
5764
```
5865

5966
- [smol runtime](https://crates.io/crates/smol)
67+
6068
```toml
6169
[dependencies]
62-
fs4 = { version = "0.12", features = ["smol"] }
70+
fs4 = { version = "0.13", features = ["smol"] }
6371
```
6472

6573
- [tokio runtime](https://crates.io/crates/tokio)
74+
6675
```toml
6776
[dependencies]
68-
fs4 = { version = "0.12", features = ["tokio"] }
77+
fs4 = { version = "0.13", features = ["tokio"] }
6978
```
7079

7180
## Features
@@ -86,7 +95,7 @@ Apache License (Version 2.0).
8695

8796
See [LICENSE-APACHE](LICENSE-APACHE), [LICENSE-MIT](LICENSE-MIT) for details.
8897

89-
Copyright (c) 2021 Al Liu.
98+
Copyright (c) 2025 Al Liu.
9099

91100
Copyright (c) 2015 Dan Burkert.
92101

src/file_ext/async_impl.rs

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -48,11 +48,11 @@ macro_rules! async_file_ext {
4848

4949
/// Locks the file for shared usage, or returns an error if the file is
5050
/// currently locked (see `lock_contended_error`).
51-
fn try_lock_shared(&self) -> Result<()>;
51+
fn try_lock_shared(&self) -> Result<bool>;
5252

5353
/// Locks the file for exclusive usage, or returns an error if the file is
5454
/// currently locked (see `lock_contended_error`).
55-
fn try_lock_exclusive(&self) -> Result<()>;
55+
fn try_lock_exclusive(&self) -> Result<bool>;
5656

5757
/// Unlocks the file.
5858
fn unlock(&self) -> Result<()>;
@@ -79,11 +79,11 @@ macro_rules! async_file_ext {
7979
sys::lock_exclusive(self)
8080
}
8181

82-
fn try_lock_shared(&self) -> Result<()> {
82+
fn try_lock_shared(&self) -> Result<bool> {
8383
sys::try_lock_shared(self)
8484
}
8585

86-
fn try_lock_exclusive(&self) -> Result<()> {
86+
fn try_lock_exclusive(&self) -> Result<bool> {
8787
sys::try_lock_exclusive(self)
8888
}
8989

@@ -106,7 +106,7 @@ macro_rules! test_mod {
106106
extern crate test;
107107
use crate::{
108108
allocation_granularity, available_space, free_space,
109-
lock_contended_error, total_space,
109+
total_space,
110110
};
111111

112112
$(
@@ -144,13 +144,13 @@ macro_rules! test_mod {
144144
file1.lock_shared().unwrap();
145145
file2.lock_shared().unwrap();
146146
assert_eq!(
147-
file3.try_lock_exclusive().unwrap_err().kind(),
148-
lock_contended_error().kind()
147+
file3.try_lock_exclusive().unwrap(),
148+
false,
149149
);
150150
file1.unlock().unwrap();
151151
assert_eq!(
152-
file3.try_lock_exclusive().unwrap_err().kind(),
153-
lock_contended_error().kind()
152+
file3.try_lock_exclusive().unwrap(),
153+
false,
154154
);
155155

156156
// Once all shared file locks are dropped, an exclusive lock may be created;
@@ -181,12 +181,12 @@ macro_rules! test_mod {
181181
// No other access is possible once an exclusive lock is created.
182182
file1.lock_exclusive().unwrap();
183183
assert_eq!(
184-
file2.try_lock_exclusive().unwrap_err().kind(),
185-
lock_contended_error().kind()
184+
file2.try_lock_exclusive().unwrap(),
185+
false,
186186
);
187187
assert_eq!(
188-
file2.try_lock_shared().unwrap_err().kind(),
189-
lock_contended_error().kind()
188+
file2.try_lock_shared().unwrap(),
189+
false,
190190
);
191191

192192
// Once the exclusive lock is dropped, the second file is able to create a lock.
@@ -216,8 +216,8 @@ macro_rules! test_mod {
216216

217217
file1.lock_exclusive().unwrap();
218218
assert_eq!(
219-
file2.try_lock_shared().unwrap_err().kind(),
220-
lock_contended_error().kind()
219+
file2.try_lock_shared().unwrap(),
220+
false,
221221
);
222222

223223
// Drop file1; the lock should be released.

src/file_ext/sync_impl.rs

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -48,11 +48,11 @@ macro_rules! file_ext {
4848

4949
/// Locks the file for shared usage, or returns an error if the file is
5050
/// currently locked (see `lock_contended_error`).
51-
fn try_lock_shared(&self) -> Result<()>;
51+
fn try_lock_shared(&self) -> Result<bool>;
5252

5353
/// Locks the file for exclusive usage, or returns an error if the file is
5454
/// currently locked (see `lock_contended_error`).
55-
fn try_lock_exclusive(&self) -> Result<()>;
55+
fn try_lock_exclusive(&self) -> Result<bool>;
5656

5757
/// Unlocks the file.
5858
fn unlock(&self) -> Result<()>;
@@ -71,10 +71,10 @@ macro_rules! file_ext {
7171
fn lock_exclusive(&self) -> Result<()> {
7272
sys::lock_exclusive(self)
7373
}
74-
fn try_lock_shared(&self) -> Result<()> {
74+
fn try_lock_shared(&self) -> Result<bool> {
7575
sys::try_lock_shared(self)
7676
}
77-
fn try_lock_exclusive(&self) -> Result<()> {
77+
fn try_lock_exclusive(&self) -> Result<bool> {
7878
sys::try_lock_exclusive(self)
7979
}
8080
fn unlock(&self) -> Result<()> {
@@ -93,7 +93,7 @@ macro_rules! test_mod {
9393

9494
use super::*;
9595
use crate::{
96-
allocation_granularity, available_space, free_space, lock_contended_error, statvfs,
96+
allocation_granularity, available_space, free_space, statvfs,
9797
total_space, FsStats,
9898
};
9999

@@ -132,13 +132,13 @@ macro_rules! test_mod {
132132
file1.lock_shared().unwrap();
133133
file2.lock_shared().unwrap();
134134
assert_eq!(
135-
file3.try_lock_exclusive().unwrap_err().kind(),
136-
lock_contended_error().kind()
135+
file3.try_lock_exclusive().unwrap(),
136+
false,
137137
);
138138
file1.unlock().unwrap();
139139
assert_eq!(
140-
file3.try_lock_exclusive().unwrap_err().kind(),
141-
lock_contended_error().kind()
140+
file3.try_lock_exclusive().unwrap(),
141+
false,
142142
);
143143

144144
// Once all shared file locks are dropped, an exclusive lock may be created;
@@ -169,12 +169,12 @@ macro_rules! test_mod {
169169
// No other access is possible once an exclusive lock is created.
170170
file1.lock_exclusive().unwrap();
171171
assert_eq!(
172-
file2.try_lock_exclusive().unwrap_err().kind(),
173-
lock_contended_error().kind()
172+
file2.try_lock_exclusive().unwrap(),
173+
false,
174174
);
175175
assert_eq!(
176-
file2.try_lock_shared().unwrap_err().kind(),
177-
lock_contended_error().kind()
176+
file2.try_lock_shared().unwrap(),
177+
false,
178178
);
179179

180180
// Once the exclusive lock is dropped, the second file is able to create a lock.
@@ -204,8 +204,8 @@ macro_rules! test_mod {
204204

205205
file1.lock_exclusive().unwrap();
206206
assert_eq!(
207-
file2.try_lock_shared().unwrap_err().kind(),
208-
lock_contended_error().kind()
207+
file2.try_lock_shared().unwrap(),
208+
false,
209209
);
210210

211211
// Drop file1; the lock should be released.

src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
//! Extended utilities for working with files and filesystems in Rust.
2-
#![doc(html_root_url = "https://docs.rs/fs4/0.12.0")]
2+
#![doc(html_root_url = "https://docs.rs/fs4/0.13.0")]
33
#![cfg_attr(test, feature(test))]
44
#![cfg_attr(docsrs, feature(doc_cfg))]
55
#![cfg_attr(docsrs, allow(unused_attributes))]

src/unix.rs

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,13 +11,13 @@ macro_rules! lock_impl {
1111
}
1212

1313
#[cfg(not(target_os = "wasi"))]
14-
pub fn try_lock_shared(file: &$file) -> std::io::Result<()> {
15-
flock(file, rustix::fs::FlockOperation::NonBlockingLockShared)
14+
pub fn try_lock_shared(file: &$file) -> std::io::Result<bool> {
15+
try_flock(file, rustix::fs::FlockOperation::NonBlockingLockShared)
1616
}
1717

1818
#[cfg(not(target_os = "wasi"))]
19-
pub fn try_lock_exclusive(file: &$file) -> std::io::Result<()> {
20-
flock(file, rustix::fs::FlockOperation::NonBlockingLockExclusive)
19+
pub fn try_lock_exclusive(file: &$file) -> std::io::Result<bool> {
20+
try_flock(file, rustix::fs::FlockOperation::NonBlockingLockExclusive)
2121
}
2222

2323
#[cfg(not(target_os = "wasi"))]
@@ -34,6 +34,22 @@ macro_rules! lock_impl {
3434
Err(e) => Err(std::io::Error::from_raw_os_error(e.raw_os_error())),
3535
}
3636
}
37+
38+
#[cfg(not(target_os = "wasi"))]
39+
fn try_flock(file: &$file, flag: rustix::fs::FlockOperation) -> std::io::Result<bool> {
40+
let borrowed_fd = unsafe { rustix::fd::BorrowedFd::borrow_raw(file.as_raw_fd()) };
41+
42+
match rustix::fs::flock(borrowed_fd, flag) {
43+
Ok(_) => Ok(true),
44+
Err(e) => {
45+
let err = std::io::Error::from_raw_os_error(e.raw_os_error());
46+
if let std::io::ErrorKind::WouldBlock = err.kind() {
47+
return Ok(false);
48+
}
49+
Err(err)
50+
}
51+
}
52+
}
3753
};
3854
}
3955

src/unix/async_impl.rs

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -60,8 +60,6 @@ macro_rules! test_mod {
6060
mod test {
6161
extern crate tempfile;
6262

63-
use crate::lock_contended_error;
64-
6563
$(
6664
$use_stmt
6765
)*
@@ -95,8 +93,8 @@ macro_rules! test_mod {
9593
// Attempting to replace a shared lock with an exclusive lock will fail
9694
// with multiple lock holders, and remove the original shared lock.
9795
assert_eq!(
98-
file2.try_lock_exclusive().unwrap_err().raw_os_error(),
99-
lock_contended_error().raw_os_error()
96+
file2.try_lock_exclusive().unwrap(),
97+
false,
10098
);
10199
file1.lock_shared().unwrap();
102100
}

src/unix/sync_impl.rs

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -60,8 +60,6 @@ macro_rules! test_mod {
6060
mod test {
6161
extern crate tempfile;
6262

63-
use crate::lock_contended_error;
64-
6563
$(
6664
$use_stmt
6765
)*
@@ -86,17 +84,17 @@ macro_rules! test_mod {
8684
.unwrap();
8785

8886
// Creating a shared lock will drop an exclusive lock.
89-
file1.lock_exclusive().unwrap();
90-
file1.lock_shared().unwrap();
91-
file2.lock_shared().unwrap();
87+
FileExt::lock_exclusive(&file1).unwrap();
88+
FileExt::lock_shared(&file1).unwrap();
89+
FileExt::lock_shared(&file2).unwrap();
9290

9391
// Attempting to replace a shared lock with an exclusive lock will fail
9492
// with multiple lock holders, and remove the original shared lock.
9593
assert_eq!(
96-
file2.try_lock_exclusive().unwrap_err().raw_os_error(),
97-
lock_contended_error().raw_os_error()
94+
FileExt::try_lock_exclusive(&file2).unwrap(),
95+
false,
9896
);
99-
file1.lock_shared().unwrap();
97+
FileExt::lock_shared(&file1).unwrap();
10098
}
10199
}
102100
};

0 commit comments

Comments
 (0)