Merge branch 'flock' into 'master'

feat(redox): flocking

See merge request redox-os/relibc!1037
This commit is contained in:
Jeremy Soller
2026-02-25 08:20:46 -07:00
4 changed files with 156 additions and 16 deletions
+150 -2
View File
@@ -4,13 +4,14 @@ use core::{
num::NonZeroU64,
ptr, slice, str,
};
use object::bytes_of_slice_mut;
use redox_rt::{
RtTcb,
protocol::{WaitFlags, wifstopped},
sys::{Resugid, WaitpidTarget},
};
use syscall::{
self, EILSEQ, Error, MODE_PERM,
self, EILSEQ, ESRCH, Error, MODE_PERM, StdFsCallKind, StdFsCallMeta,
data::{Map, TimeSpec as redox_timespec},
dirent::{DirentHeader, DirentKind},
};
@@ -30,7 +31,10 @@ use crate::{
EBADF, EBADFD, EBADR, EEXIST, EFAULT, EFBIG, EINTR, EINVAL, EIO, ENAMETOOLONG, ENOENT,
ENOMEM, ENOSYS, EOPNOTSUPP, EPERM, ERANGE,
},
fcntl::{self, AT_EMPTY_PATH, AT_FDCWD, AT_SYMLINK_NOFOLLOW},
fcntl::{
self, AT_EMPTY_PATH, AT_FDCWD, AT_SYMLINK_NOFOLLOW, F_GETLK, F_OFD_GETLK, F_OFD_SETLK,
F_RDLCK, F_SETLK, F_SETLKW, F_UNLCK, F_WRLCK, flock,
},
limits,
pthread::{pthread_cancel, pthread_create},
signal::{NSIG, SIGEV_NONE, SIGEV_SIGNAL, SIGEV_THREAD, SIGRTMIN, sigevent},
@@ -293,6 +297,116 @@ impl Pal for Sys {
}
fn fcntl(fd: c_int, cmd: c_int, args: c_ulonglong) -> Result<c_int> {
match cmd {
F_SETLK | F_OFD_SETLK => {
let is_ofd = cmd == F_OFD_SETLK;
let flock = unsafe { &mut *(args as *mut flock) };
let (start, len) = Self::relative_to_absolute_foffset(
fd as usize,
flock.l_whence,
flock.l_start,
flock.l_len,
)?;
let start = start as u64 | if is_ofd { 1 << 63 } else { 0 };
let len = len as u64;
match flock.l_type as i32 {
F_UNLCK => {
let meta = StdFsCallMeta::new(StdFsCallKind::Unlock, start, len);
syscall::std_fs_call(fd as usize, &mut [], &meta)?;
return Ok(0);
}
F_RDLCK | F_WRLCK => {
let meta = StdFsCallMeta::new(
StdFsCallKind::Lock,
start,
len | if flock.l_type as i32 == F_WRLCK {
1 << 63
} else {
0
},
);
syscall::std_fs_call(fd as usize, &mut [], &meta)?;
return Ok(0);
}
_ => return Err(Errno(EINVAL)),
};
}
F_GETLK | F_OFD_GETLK => {
let is_ofd = cmd == F_OFD_GETLK;
let flock = unsafe { &mut *(args as *mut flock) };
if is_ofd && flock.l_pid != 0 {
log::warn!("POSIX requires `l_pid` to be 0 on input for `F_OFD_GETLK`");
return Err(Errno(EINVAL));
}
let (start, len) = Self::relative_to_absolute_foffset(
fd as usize,
flock.l_whence,
flock.l_start,
flock.l_len,
)?;
let mut start = start as u64;
if is_ofd {
start |= 1 << 63;
}
let mut len = len as u64;
if flock.l_type as i32 == F_WRLCK {
len |= 1 << 63;
}
let meta = StdFsCallMeta::new(StdFsCallKind::GetLock, 0, 0);
let payload = &mut [start, len];
// `pid` if traditional POSIX otherwise 0
let val =
match syscall::std_fs_call(fd as usize, bytes_of_slice_mut(payload), &meta) {
// According to POSIX Issue 8:
// > If no lock is found that would prevent this lock from being created, then
// > the structure shall be left unchanged except for the lock type in `l_type`
// > which shall be set to F_UNLCK.
Err(err) if err.errno == ESRCH => {
flock.l_type = F_UNLCK as i16;
return Ok(0);
}
Ok(val) => val,
Err(err) => return Err(Errno(err.errno)),
};
debug_assert_ne!(payload[0] & (1 << 63), 1 << 63);
if is_ofd {
flock.l_pid = -1;
} else {
flock.l_pid = val as i32;
}
let len = payload[1] & !(1 << 63);
if payload[1] & (1 << 63) == (1 << 63) {
flock.l_type = F_WRLCK as i16;
} else {
flock.l_type = F_RDLCK as i16;
}
flock.l_whence = SEEK_SET as _;
flock.l_start = start as i64;
flock.l_len = len as i64;
return Ok(0);
}
F_SETLKW => log::warn!("F_SETLKW: not yet implemented"),
_ => {}
}
Ok(syscall::fcntl(fd as usize, cmd as usize, args as usize)? as c_int)
}
@@ -1490,3 +1604,37 @@ impl Pal for Sys {
unsafe { redox_rt::thread::exit_this_thread(stack_base, stack_size) }
}
}
impl Sys {
fn relative_to_absolute_foffset(
fd: usize,
whence: c_short,
start: off_t,
len: off_t,
) -> Result<(off_t, off_t)> {
// let file_off = Self::lseek(fd, 0, SEEK_SET)?;
match whence as i32 {
SEEK_SET => {
let (start, len) = if len < 0 {
(start + len, -len)
} else {
(start, len)
};
if start < 0 {
return Err(Errno(EINVAL));
}
assert!(len >= 0);
Ok((start, len))
}
// FIXME: andypython: SEEK_CUR, SEEK_END
c => {
log::warn!(
"Sys::relative_to_absolute_foffset: whence={whence} not yet implemented"
);
Ok((0, 0))
}
}
}
}