feat(redox): F_{OFD}_{GETLK,SETLK}

Signed-off-by: Anhad Singh <andypython@protonmail.com>
This commit is contained in:
Anhad Singh
2026-02-25 01:43:45 +11:00
parent 73ef851d59
commit d1c031f1b5
+111 -24
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, StdFsCallKind, StdFsCallMeta,
self, EILSEQ, ESRCH, Error, MODE_PERM, StdFsCallKind, StdFsCallMeta,
data::{Map, TimeSpec as redox_timespec},
dirent::{DirentHeader, DirentKind},
};
@@ -31,8 +32,8 @@ use crate::{
ENOMEM, ENOSYS, EOPNOTSUPP, EPERM, ERANGE,
},
fcntl::{
self, AT_EMPTY_PATH, AT_FDCWD, AT_SYMLINK_NOFOLLOW, F_GETLK, F_OFD_SETLK, F_RDLCK,
F_SETLK, F_SETLKW, F_UNLCK, F_WRLCK, flock,
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},
@@ -300,29 +301,17 @@ impl Pal for Sys {
F_SETLK | F_OFD_SETLK => {
let is_ofd = cmd == F_OFD_SETLK;
let flock = unsafe { &mut *(args as *mut flock) };
// let file_off = Self::lseek(fd, 0, SEEK_SET)?;
// TODO: overflow checks
let (start, len) = match flock.l_whence as i32 {
SEEK_SET => {
let (start, len) = if flock.l_len < 0 {
(flock.l_start + flock.l_len, -flock.l_len)
} else {
(flock.l_start, flock.l_len)
};
let (start, len) = Self::relative_to_absolute_foffset(
fd as usize,
flock.l_whence,
flock.l_start,
flock.l_len,
)?;
if start < 0 {
return Err(Errno(EINVAL));
}
let start = start as u64 | if is_ofd { 1 << 63 } else { 0 };
let len = len as u64;
assert!(len >= 0);
(start as u64, len as u64)
}
// FIXME: SEEK_CUR, SEEK_END
c => unreachable!("{c}"),
};
let start = start | if is_ofd { 1 << 63 } else { 0 };
match flock.l_type as i32 {
F_UNLCK => {
let meta = StdFsCallMeta::new(StdFsCallKind::Unlock, start, len);
@@ -348,7 +337,71 @@ impl Pal for Sys {
};
}
F_GETLK => log::warn!("F_GETLK: not yet implemented"),
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"),
_ => {}
@@ -1555,3 +1608,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))
}
}
}
}