Skip to content

Commit e0a13df

Browse files
committed
ci: patch vendor/fs2
1 parent 884ded8 commit e0a13df

6 files changed

Lines changed: 499 additions & 2 deletions

File tree

Cargo.lock

Lines changed: 0 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,3 +4,6 @@ members = [
44
'crates/embedded-ffi'
55
]
66
default-members = ['crates/embedded-ffi']
7+
8+
[patch.crates-io]
9+
fs2 = { path = 'vendor/fs2' }

vendor/fs2/Cargo.toml

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
[package]
2+
name = "fs2"
3+
version = "0.4.3"
4+
edition = "2015"
5+
authors = ["Dan Burkert <dan@danburkert.com>"]
6+
description = "Cross-platform file locks and file duplication."
7+
documentation = "https://docs.rs/fs2"
8+
keywords = ["file", "file-system", "lock", "duplicate", "flock"]
9+
license = "MIT/Apache-2.0"
10+
repository = "https://github.com/danburkert/fs2-rs"
11+
12+
[target.'cfg(unix)'.dependencies]
13+
libc = "0.2.30"
14+
15+
[target.'cfg(windows)'.dependencies]
16+
winapi = { version = "0.3", features = ["handleapi", "processthreadsapi", "winerror", "fileapi", "winbase", "std"] }

vendor/fs2/src/lib.rs

Lines changed: 125 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,125 @@
1+
//! Extended utilities for working with files and filesystems in Rust.
2+
3+
#![doc(html_root_url = "https://docs.rs/fs2/0.4.3")]
4+
#![cfg_attr(test, feature(test))]
5+
6+
#[cfg(windows)]
7+
extern crate winapi;
8+
9+
#[cfg(unix)]
10+
mod unix;
11+
#[cfg(unix)]
12+
use unix as sys;
13+
14+
#[cfg(windows)]
15+
mod windows;
16+
#[cfg(windows)]
17+
use windows as sys;
18+
19+
use std::fs::File;
20+
use std::io::{Error, Result};
21+
use std::path::Path;
22+
23+
/// Extension trait for `std::fs::File` which provides allocation, duplication and locking methods.
24+
pub trait FileExt {
25+
fn duplicate(&self) -> Result<File>;
26+
fn allocated_size(&self) -> Result<u64>;
27+
fn allocate(&self, len: u64) -> Result<()>;
28+
fn lock_shared(&self) -> Result<()>;
29+
fn lock_exclusive(&self) -> Result<()>;
30+
fn try_lock_shared(&self) -> Result<()>;
31+
fn try_lock_exclusive(&self) -> Result<()>;
32+
fn unlock(&self) -> Result<()>;
33+
}
34+
35+
impl FileExt for File {
36+
fn duplicate(&self) -> Result<File> {
37+
sys::duplicate(self)
38+
}
39+
fn allocated_size(&self) -> Result<u64> {
40+
sys::allocated_size(self)
41+
}
42+
fn allocate(&self, len: u64) -> Result<()> {
43+
sys::allocate(self, len)
44+
}
45+
fn lock_shared(&self) -> Result<()> {
46+
sys::lock_shared(self)
47+
}
48+
fn lock_exclusive(&self) -> Result<()> {
49+
sys::lock_exclusive(self)
50+
}
51+
fn try_lock_shared(&self) -> Result<()> {
52+
sys::try_lock_shared(self)
53+
}
54+
fn try_lock_exclusive(&self) -> Result<()> {
55+
sys::try_lock_exclusive(self)
56+
}
57+
fn unlock(&self) -> Result<()> {
58+
sys::unlock(self)
59+
}
60+
}
61+
62+
pub fn lock_contended_error() -> Error {
63+
sys::lock_error()
64+
}
65+
66+
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
67+
pub struct FsStats {
68+
free_space: u64,
69+
available_space: u64,
70+
total_space: u64,
71+
allocation_granularity: u64,
72+
}
73+
74+
impl FsStats {
75+
pub fn free_space(&self) -> u64 {
76+
self.free_space
77+
}
78+
79+
pub fn available_space(&self) -> u64 {
80+
self.available_space
81+
}
82+
83+
pub fn total_space(&self) -> u64 {
84+
self.total_space
85+
}
86+
87+
pub fn allocation_granularity(&self) -> u64 {
88+
self.allocation_granularity
89+
}
90+
}
91+
92+
pub fn statvfs<P>(path: P) -> Result<FsStats>
93+
where
94+
P: AsRef<Path>,
95+
{
96+
sys::statvfs(path.as_ref())
97+
}
98+
99+
pub fn free_space<P>(path: P) -> Result<u64>
100+
where
101+
P: AsRef<Path>,
102+
{
103+
statvfs(path).map(|stat| stat.free_space)
104+
}
105+
106+
pub fn available_space<P>(path: P) -> Result<u64>
107+
where
108+
P: AsRef<Path>,
109+
{
110+
statvfs(path).map(|stat| stat.available_space)
111+
}
112+
113+
pub fn total_space<P>(path: P) -> Result<u64>
114+
where
115+
P: AsRef<Path>,
116+
{
117+
statvfs(path).map(|stat| stat.total_space)
118+
}
119+
120+
pub fn allocation_granularity<P>(path: P) -> Result<u64>
121+
where
122+
P: AsRef<Path>,
123+
{
124+
statvfs(path).map(|stat| stat.allocation_granularity)
125+
}

vendor/fs2/src/unix.rs

Lines changed: 182 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,182 @@
1+
extern crate libc;
2+
3+
use std::ffi::CString;
4+
use std::fs::File;
5+
use std::io::{Error, ErrorKind, Result};
6+
use std::mem;
7+
use std::os::unix::ffi::OsStrExt;
8+
use std::os::unix::fs::MetadataExt;
9+
use std::os::unix::io::{AsRawFd, FromRawFd};
10+
use std::path::Path;
11+
12+
use FsStats;
13+
14+
pub fn duplicate(file: &File) -> Result<File> {
15+
unsafe {
16+
let fd = libc::dup(file.as_raw_fd());
17+
18+
if fd < 0 {
19+
Err(Error::last_os_error())
20+
} else {
21+
Ok(File::from_raw_fd(fd))
22+
}
23+
}
24+
}
25+
26+
pub fn lock_shared(file: &File) -> Result<()> {
27+
flock(file, libc::LOCK_SH)
28+
}
29+
30+
pub fn lock_exclusive(file: &File) -> Result<()> {
31+
flock(file, libc::LOCK_EX)
32+
}
33+
34+
pub fn try_lock_shared(file: &File) -> Result<()> {
35+
flock(file, libc::LOCK_SH | libc::LOCK_NB)
36+
}
37+
38+
pub fn try_lock_exclusive(file: &File) -> Result<()> {
39+
flock(file, libc::LOCK_EX | libc::LOCK_NB)
40+
}
41+
42+
pub fn unlock(file: &File) -> Result<()> {
43+
flock(file, libc::LOCK_UN)
44+
}
45+
46+
pub fn lock_error() -> Error {
47+
Error::from_raw_os_error(libc::EWOULDBLOCK)
48+
}
49+
50+
#[cfg(not(target_os = "solaris"))]
51+
fn flock(file: &File, flag: libc::c_int) -> Result<()> {
52+
let ret = unsafe { libc::flock(file.as_raw_fd(), flag) };
53+
if ret < 0 {
54+
Err(Error::last_os_error())
55+
} else {
56+
Ok(())
57+
}
58+
}
59+
60+
#[cfg(target_os = "solaris")]
61+
fn flock(file: &File, flag: libc::c_int) -> Result<()> {
62+
let mut fl = libc::flock {
63+
l_whence: 0,
64+
l_start: 0,
65+
l_len: 0,
66+
l_type: 0,
67+
l_pad: [0; 4],
68+
l_pid: 0,
69+
l_sysid: 0,
70+
};
71+
72+
let (cmd, operation) = match flag & libc::LOCK_NB {
73+
0 => (libc::F_SETLKW, flag),
74+
_ => (libc::F_SETLK, flag & !libc::LOCK_NB),
75+
};
76+
77+
match operation {
78+
libc::LOCK_SH => fl.l_type |= libc::F_RDLCK,
79+
libc::LOCK_EX => fl.l_type |= libc::F_WRLCK,
80+
libc::LOCK_UN => fl.l_type |= libc::F_UNLCK,
81+
_ => return Err(Error::from_raw_os_error(libc::EINVAL)),
82+
}
83+
84+
let ret = unsafe { libc::fcntl(file.as_raw_fd(), cmd, &fl) };
85+
match ret {
86+
-1 => match Error::last_os_error().raw_os_error() {
87+
Some(libc::EACCES) => Err(lock_error()),
88+
_ => Err(Error::last_os_error()),
89+
},
90+
_ => Ok(()),
91+
}
92+
}
93+
94+
pub fn allocated_size(file: &File) -> Result<u64> {
95+
file.metadata().map(|m| m.blocks() as u64 * 512)
96+
}
97+
98+
#[cfg(any(
99+
target_os = "linux",
100+
target_os = "freebsd",
101+
target_os = "android"
102+
))]
103+
pub fn allocate(file: &File, len: u64) -> Result<()> {
104+
let ret = unsafe { libc::posix_fallocate(file.as_raw_fd(), 0, len as libc::off_t) };
105+
if ret == 0 {
106+
Ok(())
107+
} else {
108+
Err(Error::last_os_error())
109+
}
110+
}
111+
112+
#[cfg(any(
113+
target_os = "macos",
114+
target_os = "ios",
115+
target_os = "tvos",
116+
target_os = "watchos",
117+
target_os = "visionos"
118+
))]
119+
pub fn allocate(file: &File, len: u64) -> Result<()> {
120+
let stat = file.metadata()?;
121+
122+
if len > stat.blocks() as u64 * 512 {
123+
let mut fstore = libc::fstore_t {
124+
fst_flags: libc::F_ALLOCATECONTIG,
125+
fst_posmode: libc::F_PEOFPOSMODE,
126+
fst_offset: 0,
127+
fst_length: len as libc::off_t,
128+
fst_bytesalloc: 0,
129+
};
130+
131+
let ret = unsafe { libc::fcntl(file.as_raw_fd(), libc::F_PREALLOCATE, &fstore) };
132+
if ret == -1 {
133+
fstore.fst_flags = libc::F_ALLOCATEALL;
134+
let ret = unsafe { libc::fcntl(file.as_raw_fd(), libc::F_PREALLOCATE, &fstore) };
135+
if ret == -1 {
136+
return Err(Error::last_os_error());
137+
}
138+
}
139+
}
140+
141+
if len > stat.size() as u64 {
142+
file.set_len(len)
143+
} else {
144+
Ok(())
145+
}
146+
}
147+
148+
#[cfg(any(
149+
target_os = "openbsd",
150+
target_os = "netbsd",
151+
target_os = "dragonfly",
152+
target_os = "solaris",
153+
target_os = "haiku"
154+
))]
155+
pub fn allocate(file: &File, len: u64) -> Result<()> {
156+
if len > file.metadata()?.len() as u64 {
157+
file.set_len(len)
158+
} else {
159+
Ok(())
160+
}
161+
}
162+
163+
pub fn statvfs(path: &Path) -> Result<FsStats> {
164+
let cstr = match CString::new(path.as_os_str().as_bytes()) {
165+
Ok(cstr) => cstr,
166+
Err(..) => return Err(Error::new(ErrorKind::InvalidInput, "path contained a null")),
167+
};
168+
169+
unsafe {
170+
let mut stat: libc::statvfs = mem::zeroed();
171+
if libc::statvfs(cstr.as_ptr() as *const _, &mut stat) != 0 {
172+
Err(Error::last_os_error())
173+
} else {
174+
Ok(FsStats {
175+
free_space: stat.f_frsize as u64 * stat.f_bfree as u64,
176+
available_space: stat.f_frsize as u64 * stat.f_bavail as u64,
177+
total_space: stat.f_frsize as u64 * stat.f_blocks as u64,
178+
allocation_granularity: stat.f_frsize as u64,
179+
})
180+
}
181+
}
182+
}

0 commit comments

Comments
 (0)