feat(redox): F_{OFD}_{GETLK,SETLK}
Signed-off-by: Anhad Singh <andypython@protonmail.com>
This commit is contained in:
+111
-24
@@ -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))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user