feat(std): emulate flock for solaris via fcntl

Upstream Solaris flock emulation to libstd from cargo.

This is borrowed from
https://github.com/rust-lang/cargo/blob/3b379fcc541b39321a7758552d37e5e0cc4277b9/src/cargo/util/flock.rs#L502-L536
which was implemented by an Oracle employee.
The code has been in cargo since 2022-12.

Python's `fcntl.flock` emulates like this as well:
https://github.com/python/cpython/blob/c919d02edecfe9d75fe374756fb8aa1db8d95f55/Modules/fcntlmodule.c#L337-L400

We did the same thing in
https://github.com/rust-lang/rust/blob/0d0f4eac8b98133e5da6d3604d86a8f3b5a67844/compiler/rustc_data_structures/src/flock/unix.rs#L13-L39
This commit is contained in:
Weihang Lo
2025-09-06 02:30:50 -06:00
parent 0d0f4eac8b
commit 01edb24d3c
2 changed files with 70 additions and 0 deletions
+4
View File
@@ -226,6 +226,7 @@ fn file_test_io_seek_and_write() {
target_os = "freebsd",
target_os = "linux",
target_os = "netbsd",
target_os = "solaris",
target_vendor = "apple",
))]
fn file_lock_multiple_shared() {
@@ -249,6 +250,7 @@ fn file_lock_multiple_shared() {
target_os = "freebsd",
target_os = "linux",
target_os = "netbsd",
target_os = "solaris",
target_vendor = "apple",
))]
fn file_lock_blocking() {
@@ -273,6 +275,7 @@ fn file_lock_blocking() {
target_os = "freebsd",
target_os = "linux",
target_os = "netbsd",
target_os = "solaris",
target_vendor = "apple",
))]
fn file_lock_drop() {
@@ -294,6 +297,7 @@ fn file_lock_drop() {
target_os = "freebsd",
target_os = "linux",
target_os = "netbsd",
target_os = "solaris",
target_vendor = "apple",
))]
fn file_lock_dup() {
+66
View File
@@ -1293,6 +1293,15 @@ pub fn lock(&self) -> io::Result<()> {
return Ok(());
}
#[cfg(target_os = "solaris")]
pub fn lock(&self) -> io::Result<()> {
let mut flock: libc::flock = unsafe { mem::zeroed() };
flock.l_type = libc::F_WRLCK as libc::c_short;
flock.l_whence = libc::SEEK_SET as libc::c_short;
cvt(unsafe { libc::fcntl(self.as_raw_fd(), libc::F_SETLKW, &flock) })?;
Ok(())
}
#[cfg(not(any(
target_os = "freebsd",
target_os = "fuchsia",
@@ -1300,6 +1309,7 @@ pub fn lock(&self) -> io::Result<()> {
target_os = "netbsd",
target_os = "openbsd",
target_os = "cygwin",
target_os = "solaris",
target_vendor = "apple",
)))]
pub fn lock(&self) -> io::Result<()> {
@@ -1320,6 +1330,15 @@ pub fn lock_shared(&self) -> io::Result<()> {
return Ok(());
}
#[cfg(target_os = "solaris")]
pub fn lock_shared(&self) -> io::Result<()> {
let mut flock: libc::flock = unsafe { mem::zeroed() };
flock.l_type = libc::F_RDLCK as libc::c_short;
flock.l_whence = libc::SEEK_SET as libc::c_short;
cvt(unsafe { libc::fcntl(self.as_raw_fd(), libc::F_SETLKW, &flock) })?;
Ok(())
}
#[cfg(not(any(
target_os = "freebsd",
target_os = "fuchsia",
@@ -1327,6 +1346,7 @@ pub fn lock_shared(&self) -> io::Result<()> {
target_os = "netbsd",
target_os = "openbsd",
target_os = "cygwin",
target_os = "solaris",
target_vendor = "apple",
)))]
pub fn lock_shared(&self) -> io::Result<()> {
@@ -1355,6 +1375,23 @@ pub fn try_lock(&self) -> Result<(), TryLockError> {
}
}
#[cfg(target_os = "solaris")]
pub fn try_lock(&self) -> Result<(), TryLockError> {
let mut flock: libc::flock = unsafe { mem::zeroed() };
flock.l_type = libc::F_WRLCK as libc::c_short;
flock.l_whence = libc::SEEK_SET as libc::c_short;
let result = cvt(unsafe { libc::fcntl(self.as_raw_fd(), libc::F_SETLK, &flock) });
if let Err(err) = result {
if err.kind() == io::ErrorKind::WouldBlock {
Err(TryLockError::WouldBlock)
} else {
Err(TryLockError::Error(err))
}
} else {
Ok(())
}
}
#[cfg(not(any(
target_os = "freebsd",
target_os = "fuchsia",
@@ -1362,6 +1399,7 @@ pub fn try_lock(&self) -> Result<(), TryLockError> {
target_os = "netbsd",
target_os = "openbsd",
target_os = "cygwin",
target_os = "solaris",
target_vendor = "apple",
)))]
pub fn try_lock(&self) -> Result<(), TryLockError> {
@@ -1393,6 +1431,23 @@ pub fn try_lock_shared(&self) -> Result<(), TryLockError> {
}
}
#[cfg(target_os = "solaris")]
pub fn try_lock_shared(&self) -> Result<(), TryLockError> {
let mut flock: libc::flock = unsafe { mem::zeroed() };
flock.l_type = libc::F_RDLCK as libc::c_short;
flock.l_whence = libc::SEEK_SET as libc::c_short;
let result = cvt(unsafe { libc::fcntl(self.as_raw_fd(), libc::F_SETLK, &flock) });
if let Err(err) = result {
if err.kind() == io::ErrorKind::WouldBlock {
Err(TryLockError::WouldBlock)
} else {
Err(TryLockError::Error(err))
}
} else {
Ok(())
}
}
#[cfg(not(any(
target_os = "freebsd",
target_os = "fuchsia",
@@ -1400,6 +1455,7 @@ pub fn try_lock_shared(&self) -> Result<(), TryLockError> {
target_os = "netbsd",
target_os = "openbsd",
target_os = "cygwin",
target_os = "solaris",
target_vendor = "apple",
)))]
pub fn try_lock_shared(&self) -> Result<(), TryLockError> {
@@ -1423,6 +1479,15 @@ pub fn unlock(&self) -> io::Result<()> {
return Ok(());
}
#[cfg(target_os = "solaris")]
pub fn unlock(&self) -> io::Result<()> {
let mut flock: libc::flock = unsafe { mem::zeroed() };
flock.l_type = libc::F_UNLCK as libc::c_short;
flock.l_whence = libc::SEEK_SET as libc::c_short;
cvt(unsafe { libc::fcntl(self.as_raw_fd(), libc::F_SETLKW, &flock) })?;
Ok(())
}
#[cfg(not(any(
target_os = "freebsd",
target_os = "fuchsia",
@@ -1430,6 +1495,7 @@ pub fn unlock(&self) -> io::Result<()> {
target_os = "netbsd",
target_os = "openbsd",
target_os = "cygwin",
target_os = "solaris",
target_vendor = "apple",
)))]
pub fn unlock(&self) -> io::Result<()> {